WorkspaceContent.jsx 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. import React from 'react'
  2. import { connect } from 'react-redux'
  3. import { withRouter } from 'react-router-dom'
  4. import appFactory from '../appFactory.js'
  5. import { PAGE } from '../helper.js'
  6. import Sidebar from './Sidebar.jsx'
  7. import Folder from '../component/Workspace/Folder.jsx'
  8. import ContentItem from '../component/Workspace/ContentItem.jsx'
  9. import ContentItemHeader from '../component/Workspace/ContentItemHeader.jsx'
  10. import PageWrapper from '../component/common/layout/PageWrapper.jsx'
  11. import PageTitle from '../component/common/layout/PageTitle.jsx'
  12. import PageContent from '../component/common/layout/PageContent.jsx'
  13. import DropdownCreateButton from '../component/common/Input/DropdownCreateButton.jsx'
  14. import OpenContentApp from './OpenContentApp.jsx'
  15. import {
  16. getAppList,
  17. getContentTypeList,
  18. getWorkspaceContentList,
  19. // getWorkspaceContent,
  20. getFolderContent,
  21. getWorkspaceList
  22. } from '../action-creator.async.js'
  23. import {
  24. newFlashMessage,
  25. setAppList,
  26. setContentTypeList,
  27. setWorkspaceContent,
  28. setWorkspaceListIsOpenInSidebar,
  29. updateWorkspaceListData
  30. } from '../action-creator.sync.js'
  31. const qs = require('query-string')
  32. class WorkspaceContent extends React.Component {
  33. constructor (props) {
  34. super(props)
  35. this.state = {
  36. popupCreateContent: {
  37. display: false,
  38. type: undefined,
  39. folder: undefined
  40. },
  41. workspaceIdInUrl: props.match.params.idws ? parseInt(props.match.params.idws) : null, // this is used to avoid handling the parseInt everytime
  42. appOpened: false
  43. }
  44. document.addEventListener('appCustomEvent', this.customEventReducer)
  45. }
  46. customEventReducer = ({ detail: { type, data } }) => {
  47. console.log(type, data)
  48. switch (type) {
  49. case 'openContentUrl':
  50. this.props.history.push(PAGE.WORKSPACE.CONTENT(data.idWorkspace, data.contentType, data.idContent))
  51. break
  52. case 'appClosed':
  53. this.props.history.push(PAGE.WORKSPACE.CONTENT_LIST(this.state.workspaceIdInUrl))
  54. this.setState({appOpened: false})
  55. break
  56. }
  57. }
  58. async componentDidMount () {
  59. const { workspaceIdInUrl } = this.state
  60. const { user, workspaceList, app, contentType, match, location, dispatch } = this.props
  61. console.log('<WorkspaceContent> componentDidMount')
  62. if (app.length === 0) {
  63. const fetchGetAppList = await dispatch(getAppList())
  64. if (fetchGetAppList.status === 200) dispatch(setAppList(fetchGetAppList.json))
  65. }
  66. if (contentType.length === 0) {
  67. const fetchGetContentTypeList = await dispatch(getContentTypeList())
  68. if (fetchGetContentTypeList.status === 200) dispatch(setContentTypeList(fetchGetContentTypeList.json))
  69. }
  70. let wsToLoad = null
  71. if (match.params.idws !== undefined) wsToLoad = match.params.idws
  72. if (user.user_id !== -1 && workspaceList.length === 0) {
  73. const fetchGetWorkspaceList = await dispatch(getWorkspaceList(user.user_id))
  74. if (fetchGetWorkspaceList.status === 200) {
  75. dispatch(updateWorkspaceListData(fetchGetWorkspaceList.json))
  76. dispatch(setWorkspaceListIsOpenInSidebar(workspaceIdInUrl || fetchGetWorkspaceList.json[0].workspace_id, true))
  77. if (match.params.idws === undefined && fetchGetWorkspaceList.json.length > 0) {
  78. wsToLoad = fetchGetWorkspaceList.json[0].workspace_id // load first ws if none specified
  79. }
  80. }
  81. }
  82. if (wsToLoad === null) return // ws already loaded
  83. const wsContent = await dispatch(getWorkspaceContentList(wsToLoad, 0))
  84. if (wsContent.status === 200) dispatch(setWorkspaceContent(wsContent.json, qs.parse(location.search).type))
  85. else dispatch(newFlashMessage('Error while loading workspace', 'danger'))
  86. }
  87. async componentDidUpdate (prevProps, prevState) {
  88. const { match, location, dispatch } = this.props
  89. console.log('<WorkspaceContent> componentDidUpdate')
  90. if (this.state.workspaceIdInUrl === null) return
  91. const idWorkspace = parseInt(match.params.idws)
  92. if (isNaN(idWorkspace)) return
  93. if (prevState.workspaceIdInUrl !== idWorkspace) {
  94. this.setState({workspaceIdInUrl: idWorkspace})
  95. const wsContent = await dispatch(getWorkspaceContentList(idWorkspace, 0))
  96. if (wsContent.status === 200) dispatch(setWorkspaceContent(wsContent.json, qs.parse(location.search).type))
  97. else dispatch(newFlashMessage('Error while loading workspace', 'danger'))
  98. }
  99. // if (user.user_id !== -1 && prevProps.user.id !== user.id) dispatch(getWorkspaceList(user.user_id, idWorkspace))
  100. }
  101. handleClickContentItem = content => {
  102. console.log('content clicked', content)
  103. this.props.history.push(`/workspaces/${content.idWorkspace}/${content.type}/${content.id}`)
  104. }
  105. handleClickEditContentItem = (e, content) => {
  106. e.stopPropagation()
  107. console.log('edit nyi', content)
  108. }
  109. handleClickMoveContentItem = (e, content) => {
  110. e.stopPropagation()
  111. console.log('move nyi', content)
  112. }
  113. handleClickDownloadContentItem = (e, content) => {
  114. e.stopPropagation()
  115. console.log('download nyi', content)
  116. }
  117. handleClickArchiveContentItem = (e, content) => {
  118. e.stopPropagation()
  119. console.log('archive nyi', content)
  120. }
  121. handleClickDeleteContentItem = (e, content) => {
  122. e.stopPropagation()
  123. console.log('delete nyi', content)
  124. }
  125. handleClickFolder = folderId => {
  126. this.props.dispatch(getFolderContent(this.props.workspace.id, folderId))
  127. }
  128. handleClickCreateContent = (e, idFolder, contentType) => {
  129. e.stopPropagation()
  130. this.props.renderCreateContentApp(
  131. this.props.contentType.find(ct => ct.slug === contentType),
  132. this.props.user,
  133. this.props.match.params.idws,
  134. idFolder
  135. )
  136. }
  137. handleUpdateAppOpened = opened => this.setState({appOpened: opened})
  138. render () {
  139. const { workspaceContent, contentType, match } = this.props
  140. const filterWorkspaceContent = (contentList, filter) => {
  141. return filter.length === 0
  142. ? contentList
  143. : contentList.filter(c => c.type === 'folder' || filter.includes(c.type)) // keep unfiltered files and folders
  144. // @FIXME we need to filter subfolder too, but right now, we dont handle subfolder
  145. // .map(c => c.type !== 'folder' ? c : {...c, content: filterWorkspaceContent(c.content, filter)}) // recursively filter folder content
  146. }
  147. // .filter(c => c.type !== 'folder' || c.content.length > 0) // remove empty folder => 2018/05/21 - since we load only one lvl of content, don't remove empty
  148. const urlFilter = qs.parse(this.props.location.search).type
  149. const filteredWorkspaceContent = workspaceContent.length > 0
  150. ? filterWorkspaceContent(workspaceContent, urlFilter ? [urlFilter] : [])
  151. : []
  152. console.log('workspaceContent => filteredWorkspaceContent', filteredWorkspaceContent, 'urlFilter', urlFilter)
  153. return (
  154. <div className='sidebarpagecontainer'>
  155. <Sidebar />
  156. <OpenContentApp idWorkspace={match.params.idws} appOpened={this.state.appOpened} updateAppOpened={this.handleUpdateAppOpened} />
  157. <PageWrapper customeClass='workspace'>
  158. <PageTitle
  159. parentClass='workspace__header'
  160. customClass='justify-content-between'
  161. title={workspaceContent.label ? workspaceContent.label : ''}
  162. >
  163. <DropdownCreateButton
  164. parentClass='workspace__header__btnaddworkspace'
  165. idFolder={null}
  166. onClickCreateContent={this.handleClickCreateContent}
  167. availableApp={contentType}
  168. />
  169. </PageTitle>
  170. <PageContent parentClass='workspace__content'>
  171. <div id='popupCreateContentContainer' />
  172. <div className='workspace__content__fileandfolder folder__content active'>
  173. <ContentItemHeader />
  174. { filteredWorkspaceContent.map((c, i) => c.type === 'folder'
  175. ? (
  176. <Folder
  177. availableApp={contentType}
  178. folderData={c}
  179. onClickItem={this.handleClickContentItem}
  180. onClickExtendedAction={{
  181. edit: this.handleClickEditContentItem,
  182. move: this.handleClickMoveContentItem,
  183. download: this.handleClickDownloadContentItem,
  184. archive: this.handleClickArchiveContentItem,
  185. delete: this.handleClickDeleteContentItem
  186. }}
  187. onClickFolder={this.handleClickFolder}
  188. onClickCreateContent={this.handleClickCreateContent}
  189. isLast={i === filteredWorkspaceContent.length - 1}
  190. key={c.id}
  191. />
  192. )
  193. : (
  194. <ContentItem
  195. label={c.label}
  196. type={c.type}
  197. faIcon={contentType.length ? contentType.find(a => a.slug === c.type).faIcon : ''}
  198. statusSlug={c.statusSlug}
  199. contentType={contentType.find(ct => ct.slug === c.type)}
  200. onClickItem={() => this.handleClickContentItem(c)}
  201. onClickExtendedAction={{
  202. edit: e => this.handleClickEditContentItem(e, c),
  203. move: e => this.handleClickMoveContentItem(e, c),
  204. download: e => this.handleClickDownloadContentItem(e, c),
  205. archive: e => this.handleClickArchiveContentItem(e, c),
  206. delete: e => this.handleClickDeleteContentItem(e, c)
  207. }}
  208. onClickCreateContent={this.handleClickCreateContent}
  209. isLast={i === filteredWorkspaceContent.length - 1}
  210. key={c.id}
  211. />
  212. )
  213. )}
  214. </div>
  215. <DropdownCreateButton
  216. customClass='workspace__content__button mb-5'
  217. idFolder={null}
  218. onClickCreateContent={this.handleClickCreateContent}
  219. availableApp={contentType}
  220. />
  221. <div id='appContainer' />
  222. </PageContent>
  223. </PageWrapper>
  224. </div>
  225. )
  226. }
  227. }
  228. const mapStateToProps = ({ user, workspaceContent, workspaceList, app, contentType }) => ({ user, workspaceContent, workspaceList, app, contentType })
  229. export default withRouter(connect(mapStateToProps)(appFactory(WorkspaceContent)))