mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-05 17:02:47 +00:00
add repo deleted page
This commit is contained in:
@@ -17,6 +17,7 @@ import ShareAdminShareLinks from './pages/share-admin/share-links';
|
|||||||
import ShareAdminUploadLinks from './pages/share-admin/upload-links';
|
import ShareAdminUploadLinks from './pages/share-admin/upload-links';
|
||||||
import SharedLibraries from './pages/shared-libs/shared-libs';
|
import SharedLibraries from './pages/shared-libs/shared-libs';
|
||||||
import MyLibraries from './pages/my-libs/my-libs';
|
import MyLibraries from './pages/my-libs/my-libs';
|
||||||
|
import MyLibDeleted from './pages/my-libs/my-libs-deleted';
|
||||||
import DirView from './components/dir-view/dir-view';
|
import DirView from './components/dir-view/dir-view';
|
||||||
import Group from './pages/groups/group-view';
|
import Group from './pages/groups/group-view';
|
||||||
import Groups from './pages/groups/groups-view';
|
import Groups from './pages/groups/groups-view';
|
||||||
@@ -171,6 +172,7 @@ class App extends Component {
|
|||||||
<ShareAdminUploadLinksWrapper path={siteRoot + 'share-admin-upload-links'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} />
|
<ShareAdminUploadLinksWrapper path={siteRoot + 'share-admin-upload-links'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} />
|
||||||
<SharedLibrariesWrapper path={siteRoot + 'shared-libs'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} />
|
<SharedLibrariesWrapper path={siteRoot + 'shared-libs'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} />
|
||||||
<MyLibraries path={siteRoot + 'my-libs'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} />
|
<MyLibraries path={siteRoot + 'my-libs'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} />
|
||||||
|
<MyLibDeleted path={siteRoot + 'my-libs/deleted/'} onSearchedClick={this.onSearchedClick} />
|
||||||
<DirView path={siteRoot + 'library/:repoID/*'} pathPrefix={this.state.pathPrefix} onMenuClick={this.onShowSidePanel}/>
|
<DirView path={siteRoot + 'library/:repoID/*'} pathPrefix={this.state.pathPrefix} onMenuClick={this.onShowSidePanel}/>
|
||||||
<Groups path={siteRoot + 'groups'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick}/>
|
<Groups path={siteRoot + 'groups'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick}/>
|
||||||
<Group path={siteRoot + 'group/:groupID'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick}/>
|
<Group path={siteRoot + 'group/:groupID'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick}/>
|
||||||
|
@@ -26,7 +26,7 @@ class LibHistorySetting extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
seafileAPI.getRepoHistortLimit(this.props.repoID).then(res => {
|
seafileAPI.getRepoHistoryLimit(this.props.repoID).then(res => {
|
||||||
this.setState({
|
this.setState({
|
||||||
keepDays: res.data.keep_days,
|
keepDays: res.data.keep_days,
|
||||||
allHistory: res.data.keep_days < 0 ? true : false,
|
allHistory: res.data.keep_days < 0 ? true : false,
|
||||||
@@ -44,7 +44,7 @@ class LibHistorySetting extends React.Component {
|
|||||||
let reg = /^-?\d+$/;
|
let reg = /^-?\d+$/;
|
||||||
let flag = reg.test(days);
|
let flag = reg.test(days);
|
||||||
if (flag) {
|
if (flag) {
|
||||||
seafileAPI.setRepoHistortLimit(repoID, days).then(res => {
|
seafileAPI.setRepoHistoryLimit(repoID, days).then(res => {
|
||||||
this.setState({
|
this.setState({
|
||||||
keepDays: res.data.keep_days
|
keepDays: res.data.keep_days
|
||||||
});
|
});
|
||||||
|
@@ -127,7 +127,7 @@ class MainSideNav extends React.Component {
|
|||||||
<h3 className="sf-heading">Files</h3>
|
<h3 className="sf-heading">Files</h3>
|
||||||
<ul className="nav nav-pills flex-column nav-container">
|
<ul className="nav nav-pills flex-column nav-container">
|
||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
<Link to={ siteRoot + 'my-libs/' } className={`nav-link ellipsis ${this.getActiveClass('my-libs')}`} title={gettext('My Libraries')} onClick={() => this.tabItemClick('my-libs')}>
|
<Link to={ siteRoot + 'my-libs/' } className={`nav-link ellipsis ${this.getActiveClass('my-libs') || this.getActiveClass('deleted') }`} title={gettext('My Libraries')} onClick={() => this.tabItemClick('my-libs')}>
|
||||||
<span className="sf2-icon-user" aria-hidden="true"></span>
|
<span className="sf2-icon-user" aria-hidden="true"></span>
|
||||||
<span className="nav-text">{gettext('My Libraries')}</span>
|
<span className="nav-text">{gettext('My Libraries')}</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
@@ -1,8 +1,10 @@
|
|||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { gettext } from '../../utils/constants';
|
import { Link } from '@reach/router';
|
||||||
|
import { siteRoot, gettext } from '../../utils/constants';
|
||||||
import ModalPortal from '../modal-portal';
|
import ModalPortal from '../modal-portal';
|
||||||
import CreateRepoDialog from '../dialog/create-repo-dialog';
|
import CreateRepoDialog from '../dialog/create-repo-dialog';
|
||||||
|
import { DropdownToggle, Dropdown, DropdownMenu, DropdownItem } from 'reactstrap';
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
// isOwnLibrary: PropTypes.bool.isRequired,
|
// isOwnLibrary: PropTypes.bool.isRequired,
|
||||||
@@ -16,6 +18,7 @@ class RepoViewToolbar extends React.Component {
|
|||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
isCreateRepoDialogShow: false,
|
isCreateRepoDialogShow: false,
|
||||||
|
isOpen: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,6 +31,14 @@ class RepoViewToolbar extends React.Component {
|
|||||||
this.setState({isCreateRepoDialogShow: !this.state.isCreateRepoDialogShow});
|
this.setState({isCreateRepoDialogShow: !this.state.isCreateRepoDialogShow});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleMore = () => {
|
||||||
|
this.setState({ isOpen: !this.state.isOpen });
|
||||||
|
}
|
||||||
|
|
||||||
|
onDeleteRepoPage = () => {
|
||||||
|
console.log('turn to delete page');
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
@@ -39,7 +50,16 @@ class RepoViewToolbar extends React.Component {
|
|||||||
{gettext('New Library')}
|
{gettext('New Library')}
|
||||||
</button>
|
</button>
|
||||||
{this.props.libraryType !== 'group' && (
|
{this.props.libraryType !== 'group' && (
|
||||||
<button className="btn btn-secondary operation-item" title={gettext('More')} onClick={this.onShareClick}>{gettext('More')}</button>
|
<Dropdown isOpen={this.state.isOpen} toggle={this.toggleMore}>
|
||||||
|
<DropdownToggle className='btn btn-secondary operation-item'>
|
||||||
|
{gettext('More')}
|
||||||
|
</DropdownToggle>
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownItem>
|
||||||
|
<Link to={siteRoot + 'my-libs/deleted/'}>{gettext('Deleted Libraries')}</Link>
|
||||||
|
</DropdownItem>
|
||||||
|
</DropdownMenu>
|
||||||
|
</Dropdown>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
124
frontend/src/pages/my-libs/my-libs-deleted.js
Normal file
124
frontend/src/pages/my-libs/my-libs-deleted.js
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
import React, { Component, Fragment } from 'react';
|
||||||
|
import { Link } from '@reach/router';
|
||||||
|
import { gettext, siteRoot, lang } from '../../utils/constants';
|
||||||
|
import { seafileAPI } from '../../utils/seafile-api';
|
||||||
|
import CommonToolbar from '../../components/toolbar/common-toolbar';
|
||||||
|
import moment from 'moment';
|
||||||
|
moment.locale(lang);
|
||||||
|
|
||||||
|
class MyLibsDeleted extends Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
deletedRepoList: [],
|
||||||
|
isLoading: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
seafileAPI.listDeletedRepo().then(res => {
|
||||||
|
this.setState({
|
||||||
|
deletedRepoList: res.data
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshDeletedRepoList = (repoID) => {
|
||||||
|
this.setState({
|
||||||
|
deletedRepoList: this.state.deletedRepoList.filter(item => item.repo_id !== repoID)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<div className="main-panel-north">
|
||||||
|
<CommonToolbar onSearchedClick={this.props.onSearchedClick} />
|
||||||
|
</div>
|
||||||
|
<div className="main-panel-center">
|
||||||
|
<div className="cur-view-container">
|
||||||
|
<div className="cur-view-path">
|
||||||
|
<div className="path-container">
|
||||||
|
<Link to={ siteRoot + 'my-libs/' }>{gettext("My Libraries")}</Link>
|
||||||
|
<span className="path-split">/</span>
|
||||||
|
<span>{gettext('Deleted Libraries')}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="cur-view-content">
|
||||||
|
{(!this.state.isLoading && this.state.deletedRepoList.length === 0) &&
|
||||||
|
<div className="message empty-tip">
|
||||||
|
<h2>{gettext('No deleted libraries.')}</h2>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
{ this.state.deletedRepoList.length !== 0 &&
|
||||||
|
<div>
|
||||||
|
<p className="tip">{gettext('Tip: libraries deleted 30 days ago will be cleaned automatically.')}</p>
|
||||||
|
<DeletedRepoTable deletedRepoList={this.state.deletedRepoList}
|
||||||
|
refreshDeletedRepoList={this.refreshDeletedRepoList}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeletedRepoTable extends Component {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let deletedRepos = this.props.deletedRepoList;
|
||||||
|
return (
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style={{width: '4%'}}>{/*img*/}</th>
|
||||||
|
<th style={{width: '52%'}}>{gettext('Name')}</th>
|
||||||
|
<th style={{width: '30%'}}>{gettext('Deleted Time')}</th>
|
||||||
|
<th style={{width: '14%'}}></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{ deletedRepos && deletedRepos.map((item) => {
|
||||||
|
return (
|
||||||
|
<DeletedRepoItem
|
||||||
|
key={item.repo_id}
|
||||||
|
repo={item}
|
||||||
|
refreshDeletedRepoList={this.props.refreshDeletedRepoList}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeletedRepoItem extends Component {
|
||||||
|
|
||||||
|
restoreDeletedRepo = () => {
|
||||||
|
let repoID = this.props.repo.repo_id;
|
||||||
|
seafileAPI.restoreDeletedRepo(repoID).then(res => {
|
||||||
|
this.props.refreshDeletedRepoList(repoID);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let localTime = moment.utc(this.props.repo.del_time).toDate();
|
||||||
|
localTime = moment(localTime).fromNow();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<tr>
|
||||||
|
<td className="icon"><img src={siteRoot + 'media/img/lib/48/lib.png'} alt='icon' /></td>
|
||||||
|
<td className="name">{this.props.repo.repo_name}</td>
|
||||||
|
<td className="update">{localTime}</td>
|
||||||
|
<td className="menu-toggle"><i onClick={this.restoreDeletedRepo}className="fas fa-reply"></i></td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MyLibsDeleted;
|
@@ -206,6 +206,7 @@ urlpatterns = [
|
|||||||
url(r'^groups/$', react_fake_view, name="groups"),
|
url(r'^groups/$', react_fake_view, name="groups"),
|
||||||
url(r'^group/(?P<group_id>\d+)/$', react_group, name="group"),
|
url(r'^group/(?P<group_id>\d+)/$', react_group, name="group"),
|
||||||
url(r'^library/.*$', react_fake_view, name="lib_view"),
|
url(r'^library/.*$', react_fake_view, name="lib_view"),
|
||||||
|
url(r'^my-libs/deleted/$', react_fake_view, name="my_libs_deleted"),
|
||||||
|
|
||||||
### Ajax ###
|
### Ajax ###
|
||||||
url(r'^ajax/repo/(?P<repo_id>[-0-9a-f]{36})/dirents/$', get_dirents, name="get_dirents"),
|
url(r'^ajax/repo/(?P<repo_id>[-0-9a-f]{36})/dirents/$', get_dirents, name="get_dirents"),
|
||||||
|
Reference in New Issue
Block a user