@@ -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 = (
-
-
-
- |
- {gettext('Name')} |
- {gettext('Shared by')} |
- {gettext('At server')} |
- {gettext('Time')} |
- {/* operations */} |
-
-
-
- {items.map((item, index) => {
- return ;
- })}
-
-
- );
+ 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
+ ? (
+
+ )
+ : (
+
+ {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.repo_name} |
- {item.from_user} |
- {item.from_server_url} |
- {dayjs(item.ctime).fromNow()} |
-
-
- |
-
- );
+ this.repoURL = shareRepoUrl;
+
+ if (isDesktop) {
+ return currentViewMode == LIST_MODE
+ ? (
+
+ |
+  |
+ {item.repo_name} |
+
+
+ |
+ {inAllLibs
+ ? (
+ <>
+ |
+ |
+ >
+ )
+ : (
+ <>
+ {item.from_server_url} |
+ >
+ )}
+ {item.from_user} |
+
+ )
+ : (
+
+
+

+
{item.repo_name}
+
+
+
+
+
+ );
+
+ } else {
+ // mobile
+ return (
+
+
+
+ |
+
+ {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(() => {