Web: Files: Added SelectFile component for documents, refactoring.

This commit is contained in:
Tatiana Lopaeva 2021-06-15 18:11:48 +03:00
parent f9ee63f723
commit 058445461b
16 changed files with 510 additions and 20 deletions

View File

@ -706,6 +706,13 @@ export function getEncryptionAccess(fileId) {
});
}
export function getFiles(folderId) {
return request({
method: "get",
url: `files/${folderId}?filterType=1`,
});
}
export function updateFileStream(file, fileId, encrypted, forcesave) {
let fd = new FormData();
fd.append("file", file);

View File

@ -0,0 +1,4 @@
{
"SelectFile": "Select file",
"ChooseByUser": "Выберите папу:"
}

View File

@ -17,5 +17,6 @@
"StoringFileVersion": "Storing file versions",
"ThirdPartyBtn": "Allow users to connect third-party storages",
"ThirdPartySettings": "Connected clouds",
"UpdateOrCreate": "Update the file version for the existing file with the same name. Otherwise, a copy of the file will be created."
}
"UpdateOrCreate": "Update the file version for the existing file with the same name. Otherwise, a copy of the file will be created.",
"SelectFile": "SelectFile"
}

View File

@ -0,0 +1,4 @@
{
"SelectFile": "Выбрать файл",
"ChooseByUser": "Выберите папу:"
}

View File

@ -17,5 +17,6 @@
"StoringFileVersion": "Хранение версий файлов",
"ThirdPartyBtn": "Разрешить пользователям подключать сторонние хранилища",
"ThirdPartySettings": "Подключенные облака",
"UpdateOrCreate": "Обновлять версию файла для существующего файла с таким же именем. В противном случае будет создаваться копия файла."
}
"UpdateOrCreate": "Обновлять версию файла для существующего файла с таким же именем. В противном случае будет создаваться копия файла.",
"SelectFile": "Выбрать файл"
}

View File

@ -0,0 +1,146 @@
import React from "react";
import { Provider as MobxProvider } from "mobx-react";
import { inject, observer } from "mobx-react";
import { I18nextProvider } from "react-i18next";
import { withTranslation } from "react-i18next";
import PropTypes from "prop-types";
import SelectFolderInput from "../SelectFolderInput";
import stores from "../../../store/index";
import i18n from "../SelectFileInput/i18n";
import { StyledAsidePanel, StyledSelectFilePanel } from "../StyledPanels";
import ModalDialog from "@appserver/components/modal-dialog";
import IconButton from "@appserver/components/icon-button";
import { getBackupFiles, getFolderInfo } from "@appserver/common/api/files";
import SelectFolderDialog from "../SelectFolderDialog";
import Text from "@appserver/components/text";
class SelectFileDialogBody extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoadingData: false,
isAvailableFolders: true,
certainFolders: true,
isVisible: false,
selectedFolder: "",
filesList: [],
};
this.backupList;
this.convertedData = [];
}
componentDidMount() {}
componentDidUpdate(prevProps, prevState) {
const { selectedFolder } = this.state;
const { foldersType, getBackupFiles } = this.props;
if (selectedFolder !== prevState.selectedFolder) {
if (foldersType === "common") {
//debugger;
getBackupFiles(selectedFolder).then((filesList) =>
this.setState({ filesList: filesList })
);
console.log("selectedFolder", selectedFolder);
}
}
}
onClickInput = () => {
this.setState({
isVisible: !this.state.isVisible,
});
};
onClose = () => {
this.setState({
isVisible: false,
});
};
onSelectFolder = (id) => {
this.setState({
selectedFolder: id,
});
};
onFileClick = (e) => {
console.log("e", e.target.id);
const { onSetFileName, onClose } = this.props;
const { filesList } = this.state;
const index = e.target.id;
this.setState(
{
selectedFile: filesList[index].id,
},
function () {
onClose && onClose();
}
);
onSetFileName & onSetFileName(filesList[index].title);
};
render() {
const { t, isPanelVisible, onClose, zIndex, foldersType } = this.props;
const { isVisible, filesList, selectedFolder } = this.state;
console.log("filesList", filesList);
return (
<StyledAsidePanel visible={isPanelVisible}>
<ModalDialog visible={isPanelVisible} zIndex={zIndex} onClose={onClose}>
<ModalDialog.Header>{t("SelectFile")}</ModalDialog.Header>
<ModalDialog.Body>
<StyledSelectFilePanel>
<Text fontWeight="600">{t("ChooseByUser")}</Text>
<SelectFolderInput
onClickInput={this.onClickInput}
onClose={this.onClose}
onSelectFolder={this.onSelectFolder}
isPanelVisible={isVisible}
foldersType={foldersType}
isNeedArrowIcon
/>
<div className="modal-dialog_body-files-list">
<Text fontWeight="600"> {"Список файлов:"}</Text>
{filesList &&
filesList.map((data, index) => (
<div className="file-name">
<div
id={`${index}`}
key={`${index}`}
className="entry-title"
onClick={this.onFileClick}
>
{data.title.substring(0, data.title.indexOf(".gz"))}
</div>
<div className="file-exst">{".gz"}</div>
</div>
))}
</div>
</StyledSelectFilePanel>
</ModalDialog.Body>
</ModalDialog>
</StyledAsidePanel>
);
}
}
const SelectFileDialogWrapper = inject(
({ filesStore, treeFoldersStore, selectedFolderStore }) => {
const { getBackupFiles, filter } = filesStore;
const { expandedPanelKeys } = treeFoldersStore;
return {
getBackupFiles,
expandedKeys: expandedPanelKeys
? expandedPanelKeys
: selectedFolderStore.pathParts,
filter,
};
}
)(observer(withTranslation(["SelectFile", "Common"])(SelectFileDialogBody)));
class SelectFileDialog extends React.Component {
render() {
return (
<MobxProvider {...stores}>
<I18nextProvider i18n={i18n}>
<SelectFileDialogWrapper {...this.props} />
</I18nextProvider>
</MobxProvider>
);
}
}
export default SelectFileDialog;

