1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-03 16:10:26 +00:00

[shared with me] mobile: improvement (#3861)

This commit is contained in:
llj
2019-07-17 17:37:39 +08:00
committed by plt
parent 320cc48c60
commit c84984c5cb
5 changed files with 95 additions and 48 deletions

View File

@@ -7,7 +7,7 @@ const propTypes = {
toggleDialog: PropTypes.func.isRequired, toggleDialog: PropTypes.func.isRequired,
sortBy: PropTypes.string.isRequired, sortBy: PropTypes.string.isRequired,
sortOrder: PropTypes.string.isRequired, sortOrder: PropTypes.string.isRequired,
sortList: PropTypes.func.isRequired sortItems: PropTypes.func.isRequired
}; };
class SortOptions extends React.Component { class SortOptions extends React.Component {
@@ -38,7 +38,7 @@ class SortOptions extends React.Component {
}); });
const [sortBy, sortOrder] = e.target.value.split('-'); const [sortBy, sortOrder] = e.target.value.split('-');
this.props.sortList(sortBy, sortOrder); this.props.sortItems(sortBy, sortOrder);
this.props.toggleDialog(); this.props.toggleDialog();
} }

View File

@@ -186,7 +186,7 @@ class MyLibraries extends Component {
toggleDialog={this.toggleSortOptionsDialog} toggleDialog={this.toggleSortOptionsDialog}
sortBy={this.state.sortBy} sortBy={this.state.sortBy}
sortOrder={this.state.sortOrder} sortOrder={this.state.sortOrder}
sortList={this.sortRepoList} sortItems={this.sortRepoList}
/> />
} }
{this.state.isShowDetails && ( {this.state.isShowDetails && (

View File

@@ -110,11 +110,14 @@ class MylibRepoListItem extends React.Component {
} }
onStarRepo = () => { onStarRepo = () => {
const repoName = this.props.repo.repo_name;
if (this.state.isStarred) { if (this.state.isStarred) {
seafileAPI.unstarItem(this.props.repo.repo_id, '/').then(() => { seafileAPI.unstarItem(this.props.repo.repo_id, '/').then(() => {
this.setState({isStarred: !this.state.isStarred}); this.setState({isStarred: !this.state.isStarred});
if (window.innerWidth < 728) { if (window.innerWidth < 768) {
toaster.success(gettext('Successfully unstarred the library.')); const msg = gettext('Successfully unstarred {library_name_placeholder}.')
.replace('{library_name_placeholder}', repoName);
toaster.success(msg);
} }
}).catch(error => { }).catch(error => {
let errMessage = Utils.getErrorMsg(error); let errMessage = Utils.getErrorMsg(error);
@@ -123,8 +126,10 @@ class MylibRepoListItem extends React.Component {
} else { } else {
seafileAPI.starItem(this.props.repo.repo_id, '/').then(() => { seafileAPI.starItem(this.props.repo.repo_id, '/').then(() => {
this.setState({isStarred: !this.state.isStarred}); this.setState({isStarred: !this.state.isStarred});
if (window.innerWidth < 728) { if (window.innerWidth < 768) {
toaster.success(gettext('Successfully starred the library.')); const msg = gettext('Successfully starred {library_name_placeholder}.')
.replace('{library_name_placeholder}', repoName);
toaster.success(msg);
} }
}).catch(error => { }).catch(error => {
let errMessage = Utils.getErrorMsg(error); let errMessage = Utils.getErrorMsg(error);

View File

@@ -103,9 +103,9 @@ class MylibRepoListView extends React.Component {
<table className="table-thead-hidden"> <table className="table-thead-hidden">
<thead> <thead>
<tr> <tr>
<th width="10%"><span className="sr-only">{gettext('Library Type')}</span></th> <th width="12%"><span className="sr-only">{gettext('Library Type')}</span></th>
<th width="84%"></th> <th width="80%"></th>
<th width="6%"><span className="sr-only">{gettext('Actions')}</span></th> <th width="8%"><span className="sr-only">{gettext('Actions')}</span></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>

View File

@@ -1,4 +1,5 @@
import React, { Component, Fragment } from 'react'; import React, { Component, Fragment } from 'react';
import { Dropdown, DropdownToggle, DropdownItem } from 'reactstrap';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import moment from 'moment'; import moment from 'moment';
import cookie from 'react-cookies'; import cookie from 'react-cookies';
@@ -12,6 +13,7 @@ import Loading from '../../components/loading';
import EmptyTip from '../../components/empty-tip'; import EmptyTip from '../../components/empty-tip';
import ModalPotal from '../../components/modal-portal'; import ModalPotal from '../../components/modal-portal';
import ShareDialog from '../../components/dialog/share-dialog'; import ShareDialog from '../../components/dialog/share-dialog';
import SortOptionsDialog from '../../components/dialog/sort-options';
class Content extends Component { class Content extends Component {
@@ -74,19 +76,15 @@ class Content extends Component {
const mobileThead = ( const mobileThead = (
<thead> <thead>
<tr> <tr>
<th width="18%"><span className="sr-only">{gettext('Library Type')}</span></th> <th width="12%"><span className="sr-only">{gettext('Library Type')}</span></th>
<th width="76%"> <th width="80%"></th>
{gettext('Sort:')} <th width="8%"><span className="sr-only">{gettext('Actions')}</span></th>
<a className="table-sort-op" href="#" onClick={this.sortByName}>{gettext('name')} {sortByName && sortIcon}</a>
<a className="table-sort-op" href="#" onClick={this.sortByTime}>{gettext('last update')} {sortByTime && sortIcon}</a>
</th>
<th width="6%"><span className="sr-only">{gettext('Actions')}</span></th>
</tr> </tr>
</thead> </thead>
); );
const table = ( const table = (
<table> <table className={window.innerWidth >= 768 ? '' : 'table-thead-hidden'}>
{window.innerWidth >= 768 ? desktopThead : mobileThead} {window.innerWidth >= 768 ? desktopThead : mobileThead}
<TableBody items={items} /> <TableBody items={items} />
</table> </table>
@@ -133,33 +131,34 @@ class Item extends Component {
unshared: false, unshared: false,
isShowSharedDialog: false, isShowSharedDialog: false,
isStarred: this.props.data.starred, isStarred: this.props.data.starred,
isOpMenuOpen: false // for mobile
}; };
this.handleMouseOver = this.handleMouseOver.bind(this);
this.handleMouseOut = this.handleMouseOut.bind(this);
this.share = this.share.bind(this);
this.leaveShare = this.leaveShare.bind(this);
} }
handleMouseOver() { toggleOpMenu = () => {
this.setState({
isOpMenuOpen: !this.state.isOpMenuOpen
});
}
handleMouseOver = () => {
this.setState({ this.setState({
showOpIcon: true showOpIcon: true
}); });
} }
handleMouseOut() { handleMouseOut = () => {
this.setState({ this.setState({
showOpIcon: false showOpIcon: false
}); });
} }
share(e) { share = (e) => {
e.preventDefault(); e.preventDefault();
this.setState({isShowSharedDialog: true}); this.setState({isShowSharedDialog: true});
} }
leaveShare(e) { leaveShare = (e) => {
e.preventDefault(); e.preventDefault();
const data = this.props.data; const data = this.props.data;
@@ -193,9 +192,15 @@ class Item extends Component {
} }
onStarRepo = () => { onStarRepo = () => {
const repoName = this.props.data.repo_name;
if (this.state.isStarred) { if (this.state.isStarred) {
seafileAPI.unstarItem(this.props.data.repo_id, '/').then(() => { seafileAPI.unstarItem(this.props.data.repo_id, '/').then(() => {
this.setState({isStarred: !this.state.isStarred}); this.setState({isStarred: !this.state.isStarred});
if (window.innerWidth < 768) {
const msg = gettext('Successfully unstarred {library_name_placeholder}.')
.replace('{library_name_placeholder}', repoName);
toaster.success(msg);
}
}).catch(error => { }).catch(error => {
let errMessage = Utils.getErrorMsg(error); let errMessage = Utils.getErrorMsg(error);
toaster.danger(errMessage); toaster.danger(errMessage);
@@ -203,6 +208,11 @@ class Item extends Component {
} else { } else {
seafileAPI.starItem(this.props.data.repo_id, '/').then(() => { seafileAPI.starItem(this.props.data.repo_id, '/').then(() => {
this.setState({isStarred: !this.state.isStarred}); this.setState({isStarred: !this.state.isStarred});
if (window.innerWidth < 768) {
const msg = gettext('Successfully starred {library_name_placeholder}.')
.replace('{library_name_placeholder}', repoName);
toaster.success(msg);
}
}).catch(error => { }).catch(error => {
let errMessage = Utils.getErrorMsg(error); let errMessage = Utils.getErrorMsg(error);
toaster.danger(errMessage); toaster.danger(errMessage);
@@ -273,10 +283,25 @@ class Item extends Component {
<span className="item-meta-info" title={moment(data.last_modified).format('llll')}>{moment(data.last_modified).fromNow()}</span> <span className="item-meta-info" title={moment(data.last_modified).format('llll')}>{moment(data.last_modified).fromNow()}</span>
</td> </td>
<td> <td>
{(isPro && data.is_admin) && <Dropdown isOpen={this.state.isOpMenuOpen} toggle={this.toggleOpMenu}>
<a href="#" className={shareIconClassName} title={gettext('Share')} onClick={this.share}></a> <DropdownToggle
} tag="i"
<a href="#" className={leaveShareIconClassName} title={gettext('Leave Share')} onClick={this.leaveShare}></a> className="sf-dropdown-toggle fa fa-ellipsis-v ml-0"
title={gettext('More Operations')}
data-toggle="dropdown"
aria-expanded={this.state.isOpMenuOpen}
/>
<div className={this.state.isOpMenuOpen ? '' : 'd-none'} onClick={this.toggleOpMenu}>
<div className="mobile-operation-menu-bg-layer"></div>
<div className="mobile-operation-menu">
<DropdownItem className="mobile-menu-item" onClick={this.onStarRepo}>{this.state.isStarred ? gettext('Unstar') : gettext('Star')}</DropdownItem>
{(isPro && data.is_admin) &&
<DropdownItem className="mobile-menu-item" onClick={this.share}>{gettext('Share')}</DropdownItem>
}
<DropdownItem className="mobile-menu-item" onClick={this.leaveShare}>{gettext('Leave Share')}</DropdownItem>
</div>
</div>
</Dropdown>
</td> </td>
</tr> </tr>
{this.state.isShowSharedDialog && ( {this.state.isShowSharedDialog && (
@@ -314,12 +339,12 @@ class SharedLibraries extends Component {
items: [], items: [],
sortBy: cookie.load('seafile-repo-dir-sort-by') || 'name', // 'name' or 'time' or 'size' sortBy: cookie.load('seafile-repo-dir-sort-by') || 'name', // 'name' or 'time' or 'size'
sortOrder: cookie.load('seafile-repo-dir-sort-order') || 'asc', // 'asc' or 'desc' sortOrder: cookie.load('seafile-repo-dir-sort-order') || 'asc', // 'asc' or 'desc'
isSortOptionsDialogOpen: false
}; };
} }
componentDidMount() { componentDidMount() {
seafileAPI.listRepos({type:'shared'}).then((res) => { seafileAPI.listRepos({type:'shared'}).then((res) => {
// res: {data: {...}, status: 200, statusText: "OK", headers: {…}, config: {…}, …}
let repoList = res.data.repos.map((item) => { let repoList = res.data.repos.map((item) => {
return new Repo(item); return new Repo(item);
}); });
@@ -361,25 +386,42 @@ class SharedLibraries extends Component {
}); });
} }
toggleSortOptionsDialog = () => {
this.setState({
isSortOptionsDialogOpen: !this.state.isSortOptionsDialogOpen
});
}
render() { render() {
return ( return (
<div className="main-panel-center"> <Fragment>
<div className="cur-view-container"> <div className="main-panel-center">
<div className="cur-view-path"> <div className="cur-view-container">
<h3 className="sf-heading">{gettext('Shared with me')}</h3> <div className="cur-view-path align-items-center">
</div> <h3 className="sf-heading m-0">{gettext('Shared with me')}</h3>
<div className="cur-view-content"> {(window.innerWidth < 768) && <span className="sf3-font sf3-font-sort action-icon" onClick={this.toggleSortOptionsDialog}></span>}
<Content </div>
loading={this.state.loading} <div className="cur-view-content">
errorMsg={this.state.errorMsg} <Content
items={this.state.items} loading={this.state.loading}
sortBy={this.state.sortBy} errorMsg={this.state.errorMsg}
sortOrder={this.state.sortOrder} items={this.state.items}
sortItems={this.sortItems} sortBy={this.state.sortBy}
/> sortOrder={this.state.sortOrder}
sortItems={this.sortItems}
/>
</div>
</div> </div>
</div> </div>
</div> {this.state.isSortOptionsDialogOpen &&
<SortOptionsDialog
toggleDialog={this.toggleSortOptionsDialog}
sortBy={this.state.sortBy}
sortOrder={this.state.sortOrder}
sortItems={this.sortItems}
/>
}
</Fragment>
); );
} }
} }