Folder.jsx 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import React from 'react'
  2. import { translate } from 'react-i18next'
  3. import PropTypes from 'prop-types'
  4. import classnames from 'classnames'
  5. import FileItem from './ContentItem.jsx'
  6. // import PopupExtandedAction from '../../container/PopupExtandedAction.jsx'
  7. import BtnExtandedAction from './BtnExtandedAction.jsx'
  8. class Folder extends React.Component {
  9. constructor (props) {
  10. super(props)
  11. this.state = {
  12. open: false
  13. }
  14. }
  15. handleClickToggleFolder = () => {
  16. !this.state.open && this.props.folderData.content.length === 0 && this.props.onClickFolder(this.props.folderData.id)
  17. this.setState({open: !this.state.open})
  18. }
  19. handleClickCreateContent = (e, folder, type) => {
  20. e.preventDefault()
  21. e.stopPropagation() // because we have a link inside a link (togler and newFile)
  22. this.props.onClickCreateContent(folder, type)
  23. }
  24. render () {
  25. const {
  26. app,
  27. folderData,
  28. onClickItem,
  29. onClickExtendedAction,
  30. onClickFolder,
  31. isLast,
  32. t
  33. } = this.props
  34. return (
  35. <div className={classnames('folder', {'active': this.state.open && folderData.content.length > 0, 'item-last': isLast})}>
  36. <div className='folder__header align-items-center' onClick={this.handleClickToggleFolder}>
  37. <div className='folder__header__triangleborder'>
  38. <div className='folder__header__triangleborder__triangle' />
  39. </div>
  40. <div className='folder__header__icon'>
  41. <i className={classnames('fa fa-fw', {'fa-folder-open-o': this.state.open, 'fa-folder-o': !this.state.open})} />
  42. </div>
  43. <div className='folder__header__name'>
  44. { folderData.title }
  45. </div>
  46. <div className='folder__header__button'>
  47. <div className='folder__header__button__addbtn'>
  48. <button className='addbtn__text btn btn-outline-primary dropdown-toggle' type='button' id='dropdownMenuButton' data-toggle='dropdown' aria-haspopup='true' aria-expanded='false'>
  49. {t('Folder.create')} ...
  50. </button>
  51. {/* @TODO generate the subdropdown with available app from redux */}
  52. <div className='addbtn__subdropdown dropdown-menu' aria-labelledby='dropdownMenuButton'>
  53. <div className='subdropdown__link dropdown-item' onClick={e => this.handleClickCreateContent(e, folderData, 'folder')}>
  54. <div className='subdropdown__link__folder d-flex align-items-center'>
  55. <div className='subdropdown__link__folder__icon mr-3'>
  56. <i className='fa fa-fw fa-folder-o' />
  57. </div>
  58. <div className='subdropdown__link__folder__text'>
  59. Créer un dossier
  60. </div>
  61. </div>
  62. </div>
  63. <div className='subdropdown__link dropdown-item' onClick={e => this.handleClickCreateContent(e, folderData, 'PageHtml')}>
  64. <div className='subdropdown__link__apphtml d-flex align-items-center'>
  65. <div className='subdropdown__link__apphtml__icon mr-3'>
  66. <i className='fa fa-fw fa-file-text-o' />
  67. </div>
  68. <div className='subdropdown__link__apphtml__text'>
  69. Rédiger un document
  70. </div>
  71. </div>
  72. </div>
  73. <div className='subdropdown__link dropdown-item' onClick={e => this.handleClickCreateContent(e, folderData, 'File')}>
  74. <div className='subdropdown__link__appfile d-flex align-items-center'>
  75. <div className='subdropdown__link__appfile__icon mr-3'>
  76. <i className='fa fa-fw fa-file-image-o' />
  77. </div>
  78. <div className='subdropdown__link__appfile__text'>
  79. Importer un fichier
  80. </div>
  81. </div>
  82. </div>
  83. <div className='subdropdown__link dropdown-item' onClick={e => this.handleClickCreateContent(e, folderData, 'PageMarkdown')}>
  84. <div className='subdropdown__link__appmarkdown d-flex align-items-center'>
  85. <div className='subdropdown__link__appmarkdown__icon mr-3'>
  86. <i className='fa fa-fw fa-file-code-o' />
  87. </div>
  88. <div className='subdropdown__link__appmarkdown__text'>
  89. Rédiger un document markdown
  90. </div>
  91. </div>
  92. </div>
  93. <div className='subdropdown__link dropdown-item' onClick={e => this.handleClickCreateContent(e, folderData, 'Thread')}>
  94. <div className='subdropdown__link__appthread d-flex align-items-center'>
  95. <div className='subdropdown__link__appthread__icon mr-3'>
  96. <i className='fa fa-fw fa-comments-o' />
  97. </div>
  98. <div className='subdropdown__link__appthread__text'>
  99. Lancer une discussion
  100. </div>
  101. </div>
  102. </div>
  103. <div className='subdropdown__link dropdown-item' onClick={e => this.handleClickCreateContent(e, folderData, 'Task')}>
  104. <div className='subdropdown__link__apptask d-flex align-items-center'>
  105. <div className='subdropdown__link__apptask__icon mr-3'>
  106. <i className='fa fa-fw fa-list-ul' />
  107. </div>
  108. <div className='subdropdown__link__apptask__text'>
  109. Créer une tâche
  110. </div>
  111. </div>
  112. </div>
  113. <div className='subdropdown__link dropdown-item' onClick={e => this.handleClickCreateContent(e, folderData, 'Issue')}>
  114. <div className='subdropdown__link__appissue d-flex align-items-center'>
  115. <div className='subdropdown__link__appissue__icon mr-3'>
  116. <i className='fa fa-fw fa-ticket' />
  117. </div>
  118. <div className='subdropdown__link__appissue__text'>
  119. Ouvrir un ticket
  120. </div>
  121. </div>
  122. </div>
  123. </div>
  124. <div className='d-none d-md-flex'>
  125. <BtnExtandedAction onClickExtendedAction={{
  126. edit: e => onClickExtendedAction.edit(e, folderData),
  127. move: e => onClickExtendedAction.move(e, folderData),
  128. download: e => onClickExtendedAction.download(e, folderData),
  129. archive: e => onClickExtendedAction.archive(e, folderData),
  130. delete: e => onClickExtendedAction.delete(e, folderData)
  131. }} />
  132. </div>
  133. </div>
  134. </div>
  135. <div className='folder__header__status' />
  136. </div>
  137. <div className='folder__content'>
  138. { folderData.content.map((c, i) => c.type === 'folder'
  139. ? <Folder
  140. app={app}
  141. folderData={c}
  142. onClickItem={onClickItem}
  143. onClickExtendedAction={onClickExtendedAction}
  144. onClickFolder={onClickFolder}
  145. isLast={isLast}
  146. t={t}
  147. key={c.id}
  148. />
  149. : <FileItem
  150. icon={(app[c.type] || {icon: ''}).icon}
  151. name={c.title}
  152. type={c.type}
  153. status={c.status}
  154. onClickItem={() => onClickItem(c)}
  155. onClickExtendedAction={{
  156. // we have to use the event here because it is the only place where we also have the content (c)
  157. edit: e => onClickExtendedAction.edit(e, c),
  158. move: e => onClickExtendedAction.move(e, c),
  159. download: e => onClickExtendedAction.download(e, c),
  160. archive: e => onClickExtendedAction.archive(e, c),
  161. delete: e => onClickExtendedAction.delete(e, c)
  162. }}
  163. isLast={isLast && i === folderData.content.length - 1}
  164. key={c.id}
  165. />
  166. )}
  167. </div>
  168. </div>
  169. )
  170. }
  171. }
  172. export default translate()(Folder)
  173. Folder.propTypes = {
  174. folderData: PropTypes.shape({
  175. title: PropTypes.string.isRequired,
  176. content: PropTypes.array
  177. }),
  178. app: PropTypes.object,
  179. onClickItem: PropTypes.func.isRequired,
  180. onClickFolder: PropTypes.func.isRequired,
  181. isLast: PropTypes.bool.isRequired
  182. }