View File

@ -0,0 +1,92 @@
import React from "react";
import PropTypes from "prop-types";
import IconButton from "@appserver/components/icon-button";
import TextInput from "@appserver/components/text-input";
import StyledFileInput from "@appserver/components/file-input/styled-file-input";
const FileInput = (
{
size,
placeholder,
isDisabled,
scale,
isError,
hasWarning,
id,
onClickInput,
name,
className,
fileName,
},
...rest
) => {
return (
<StyledFileInput
size={size}
scale={scale ? 1 : 0}
hasError={isError}
hasWarning={hasWarning}
isDisabled={isDisabled}
className={className}
{...rest}
>
<TextInput
id={id}
className="file-text-input"
placeholder={placeholder}
value={fileName}
size={size}
isDisabled={isDisabled}
hasError={isError}
hasWarning={hasWarning}
scale={scale}
onClick={onClickInput}
isReadOnly
name={name}
/>
<div className="icon" onClick={!isDisabled ? onClickInput : null}>
<IconButton
className="icon-button"
iconName={"/static/images/catalog.folder.react.svg"}
color={"#A3A9AE"}
isDisabled={isDisabled}
/>
</div>
</StyledFileInput>
);
};
FileInput.propTypes = {
/** Accepts css style */
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
/** Placeholder text for the input */
placeholder: PropTypes.string,
/** Supported size of the input fields */
size: PropTypes.oneOf(["base", "middle", "big", "huge", "large"]),
/** Indicates the input field has scale */
scale: PropTypes.bool,
/** Accepts class */
className: PropTypes.string,
/** Indicates the input field has an error */
hasError: PropTypes.bool,
/** Indicates the input field has a warning */
hasWarning: PropTypes.bool,
/** Used as HTML `id` property */
id: PropTypes.string,
/** Indicates that the field cannot be used (e.g not authorised, or changes not saved) */
isDisabled: PropTypes.bool,
/** Used as HTML `name` property */
name: PropTypes.string,
};
FileInput.defaultProps = {
size: "base",
scale: false,
hasWarning: false,
hasError: false,
isDisabled: false,
baseFolder: "",
};
export default FileInput;

View File

@ -0,0 +1,35 @@
import i18n from "i18next";
import Backend from "i18next-http-backend";
import { LANGUAGE } from "@appserver/common/constants";
import config from "../../../../package.json";
import { loadLanguagePath } from "@appserver/common/utils";
const newInstance = i18n.createInstance();
newInstance.use(Backend).init({
lng: localStorage.getItem(LANGUAGE) || "en",
fallbackLng: "en",
load: "all",
//debug: true,
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
format: function (value, format) {
if (format === "lowercase") return value.toLowerCase();
return value;
},
},
backend: {
loadPath: loadLanguagePath(config.homepage, "SelectFile"),
},
ns: ["SelectFile", "Common"],
defaultNS: "SelectFile",
react: {
useSuspense: false,
},
});
export default newInstance;

View File

