2019-05-15 00:01:48 +00:00
import React , { Fragment } from 'react' ;
import PropTypes from 'prop-types' ;
import { gettext , isPro , siteRoot } from '../../utils/constants' ;
import { Button , Input , InputGroup , InputGroupAddon } from 'reactstrap' ;
2023-09-04 01:50:14 +00:00
import { seafileAPI } from '../../utils/seafile-api' ;
import { Utils } from '../../utils/utils' ;
2019-05-15 00:01:48 +00:00
import UserSelect from '../user-select' ;
import SharePermissionEditor from '../select-editor/share-permission-editor' ;
2024-09-23 01:48:43 +00:00
import FileChooser from '../file-chooser' ;
2024-07-24 06:59:26 +00:00
import toaster from '../../components/toast' ;
2019-05-15 00:01:48 +00:00
class UserItem extends React . Component {
constructor ( props ) {
super ( props ) ;
this . state = {
isOperationShow : false
} ;
}
2020-11-02 05:56:35 +00:00
2019-05-15 00:01:48 +00:00
onMouseEnter = ( ) => {
2024-07-18 03:58:42 +00:00
this . setState ( { isOperationShow : true } ) ;
2023-09-13 00:40:50 +00:00
} ;
2019-05-15 00:01:48 +00:00
onMouseLeave = ( ) => {
2024-07-18 03:58:42 +00:00
this . setState ( { isOperationShow : false } ) ;
2023-09-13 00:40:50 +00:00
} ;
2019-05-15 00:01:48 +00:00
deleteUserFolderPermission = ( ) => {
let item = this . props . item ;
this . props . deleteUserFolderPermission ( item ) ;
2023-09-13 00:40:50 +00:00
} ;
2020-11-02 05:56:35 +00:00
2019-05-15 00:01:48 +00:00
onChangeUserFolderPerm = ( permission ) => {
let item = this . props . item ;
this . props . onChangeUserFolderPerm ( item . repo _id , permission , item . folder _path , item . user _email ) ;
2023-09-13 00:40:50 +00:00
} ;
2019-05-15 00:01:48 +00:00
render ( ) {
let item = this . props . item ;
let currentPermission = item . permission ;
return (
2021-10-08 08:52:17 +00:00
< tr onMouseEnter = { this . onMouseEnter } onMouseLeave = { this . onMouseLeave } onFocus = { this . onMouseEnter } >
2019-05-15 00:01:48 +00:00
< td >
2023-09-13 00:40:50 +00:00
< a href = { ` ${ siteRoot } profile/ ${ encodeURIComponent ( item . user _email ) } / ` } target = "_blank" rel = "noreferrer" > { item . user _name } < / a >
2019-05-15 00:01:48 +00:00
< / t d >
{ this . props . showPath &&
< td >
< a href = { ` ${ siteRoot } library/ ${ item . repo _id } / ${ Utils . encodePath ( this . props . repoName + item . folder _path ) } ` } > { item . folder _name } < / a >
< / t d >
}
< td >
2020-11-02 05:56:35 +00:00
< SharePermissionEditor
2019-05-15 00:01:48 +00:00
isTextMode = { true }
2023-08-24 04:10:05 +00:00
autoFocus = { true }
2019-05-15 00:01:48 +00:00
isEditIconShow = { this . state . isOperationShow }
currentPermission = { currentPermission }
permissions = { this . props . permissions }
onPermissionChanged = { this . onChangeUserFolderPerm }
/ >
< / t d >
< td >
< span
2021-10-08 08:52:17 +00:00
tabIndex = "0"
role = "button"
2019-05-15 00:01:48 +00:00
className = { ` sf2-icon-x3 action-icon ${ this . state . isOperationShow ? '' : 'hide' } ` }
2020-11-02 05:56:35 +00:00
onClick = { this . deleteUserFolderPermission }
2021-10-08 08:52:17 +00:00
onKeyDown = { Utils . onKeyDown }
2019-05-15 00:01:48 +00:00
title = { gettext ( 'Delete' ) }
2021-10-08 08:52:17 +00:00
aria - label = { gettext ( 'Delete' ) }
2019-05-15 00:01:48 +00:00
>
< / s p a n >
< / t d >
< / t r >
) ;
}
}
2023-09-13 00:40:50 +00:00
UserItem . propTypes = {
item : PropTypes . object . isRequired ,
permissions : PropTypes . array . isRequired ,
deleteUserFolderPermission : PropTypes . func . isRequired ,
onChangeUserFolderPerm : PropTypes . func . isRequired ,
showPath : PropTypes . bool . isRequired ,
2024-07-24 06:59:26 +00:00
repoName : PropTypes . string ,
2023-09-13 00:40:50 +00:00
} ;
2019-05-15 00:01:48 +00:00
const propTypes = {
2019-05-16 09:28:04 +00:00
repoID : PropTypes . string . isRequired ,
2023-09-13 00:40:50 +00:00
isDepartmentRepo : PropTypes . bool ,
2024-05-29 12:29:50 +00:00
folderPath : PropTypes . string ,
2024-03-07 07:37:09 +00:00
repoName : PropTypes . string ,
2019-05-15 00:01:48 +00:00
} ;
class LibSubFolderSetUserPermissionDialog extends React . Component {
constructor ( props ) {
super ( props ) ;
this . state = {
selectedUsers : null ,
errorMsg : [ ] ,
permission : 'rw' ,
userFolderPermItems : [ ] ,
folderPath : '' ,
showFileChooser : false
} ;
if ( ! isPro ) {
this . permissions = [ 'r' , 'rw' ] ;
} else {
2023-07-10 07:48:34 +00:00
this . permissions = [ 'r' , 'rw' , 'cloud-edit' , 'preview' , 'invisible' ] ;
2019-05-15 00:01:48 +00:00
}
}
handleUserSelectChange = ( option ) => {
2024-07-18 03:58:42 +00:00
this . setState ( { selectedUsers : option } ) ;
2023-09-13 00:40:50 +00:00
} ;
2019-05-15 00:01:48 +00:00
componentDidMount ( ) {
2024-07-18 03:58:42 +00:00
const { repoID , folderPath , isDepartmentRepo } = this . props ;
2019-05-17 01:14:26 +00:00
const request = isDepartmentRepo ?
seafileAPI . listDepartmentRepoUserFolderPerm ( repoID , folderPath ) :
seafileAPI . listUserFolderPerm ( repoID , folderPath ) ;
request . then ( ( res ) => {
2019-05-15 00:01:48 +00:00
if ( res . data . length !== 0 ) {
2024-07-18 03:58:42 +00:00
this . setState ( { userFolderPermItems : res . data } ) ;
2019-05-15 00:01:48 +00:00
}
2024-07-24 06:59:26 +00:00
} ) . catch ( error => {
let errMessage = Utils . getErrorMsg ( error ) ;
toaster . danger ( errMessage ) ;
2019-05-15 00:01:48 +00:00
} ) ;
}
setPermission = ( permission ) => {
2024-07-18 03:58:42 +00:00
this . setState ( { permission : permission } ) ;
2023-09-13 00:40:50 +00:00
} ;
2019-05-15 00:01:48 +00:00
addUserFolderPerm = ( ) => {
const { selectedUsers } = this . state ;
const folderPath = this . props . folderPath || this . state . folderPath ;
if ( ! selectedUsers || ! selectedUsers . length || ! folderPath ) { // selectedUsers: null or []
return false ;
}
2020-11-02 05:56:35 +00:00
const users = selectedUsers . map ( ( item , index ) => item . email ) ;
2019-05-17 01:14:26 +00:00
const request = this . props . isDepartmentRepo ?
seafileAPI . addDepartmentRepoUserFolderPerm ( this . props . repoID , this . state . permission , folderPath , users ) :
seafileAPI . addUserFolderPerm ( this . props . repoID , this . state . permission , folderPath , users ) ;
request . then ( res => {
2019-05-15 00:01:48 +00:00
let errorMsg = [ ] ;
if ( res . data . failed . length > 0 ) {
for ( let i = 0 ; i < res . data . failed . length ; i ++ ) {
errorMsg [ i ] = res . data . failed [ i ] ;
}
}
this . setState ( {
errorMsg : errorMsg ,
userFolderPermItems : this . state . userFolderPermItems . concat ( res . data . success ) ,
selectedUsers : null ,
permission : 'rw' ,
folderPath : '' ,
} ) ;
this . refs . userSelect . clearSelect ( ) ;
2024-07-24 06:59:26 +00:00
} ) . catch ( error => {
let errMessage = Utils . getErrorMsg ( error ) ;
toaster . danger ( errMessage ) ;
2020-11-02 05:56:35 +00:00
} ) ;
2023-09-13 00:40:50 +00:00
} ;
2019-05-15 00:01:48 +00:00
deleteUserFolderPermItem = ( item ) => {
2019-05-17 01:14:26 +00:00
const request = this . props . isDepartmentRepo ?
seafileAPI . deleteDepartmentRepoUserFolderPerm ( item . repo _id , item . permission , item . folder _path , item . user _email ) :
seafileAPI . deleteUserFolderPerm ( item . repo _id , item . permission , item . folder _path , item . user _email ) ;
request . then ( res => {
2019-05-15 00:01:48 +00:00
this . setState ( {
userFolderPermItems : this . state . userFolderPermItems . filter ( deletedItem => {
return deletedItem != item ;
2020-11-02 05:56:35 +00:00
} )
2019-05-15 00:01:48 +00:00
} ) ;
2024-07-24 06:59:26 +00:00
} ) . catch ( error => {
let errMessage = Utils . getErrorMsg ( error ) ;
toaster . danger ( errMessage ) ;
2019-05-15 00:01:48 +00:00
} ) ;
2023-09-13 00:40:50 +00:00
} ;
2019-05-15 00:01:48 +00:00
onChangeUserFolderPerm = ( repoID , permission , folderPath , userEmail ) => {
2019-05-17 01:14:26 +00:00
const request = this . props . isDepartmentRepo ?
seafileAPI . updateDepartmentRepoUserFolderPerm ( repoID , permission , folderPath , userEmail ) :
seafileAPI . updateUserFolderPerm ( repoID , permission , folderPath , userEmail ) ;
request . then ( res => {
2019-05-15 00:01:48 +00:00
let userFolderPermItems = this . state . userFolderPermItems . map ( item => {
if ( item . user _email === userEmail && item . folder _path === folderPath ) {
item . permission = permission ;
}
return item ;
} ) ;
2024-07-18 03:58:42 +00:00
this . setState ( { userFolderPermItems : userFolderPermItems } ) ;
2024-07-24 06:59:26 +00:00
} ) . catch ( error => {
let errMessage = Utils . getErrorMsg ( error ) ;
toaster . danger ( errMessage ) ;
2019-05-15 00:01:48 +00:00
} ) ;
2023-09-13 00:40:50 +00:00
} ;
2019-05-15 00:01:48 +00:00
onSetSubFolder = ( e ) => {
this . setState ( {
2020-11-02 05:56:35 +00:00
folderPath : e . target . value
2019-05-15 00:01:48 +00:00
} ) ;
2023-09-13 00:40:50 +00:00
} ;
2019-05-15 00:01:48 +00:00
toggleFileChooser = ( ) => {
this . setState ( {
showFileChooser : ! this . state . showFileChooser ,
folderPath : ''
} ) ;
2023-09-13 00:40:50 +00:00
} ;
2019-05-15 00:01:48 +00:00
toggleSubFolder = ( repo , path , item ) => {
this . setState ( {
folderPath : path ,
2020-11-02 05:56:35 +00:00
} ) ;
2023-09-13 00:40:50 +00:00
} ;
2019-05-15 00:01:48 +00:00
handleFileChooserSubmit = ( ) => {
this . setState ( {
2024-05-29 12:29:50 +00:00
folderPath : this . state . folderPath || '/' ,
2019-05-15 00:01:48 +00:00
showFileChooser : ! this . state . showFileChooser
} ) ;
2023-09-13 00:40:50 +00:00
} ;
2019-05-15 00:01:48 +00:00
onRepoItemClick = ( ) => {
this . setState ( {
2020-11-02 05:56:35 +00:00
folderPath : '/'
2019-05-15 00:01:48 +00:00
} ) ;
2023-09-13 00:40:50 +00:00
} ;
2019-05-15 00:01:48 +00:00
render ( ) {
let showPath = this . props . folderPath ? false : true ;
let { userFolderPermItems } = this . state ;
if ( this . state . showFileChooser ) {
return (
< div >
2021-12-15 06:55:16 +00:00
< FileChooser
repoID = { this . props . repoID }
2019-05-15 00:01:48 +00:00
mode = { 'only_current_library' }
onDirentItemClick = { this . toggleSubFolder }
onRepoItemClick = { this . onRepoItemClick }
/ >
< div className = "modal-footer" >
< Button color = "secondary" onClick = { this . toggleFileChooser } > { gettext ( 'Cancel' ) } < / B u t t o n >
< Button color = "primary" onClick = { this . handleFileChooserSubmit } > { gettext ( 'Submit' ) } < / B u t t o n >
< / d i v >
< / d i v >
) ;
}
2020-04-04 06:32:11 +00:00
const thead = (
< thead >
< tr >
2024-07-18 03:58:42 +00:00
< th width = { showPath ? '32%' : '55%' } > { gettext ( 'User' ) } < / t h >
2020-04-04 06:32:11 +00:00
{ showPath &&
< th width = "32%" > { gettext ( 'Folder' ) } < / t h >
}
2024-07-18 03:58:42 +00:00
< th width = { showPath ? '24%' : '30%' } > { gettext ( 'Permission' ) } < / t h >
2020-04-04 06:32:11 +00:00
< th width = { showPath ? '12%' : '15%' } > < / t h >
< / t r >
< / t h e a d >
) ;
2019-05-15 00:01:48 +00:00
return (
< Fragment >
2024-10-15 04:02:31 +00:00
< p className = "text-gray small" > { gettext ( 'Folder permission is only effective after the library is shared to users or groups. It is used to fine tune sub-folder permissions.' ) } < / p >
2020-04-04 06:32:11 +00:00
< table className = "w-xs-250" >
{ thead }
2019-05-15 00:01:48 +00:00
< tbody >
< tr >
< td >
< UserSelect
ref = "userSelect"
isMulti = { true }
2023-12-04 07:13:56 +00:00
placeholder = { gettext ( 'Search users' ) }
2019-05-15 00:01:48 +00:00
onSelectChange = { this . handleUserSelectChange }
value = { this . state . selectedUsers }
/ >
< / t d >
{ showPath &&
< td >
< InputGroup >
< Input value = { this . state . folderPath } onChange = { this . onSetSubFolder } / >
< InputGroupAddon addonType = "append" > < Button className = "sf2-icon-plus" onClick = { this . toggleFileChooser } > < / B u t t o n > < / I n p u t G r o u p A d d o n >
< / I n p u t G r o u p >
< / t d >
}
< td >
2020-11-02 05:56:35 +00:00
< SharePermissionEditor
2019-05-15 00:01:48 +00:00
isTextMode = { false }
isEditIconShow = { false }
currentPermission = { this . state . permission }
permissions = { this . permissions }
onPermissionChanged = { this . setPermission }
/ >
< / t d >
< td >
2024-07-13 07:15:22 +00:00
< Button color = "primary" onClick = { this . addUserFolderPerm } > { gettext ( 'Submit' ) } < / B u t t o n >
2019-05-15 00:01:48 +00:00
< / t d >
< / t r >
{ this . state . errorMsg . length > 0 &&
this . state . errorMsg . map ( ( item , index ) => {
let errMessage = '' ;
if ( item . user _email ) {
errMessage = item . user _email + ': ' + item . error _msg ;
} else {
errMessage = item ;
}
return (
< tr key = { index } >
< td colSpan = { 3 } > < p className = "error" > { errMessage } < / p > < / t d >
< / t r >
) ;
} )
}
< / t b o d y >
< / t a b l e >
< div className = "share-list-container" >
2020-04-04 06:32:11 +00:00
< table className = "table-thead-hidden w-xs-250" >
{ thead }
2019-05-15 00:01:48 +00:00
< tbody >
{ userFolderPermItems . map ( ( item , index ) => {
return (
2020-11-02 05:56:35 +00:00
< UserItem
key = { index }
item = { item }
2019-05-15 00:01:48 +00:00
permissions = { this . permissions }
deleteUserFolderPermission = { this . deleteUserFolderPermItem }
onChangeUserFolderPerm = { this . onChangeUserFolderPerm }
showPath = { showPath }
repoName = { this . props . repoName }
/ >
) ;
} ) }
< / t b o d y >
< / t a b l e >
< / d i v >
< / F r a g m e n t >
) ;
}
}
LibSubFolderSetUserPermissionDialog . propTypes = propTypes ;
export default LibSubFolderSetUserPermissionDialog ;