diff --git a/frontend/src/components/dialog/sort-options.js b/frontend/src/components/dialog/sort-options.js new file mode 100644 index 0000000000..00e311d215 --- /dev/null +++ b/frontend/src/components/dialog/sort-options.js @@ -0,0 +1,65 @@ +import React, { Fragment } from 'react'; +import PropTypes from 'prop-types'; +import { Modal, ModalBody } from 'reactstrap'; +import { gettext } from '../../utils/constants'; + +const propTypes = { + toggleDialog: PropTypes.func.isRequired, + sortBy: PropTypes.string.isRequired, + sortOrder: PropTypes.string.isRequired, + sortList: PropTypes.func.isRequired +}; + +class SortOptions extends React.Component { + + constructor(props) { + super(props); + this.sortOptions = [ + {id: 'sort-option-1', value: 'name-asc', text: gettext('By name ascending')}, + {id: 'sort-option-2', value: 'name-desc', text: gettext('By name descending')}, + {id: 'sort-option-3', value: 'size-asc', text: gettext('By size ascending')}, + {id: 'sort-option-4', value: 'size-desc', text: gettext('By size descending')}, + {id: 'sort-option-5', value: 'time-asc', text: gettext('By time ascending')}, + {id: 'sort-option-6', value: 'time-desc', text: gettext('By time descending')} + ]; + const { sortBy, sortOrder } = this.props; + this.state = { + currentOption: `${sortBy}-${sortOrder}` + }; + } + + switchOption = (e) => { + if (!e.target.checked) { + return; + } + + this.setState({ + currentOption: e.target.value + }); + + const [sortBy, sortOrder] = e.target.value.split('-'); + this.props.sortList(sortBy, sortOrder); + this.props.toggleDialog(); + } + + render() { + return ( + + + {this.sortOptions.map((item, index) => { + return ( + + +
+
+ ); + })} +
+
+ ); + } +} + +SortOptions.propTypes = propTypes; + +export default SortOptions; diff --git a/frontend/src/pages/my-libs/my-libs.js b/frontend/src/pages/my-libs/my-libs.js index cfc153b52e..10ee963e5d 100644 --- a/frontend/src/pages/my-libs/my-libs.js +++ b/frontend/src/pages/my-libs/my-libs.js @@ -11,6 +11,7 @@ import CommonToolbar from '../../components/toolbar/common-toolbar'; import RepoViewToolbar from '../../components/toolbar/repo-view-toobar'; import LibDetail from '../../components/dirent-detail/lib-details'; import MylibRepoListView from './mylib-repo-list-view'; +import SortOptionsDialog from '../../components/dialog/sort-options'; const propTypes = { onShowSidePanel: PropTypes.func.isRequired, @@ -25,6 +26,7 @@ class MyLibraries extends Component { isLoading: true, repoList: [], isShowDetails: false, + isSortOptionsDialogOpen: false, 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' }; @@ -70,6 +72,12 @@ class MyLibraries extends Component { }); } + toggleSortOptionsDialog = () => { + this.setState({ + isSortOptionsDialogOpen: !this.state.isSortOptionsDialogOpen + }); + } + onCreateRepo = (repo) => { let permission = repo.permission; seafileAPI.createMineRepo(repo).then((res) => { @@ -147,8 +155,9 @@ class MyLibraries extends Component {
-
-

{gettext('My Libraries')}

+
+

{gettext('My Libraries')}

+ {(window.innerWidth < 768) && }
{this.state.isLoading && } @@ -168,6 +177,14 @@ class MyLibraries extends Component { }
+ {this.state.isSortOptionsDialogOpen && + + } {this.state.isShowDetails && (
{ switch(item) { + case 'Star': + case 'Unstar': + this.onStarRepo(); + break; case 'Share': this.onShareToggle(); break; @@ -109,10 +113,16 @@ class MylibRepoListItem extends React.Component { if (this.state.isStarred) { seafileAPI.unstarItem(this.props.repo.repo_id, '/').then(() => { this.setState({isStarred: !this.state.isStarred}); + if (window.innerWidth < 728) { + toaster.success(gettext('Successfully unstarred the library.')); + } }); } else { seafileAPI.starItem(this.props.repo.repo_id, '/').then(() => { this.setState({isStarred: !this.state.isStarred}); + if (window.innerWidth < 728) { + toaster.success(gettext('Successfully starred the library.')); + } }); } } @@ -284,6 +294,7 @@ class MylibRepoListItem extends React.Component { {repo.repo_name && ( { - const sortIcon = this.props.sortOrder === 'asc' ? : ; return ( - +
- + diff --git a/frontend/src/pages/my-libs/mylib-repo-menu.js b/frontend/src/pages/my-libs/mylib-repo-menu.js index e4c040a815..6dc2f0623e 100644 --- a/frontend/src/pages/my-libs/mylib-repo-menu.js +++ b/frontend/src/pages/my-libs/mylib-repo-menu.js @@ -7,6 +7,7 @@ import { Utils } from '../../utils/utils'; const propTypes = { isPC: PropTypes.bool, repo: PropTypes.object.isRequired, + isStarred: PropTypes.bool, onFreezedItem: PropTypes.func.isRequired, onUnfreezedItem: PropTypes.func.isRequired, onMenuItemClick: PropTypes.func.isRequired, @@ -71,6 +72,12 @@ class MylibRepoMenu extends React.Component { translateOperations = (item) => { let translateResult = ''; switch(item) { + case 'Star': + translateResult = gettext('Star'); + break; + case 'Unstar': + translateResult = gettext('Unstar'); + break; case 'Share': translateResult = gettext('Share'); break; @@ -130,14 +137,15 @@ class MylibRepoMenu extends React.Component { } // mobile menu - operations.unshift('Share'); operations.unshift('Delete'); + operations.unshift('Share'); + this.props.isStarred ? operations.unshift('Unstar') : operations.unshift('Star'); return ( .svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}")}catch(t){console&&console.log(t)}}!function(t){if(document.addEventListener)if(~["complete","loaded","interactive"].indexOf(document.readyState))setTimeout(t,0);else{var e=function(){document.removeEventListener("DOMContentLoaded",e,!1),t()};document.addEventListener("DOMContentLoaded",e,!1)}else document.attachEvent&&(c=t,o=d.document,i=!1,(l=function(){try{o.documentElement.doScroll("left")}catch(t){return void setTimeout(l,50)}n()})(),o.onreadystatechange=function(){"complete"==o.readyState&&(o.onreadystatechange=null,n())});function n(){i||(i=!0,c())}var c,o,i,l}(function(){var t,e;(t=document.createElement("div")).innerHTML=n,n=null,(e=t.getElementsByTagName("svg")[0])&&(e.setAttribute("aria-hidden","true"),e.style.position="absolute",e.style.width=0,e.style.height=0,e.style.overflow="hidden",function(t,e){e.firstChild?function(t,e){e.parentNode.insertBefore(t,e)}(t,e.firstChild):e.appendChild(t)}(e,document.body))})}(window); \ No newline at end of file +!function(h){var c,e='',t=(c=document.getElementsByTagName("script"))[c.length-1].getAttribute("data-injectcss");if(t&&!h.__iconfont__svg__cssinject__){h.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}!function(c){if(document.addEventListener)if(~["complete","loaded","interactive"].indexOf(document.readyState))setTimeout(c,0);else{var t=function(){document.removeEventListener("DOMContentLoaded",t,!1),c()};document.addEventListener("DOMContentLoaded",t,!1)}else document.attachEvent&&(n=c,o=h.document,l=!1,(i=function(){try{o.documentElement.doScroll("left")}catch(c){return void setTimeout(i,50)}e()})(),o.onreadystatechange=function(){"complete"==o.readyState&&(o.onreadystatechange=null,e())});function e(){l||(l=!0,n())}var n,o,l,i}(function(){var c,t;(c=document.createElement("div")).innerHTML=e,e=null,(t=c.getElementsByTagName("svg")[0])&&(t.setAttribute("aria-hidden","true"),t.style.position="absolute",t.style.width=0,t.style.height=0,t.style.overflow="hidden",function(c,t){t.firstChild?function(c,t){t.parentNode.insertBefore(c,t)}(c,t.firstChild):t.appendChild(c)}(t,document.body))})}(window); \ No newline at end of file diff --git a/media/css/sf_font3/iconfont.svg b/media/css/sf_font3/iconfont.svg index 0312ad4495..05920c8701 100644 --- a/media/css/sf_font3/iconfont.svg +++ b/media/css/sf_font3/iconfont.svg @@ -20,10 +20,19 @@ Created by iconfont /> - + - + + + + + + + + + + diff --git a/media/css/sf_font3/iconfont.ttf b/media/css/sf_font3/iconfont.ttf index bddfff53f1..05c8fb3953 100644 Binary files a/media/css/sf_font3/iconfont.ttf and b/media/css/sf_font3/iconfont.ttf differ diff --git a/media/css/sf_font3/iconfont.woff b/media/css/sf_font3/iconfont.woff index 194b8459a7..e8aa715e1d 100644 Binary files a/media/css/sf_font3/iconfont.woff and b/media/css/sf_font3/iconfont.woff differ diff --git a/media/css/sf_font3/iconfont.woff2 b/media/css/sf_font3/iconfont.woff2 index dafdbaab2c..f15e9bf543 100644 Binary files a/media/css/sf_font3/iconfont.woff2 and b/media/css/sf_font3/iconfont.woff2 differ
{gettext('Library Type')} - {gettext('Sort:')} - {gettext('name')} {this.props.sortBy === 'name' && sortIcon} - {gettext('last update')} {this.props.sortBy === 'time' && sortIcon} - {gettext('Actions')}