@ -0,0 +1,103 @@
import React from "react";
import { Provider as MobxProvider } from "mobx-react";
import { I18nextProvider } from "react-i18next";
import { withTranslation } from "react-i18next";
import styled from "styled-components";
import PropTypes from "prop-types";
import i18n from "./i18n";
import stores from "../../../store/index";
import FileInput from "./fileInput";
import SelectFileDialog from "../SelectFileDialog";
let path = "";
const StyledComponent = styled.div`
.file-input {
margin-top: 16px;
}
.file-input,
.file-text-input {
width: 100%;
max-width: 820px;
}
`;
class SelectFile extends React.PureComponent {
constructor(props) {
super(props);
this.inputRef = React.createRef();
this.state = {
isLoading: false,
fileName: "",
};
}
onSetFileName = (fileName) => {
this.setState({
fileName: fileName,
});
};
render() {
const {
name,
onClickInput,
isPanelVisible,
isCommonWithoutProvider,
onClose,
isError,
isSavingProcess,
isDisabled,
foldersType,
} = this.props;
const { isLoading, fileName } = this.state;
const zIndex = 310;
return (
<StyledComponent>
<FileInput
name={name}
className="file-input"
fileName={fileName}
isDisabled={isDisabled}
isError={isError}
onClickInput={onClickInput}
/>
<SelectFileDialog
zIndex={zIndex}
onClose={onClose}
isPanelVisible={isPanelVisible}
foldersType={foldersType}
onSetFileName={this.onSetFileName}
isCommonWithoutProvider={isCommonWithoutProvider}
/>
</StyledComponent>
);
}
}
SelectFile.propTypes = {
onClickInput: PropTypes.func.isRequired,
};
SelectFile.defaultProps = {
isCommonWithoutProvider: false,
isDisabled: false,
};
const SelectFileWrapper = withTranslation(["SelectedFolder", "Common"])(
SelectFile
);
class SelectFileModal extends React.Component {
render() {
return (
<MobxProvider {...stores}>
<I18nextProvider i18n={i18n}>
<SelectFileWrapper {...this.props} />
</I18nextProvider>
</MobxProvider>
);
}
}
export default SelectFileModal;

View File

