2020-11-16 02:45:19 +00:00
import React from 'react' ;
import PropTypes from 'prop-types' ;
2024-10-21 03:29:17 +00:00
import dayjs from 'dayjs' ;
import relativeTime from 'dayjs/plugin/relativeTime' ;
2024-12-24 03:20:40 +00:00
import { Button , Modal , ModalBody , ModalFooter , Alert } from 'reactstrap' ;
2020-11-16 02:45:19 +00:00
import { Utils } from '../../utils/utils' ;
2023-09-04 01:50:14 +00:00
import { seafileAPI } from '../../utils/seafile-api' ;
2020-11-16 02:45:19 +00:00
import { gettext , siteRoot } from '../../utils/constants' ;
2024-12-24 03:20:40 +00:00
import SeahubModalHeader from '@/components/common/seahub-modal-header' ;
2020-11-16 02:45:19 +00:00
const propTypes = {
repoID : PropTypes . string . isRequired ,
repoName : PropTypes . string . isRequired ,
toggleDialog : PropTypes . func . isRequired
} ;
2024-10-21 03:29:17 +00:00
dayjs . extend ( relativeTime ) ;
2020-11-16 02:45:19 +00:00
class SearchFileDialog extends React . Component {
constructor ( props ) {
super ( props ) ;
this . state = {
isSubmitDisabled : true ,
2021-01-12 08:17:16 +00:00
isSubmitting : false ,
2020-11-16 02:45:19 +00:00
q : '' ,
errMessage : '' ,
2021-01-12 08:17:16 +00:00
fileList : null
2020-11-16 02:45:19 +00:00
} ;
}
searchFile = ( ) => {
const { q } = this . state ;
if ( ! q . trim ( ) ) {
return false ;
}
2021-01-12 08:17:16 +00:00
this . setState ( {
isSubmitDisabled : true ,
isSubmitting : true
} ) ;
2020-11-16 02:45:19 +00:00
seafileAPI . searchFileInRepo ( this . props . repoID , q ) . then ( ( res ) => {
this . setState ( {
fileList : res . data . data ,
2021-01-12 08:17:16 +00:00
errMessage : '' ,
isSubmitDisabled : false ,
isSubmitting : false
2020-11-16 02:45:19 +00:00
} ) ;
} ) . catch ( error => {
let errMessage = Utils . getErrorMsg ( error ) ;
this . setState ( {
2021-01-12 08:17:16 +00:00
errMessage : errMessage ,
isSubmitDisabled : false ,
isSubmitting : false
2020-11-16 02:45:19 +00:00
} ) ;
} ) ;
2023-09-13 00:40:50 +00:00
} ;
2020-11-16 02:45:19 +00:00
handleKeyDown = ( e ) => {
if ( e . key == 'Enter' ) {
e . preventDefault ( ) ;
this . searchFile ( ) ;
}
2023-09-13 00:40:50 +00:00
} ;
2020-11-16 02:45:19 +00:00
toggle = ( ) => {
this . props . toggleDialog ( ) ;
2023-09-13 00:40:50 +00:00
} ;
2020-11-16 02:45:19 +00:00
handleInputChange = ( e ) => {
const q = e . target . value ;
this . setState ( {
q : q ,
isSubmitDisabled : ! q . trim ( )
} ) ;
2023-09-13 00:40:50 +00:00
} ;
2020-11-16 02:45:19 +00:00
render ( ) {
2021-01-12 08:17:16 +00:00
const { q , errMessage , fileList , isSubmitDisabled , isSubmitting } = this . state ;
2020-11-16 02:45:19 +00:00
return (
2022-12-24 02:41:34 +00:00
< Modal isOpen = { true } toggle = { this . toggle } autoFocus = { false } >
2024-12-24 03:20:40 +00:00
< SeahubModalHeader toggle = { this . toggle } > { gettext ( 'Search' ) } < / S e a h u b M o d a l H e a d e r >
2024-07-18 03:58:42 +00:00
< ModalBody style = { { height : '250px' } } className = "o-auto" >
2020-11-16 02:45:19 +00:00
< div className = "d-flex" >
2022-12-24 02:41:34 +00:00
< input className = "form-control mr-2" type = "text" placeholder = { gettext ( 'Search files in this library' ) } value = { q } onChange = { this . handleInputChange } onKeyDown = { this . handleKeyDown } autoFocus = { true } / >
2021-01-12 08:17:16 +00:00
< button type = "submit" className = { ` btn btn-primary flex-shrink-0 ${ isSubmitting ? 'btn-loading' : '' } ` } onClick = { this . searchFile } disabled = { isSubmitDisabled } > { gettext ( 'Search' ) } < / b u t t o n >
2020-11-16 02:45:19 +00:00
< / d i v >
{ errMessage && < Alert color = "danger" className = "mt-2" > { errMessage } < / A l e r t > }
< div className = "mt-2" >
2021-01-12 08:17:16 +00:00
{ ! fileList ?
null :
fileList . length == 0 ?
< p > { gettext ( 'No result' ) } < / p > :
< table className = "table-hover" >
< thead >
< tr >
< th width = "8%" > < / t h >
< th width = "42%" > { gettext ( 'Name' ) } < / t h >
< th width = "25%" > { gettext ( 'Size' ) } < / t h >
< th width = "25%" > { gettext ( 'Last Update' ) } < / t h >
< / t r >
< / t h e a d >
< tbody >
{ fileList . map ( ( item , index ) => {
return (
< FileItem
key = { index }
item = { item }
repoID = { this . props . repoID }
repoName = { this . props . repoName }
/ >
) ;
} )
}
< / t b o d y >
< / t a b l e > }
2020-11-16 02:45:19 +00:00
< / d i v >
< / M o d a l B o d y >
< ModalFooter >
< Button color = "secondary" onClick = { this . toggle } > { gettext ( 'Close' ) } < / B u t t o n >
< / M o d a l F o o t e r >
< / M o d a l >
) ;
}
}
SearchFileDialog . propTypes = propTypes ;
const FileItemPropTypes = {
repoID : PropTypes . string . isRequired ,
repoName : PropTypes . string . isRequired ,
item : PropTypes . object . isRequired
} ;
class FileItem extends React . PureComponent {
render ( ) {
const { item , repoID , repoName } = this . props ;
const name = item . path . substr ( item . path . lastIndexOf ( '/' ) + 1 ) ;
const url = item . type == 'file' ?
` ${ siteRoot } lib/ ${ repoID } /file ${ Utils . encodePath ( item . path ) } ` :
` ${ siteRoot } library/ ${ repoID } / ${ Utils . encodePath ( repoName + item . path ) } ` ;
2024-07-18 03:58:42 +00:00
return (
2020-11-16 02:45:19 +00:00
< tr >
< td className = "text-center" > < img src = { item . type == 'file' ? Utils . getFileIconUrl ( item . path ) : Utils . getFolderIconUrl ( ) } alt = "" width = "24" / > < / t d >
< td >
< a href = { url } > { name } < / a >
< / t d >
< td > { item . type == 'file' ? Utils . bytesToSize ( item . size ) : '' } < / t d >
2024-10-21 03:29:17 +00:00
< td > { dayjs ( item . mtime ) . fromNow ( ) } < / t d >
2020-11-16 02:45:19 +00:00
< / t r >
) ;
}
}
FileItem . propTypes = FileItemPropTypes ;
export default SearchFileDialog ;