VizList.tsx 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. import React from 'react'
  2. import classnames from 'classnames'
  3. import Helmet from 'react-helmet'
  4. import { Link } from 'react-router-dom'
  5. import { compose } from 'redux'
  6. import { connect } from 'react-redux'
  7. import { createStructuredSelector } from 'reselect'
  8. import { checkNameUniqueAction } from '../App/actions'
  9. import { ProjectActions } from '../Projects/actions'
  10. import { VizActions } from '../Viz/actions'
  11. import { makeSelectCurrentProject } from '../Projects/selectors'
  12. import { makeSelectPortals, makeSelectDisplays } from '../Viz/selectors'
  13. import { Icon, Row, Col, Breadcrumb } from 'antd'
  14. import Box from 'components/Box'
  15. import Container, { ContainerTitle, ContainerBody } from 'components/Container'
  16. import PortalList from './components/PortalList'
  17. import DisplayList from './components/DisplayList'
  18. import { IProject } from '../Projects/types'
  19. import { IPortal, Display, IDisplayFormed } from './types'
  20. import styles from './Viz.less'
  21. import utilStyles from 'assets/less/util.less'
  22. import { RouteComponentWithParams } from 'utils/types'
  23. import OrganizationActions from '../Organizations/actions'
  24. interface IVizProps {
  25. currentProject: IProject
  26. displays: Display[]
  27. portals: IPortal[]
  28. onLoadDisplays: (projectId: number) => void
  29. onAddDisplay: (display: IDisplayFormed, resolve: () => void) => void
  30. onEditDisplay: (display: IDisplayFormed, resolve: () => void) => void
  31. onDeleteDisplay: (displayId: number) => void
  32. onCopyDisplay: (display: IDisplayFormed, resolve: () => void) => void
  33. onLoadPortals: (projectId: number) => void
  34. onAddPortal: (portal: IPortal, resolve) => void
  35. onEditPortal: (portal: IPortal, resolve) => void
  36. onDeletePortal: (portalId: number) => void
  37. onCheckUniqueName: (
  38. pathname: string,
  39. data: any,
  40. resolve: () => any,
  41. reject: (error: string) => any
  42. ) => any
  43. onLoadProjectRoles: (projectId: number) => void
  44. onExcludeRoles: (type: string, id: number, resolve?: any) => any
  45. }
  46. interface IVizStates {
  47. collapse: { dashboard: boolean; display: boolean }
  48. }
  49. export class VizList extends React.Component<
  50. IVizProps & RouteComponentWithParams,
  51. IVizStates
  52. > {
  53. public state: Readonly<IVizStates> = {
  54. collapse: {
  55. dashboard: true,
  56. display: true
  57. }
  58. }
  59. public componentWillMount() {
  60. const { match, onLoadDisplays, onLoadPortals, onLoadProjectRoles } = this.props
  61. const projectId = +match.params.projectId
  62. onLoadDisplays(projectId)
  63. onLoadPortals(projectId)
  64. onLoadProjectRoles(projectId)
  65. }
  66. private goToPortal = (portalId: number) => () => {
  67. const { history, match } = this.props
  68. history.push(`/project/${match.params.projectId}/portal/${portalId}`)
  69. }
  70. private goToDisplay = (displayId: number) => () => {
  71. const {
  72. match,
  73. currentProject: {
  74. permission: { vizPermission }
  75. }
  76. } = this.props
  77. const projectId = match.params.projectId
  78. const isToPreview = vizPermission === 1
  79. const path = `/project/${projectId}/display/${displayId}${isToPreview ? '/preview' : ''
  80. }`
  81. this.props.history.push(path)
  82. }
  83. private onCollapseChange = (key: string) => () => {
  84. const { collapse } = this.state
  85. this.setState({
  86. collapse: {
  87. ...collapse,
  88. [key]: !collapse[key]
  89. }
  90. })
  91. }
  92. public render() {
  93. const {
  94. displays,
  95. match,
  96. onAddDisplay,
  97. onEditDisplay,
  98. onDeleteDisplay,
  99. onCopyDisplay,
  100. portals,
  101. onAddPortal,
  102. onEditPortal,
  103. onDeletePortal,
  104. currentProject,
  105. onCheckUniqueName
  106. } = this.props
  107. const projectId = +match.params.projectId
  108. const isHideDashboardStyle = classnames({
  109. [styles.listPadding]: true,
  110. [utilStyles.hide]: !this.state.collapse.dashboard
  111. })
  112. const isHideDisplayStyle = classnames({
  113. [styles.listPadding]: true,
  114. [utilStyles.hide]: !this.state.collapse.display
  115. })
  116. return (
  117. <Container>
  118. <Helmet title="Viz" />
  119. <ContainerTitle>
  120. <Row>
  121. <Col span={24} className={utilStyles.shortcut}>
  122. <Breadcrumb className={utilStyles.breadcrumb}>
  123. <Breadcrumb.Item>
  124. <Link to="">Viz</Link>
  125. </Breadcrumb.Item>
  126. </Breadcrumb>
  127. <Link to={`/account/organization/${currentProject.orgId}`}>
  128. <i className='iconfont icon-organization' />
  129. </Link>
  130. </Col>
  131. </Row>
  132. </ContainerTitle>
  133. <ContainerBody>
  134. <Box>
  135. <Box.Header>
  136. <Box.Title>
  137. <Row onClick={this.onCollapseChange('dashboard')}>
  138. <Col span={20}>
  139. <Icon
  140. type={`${this.state.collapse.dashboard ? 'down' : 'right'
  141. }`}
  142. />
  143. Dashboard
  144. </Col>
  145. </Row>
  146. </Box.Title>
  147. </Box.Header>
  148. <div className={isHideDashboardStyle}>
  149. <PortalList
  150. currentProject={currentProject}
  151. projectId={projectId}
  152. portals={portals}
  153. onPortalClick={this.goToPortal}
  154. onAdd={onAddPortal}
  155. onEdit={onEditPortal}
  156. onDelete={onDeletePortal}
  157. onCheckUniqueName={onCheckUniqueName}
  158. onExcludeRoles={this.props.onExcludeRoles}
  159. />
  160. </div>
  161. </Box>
  162. <div className={styles.spliter16} />
  163. <Box>
  164. <Box.Header>
  165. <Box.Title>
  166. <Row onClick={this.onCollapseChange('display')}>
  167. <Col span={20}>
  168. <Icon
  169. type={`${this.state.collapse.display ? 'down' : 'right'}`}
  170. />
  171. Display
  172. </Col>
  173. </Row>
  174. </Box.Title>
  175. </Box.Header>
  176. <div className={isHideDisplayStyle}>
  177. <DisplayList
  178. currentProject={currentProject}
  179. projectId={projectId}
  180. displays={displays}
  181. onDisplayClick={this.goToDisplay}
  182. onAdd={onAddDisplay}
  183. onEdit={onEditDisplay}
  184. onCopy={onCopyDisplay}
  185. onDelete={onDeleteDisplay}
  186. onCheckName={onCheckUniqueName}
  187. onExcludeRoles={this.props.onExcludeRoles}
  188. />
  189. </div>
  190. </Box>
  191. </ContainerBody>
  192. </Container>
  193. )
  194. }
  195. }
  196. const mapStateToProps = createStructuredSelector({
  197. displays: makeSelectDisplays(),
  198. portals: makeSelectPortals(),
  199. currentProject: makeSelectCurrentProject()
  200. })
  201. export function mapDispatchToProps(dispatch) {
  202. return {
  203. onLoadDisplays: (projectId) => dispatch(VizActions.loadDisplays(projectId)),
  204. onAddDisplay: (display: IDisplayFormed, resolve) =>
  205. dispatch(VizActions.addDisplay(display, resolve)),
  206. onEditDisplay: (display: IDisplayFormed, resolve) =>
  207. dispatch(VizActions.editDisplay(display, resolve)),
  208. onDeleteDisplay: (id) => dispatch(VizActions.deleteDisplay(id)),
  209. onCopyDisplay: (display: IDisplayFormed, resolve) =>
  210. dispatch(VizActions.copyDisplay(display, resolve)),
  211. onLoadPortals: (projectId) => dispatch(VizActions.loadPortals(projectId)),
  212. onAddPortal: (portal, resolve) =>
  213. dispatch(VizActions.addPortal(portal, resolve)),
  214. onEditPortal: (portal, resolve) =>
  215. dispatch(VizActions.editPortal(portal, resolve)),
  216. onDeletePortal: (id) => dispatch(VizActions.deletePortal(id)),
  217. onCheckUniqueName: (pathname, data, resolve, reject) =>
  218. dispatch(checkNameUniqueAction(pathname, data, resolve, reject)),
  219. onLoadProjectRoles: (projectId) =>
  220. dispatch(OrganizationActions.loadProjectRoles(projectId)),
  221. onExcludeRoles: (type, id, resolve) =>
  222. dispatch(ProjectActions.excludeRoles(type, id, resolve))
  223. }
  224. }
  225. const withConnect = connect(
  226. mapStateToProps,
  227. mapDispatchToProps
  228. )
  229. export default compose(withConnect)(VizList)