@ -9,12 +9,13 @@ import { getCommonThirdPartyList } from "@appserver/common/api/settings";
import ModalDialog from "@appserver/components/modal-dialog";
import Loader from "@appserver/components/loader";
import Text from "@appserver/components/text";
import { StyledAsidePanel } from "../StyledPanels";
import { StyledAsidePanel, StyledSelectFolderPanel } from "../StyledPanels";
import TreeFolders from "../../Article/Body/TreeFolders";
import {
getCommonFolderList,
getFolderPath,
} from "@appserver/common/api/files";
import IconButton from "@appserver/components/icon-button";
import SelectFolderModal from "../SelectFolderInput";
import i18n from "../SelectFolderInput/i18n";
@ -87,17 +88,15 @@ class SelectFolderModalDialog extends React.Component {
}
onSelect = (folder) => {
const { onSelectFolder, onClose, onSetFullPath } = this.props;
this.setState({ isLoadingData: true }, function () {
getFolderPath(folder)
.then(
(foldersArray) =>
(pathName = SelectFolderModal.setFullFolderPath(foldersArray))
)
.then(() => onSetFullPath && onSetFullPath(pathName))
.then(() => onSelectFolder && onSelectFolder(folder[0]))
.then(() => onClose && onClose())
.finally(() => this.setState({ isLoadingData: false }));
});
getFolderPath(folder)
.then(
(foldersArray) =>
(pathName = SelectFolderModal.setFullFolderPath(foldersArray))
)
.then(() => onSetFullPath && onSetFullPath(pathName))
.then(() => onSelectFolder && onSelectFolder(folder[0]))
.finally(() => onClose && onClose());
};
render() {
const {
@ -108,13 +107,30 @@ class SelectFolderModalDialog extends React.Component {
expandedKeys,
filter,
isCommonWithoutProvider,
isNeedArrowIcon,
} = this.props;
const { isLoadingData, isAvailableFolders, certainFolders } = this.state;
return (
<StyledAsidePanel visible={isPanelVisible}>
<ModalDialog visible={isPanelVisible} zIndex={zIndex} onClose={onClose}>
<ModalDialog.Header>{t("ChooseFolder")}</ModalDialog.Header>
<ModalDialog.Header>
<StyledSelectFolderPanel isNeedArrowIcon={isNeedArrowIcon}>
<div className="modal-dialog_header">
{isNeedArrowIcon && (
<IconButton
size="16"
iconName="/static/images/arrow.path.react.svg"
onClick={onClose}
color="#A3A9AE"
/>
)}
<div className="modal-dialog_header-title">
{t("ChooseFolder")}
</div>
</div>
</StyledSelectFolderPanel>
</ModalDialog.Header>
<ModalDialog.Body>
{!isLoadingData ? (
@ -151,6 +167,9 @@ SelectFolderModalDialog.propTypes = {
isPanelVisible: PropTypes.bool.isRequired,
foldersType: PropTypes.oneOf(["common", "third-party"]),
};
SelectFolderModalDialog.defaultProps = {
isNeedArrowIcon: false,
};
const SelectFolderDialogWrapper = inject(
({ filesStore, treeFoldersStore, selectedFolderStore }) => {

View File

@ -102,6 +102,7 @@ class SelectFolder extends React.PureComponent {
onSetLoadingData,
foldersType,
folderPath,
isNeedArrowIcon,
} = this.props;
const { isLoading, baseFolderPath, fullFolderPath } = this.state;
const zIndex = 310;
@ -130,6 +131,7 @@ class SelectFolder extends React.PureComponent {
onSetFullPath={this.onSetFullPath}
onSetBaseFolderPath={this.onSetBaseFolderPath}
onSetLoadingData={onSetLoadingData}
isNeedArrowIcon={isNeedArrowIcon}
/>
</StyledComponent>
);

View File

@ -503,6 +503,37 @@ const StyledLinkRow = styled.div`
}
`;
const StyledSelectFolderPanel = styled.div`
.modal-dialog_header {
display: flex;
align-items: center;
}
.modal-dialog_header-title {
${(props) => props.isNeedArrowIcon && `margin-left:16px;`}
}
`;
const StyledSelectFilePanel = styled.div`
.modal-dialog_body-files-list {
margin-top: 16px;
}
.entry-title,
.file-exst {
margin-top: 7px;
font-weight: 600;
}
.entry-title:hover {
cursor: pointer;
text-decoration: underline;
}
.file-name {
display: flex;
border-bottom: 1px solid #eceef1;
padding: 7px 0px;
}
.file-exst {
color: #a3a9ae;
}
`;
export {
StyledAsidePanel,
StyledAddGroupsPanel,
@ -515,4 +546,6 @@ export {
StyledSharingBody,
StyledFooter,
StyledLinkRow,
StyledSelectFolderPanel,
StyledSelectFilePanel,
};

View File

@ -1278,6 +1278,18 @@ class FilesStore {
this.setFolder(folderInfo);
};
getBackupFiles = async (id) => {
const arrayInfo = await api.files.getFiles(id);
let convertedData = [];
arrayInfo.files.map((data, index) => {
if (data.fileExst === ".gz") {
convertedData.push(data);
}
});
return convertedData;
};
openDocEditor = (id, providerKey = null, tab = null, url = null) => {
if (providerKey) {
tab

View File

@ -151,6 +151,8 @@ var config = {
"./SharingDialog": "./src/components/panels/SharingDialog",
"./SelectFolderInput": "./src/components/panels/SelectFolderInput",
"./SelectFolderDialog": "./src/components/panels/SelectFolderDialog",
"./SelectFileInput": "./src/components/panels/SelectFileInput",
"./SelectFileDialog": "./src/components/panels/SelectFileDialog",
},
shared: {
...deps,

View File

@ -24,6 +24,7 @@ class RestoreBackup extends React.Component {
isChecked: false,
isNotify: true,
isVisibleDialog: false,
isPanelVisible: false,
isCheckedDocuments: true,
isCheckedThirdParty: false,
isCheckedThirdPartyStorage: false,
@ -63,11 +64,24 @@ class RestoreBackup extends React.Component {
isVisibleDialog: !this.state.isVisibleDialog,
});
};
onModalClose = () => {
this.setState({
isVisibleDialog: false,
});
};
onClickInput = () => {
this.setState({
isPanelVisible: true,
});
};
onPanelClose = () => {
this.setState({
isPanelVisible: false,
});
};
onClickShowStorage = (e) => {
const {
isCheckedTemporaryStorage,
@ -169,6 +183,7 @@ class RestoreBackup extends React.Component {
isLoading,
isNotify,
isVisibleDialog,
isPanelVisible,
isCheckedDocuments,
isCheckedThirdParty,
isCheckedThirdPartyStorage,
@ -198,7 +213,13 @@ class RestoreBackup extends React.Component {
value="value"
className="backup_radio-button"
/>
{isCheckedDocuments && <Documents />}
{isCheckedDocuments && (
<Documents
isPanelVisible={isPanelVisible}
onClose={this.onPanelClose}
onClickInput={this.onClickInput}
/>
)}
</StyledModules>
<StyledModules

View File

@ -1,10 +1,18 @@
import React from "react";
import PropTypes from "prop-types";
import FileInput from "@appserver/components/file-input";
import SelectFileInput from "files/SelectFileInput";
class Documents extends React.Component {
render() {
return <FileInput scale />;
const { onClose, isPanelVisible, onClickInput } = this.props;
return (
<SelectFileInput
isPanelVisible={isPanelVisible}
onClose={onClose}
onClickInput={onClickInput}
foldersType="common"
/>
);
}
}