Folder.jsx 8.4KB

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