2018-12-21 07:40:59 +00:00
import React , { Fragment } from 'react' ;
import PropTypes from 'prop-types' ;
2019-03-19 02:35:21 +00:00
import cookie from 'react-cookies' ;
2019-05-29 03:48:00 +00:00
import MediaQuery from 'react-responsive' ;
2019-08-28 10:30:19 +00:00
import { Dropdown , DropdownToggle , DropdownMenu , DropdownItem } from 'reactstrap' ;
2018-12-21 07:40:59 +00:00
import { seafileAPI } from '../../utils/seafile-api' ;
2019-12-05 07:45:16 +00:00
import { gettext , canAddPublicRepo } from '../../utils/constants' ;
2019-01-02 02:53:38 +00:00
import { Utils } from '../../utils/utils' ;
2018-12-21 07:40:59 +00:00
import Repo from '../../models/repo' ;
import toaster from '../../components/toast' ;
import Loading from '../../components/loading' ;
2019-06-10 09:30:10 +00:00
import EmptyTip from '../../components/empty-tip' ;
2018-12-21 07:40:59 +00:00
import ModalPortal from '../../components/modal-portal' ;
import CommonToolbar from '../../components/toolbar/common-toolbar' ;
import CreateRepoDialog from '../../components/dialog/create-repo-dialog' ;
import ShareRepoDialog from '../../components/dialog/share-repo-dialog' ;
import SharedRepoListView from '../../components/shared-repo-list-view/shared-repo-list-view' ;
2019-07-18 12:21:50 +00:00
import SortOptionsDialog from '../../components/dialog/sort-options' ;
2018-12-21 07:40:59 +00:00
const propTypes = {
onShowSidePanel : PropTypes . func . isRequired ,
onSearchedClick : PropTypes . func . isRequired ,
} ;
class PublicSharedView extends React . Component {
constructor ( props ) {
super ( props ) ;
this . state = {
isLoading : true ,
errMessage : '' ,
emptyTip : '' ,
repoList : [ ] ,
2019-05-29 05:57:12 +00:00
sortBy : cookie . load ( 'seafile-repo-dir-sort-by' ) || 'name' , // 'name' or 'time' or 'size'
2019-04-12 06:30:08 +00:00
sortOrder : cookie . load ( 'seafile-repo-dir-sort-order' ) || 'asc' , // 'asc' or 'desc'
2019-07-18 12:21:50 +00:00
isSortOptionsDialogOpen : false ,
2018-12-21 07:40:59 +00:00
libraryType : 'public' ,
isCreateMenuShow : false ,
isCreateRepoDialogShow : false ,
isSelectRepoDialpgShow : false ,
2019-01-31 09:37:02 +00:00
} ;
2018-12-21 07:40:59 +00:00
}
componentDidMount ( ) {
seafileAPI . listRepos ( { type : 'public' } ) . then ( ( res ) => {
let repoList = res . data . repos . map ( item => {
let repo = new Repo ( item ) ;
return repo ;
} ) ;
this . setState ( {
isLoading : false ,
2019-01-02 02:53:38 +00:00
repoList : Utils . sortRepos ( repoList , this . state . sortBy , this . state . sortOrder )
2018-12-21 07:40:59 +00:00
} ) ;
} ) . catch ( ( error ) => {
2019-12-05 07:45:16 +00:00
this . setState ( {
isLoading : false ,
errorMsg : Utils . getErrorMsg ( error , true ) // true: show login tip if 403
} ) ;
2018-12-21 07:40:59 +00:00
} ) ;
}
onCreateRepo = ( repo ) => {
seafileAPI . createPublicRepo ( repo ) . then ( res => {
let object = { // need modify api return value
repo _id : res . data . id ,
repo _name : res . data . name ,
permission : res . data . permission ,
size : res . data . size ,
owner _name : res . data . owner _name ,
owner _email : res . data . owner ,
mtime : res . data . mtime ,
encrypted : res . data . encrypted ,
2019-01-31 09:37:02 +00:00
} ;
2018-12-21 07:40:59 +00:00
let repo = new Repo ( object ) ;
let repoList = this . addRepoItem ( repo ) ;
this . setState ( { repoList : repoList } ) ;
this . onCreateRepoToggle ( ) ;
2019-07-16 02:01:09 +00:00
} ) . catch ( ( error ) => {
let errMessage = Utils . getErrorMsg ( error ) ;
toaster . danger ( errMessage ) ;
2019-01-31 09:37:02 +00:00
} ) ;
2023-09-13 00:40:50 +00:00
} ;
2018-12-21 07:40:59 +00:00
onRepoSelectedHandler = ( selectedRepoList ) => {
selectedRepoList . forEach ( repo => {
seafileAPI . selectOwnedRepoToPublic ( repo . repo _id , { share _type : 'public' , permission : repo . sharePermission } ) . then ( ( ) => {
let repoList = this . addRepoItem ( repo ) ;
this . setState ( { repoList : repoList } ) ;
2019-07-16 02:01:09 +00:00
} ) . catch ( ( error ) => {
let errMessage = Utils . getErrorMsg ( error ) ;
toaster . danger ( errMessage ) ;
2018-12-21 07:40:59 +00:00
} ) ;
2019-01-31 09:37:02 +00:00
} ) ;
2023-09-13 00:40:50 +00:00
} ;
2018-12-21 07:40:59 +00:00
onItemUnshare = ( repo ) => {
seafileAPI . unshareRepo ( repo . repo _id , { share _type : 'public' } ) . then ( ( ) => {
let repoList = this . state . repoList . filter ( item => {
return item . repo _id !== repo . repo _id ;
} ) ;
this . setState ( { repoList : repoList } ) ;
2019-07-16 02:01:09 +00:00
let message = gettext ( 'Successfully unshared {name}' ) . replace ( '{name}' , repo . repo _name ) ;
toaster . success ( message ) ;
} ) . catch ( error => {
let errMessage = Utils . getErrorMsg ( error ) ;
if ( errMessage === gettext ( 'Error' ) ) {
2019-07-24 23:55:52 +00:00
errMessage = gettext ( 'Failed to unshare {name}' ) . replace ( '{name}' , repo . repo _name ) ;
2019-07-16 02:01:09 +00:00
}
toaster ( errMessage ) ;
2018-12-21 07:40:59 +00:00
} ) ;
2023-09-13 00:40:50 +00:00
} ;
2018-12-21 07:40:59 +00:00
onItemDelete = ( ) => {
// todo need to optimized
2023-09-13 00:40:50 +00:00
} ;
2018-12-21 07:40:59 +00:00
addRepoItem = ( repo ) => {
let isExist = false ;
2018-12-22 07:18:53 +00:00
let repoIndex = 0 ;
2018-12-21 07:40:59 +00:00
let repoList = this . state . repoList ;
for ( let i = 0 ; i < repoList . length ; i ++ ) {
if ( repo . repo _id === repoList [ i ] . repo _id ) {
isExist = true ;
2018-12-22 07:18:53 +00:00
repoIndex = i ;
2018-12-21 07:40:59 +00:00
break ;
}
}
if ( isExist ) {
2018-12-22 07:18:53 +00:00
this . state . repoList . splice ( repoIndex , 1 ) ;
2018-12-21 07:40:59 +00:00
}
let newRepoList = this . state . repoList . map ( item => { return item ; } ) ;
2018-12-22 07:18:53 +00:00
newRepoList . unshift ( repo ) ;
2018-12-21 07:40:59 +00:00
return newRepoList ;
2023-09-13 00:40:50 +00:00
} ;
2018-12-21 07:40:59 +00:00
onAddRepoToggle = ( ) => {
this . setState ( { isCreateMenuShow : ! this . state . isCreateMenuShow } ) ;
2023-09-13 00:40:50 +00:00
} ;
2018-12-21 07:40:59 +00:00
onCreateRepoToggle = ( ) => {
this . setState ( { isCreateRepoDialogShow : ! this . state . isCreateRepoDialogShow } ) ;
2023-09-13 00:40:50 +00:00
} ;
2018-12-21 07:40:59 +00:00
onSelectRepoToggle = ( ) => {
this . setState ( { isSelectRepoDialpgShow : ! this . state . isSelectRepoDialpgShow } ) ;
2023-09-13 00:40:50 +00:00
} ;
2018-12-21 07:40:59 +00:00
2019-01-02 02:53:38 +00:00
sortItems = ( sortBy , sortOrder ) => {
2019-04-12 06:30:08 +00:00
cookie . save ( 'seafile-repo-dir-sort-by' , sortBy ) ;
cookie . save ( 'seafile-repo-dir-sort-order' , sortOrder ) ;
2019-01-02 02:53:38 +00:00
this . setState ( {
sortBy : sortBy ,
sortOrder : sortOrder ,
repoList : Utils . sortRepos ( this . state . repoList , sortBy , sortOrder )
} ) ;
2023-09-13 00:40:50 +00:00
} ;
2019-01-02 02:53:38 +00:00
2019-07-18 12:21:50 +00:00
toggleSortOptionsDialog = ( ) => {
this . setState ( {
isSortOptionsDialogOpen : ! this . state . isSortOptionsDialogOpen
} ) ;
2023-09-13 00:40:50 +00:00
} ;
2019-07-18 12:21:50 +00:00
2018-12-21 07:40:59 +00:00
render ( ) {
let errMessage = this . state . errMessage ;
let emptyTip = (
2019-06-10 09:30:10 +00:00
< EmptyTip >
2018-12-21 07:40:59 +00:00
< h2 > { gettext ( 'No public libraries' ) } < / h 2 >
2020-01-03 08:50:17 +00:00
< p > { gettext ( 'No public libraries have been created yet. A public library is accessible by all users. You can create a public library by clicking the "Add Library" button in the menu bar.' ) } < / p >
2019-06-10 09:30:10 +00:00
< / E m p t y T i p >
2018-12-21 07:40:59 +00:00
) ;
return (
< Fragment >
2019-02-20 03:54:25 +00:00
< div className = "main-panel-north border-left-show" >
2019-04-18 08:08:56 +00:00
{ canAddPublicRepo &&
< div className = "cur-view-toolbar" >
< span className = "sf2-icon-menu side-nav-toggle hidden-md-up d-md-none" title = "Side Nav Menu" onClick = { this . props . onShowSidePanel } > < / s p a n >
< div className = "operation" >
< Dropdown isOpen = { this . state . isCreateMenuShow } toggle = { this . onAddRepoToggle } >
2019-05-29 03:48:00 +00:00
< MediaQuery query = "(min-width: 768px)" >
< DropdownToggle className = 'btn btn-secondary operation-item' >
2019-08-22 12:23:08 +00:00
< i className = "fas fa-plus-square text-secondary mr-1" > < / i > { g e t t e x t ( ' A d d L i b r a r y ' ) }
2019-05-29 03:48:00 +00:00
< / D r o p d o w n T o g g l e >
< / M e d i a Q u e r y >
< MediaQuery query = "(max-width: 767.8px)" >
2020-11-02 05:56:35 +00:00
< DropdownToggle
2019-08-22 12:23:08 +00:00
tag = "span"
className = "sf2-icon-plus mobile-toolbar-icon"
title = { gettext ( 'Add Library' ) }
/ >
2019-05-29 03:48:00 +00:00
< / M e d i a Q u e r y >
2019-04-18 08:08:56 +00:00
< DropdownMenu >
< DropdownItem onClick = { this . onSelectRepoToggle } > { gettext ( 'Share existing libraries' ) } < / D r o p d o w n I t e m >
< DropdownItem onClick = { this . onCreateRepoToggle } > { gettext ( 'New Library' ) } < / D r o p d o w n I t e m >
< / D r o p d o w n M e n u >
< / D r o p d o w n >
< / d i v >
2018-12-21 07:40:59 +00:00
< / d i v >
2019-04-18 08:08:56 +00:00
}
2018-12-21 07:40:59 +00:00
< CommonToolbar onSearchedClick = { this . props . onSearchedClick } / >
< / d i v >
< div className = "main-panel-center" >
< div className = "cur-view-container" >
2019-08-29 07:28:54 +00:00
< div className = "cur-view-path" >
2019-07-18 12:21:50 +00:00
< h3 className = "sf-heading m-0" > { gettext ( 'Shared with all' ) } < / h 3 >
2019-08-22 12:23:08 +00:00
{ ( ! Utils . isDesktop ( ) && this . state . repoList . length > 0 ) && < span className = "sf3-font sf3-font-sort action-icon" onClick = { this . toggleSortOptionsDialog } > < / s p a n > }
2018-12-21 07:40:59 +00:00
< / d i v >
< div className = "cur-view-content" >
{ this . state . isLoading && < Loading / > }
{ ( ! this . state . isLoading && errMessage ) && errMessage }
{ ( ! this . state . isLoading && this . state . repoList . length === 0 ) && emptyTip }
{ ( ! this . state . isLoading && this . state . repoList . length > 0 ) &&
2020-11-02 05:56:35 +00:00
< SharedRepoListView
2018-12-21 07:40:59 +00:00
libraryType = { this . state . libraryType }
repoList = { this . state . repoList }
2019-01-02 02:53:38 +00:00
sortBy = { this . state . sortBy }
sortOrder = { this . state . sortOrder }
sortItems = { this . sortItems }
2018-12-21 07:40:59 +00:00
onItemUnshare = { this . onItemUnshare }
onItemDelete = { this . onItemDelete }
/ >
}
< / d i v >
< / d i v >
< / d i v >
2019-07-18 12:21:50 +00:00
{ this . state . isSortOptionsDialogOpen &&
< SortOptionsDialog
toggleDialog = { this . toggleSortOptionsDialog }
sortBy = { this . state . sortBy }
sortOrder = { this . state . sortOrder }
sortItems = { this . sortItems }
/ >
}
2018-12-21 07:40:59 +00:00
{ this . state . isCreateRepoDialogShow && (
< ModalPortal >
2020-11-02 05:56:35 +00:00
< CreateRepoDialog
2018-12-21 07:40:59 +00:00
libraryType = { this . state . libraryType }
onCreateToggle = { this . onCreateRepoToggle }
onCreateRepo = { this . onCreateRepo }
/ >
< / M o d a l P o r t a l >
) }
{ this . state . isSelectRepoDialpgShow && (
< ModalPortal >
2020-11-02 05:56:35 +00:00
< ShareRepoDialog
2018-12-21 07:40:59 +00:00
onRepoSelectedHandler = { this . onRepoSelectedHandler }
onShareRepoDialogClose = { this . onSelectRepoToggle }
/ >
< / M o d a l P o r t a l >
) }
< / F r a g m e n t >
) ;
}
}
PublicSharedView . propTypes = propTypes ;
export default PublicSharedView ;