From 4826c0b8d17ba8b3591557a5e2da981b6d45ee22 Mon Sep 17 00:00:00 2001 From: ilearnit Date: Fri, 7 Dec 2018 02:46:47 +0000 Subject: [PATCH] update my libs --- .../dialog/lib-history-setting-dialog.js | 132 ++++++++++++++ .../src/components/dialog/transfer-dialog.js | 85 +++++++++ .../components/dirent-detail/lib-details.js | 62 +++++++ frontend/src/pages/my-libs/my-libs.js | 169 +++++++++++++++++- media/css/seahub_react.css | 2 + 5 files changed, 441 insertions(+), 9 deletions(-) create mode 100644 frontend/src/components/dialog/lib-history-setting-dialog.js create mode 100644 frontend/src/components/dialog/transfer-dialog.js create mode 100644 frontend/src/components/dirent-detail/lib-details.js diff --git a/frontend/src/components/dialog/lib-history-setting-dialog.js b/frontend/src/components/dialog/lib-history-setting-dialog.js new file mode 100644 index 0000000000..9cbc0df352 --- /dev/null +++ b/frontend/src/components/dialog/lib-history-setting-dialog.js @@ -0,0 +1,132 @@ +import React, { Fragment } from 'react'; +import PropTypes from 'prop-types'; +import { gettext } from '../../utils/constants'; +import { Button, Modal, ModalHeader, ModalBody, Form, FormGroup, Label, Input } from 'reactstrap'; +import { seafileAPI } from '../../utils/seafile-api.js'; + +const propTypes = { + itemName: PropTypes.string.isRequired, + toggleDialog: PropTypes.func.isRequired, + repoID: PropTypes.string.isRequired, +}; + +class LibHistorySetting extends React.Component { + + constructor(props) { + super(props); + this.state = { + keepDays: -1, + expireDays: 30, + disabled: true, + allHistory: true, + noHistory: false, + autoHistory: false, + errorInfo: '' + }; + } + + componentDidMount() { + seafileAPI.getRepoHistortLimit(this.props.repoID).then(res => { + this.setState({ + keepDays: res.data.keep_days, + allHistory: res.data.keep_days < 0 ? true : false, + noHistory: res.data.keep_days === 0 ? true : false, + autoHistory: res.data.keep_days > 0 ? true : false, + disabled: res.data.keep_days > 0 ? false : true, + expireDays: res.data.keep_days > 0 ? res.data.keep_days : 30, + }); + }); + } + + submit = () => { + let days = this.state.keepDays; + let repoID = this.props.repoID; + let reg = /^-?\d+$/; + let flag = reg.test(days); + if (flag) { + seafileAPI.setRepoHistortLimit(repoID, days).then(res => { + this.setState({ + keepDays: res.data.keep_days + }); + }); + this.props.toggleDialog(); + } else { + this.setState({ + errorInfo: gettext('Please enter a non-negative integer'), + }) + } + } + + onChange = (e) => { + let num = e.target.value; + this.setState({ + keepDays: num, + expireDays: num, + }); + } + + setLimitDays = (type) => { + if (type === 'allHistory') { + this.setState({ + keepDays: -1, + }); + } else if (type === 'noHistory') { + this.setState({ + keepDays: 0, + }); + } else { + this.setState({ + disabled: false + }); + } + + this.setState({ + allHistory: type === 'allHistory' ? true : false, + noHistory: type === 'noHistory' ? true : false, + autoHistory: type === 'autoHistory' ? true : false, + }); + } + + render() { + const itemName = this.props.itemName; + return ( + + + {itemName}{' '}{gettext('History Setting')} + + +
+ + + + + + + + + + +
+ +
+
+
+ ); + } +} + +LibHistorySetting.propTypes = propTypes; + +export default LibHistorySetting; diff --git a/frontend/src/components/dialog/transfer-dialog.js b/frontend/src/components/dialog/transfer-dialog.js new file mode 100644 index 0000000000..bc3cdf1171 --- /dev/null +++ b/frontend/src/components/dialog/transfer-dialog.js @@ -0,0 +1,85 @@ +import React, { Fragment } from 'react'; +import PropTypes from 'prop-types'; +import AsyncSelect from 'react-select/lib/Async'; +import { gettext } from '../../utils/constants'; +import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; +import { seafileAPI } from '../../utils/seafile-api.js'; + +const propTypes = { + itemName: PropTypes.string.isRequired, + repoID: PropTypes.string.isRequired, + toggleDialog: PropTypes.func.isRequired, + submit: PropTypes.func.isRequired, +}; + +class TransferDialog extends React.Component { + constructor(props) { + super(props); + this.state = { + selectedOption: null, + errorMsg: [], + sharedItems: [] + }; + this.options = []; + } + + handleSelectChange = (option) => { + this.setState({selectedOption: option}); + this.options = []; + } + + loadOptions = (value, callback) => { + if (value.trim().length > 0) { + seafileAPI.searchUsers(value.trim()).then((res) => { + this.options = []; + for (let i = 0 ; i < res.data.users.length; i++) { + let obj = {}; + obj.value = res.data.users[i].name; + obj.email = res.data.users[i].email; + obj.label = + + + {res.data.users[i].name} + ; + this.options.push(obj); + } + callback(this.options); + }); + } + } + + submit = () => { + let repoID = this.props.repoID; + let user = this.state.selectedOption.email; + seafileAPI.transferRepo(repoID, user).then(res => { + this.props.submit(repoID); + this.props.toggleDialog(); + }) + } + + render() { + const itemName = this.props.itemName; + return ( + + + {gettext('Transfer Library')} {itemName} {gettext('TO')} + + +
+ +
+
+ ); + } +} + +TransferDialog.propTypes = propTypes; + +export default TransferDialog; diff --git a/frontend/src/components/dirent-detail/lib-details.js b/frontend/src/components/dirent-detail/lib-details.js new file mode 100644 index 0000000000..81145b3b0b --- /dev/null +++ b/frontend/src/components/dirent-detail/lib-details.js @@ -0,0 +1,62 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Utils } from '../../utils/utils'; +import { siteRoot, gettext } from '../../utils/constants'; +import { seafileAPI } from '../../utils/seafile-api'; +import DetailListView from './detail-list-view'; +import Repo from '../../models/repo'; +import FileTag from '../../models/file-tag'; +import '../../css/dirent-detail.css'; + +class LibDetail extends React.Component { + + constructor(props) { + super(props); + this.state = { + fileCount: '', + libName: '', + isLoading: true, + }; + } + + componentDidMount() { + seafileAPI.getRepoInfo(this.props.libID).then(res => { + this.setState({ + fileCount: res.data.file_count, + libName: res.data.repo_name + }); + }); + } + + render() { + return ( +
+
+
+
+ icon{' '} + {this.state.libName} +
+
+
+
+ icon +
+
+ + + + + + + +
{gettext('Files')}{this.state.fileCount}
{gettext('Size')}{this.props.libSize}
{gettext('Last Update')}{this.props.libUpdateTime}
+
+
+
+ ); + } +} + + +export default LibDetail; diff --git a/frontend/src/pages/my-libs/my-libs.js b/frontend/src/pages/my-libs/my-libs.js index 9acf86edf9..83901f6b0c 100644 --- a/frontend/src/pages/my-libs/my-libs.js +++ b/frontend/src/pages/my-libs/my-libs.js @@ -6,23 +6,43 @@ import { seafileAPI } from '../../utils/seafile-api'; import { Utils } from '../../utils/utils'; import { gettext, siteRoot, loginUrl, isPro, storages, canGenerateShareLink, canGenerateUploadLink, folderPermEnabled, enableRepoSnapshotLabel } from '../../utils/constants'; import Loading from '../../components/loading'; +import ModalPortal from '../../components/modal-portal'; import DeleteItemPopup from './popups/delete-item'; import CommonToolbar from '../../components/toolbar/common-toolbar'; import RepoViewToolbar from '../../components/toolbar/repo-view-toobar'; +import TransferDialog from '../../components/dialog/transfer-dialog'; +import LibHistorySetting from '../../components/dialog/lib-history-setting-dialog'; +import LibDetail from '../../components/dirent-detail/lib-details'; class Content extends Component { constructor(props) { super(props); this.state = { - deleteItemPopupOpen: false + deleteItemPopupOpen: false, + showTransfer: false, + itemName: '', + showHistorySetting: false, + showDetails: false, + libID: '', + libSize: '', + libUpdateTime: '' }; this.toggleDeleteItemPopup = this.toggleDeleteItemPopup.bind(this); this.showDeleteItemPopup = this.showDeleteItemPopup.bind(this); + this.onTransfer = this.onTransfer.bind(this); + this.onHistorySetting = this.onHistorySetting.bind(this); + this.onFileTagChanged = this.onFileTagChanged.bind(this); + this.onDetails = this.onDetails.bind(this); + this.closeDetails = this.closeDetails.bind(this); this.operations = { - showDeleteItemPopup: this.showDeleteItemPopup + showDeleteItemPopup: this.showDeleteItemPopup, + onTransfer: this.onTransfer, + onHistorySetting: this.onHistorySetting, + onDetails: this.onDetails, + onRenameRepo: this.props.renameRepo, }; } @@ -39,6 +59,50 @@ class Content extends Component { }); } + onTransfer(itemName, itemID) { + this.setState({ + showTransfer: !this.state.showTransfer, + itemName: itemName, + libID: itemID + }); + } + + onHistorySetting(itemName, itemID) { + this.setState({ + showHistorySetting: !this.state.showHistorySetting, + itemName: itemName, + libID: itemID + }); + } + + onDetails(data) { + const libSize = Utils.formatSize({bytes: data.size}); + const libID = data.repo_id; + const libUpdateTime = moment(data.last_modified).fromNow(); + + this.setState({ + showDetails: !this.state.showDetails, + libID: libID, + libSize: libSize, + libUpdateTime: libUpdateTime + }); + } + + closeDetails() { + this.setState({ + showDetails: !this.state.showDetails + }) + } + + onFileTagChanged() { + seafileAPI.listFileTags(this.state.detailsRepoID, '/').then(res => { + let fileTags = res.data.file_tags.map(item => { + console.log(item); + }); + }); + } + + render() { const {loading, errorMsg, items} = this.props.data; @@ -96,6 +160,32 @@ class Content extends Component { {table} + {this.state.showTransfer && + + + + } + {this.state.showHistorySetting && + + + + } + {this.state.showDetails && ( +
+ +
+ )} ); @@ -132,7 +222,9 @@ class Item extends Component { this.state = { showOpIcon: false, operationMenuOpen: false, - deleted: false + deleted: false, + showChangeLibName: false, + repoName: this.props.data.repo_name, }; this.handleMouseOver = this.handleMouseOver.bind(this); @@ -213,12 +305,37 @@ class Item extends Component { } rename() { + this.setState({ + showChangeLibName: !this.state.showChangeLibName + }) + } + + onChangeLibName = (e) => { + this.setState({ + repoName: e.target.value + }) + } + + updateLibName = () => { + const itemID = this.props.data.repo_id; + seafileAPI.renameRepo(itemID, this.state.repoName).then(res => { + this.rename(); + this.props.operations.onRenameRepo(itemID, this.state.repoName); + }).catch(res => { + // TODO res error + }) } transfer() { + const itemName = this.props.data.repo_name; + const itemID = this.props.data.repo_id; + this.props.operations.onTransfer(itemName, itemID); } historySetting() { + const itemName = this.props.data.repo_name; + const itemID = this.props.data.repo_id; + this.props.operations.onHistorySetting(itemName, itemID); } changePassword() { @@ -231,6 +348,8 @@ class Item extends Component { } showDetails() { + let data = this.props.data; + this.props.operations.onDetails(data); } label() { @@ -321,11 +440,21 @@ class Item extends Component { const desktopItem = ( {data.icon_title} - - {data.repo_name ? - {data.repo_name} : - gettext('Broken (please contact your administrator to fix this library)')} - + { + this.state.showChangeLibName ? ( + + +