diff --git a/frontend/src/components/files-sub-nav.js b/frontend/src/components/files-sub-nav.js index 3e7c510c0f..6ed118fa02 100644 --- a/frontend/src/components/files-sub-nav.js +++ b/frontend/src/components/files-sub-nav.js @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Link } from '@gatsbyjs/reach-router'; import { - gettext, siteRoot, canAddRepo, canViewOrg + gettext, siteRoot, canAddRepo, canViewOrg, enableOCM, enableOCMViaWebdav } from '../utils/constants'; const propTypes = { @@ -72,6 +72,32 @@ class FilesSubNav extends React.Component { } + {enableOCM && +
  • + this.tabItemClick(e, 'shared-with-ocm')} + > + + {gettext('Shared from other servers')} + +
  • + } + {enableOCMViaWebdav && +
  • + this.tabItemClick(e, 'ocm-via-webdav')} + > + + {gettext('Shared from other servers')} + +
  • + } {this.renderSharedGroups()} ); diff --git a/frontend/src/components/main-side-nav.js b/frontend/src/components/main-side-nav.js index 57aebaa852..1fc43a2664 100644 --- a/frontend/src/components/main-side-nav.js +++ b/frontend/src/components/main-side-nav.js @@ -6,7 +6,8 @@ import { gettext, siteRoot, canAddGroup, canAddRepo, canShareRepo, canGenerateShareLink, canGenerateUploadLink, canInvitePeople, enableTC, sideNavFooterCustomHtml, enableShowAbout, showWechatSupportGroup, - canViewOrg, isPro, isDBSqlite3, customNavItems, mediaUrl + canViewOrg, enableOCM, enableOCMViaWebdav, + isPro, isDBSqlite3, customNavItems, mediaUrl } from '../utils/constants'; import { seafileAPI } from '../utils/seafile-api'; import { Utils } from '../utils/utils'; @@ -62,7 +63,7 @@ class MainSideNav extends React.Component { return group; }); - this.filesNavHeight = (groupList.length + (canAddGroup ? 1 : 0) + (canAddRepo ? 1 : 0) + (canViewOrg ? 1 : 0) + 1) * SUB_NAV_ITEM_HEIGHT; + this.filesNavHeight = (groupList.length + (canAddGroup ? 1 : 0) + (canAddRepo ? 1 : 0) + (canViewOrg ? 1 : 0) + (enableOCM ? 1 : 0) + (enableOCMViaWebdav ? 1 : 0) + 1) * SUB_NAV_ITEM_HEIGHT; this.setState({ groupItems: groupList.sort((a, b) => { return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1; diff --git a/frontend/src/components/sort-menu.js b/frontend/src/components/sort-menu.js index 5a061372c0..1bf9f931ce 100644 --- a/frontend/src/components/sort-menu.js +++ b/frontend/src/components/sort-menu.js @@ -13,7 +13,7 @@ class SortMenu extends React.Component { constructor(props) { super(props); - this.sortOptions = [ + this.sortOptions = this.props.sortOptions || [ { value: 'name-asc', text: gettext('By name ascending') }, { value: 'name-desc', text: gettext('By name descending') }, { value: 'size-asc', text: gettext('By size ascending') }, diff --git a/frontend/src/pages/libraries/index.js b/frontend/src/pages/libraries/index.js index 99b297631a..cd23881f16 100644 --- a/frontend/src/pages/libraries/index.js +++ b/frontend/src/pages/libraries/index.js @@ -2,7 +2,7 @@ import React, { Component } from 'react'; import cookie from 'react-cookies'; import { Utils } from '../../utils/utils'; import { seafileAPI } from '../../utils/seafile-api'; -import { gettext, canAddRepo, canViewOrg } from '../../utils/constants'; +import { gettext, canAddRepo, canViewOrg, enableOCM } from '../../utils/constants'; import Repo from '../../models/repo'; import Group from '../../models/group'; import toaster from '../../components/toast'; @@ -16,6 +16,7 @@ import CreateRepoDialog from '../../components/dialog/create-repo-dialog'; import MylibRepoListView from '../../pages/my-libs/mylib-repo-list-view'; import SharedLibraries from '../../pages/shared-libs'; import SharedWithAll from '../../pages/shared-with-all'; +import SharedWithOCM from '../../pages/share-with-ocm/shared-with-ocm'; import GroupItem from '../../pages/groups/group-item'; import { GroupsReposManager } from './groups-repos-manager'; import EventBus from '../../components/common/event-bus'; @@ -62,7 +63,6 @@ class Libraries extends Component { this.unsubscribeUnsharedRepoToGroup(); } - initLibraries = () => { const promiseListRepos = seafileAPI.listRepos({ 'type': ['mine', 'shared', 'public'] }); const promiseListGroups = seafileAPI.listGroups(true); @@ -515,6 +515,17 @@ class Libraries extends Component { } + {enableOCM && +
    + +
    + } + {groupList.length > 0 && groupList.map((group) => { return ( { const url = seafileAPI.server + '/ocm-via-webdav/received-shares/'; seafileAPI.req.get(url).then((res) => { + const { received_share_list } = res.data; this.setState({ loading: false, shareID: '', path: '', - items: res.data.received_share_list, + items: this.sortItems(received_share_list) }); }).catch(error => { let errMessage = Utils.getErrorMsg(error); @@ -59,18 +62,18 @@ class OCMViaWebdav extends Component { }; openFolder = (item) => { - this.setState({ loading: true, }); const url = seafileAPI.server + '/ocm-via-webdav/received-shares/' + item.id + '/?path=' + item.path; seafileAPI.req.get(url).then((res) => { + const { received_share_list, parent_dir } = res.data; this.setState({ loading: false, shareID: item.id, - path: res.data.parent_dir, - items: res.data.received_share_list, + path: parent_dir, + items: this.sortItems(received_share_list) }); }).catch(error => { let errMessage = Utils.getErrorMsg(error); @@ -79,17 +82,17 @@ class OCMViaWebdav extends Component { }; onPathClick = (path) => { - this.setState({ - loading: true, + loading: true }); const url = seafileAPI.server + '/ocm-via-webdav/received-shares/' + this.state.shareID + '/?path=' + path; seafileAPI.req.get(url).then((res) => { + const { received_share_list, parent_dir } = res.data; this.setState({ loading: false, - items: res.data.received_share_list, - path: res.data.parent_dir, + path: parent_dir, + items: this.sortItems(received_share_list) }); }).catch(error => { let errMessage = Utils.getErrorMsg(error); @@ -97,25 +100,33 @@ class OCMViaWebdav extends Component { }); }; + sortItems = (items) => { + return items.sort((a, b) => { + return a.is_dir ? -1 : 1; + }); + }; + render() { + const { loading, errorMsg, items, shareID, path } = this.state; + return (
    @@ -143,29 +154,29 @@ class Content extends Component { render() { const { loading, errorMsg, items, path } = this.props; - const emptyTip = ( - - - ); if (loading) { return ; } else if (errorMsg) { return

    {errorMsg}

    ; } else { + const emptyTip = ( + + + ); + const table = ( - - - - - + + + + @@ -188,7 +199,6 @@ class Content extends Component { } Content.propTypes = { - data: PropTypes.object.isRequired, loading: PropTypes.bool.isRequired, errorMsg: PropTypes.string.isRequired, items: PropTypes.array.isRequired, @@ -206,18 +216,21 @@ class Item extends Component { constructor(props) { super(props); this.state = { + isHighlighted: false, isOpIconShown: false }; } handleMouseOver = () => { this.setState({ + isHighlighted: true, isOpIconShown: true }); }; handleMouseOut = () => { this.setState({ + isHighlighted: false, isOpIconShown: false }); }; @@ -227,8 +240,7 @@ class Item extends Component { window.location.href = downloadUrl; }; - leaveShare = (e) => { - e.preventDefault(); + leaveShare = () => { this.props.leaveShare(this.props.item); }; @@ -238,8 +250,8 @@ class Item extends Component { }; render() { - const item = this.props.item; - const { isOpIconShown } = this.state; + const { item, path } = this.props; + const { isHighlighted, isOpIconShown } = this.state; if (item.is_dir) { item.icon_url = Utils.getFolderIconUrl(); @@ -247,17 +259,27 @@ class Item extends Component { item.icon_url = Utils.getFileIconUrl(item.name); } return ( - - + + + - - - + ); } @@ -298,7 +320,7 @@ class DirPath extends React.Component { return ( / - {item} + {item} ); } else { @@ -310,7 +332,14 @@ class DirPath extends React.Component { return ( / - {item} + + {item} + ); } @@ -319,11 +348,17 @@ class DirPath extends React.Component { }; render() { - let pathElem = this.turnPathToLink(this.props.currentPath); + const { currentPath } = this.props; return ( -
    - {gettext('All')} - {pathElem} +
    + + {gettext('Shared from other servers')} + + {currentPath && this.turnPathToLink(currentPath)}
    ); } diff --git a/frontend/src/pages/share-with-ocm/last-path-item-wrapper.js b/frontend/src/pages/share-with-ocm/last-path-item-wrapper.js new file mode 100644 index 0000000000..fd0aa6e81e --- /dev/null +++ b/frontend/src/pages/share-with-ocm/last-path-item-wrapper.js @@ -0,0 +1,87 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap'; +import { gettext } from '../../utils/constants'; + +const propTypes = { + userPerm: PropTypes.string.isRequired, + openFileInput: PropTypes.func.isRequired +}; + +class LastPathItemWrapper extends React.Component { + + constructor(props) { + super(props); + this.state = { + isDesktopMenuOpen: false + }; + } + + toggleDesktopOpMenu = () => { + this.setState({ isDesktopMenuOpen: !this.state.isDesktopMenuOpen }); + }; + + onDropdownToggleKeyDown = (e) => { + if (e.key == 'Enter' || e.key == 'Space') { + this.toggleDesktopOpMenu(); + } + }; + + onMenuItemKeyDown = (item, e) => { + if (e.key == 'Enter' || e.key == 'Space') { + item.onClick(); + } + }; + + render() { + const { userPerm } = this.props; + let dropdownMenu = null; + if (userPerm == 'rw') { + const opList = [ + { + 'icon': 'upload-files', + 'text': gettext('Upload'), + 'onClick': this.props.openFileInput + } + ]; + + dropdownMenu = ( + + + + + + + {opList.map((item, index) => { + return ( + + + {item.text} + + ); + })} + + + ); + } + + + return ( +
    + {this.props.children} + {userPerm == 'rw' && dropdownMenu} +
    + ); + } +} + +LastPathItemWrapper.propTypes = propTypes; + +export default LastPathItemWrapper; diff --git a/frontend/src/pages/share-with-ocm/remote-dir-content.js b/frontend/src/pages/share-with-ocm/remote-dir-content.js index e428a3d3ed..6c0104b169 100644 --- a/frontend/src/pages/share-with-ocm/remote-dir-content.js +++ b/frontend/src/pages/share-with-ocm/remote-dir-content.js @@ -1,6 +1,7 @@ import React, { Fragment } from 'react'; import PropTypes from 'prop-types'; import { Link } from '@gatsbyjs/reach-router'; +import classnames from 'classnames'; import dayjs from 'dayjs'; import relativeTime from 'dayjs/plugin/relativeTime'; import { gettext } from '../../utils/constants'; @@ -14,18 +15,21 @@ class DirentItem extends React.Component { constructor(props) { super(props); this.state = { + isHighlighted: false, isOpIconShown: false }; } handleMouseOver = () => { this.setState({ + isHighlighted: true, isOpIconShown: true }); }; handleMouseOut = () => { this.setState({ + isHighlighted: false, isOpIconShown: false }); }; @@ -34,19 +38,22 @@ class DirentItem extends React.Component { this.props.openFolder(this.props.dirent); }; - downloadDirent = (e) => { - e.preventDefault(); + downloadDirent = () => { this.props.downloadDirent(this.props.dirent); }; render() { - let { isOpIconShown } = this.state; + let { isHighlighted, isOpIconShown } = this.state; let { dirent } = this.props; let iconUrl = Utils.getDirentIcon(dirent); return ( -
    + @@ -70,7 +77,6 @@ class DirentItem extends React.Component { DirentItem.propTypes = { dirent: PropTypes.object.isRequired, openFolder: PropTypes.func.isRequired, - deleteDirent: PropTypes.func.isRequired, downloadDirent: PropTypes.func.isRequired, }; @@ -93,7 +99,7 @@ class DirContent extends React.Component { return ( -
    {gettext('Name')}{gettext('Shared By')}{gettext('Time')}{/* operations */}{/* operations */}{gettext('Name')}{/* operations */}{gettext('Shared By')}{gettext('Sharing Time')}
    + + - {item.is_dir ? {item.name} : item.name} + {item.is_dir + ? {item.name} + : item.name + } + + {item.is_dir ? '' : } + {path ? '' : } {item.shared_by}{dayjs(item.ctime).fromNow()}{item.is_dir ? '' : } - {this.props.path ? '' : } - {dayjs(item.ctime).fromNow()}
    {dirent.is_file ? @@ -56,7 +63,7 @@ class DirentItem extends React.Component { {isOpIconShown && dirent.is_file && - + } {Utils.bytesToSize(dirent.size)}
    +
    @@ -109,7 +115,6 @@ class DirContent extends React.Component { key={index} dirent={dirent} openFolder={this.props.openFolder} - deleteDirent={this.props.deleteDirent} downloadDirent={this.props.downloadDirent} />; })} @@ -125,7 +130,6 @@ DirContent.propTypes = { errorMsg: PropTypes.string.isRequired, direntList: PropTypes.array.isRequired, openFolder: PropTypes.func.isRequired, - deleteDirent: PropTypes.func.isRequired, downloadDirent: PropTypes.func.isRequired, }; diff --git a/frontend/src/pages/share-with-ocm/remote-dir-path.js b/frontend/src/pages/share-with-ocm/remote-dir-path.js index 339244efdf..b839800ad1 100644 --- a/frontend/src/pages/share-with-ocm/remote-dir-path.js +++ b/frontend/src/pages/share-with-ocm/remote-dir-path.js @@ -3,13 +3,16 @@ import PropTypes from 'prop-types'; import { Link } from '@gatsbyjs/reach-router'; import { siteRoot, gettext } from '../../utils/constants'; import { Utils } from '../../utils/utils'; +import LastPathItemWrapper from './last-path-item-wrapper'; const propTypes = { + repoID: PropTypes.string.isRequired, repoName: PropTypes.string.isRequired, currentPath: PropTypes.string.isRequired, onPathClick: PropTypes.func.isRequired, onTabNavClick: PropTypes.func.isRequired, - repoID: PropTypes.string.isRequired, + userPerm: PropTypes.string.isRequired, + openFileInput: PropTypes.func.isRequired }; class DirPath extends React.Component { @@ -31,7 +34,12 @@ class DirPath extends React.Component { return ( / - {item} + + {item} + ); } else { @@ -39,7 +47,7 @@ class DirPath extends React.Component { return ( / - {item} + {item} ); } @@ -48,16 +56,23 @@ class DirPath extends React.Component { }; render() { - let { currentPath, repoName } = this.props; - let pathElem = this.turnPathToLink(currentPath); + const { currentPath, repoName } = this.props; + const pathElem = this.turnPathToLink(currentPath); return ( -
    - this.props.onTabNavClick('shared-with-ocm')}>{gettext('All')} +
    + this.props.onTabNavClick('shared-with-ocm')} title={gettext('Shared from other servers')}>{gettext('Shared from other servers')} / - {(currentPath === '/' || currentPath === '') ? - {repoName} : - {repoName} + {(currentPath === '/' || currentPath === '') + ? ( + + {repoName} + + ) + : {repoName} } {pathElem}
    diff --git a/frontend/src/pages/share-with-ocm/remote-dir-view.js b/frontend/src/pages/share-with-ocm/remote-dir-view.js index 0c6de21862..d042f49bd4 100644 --- a/frontend/src/pages/share-with-ocm/remote-dir-view.js +++ b/frontend/src/pages/share-with-ocm/remote-dir-view.js @@ -3,16 +3,19 @@ import PropTypes from 'prop-types'; import axios from 'axios'; import { Utils } from '../../utils/utils'; import { seafileAPI } from '../../utils/seafile-api'; -import { siteRoot } from '../../utils/constants'; +import { siteRoot, gettext } from '../../utils/constants'; import toaster from '../../components/toast'; import DirPathBar from './remote-dir-path'; import DirContent from './remote-dir-content'; +import '../../css/lib-content-view.css'; + class Dirent { constructor(obj) { this.name = obj.name; this.mtime = obj.mtime; this.size = obj.size; + this.type = obj.type; this.is_file = obj.type === 'file'; } @@ -119,6 +122,9 @@ class DirView extends Component { this.setState({ direntList: direntList }); + + const msg = gettext('Successfully added the file.'); + toaster.success(msg); }); }).catch((err) => { let errMessage = Utils.getErrorMsg(err); @@ -127,15 +133,11 @@ class DirView extends Component { }; render() { - const { loading, errorMsg, repoName, direntList, path } = this.state; + const { loading, errorMsg, repoName, direntList, path, userPerm } = this.state; const { repoID } = this.props; return ( - {/* - - {userPerm === 'rw' && } - */}
    @@ -145,7 +147,10 @@ class DirView extends Component { currentPath={path} onPathClick={this.onPathClick} onTabNavClick={this.props.onTabNavClick} + userPerm={userPerm} + openFileInput={this.openFileInput} /> +
    diff --git a/frontend/src/pages/share-with-ocm/shared-with-ocm.js b/frontend/src/pages/share-with-ocm/shared-with-ocm.js index 97d03d65f3..3044634f66 100644 --- a/frontend/src/pages/share-with-ocm/shared-with-ocm.js +++ b/frontend/src/pages/share-with-ocm/shared-with-ocm.js @@ -2,59 +2,133 @@ import React, { Component, Fragment } from 'react'; import PropTypes from 'prop-types'; import dayjs from 'dayjs'; import relativeTime from 'dayjs/plugin/relativeTime'; -import { Link } from '@gatsbyjs/reach-router'; +import cookie from 'react-cookies'; +import classnames from 'classnames'; +import { Link, navigate } from '@gatsbyjs/reach-router'; +import { Dropdown, DropdownToggle, DropdownItem } from 'reactstrap'; import { gettext, siteRoot } from '../../utils/constants'; import { seafileAPI } from '../../utils/seafile-api'; import { Utils } from '../../utils/utils'; import toaster from '../../components/toast'; import Loading from '../../components/loading'; import EmptyTip from '../../components/empty-tip'; +import ViewModes from '../../components/view-modes'; +import ReposSortMenu from '../../components/sort-menu'; +import SortOptionsDialog from '../../components/dialog/sort-options'; +import LibsMobileThead from '../../components/libs-mobile-thead'; +import { LIST_MODE } from '../../components/dir-view-mode/constants'; + +const propTypes = { + currentViewMode: PropTypes.string, + inAllLibs: PropTypes.bool +}; dayjs.extend(relativeTime); class Content extends Component { - render() { - const { loading, errorMsg, items } = this.props; + sortByName = (e) => { + e.preventDefault(); + const sortBy = 'name'; + const sortOrder = this.props.sortOrder == 'asc' ? 'desc' : 'asc'; + this.props.sortItems(sortBy, sortOrder); + }; - const emptyTip = ( - - + renderItems = () => { + const { items, currentViewMode, inAllLibs } = this.props; + const isDesktop = Utils.isDesktop(); + return ( + <> + {items.map((item, index) => { + return ( + + ); + })} + ); + }; + + render() { + const { loading, errorMsg, items, sortOrder, currentViewMode, inAllLibs } = this.props; if (loading) { return ; } else if (errorMsg) { return

    {errorMsg}

    ; } else { - const table = ( -
    {/* icon*/}
    - - - - - - - - - - - - {items.map((item, index) => { - return ; - })} - -
    {gettext('Name')}{gettext('Shared by')}{gettext('At server')}{gettext('Time')}{/* operations */}
    - ); + if (items.length == 0) { + const emptyTipTitle = gettext('No libraries have been shared with you'); + const emptyTip = inAllLibs + ?

    {emptyTipTitle}

    + : ( + + + ); + return emptyTip; + } + + const isDesktop = Utils.isDesktop(); + if (isDesktop) { + const sortIcon = sortOrder === 'asc' + ? + : ; + + return currentViewMode == LIST_MODE + ? ( + + + + + + + + {inAllLibs + ? ( + <> + + + + ) + : ( + <> + + + )} + + + + + {this.renderItems()} + +
    {gettext('Library Type')}{gettext('Name')} {this.props.sortBy === 'name' && sortIcon}{gettext('Actions')}{gettext('Size')}{gettext('Last Update')}{gettext('At server')}{gettext('Owner')}
    + ) + : ( +
    + {this.renderItems()} +
    + ); + + } else { // mobile + return ( + + + + {this.renderItems()} + +
    + ); + } - return items.length ? table : emptyTip; } } } @@ -71,18 +145,22 @@ class Item extends Component { constructor(props) { super(props); this.state = { - isOpIconShown: false + isHighlighted: false, + isOpIconShown: false, + isItemMenuShow: false // for mobile }; } handleMouseOver = () => { this.setState({ + isHighlighted: true, isOpIconShown: true }); }; handleMouseOut = () => { this.setState({ + isHighlighted: false, isOpIconShown: false }); }; @@ -92,26 +170,113 @@ class Item extends Component { this.props.leaveShare(this.props.item); }; + toggleOperationMenu = () => { + this.setState({ isItemMenuShow: !this.state.isItemMenuShow }); + }; + + visitRepo = () => { + navigate(this.repoURL); + }; + render() { - const item = this.props.item; - const { isOpIconShown } = this.state; + const { item, isDesktop, currentViewMode, inAllLibs } = this.props; + const { isHighlighted, isOpIconShown } = this.state; item.icon_url = Utils.getLibIconUrl(item); item.icon_title = Utils.getLibIconTitle(item); let shareRepoUrl = `${siteRoot}remote-library/${this.props.item.provider_id}/${this.props.item.repo_id}/${Utils.encodePath(this.props.item.repo_name)}/`; - return ( - - {item.icon_title} - {item.repo_name} - {item.from_user} - {item.from_server_url} - {dayjs(item.ctime).fromNow()} - - - - - ); + this.repoURL = shareRepoUrl; + + if (isDesktop) { + return currentViewMode == LIST_MODE + ? ( + + + {item.icon_title} + {item.repo_name} + + + + {inAllLibs + ? ( + <> + + + + ) + : ( + <> + {item.from_server_url} + + )} + {item.from_user} + + ) + : ( +
    +
    + {item.icon_title} + {item.repo_name} +
    +
    + +
    +
    + ); + + } else { + // mobile + return ( + + + {item.icon_title} + + + {item.repo_name && ( +
    + {item.repo_name} +
    + )} + {item.from_user} + {item.from_server_url} + + + + +
    +
    +
    + {gettext('Leave Share')} +
    +
    +
    + + + ); + + } } } @@ -123,18 +288,30 @@ Item.propTypes = { class SharedWithOCM extends Component { constructor(props) { super(props); + this.sortOptions = [ + { value: 'name-asc', text: gettext('By name ascending') }, + { value: 'name-desc', text: gettext('By name descending') } + ]; this.state = { loading: true, errorMsg: '', - items: [] + items: [], + currentViewMode: localStorage.getItem('sf_repo_list_view_mode') || LIST_MODE, + sortBy: 'name', + sortOrder: this.props.sortOrder || cookie.load('seafile-repo-dir-sort-order') || 'asc', // 'asc' or 'desc' + isSortOptionsDialogOpen: false }; } componentDidMount() { seafileAPI.listOCMSharesReceived().then((res) => { + const { ocm_share_received_list } = res.data; this.setState({ loading: false, - items: res.data.ocm_share_received_list + items: ocm_share_received_list + }, () => { + const { sortBy, sortOrder } = this.state; + this.sortItems(sortBy, sortOrder); }); }).catch((error) => { this.setState({ @@ -144,6 +321,18 @@ class SharedWithOCM extends Component { }); } + static getDerivedStateFromProps(props, state) { + if (props.sortBy == 'name' && props.sortOrder != state.sortOrder) { + cookie.save('seafile-repo-dir-sort-order', props.sortOrder); + return { + ...state, + sortOrder: props.sortOrder, + items: Utils.sortRepos(state.items, props.sortBy, props.sortOrder) + }; + } + return null; + } + leaveShare = (item) => { const { id, repo_name } = item; seafileAPI.deleteOCMShareReceived(id).then((res) => { @@ -158,27 +347,131 @@ class SharedWithOCM extends Component { }); }; + renderSortIconInMobile = () => { + return ( + <> + {(!Utils.isDesktop() && this.state.items.length > 0) && + + + } + + ); + }; + + switchViewMode = (newMode) => { + this.setState({ + currentViewMode: newMode + }, () => { + localStorage.setItem('sf_repo_list_view_mode', newMode); + }); + }; + + onSelectSortOption = (sortOption) => { + const [sortBy, sortOrder] = sortOption.value.split('-'); + this.setState({ sortBy, sortOrder }, () => { + this.sortItems(sortBy, sortOrder); + }); + }; + + sortItems = (sortBy, sortOrder) => { + cookie.save('seafile-repo-dir-sort-by', sortBy); + cookie.save('seafile-repo-dir-sort-order', sortOrder); + + this.setState({ + sortBy: sortBy, + sortOrder: sortOrder, + items: Utils.sortRepos(this.state.items, sortBy, sortOrder) + }); + }; + + toggleSortOptionsDialog = () => { + this.setState({ + isSortOptionsDialogOpen: !this.state.isSortOptionsDialogOpen + }); + }; + + renderContent = (currentViewMode) => { + return ( + + ); + }; + render() { + const { inAllLibs = false, currentViewMode: propCurrentViewMode } = this.props; // inAllLibs: in 'All Libs'('Files') page + const { sortBy, sortOrder, currentViewMode: stateCurrentViewMode } = this.state; + const currentViewMode = inAllLibs ? propCurrentViewMode : stateCurrentViewMode; + return ( -
    -
    -
    -

    {gettext('Shared from other servers')}

    + {inAllLibs + ? ( + <> +
    +

    + + {gettext('Shared from other servers')} +

    + {/* this.renderSortIconInMobile() */} +
    + {this.renderContent(currentViewMode)} + + ) + : ( +
    +
    +
    +

    {gettext('Shared from other servers')}

    + {Utils.isDesktop() && ( +
    +
    + +
    + +
    + )} + {this.renderSortIconInMobile()} +
    +
    + {this.renderContent(currentViewMode)} +
    +
    -
    - -
    -
    -
    + )} + {this.state.isSortOptionsDialogOpen && + + } ); } } +SharedWithOCM.propTypes = propTypes; + export default SharedWithOCM; diff --git a/frontend/src/pages/shared-libs/item.js b/frontend/src/pages/shared-libs/item.js index 20468df77a..3c3fee04cd 100644 --- a/frontend/src/pages/shared-libs/item.js +++ b/frontend/src/pages/shared-libs/item.js @@ -93,8 +93,7 @@ class Item extends Component { this.setState({ isShowSharedDialog: false }); }; - onToggleStarRepo = (e) => { - e.preventDefault(); + onToggleStarRepo = () => { const repoName = this.props.data.repo_name; if (this.state.isStarred) { seafileAPI.unstarItem(this.props.data.repo_id, '/').then(() => {