diff --git a/products/ASC.Files/Client/src/components/panels/SelectFileDialog/asideView.js b/products/ASC.Files/Client/src/components/panels/SelectFileDialog/asideView.js new file mode 100644 index 0000000000..0192ab86f9 --- /dev/null +++ b/products/ASC.Files/Client/src/components/panels/SelectFileDialog/asideView.js @@ -0,0 +1,91 @@ +import React from "react"; +import { + StyledAsidePanel, + StyledSelectFilePanel, + StyledHeaderContent, +} from "../StyledPanels"; +import Text from "@appserver/components/text"; +import SelectFolderInput from "../SelectFolderInput"; +import FilesListBody from "./fileListBody"; +import Aside from "@appserver/components/aside"; +import Heading from "@appserver/components/heading"; +import Backdrop from "@appserver/components/backdrop"; +const DISPLAY_TYPE = "aside"; +const SelectFileDialogAsideView = ({ + t, + isPanelVisible, + zIndex, + onClose, + isVisible, + isCommonWithoutProvider, + foldersType, + isLoadingData, + onSelectFile, + onClickInput, + onCloseSelectFolderDialog, + onSelectFolder, + onSetLoadingData, + filesList, + hasNextPage, + isNextPageLoading, + loadNextPage, + selectedFolder, + iconUrl, +}) => { + console.log("isLoadingData", isLoadingData, "selectedFolder", selectedFolder); + return ( + + + + + ); +}; +export default SelectFileDialogAsideView; diff --git a/products/ASC.Files/Client/src/components/panels/SelectFileDialog/filesListBody.js b/products/ASC.Files/Client/src/components/panels/SelectFileDialog/filesListBody.js new file mode 100644 index 0000000000..f340d06100 --- /dev/null +++ b/products/ASC.Files/Client/src/components/panels/SelectFileDialog/filesListBody.js @@ -0,0 +1,151 @@ +import React, { useCallback } from "react"; +import Loader from "@appserver/components/loader"; +import Text from "@appserver/components/text"; +import { useTranslation, withTranslation } from "react-i18next"; +import CustomScrollbarsVirtualList from "@appserver/components/scrollbar/custom-scrollbars-virtual-list"; +import InfiniteLoader from "react-window-infinite-loader"; +import AutoSizer from "react-virtualized-auto-sizer"; +import { FixedSizeList as List } from "react-window"; +import { inject, observer } from "mobx-react"; +import ListRow from "./listRow"; + +const FilesListBody = ({ + filesList, + onSelectFile, + loadNextPage, + hasNextPage, + isNextPageLoading, + displayType, + viewer, + listHeight, + needRowSelection, + emptyFilesList, + loadingLabel, + iconUrl, +}) => { + const { t } = useTranslation(["SelectFile", "Common"]); + // Every row is loaded except for our loading indicator row. + const isItemLoaded = useCallback( + (index) => { + return !hasNextPage || index < filesList.length; + }, + [hasNextPage, filesList] + ); + // If there are more items to be loaded then add an extra row to hold a loading indicator. + const itemCount = hasNextPage ? filesList.length + 1 : filesList.length; + + const loadMoreItems = useCallback( + (startIndex) => { + if (isNextPageLoading) return; + console.log("startIndex", startIndex); + const options = { + startIndex: startIndex || 0, + }; + + loadNextPage && loadNextPage(options); + }, + [isNextPageLoading, filesList] + ); + + const renderLoader = useCallback( + (style) => { + return ( +
+
+ + {"Hello"} +
+
+ ); + }, + [loadingLabel] + ); + const Item = useCallback( + ({ index, style }) => { + const isLoaded = isItemLoaded(index); + + if (!isLoaded) { + return renderLoader(style); + } + + const file = filesList[index]; + const fileName = file.title; + const fileExst = file.fileExst; + const modifyFileName = fileName.substring( + 0, + fileName.indexOf(`${fileExst}`) + ); + + const fileOwner = + file.createdBy && + ((viewer.id === file.createdBy.id && t("Common:MeLabel")) || + file.createdBy.displayName); + + return ( +
+ + + {fileOwner} + + +
+ ); + }, + [filesList, renderLoader] + ); + return ( + <> + + {({ width, height }) => ( + + {({ onItemsRendered, ref }) => ( + + {Item} + + )} + + )} + + + {!hasNextPage && itemCount === 0 && {emptyFilesList}} + + ); +}; +FilesListBody.defaultProps = { + listHeight: 320, +}; +export default inject(({ auth }) => { + const { user } = auth.userStore; + return { + viewer: user, + }; +})(observer(withTranslation("Common")(FilesListBody))); diff --git a/products/ASC.Files/Client/src/components/panels/SelectFileDialog/index.js b/products/ASC.Files/Client/src/components/panels/SelectFileDialog/index.js new file mode 100644 index 0000000000..afff98eb3b --- /dev/null +++ b/products/ASC.Files/Client/src/components/panels/SelectFileDialog/index.js @@ -0,0 +1,241 @@ +import React from "react"; +import { Provider as MobxProvider } from "mobx-react"; +import { I18nextProvider } from "react-i18next"; +import { withTranslation } from "react-i18next"; +import PropTypes from "prop-types"; +import throttle from "lodash/throttle"; + +import stores from "../../../store/index"; +import i18n from "../SelectFileInput/i18n"; +import SelectFileDialogModalView from "./modalView"; +import SelectFileDialogAsideView from "./asideView"; +import { getFiles } from "@appserver/common/api/files"; +import utils from "@appserver/components/utils"; + +const { desktop } = utils.device; +class SelectFileDialogBody extends React.Component { + constructor(props) { + super(props); + this.state = { + isLoadingData: false, + isVisible: false, + selectedFolder: "", + selectedFile: "", + defaultSelectedFile: "", + fileName: "", + defaultFileName: "", + filesList: [], + width: window.innerWidth, + isChecked: false, + hasNextPage: true, + isNextPageLoading: false, + displayType: this.getDisplayType(), + }; + this.throttledResize = throttle(this.setDisplayType, 300); + } + + componentDidMount() { + const { isPanelVisible } = this.props; + if (isPanelVisible) { + window.addEventListener("resize", this.throttledResize); + } + } + componentWillUnmount() { + if (this.throttledResize) { + this.throttledResize && this.throttledResize.cancel(); + window.removeEventListener("resize", this.throttledResize); + } + } + + getDisplayType = () => { + const displayType = + window.innerWidth < desktop.match(/\d+/)[0] ? "aside" : "modal"; + + return displayType; + }; + + setDisplayType = () => { + const displayType = this.getDisplayType(); + + this.setState({ displayType: displayType }); + }; + + onClickInput = () => { + this.setState({ + isVisible: true, + }); + }; + + onCloseSelectFolderDialog = () => { + this.setState({ + isVisible: false, + }); + }; + onSelectFolder = (id) => { + this.setState({ + selectedFolder: id, + hasNextPage: true, + filesList: [], + }); + }; + + onSelectFile = (e) => { + const { onSetFileName, onClose } = this.props; + const { filesList } = this.state; + const index = e.target.dataset.index; + + if (!index) return; + this.setState( + { + selectedFile: filesList[index].id, + }, + function () { + onClose && onClose(); + onSetFileName & onSetFileName(filesList[index].title); + } + ); + }; + + onClickFile = (e) => { + const { filesList } = this.state; + const index = +e.target.id; + + this.setState({ + selectedFile: filesList[index].id, + fileName: filesList[index].title, + }); + }; + onClickSave = () => { + const { onSetFileName, onClose, onSetFileId } = this.props; + const { fileName, selectedFile } = this.state; + onSetFileName & onSetFileName(fileName); + onSetFileId & onSetFileId(selectedFile); + onClose && onClose(); + }; + + onCloseModalView = () => { + this.setState({ + isChecked: false, + }); + }; + + onSetLoadingData = (loading) => { + this.setState({ + isLoadingData: loading, + }); + }; + loadNextPage = ({ startIndex = 0 }) => { + //debugger; + const { filterValue, filterType, withSubfolders } = this.props; + const { selectedFolder } = this.state; + + console.log(`loadNextPage(startIndex=${startIndex}")`); + + const pageCount = 30; + + console.log("selectedFolder", selectedFolder); + + this.setState({ isNextPageLoading: true }, () => { + getFiles( + selectedFolder, + filterType, + filterValue, + withSubfolders, + pageCount, + startIndex + ) + .then((response) => { + let newFilesList = startIndex + ? this.state.filesList.concat(response.files) + : response.files; + console.log("newFilesList", newFilesList); + + this.setState({ + hasNextPage: newFilesList.length < response.total, + isNextPageLoading: false, + filesList: newFilesList, + }); + }) + .catch((error) => console.log(error)); + }); + }; + render() { + const { + t, + isPanelVisible, + onClose, + zIndex, + foldersType, + isCommonWithoutProvider, + iconUrl, + } = this.props; + const { + isVisible, + filesList, + isLoadingData, + hasNextPage, + isNextPageLoading, + selectedFolder, + displayType, + } = this.state; + + return displayType === "aside" ? ( + + ) : ( + + ); + } +} + +const SelectFileDialogWrapper = withTranslation(["SelectFile", "Common"])( + SelectFileDialogBody +); +class SelectFileDialog extends React.Component { + render() { + return ( + + + + + + ); + } +} + +export default SelectFileDialog; diff --git a/products/ASC.Files/Client/src/components/panels/SelectFileDialog/listRow.js b/products/ASC.Files/Client/src/components/panels/SelectFileDialog/listRow.js new file mode 100644 index 0000000000..3f3c989eb0 --- /dev/null +++ b/products/ASC.Files/Client/src/components/panels/SelectFileDialog/listRow.js @@ -0,0 +1,49 @@ +import React from "react"; +import { StyledFilesList } from "../StyledPanels"; +import { ReactSVG } from "react-svg"; + +import Text from "@appserver/components/text"; +import config from "../../../../package.json"; + +const ListRow = ({ + displayType, + needRowSelection, + index, + onSelectFile, + fileName, + children, + fileExst, + iconUrl, +}) => ( + +
+ +
+ + {fileName} + + +
+ {fileExst} +
+
+
{children}
+
+
+); + +ListRow.defaultProps = { + needRowSelection: true, +}; + +export default ListRow; diff --git a/products/ASC.Files/Client/src/components/panels/SelectFileDialog/modalView.js b/products/ASC.Files/Client/src/components/panels/SelectFileDialog/modalView.js new file mode 100644 index 0000000000..db783df302 --- /dev/null +++ b/products/ASC.Files/Client/src/components/panels/SelectFileDialog/modalView.js @@ -0,0 +1,189 @@ +import React from "react"; +import { Provider as MobxProvider } from "mobx-react"; + +import { I18nextProvider } from "react-i18next"; + +import PropTypes from "prop-types"; +import stores from "../../../store/index"; +import i18n from "../SelectFileInput/i18n"; +import { StyledAsidePanel, StyledSelectFilePanel } from "../StyledPanels"; +import ModalDialog from "@appserver/components/modal-dialog"; +import SelectFolderDialog from "../SelectFolderDialog"; +import FolderTreeBody from "../SelectFolderDialog/folderTreeBody"; +import FilesListBody from "./fileListBody"; +import Button from "@appserver/components/button"; +import Loader from "@appserver/components/loader"; +import Text from "@appserver/components/text"; +import { isArrayEqual } from "@appserver/components/utils/array"; +class SelectFileDialogModalViewBody extends React.Component { + constructor(props) { + super(props); + this.state = { + isLoading: false, + }; + this.backupList; + this.convertedData = []; + this.folderList = ""; + } + + componentDidMount() { + const { foldersType, onSetLoadingData, onSelectFolder } = this.props; + + switch (foldersType) { + case "common": + this.setState({ isLoading: true }, function () { + SelectFolderDialog.getCommonFolders() + .then((commonFolder) => { + this.folderList = commonFolder; + }) + + .finally(() => { + onSetLoadingData && onSetLoadingData(false); + + this.setState({ + isLoading: false, + }); + }); + }); + + break; + case "third-party": + this.setState({ isLoading: true }, function () { + SelectFolderDialog.getCommonThirdPartyList() + .then( + (commonThirdPartyArray) => + (this.folderList = commonThirdPartyArray) + ) + .finally(() => { + onSetLoadingData && onSetLoadingData(false); + + this.setState({ + isLoading: false, + }); + }); + }); + + break; + } + } + + onSetLoadingData = (loading) => { + this.setState({ + isLoadingData: loading, + }); + }; + onSelect = (folder) => { + const { onSelectFolder } = this.props; + const { isLoading, selectedKeys } = this.state; + + if (isArrayEqual(folder, selectedKeys)) { + return; + } + this.setState({ selectedKeys: folder }); + + onSelectFolder && onSelectFolder(folder[0]); + }; + render() { + const { + t, + isPanelVisible, + onClose, + zIndex, + isCommonWithoutProvider, + expandedKeys, + filter, + onSelectFile, + filesList, + isLoadingData, + hasNextPage, + isNextPageLoading, + loadNextPage, + selectedFolder, + iconUrl, + } = this.props; + const { isLoading, selectedKeys } = this.state; + console.log("filesList", filesList); + return ( + + + {t("SelectFile")} + + + {!isLoading ? ( +
+
+ +
+
+ {selectedFolder && ( + + )} +
+
+ ) : ( +
+ + {`${t("Common:LoadingProcessing")} ${t( + "Common:LoadingDescription" + )}`} +
+ )} +
+
+ +