ProjectList.tsx 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. import React from 'react'
  2. import { compose } from 'redux'
  3. import { connect } from 'react-redux'
  4. import { Row, Col, Tooltip, Button, Pagination, Input, Modal } from 'antd'
  5. import ProjectItem from './ProjectItem'
  6. import AntdFormType from 'antd/lib/form/Form'
  7. import ProjectEditForm from './Project'
  8. import ProjectForm from './ProjectForm'
  9. import ComponentPermission from 'containers/Account/components/checkMemberPermission'
  10. import { CREATE_ORGANIZATION_PROJECT } from 'containers/App/constants'
  11. import { checkNameUniqueAction } from 'containers/App/actions'
  12. import { createStructuredSelector } from 'reselect'
  13. import { OrganizationActions } from '../actions'
  14. import {
  15. makeSelectOrganizations,
  16. makeSelectCurrentOrganizations,
  17. makeSelectCurrentOrganizationProjects,
  18. makeSelectCurrentOrganizationProjectsDetail,
  19. makeSelectCurrentOrganizationRole,
  20. makeSelectCurrentOrganizationMembers,
  21. makeSelectInviteMemberList,
  22. makeSelectCurrentOrganizationProject
  23. } from '../selectors'
  24. import { makeSelectVizs } from 'containers/Schedule/selectors'
  25. import { ProjectActions } from 'containers/Projects/actions'
  26. import injectReducer from 'utils/injectReducer'
  27. import injectSaga from 'utils/injectSaga'
  28. import scheduleReducer from 'containers/Schedule/reducer'
  29. import scheduleSaga from 'containers/Schedule/sagas'
  30. import { ScheduleActions } from 'containers/Schedule/actions'
  31. import { makeSelectLoginUser } from 'containers/App/selectors'
  32. import Star from 'components/StarPanel/Star'
  33. const StarUserModal = Star.StarUser
  34. const styles = require('../Organization.less')
  35. import {
  36. makeSelectStarUserList,
  37. makeSelectCollectProjects
  38. } from 'containers/Projects/selectors'
  39. import {IProjectsProps, IProjectsStates } from '../types'
  40. export class ProjectList extends React.PureComponent<
  41. IProjectsProps,
  42. IProjectsStates
  43. > {
  44. constructor(props) {
  45. super(props)
  46. this.state = {
  47. formType: '',
  48. formVisible: false,
  49. editFormVisible: false,
  50. adminFormVisible: false,
  51. modalLoading: false,
  52. pageNum: 1,
  53. pageSize: 10,
  54. organizationProjects: null,
  55. currentProject: null,
  56. starModalVisble: false
  57. }
  58. }
  59. private ProjectForm: AntdFormType = null
  60. private ProjectEditForm: AntdFormType = null
  61. private refHandlers = {
  62. ProjectForm: (ref) => (this.ProjectForm = ref),
  63. ProjectEditForm: (ref) => (this.ProjectEditForm = ref)
  64. }
  65. private onCloseStarModal = () => {
  66. this.setState({starModalVisble: false})
  67. }
  68. private showProjectForm = (type: string) => (e) => {
  69. e.stopPropagation()
  70. this.setState({
  71. formVisible: true,
  72. formType: type
  73. })
  74. }
  75. public componentWillMount() {
  76. const {
  77. onLoadOrganizationProjects,
  78. onLoadCollectProjects,
  79. organizationId,
  80. onLoadVizs
  81. } = this.props
  82. this.props.onLoadOrganizations()
  83. onLoadOrganizationProjects({ id: Number(organizationId) })
  84. onLoadCollectProjects()
  85. }
  86. private showEditProjectForm = (formType, option) => (e) => {
  87. const { onLoadVizs } = this.props
  88. const { orgId, id, name, pic, description, visibility } = option
  89. onLoadVizs(Number(id))
  90. this.setState(
  91. {
  92. formType,
  93. editFormVisible: true,
  94. currentProject: option
  95. },
  96. () => {
  97. setTimeout(() => {
  98. this.props.onSetCurrentProject(option)
  99. this.ProjectEditForm.props.form.setFieldsValue({
  100. orgId: `${orgId}`,
  101. id,
  102. name,
  103. pic,
  104. description,
  105. visibility: `${visibility}`
  106. })
  107. }, 0)
  108. }
  109. )
  110. }
  111. private getOrganizationProjectsByPagination = (obj) => {
  112. const { onLoadOrganizationProjects, organizationId } = this.props
  113. this.setState({
  114. pageNum: obj.pageNum,
  115. pageSize: obj.pageSize
  116. })
  117. const param = {
  118. keyword: obj.keyword,
  119. id: organizationId,
  120. pageNum: obj.pageNum,
  121. pageSize: obj.pageSize
  122. }
  123. onLoadOrganizationProjects(param)
  124. }
  125. private onSearchProject = (event) => {
  126. const value = event.target.value
  127. const param = {
  128. keyword: value,
  129. pageNum: this.state.pageNum,
  130. pageSize: this.state.pageSize
  131. }
  132. this.getOrganizationProjectsByPagination(param)
  133. }
  134. private hideProjectForm = () => {
  135. this.setState({
  136. formVisible: false,
  137. editFormVisible: false,
  138. modalLoading: false
  139. })
  140. }
  141. private afterProjectFormClose = () => {
  142. this.ProjectForm.props.form.resetFields()
  143. }
  144. private afterProjectEditFormClose = () => {
  145. this.ProjectEditForm.props.form.resetFields()
  146. }
  147. private checkUniqueName = (rule, value = '', callback) => {
  148. const { onCheckUniqueName, organizationId } = this.props
  149. const { formVisible, editFormVisible } = this.state
  150. const { getFieldsValue } = formVisible
  151. ? this.ProjectForm.props.form
  152. : this.ProjectEditForm.props.form
  153. const id = getFieldsValue()['id']
  154. const data = {
  155. name: value,
  156. orgId: organizationId,
  157. id
  158. }
  159. onCheckUniqueName(
  160. 'project',
  161. data,
  162. () => {
  163. callback()
  164. },
  165. (err) => {
  166. callback(err)
  167. }
  168. )
  169. }
  170. private onModalOk = () => {
  171. const {
  172. organizationId,
  173. currentOrganization,
  174. onAddProject,
  175. onEditProject,
  176. onLoadOrganizationProjects
  177. } = this.props
  178. const { formType } = this.state
  179. const targetForm =
  180. formType === 'edit' ? this.ProjectEditForm : this.ProjectForm
  181. targetForm.props.form.validateFieldsAndScroll((err, values) => {
  182. if (!err) {
  183. this.setState({ modalLoading: true })
  184. values.visibility = values.visibility === 'true' ? true : false
  185. if (formType === 'organizationProject') {
  186. onAddProject(
  187. {
  188. ...values,
  189. ...{ orgId: organizationId },
  190. pic: `${Math.ceil(Math.random() * 19)}`
  191. },
  192. () => {
  193. this.hideProjectForm()
  194. }
  195. )
  196. } else if (formType === 'edit') {
  197. onEditProject({ ...values }, () => {
  198. onLoadOrganizationProjects({ id: currentOrganization.id })
  199. this.hideProjectForm()
  200. })
  201. }
  202. }
  203. })
  204. }
  205. private onShowSizeChange = (current, pageSize) => {
  206. this.setState(
  207. {
  208. pageNum: current,
  209. pageSize
  210. },
  211. () => {
  212. const param = {
  213. pageNum: this.state.pageNum,
  214. pageSize: this.state.pageSize
  215. }
  216. this.getOrganizationProjectsByPagination(param)
  217. }
  218. )
  219. }
  220. private onPaginationChange = (page) => {
  221. this.setState(
  222. {
  223. pageNum: page
  224. },
  225. () => {
  226. const param = {
  227. pageNum: this.state.pageNum,
  228. pageSize: this.state.pageSize
  229. }
  230. this.getOrganizationProjectsByPagination(param)
  231. }
  232. )
  233. }
  234. public componentWillReceiveProps(nextProps) {
  235. const { currentOrganizationProjects } = this.props
  236. const nextOrgProjects = nextProps.currentOrganizationProjects
  237. if (nextOrgProjects && nextOrgProjects !== currentOrganizationProjects) {
  238. this.setState({
  239. organizationProjects: nextOrgProjects
  240. })
  241. }
  242. }
  243. private starProject = (id) => () => {
  244. const { onStarProject, organizationId } = this.props
  245. const param = {
  246. id: Number(organizationId),
  247. pageNum: this.state.pageNum,
  248. pageSize: this.state.pageSize
  249. }
  250. onStarProject(id, () => {
  251. this.props.onLoadOrganizationProjects(param)
  252. })
  253. }
  254. private deleteProject = (id) => () => {
  255. if (id) {
  256. this.props.onDeleteProject(id)
  257. }
  258. }
  259. private tabsChange = (mode) => {
  260. if (mode === 'basic') {
  261. const {
  262. orgId,
  263. id,
  264. name,
  265. pic,
  266. description,
  267. visibility
  268. } = this.state.currentProject
  269. this.ProjectEditForm.props.form.setFieldsValue({
  270. orgId: `${orgId}`,
  271. id,
  272. name,
  273. pic,
  274. description,
  275. visibility: `${visibility}`
  276. })
  277. }
  278. }
  279. private onTransfer = () => {
  280. this.ProjectForm.props.form.validateFieldsAndScroll((err, values) => {
  281. if (!err) {
  282. this.setState({ modalLoading: true })
  283. const {
  284. projectDetail: { id }
  285. } = this.props
  286. const { orgId } = values
  287. this.props.onTransferProject(id, Number(orgId), () => {
  288. const param = {
  289. id: orgId,
  290. pageNum: 1,
  291. pageSize: 10
  292. }
  293. this.props.onLoadOrganizationProjects(param)
  294. })
  295. this.hideProjectForm()
  296. }
  297. })
  298. }
  299. private getStarProjectUserList = (id) => () => {
  300. const { onGetProjectStarUser } = this.props
  301. onGetProjectStarUser(id)
  302. this.setState({starModalVisble: true})
  303. }
  304. public render() {
  305. const {
  306. formVisible,
  307. formType,
  308. modalLoading,
  309. organizationProjects,
  310. editFormVisible,
  311. currentProject,
  312. adminFormVisible,
  313. starModalVisble
  314. } = this.state
  315. const {
  316. onLoadOrganizationProjects,
  317. loginUser,
  318. currentOrganization,
  319. organizationProjectsDetail,
  320. onCheckUniqueName,
  321. collectProjects,
  322. starUserList,
  323. organizations
  324. } = this.props
  325. let CreateButton = void 0
  326. if (currentOrganization) {
  327. CreateButton = ComponentPermission(
  328. currentOrganization,
  329. CREATE_ORGANIZATION_PROJECT
  330. )(Button)
  331. }
  332. const addButton = (
  333. <Tooltip placement="bottom" title="创建">
  334. <CreateButton
  335. type="primary"
  336. icon="plus"
  337. onClick={this.showProjectForm('organizationProject')}
  338. />
  339. </Tooltip>
  340. )
  341. let projectSearchPagination = void 0
  342. if (organizationProjectsDetail) {
  343. projectSearchPagination = (
  344. <Pagination
  345. showSizeChanger
  346. defaultCurrent={2}
  347. total={organizationProjectsDetail.total}
  348. onShowSizeChange={this.onShowSizeChange}
  349. onChange={this.onPaginationChange}
  350. defaultPageSize={10}
  351. pageSizeOptions={['10', '15', '20']}
  352. current={this.state.pageNum}
  353. />
  354. )
  355. }
  356. const ProjectItems = Array.isArray(organizationProjects)
  357. ? organizationProjects.map((lists, index) => (
  358. <ProjectItem
  359. key={index}
  360. pro={lists}
  361. unStar={this.starProject}
  362. toProject={this.props.toProject}
  363. loginUser={this.props.loginUser}
  364. collectProjects={collectProjects}
  365. userList={this.getStarProjectUserList}
  366. currentOrganization={currentOrganization}
  367. onLoadCollectProjects={this.props.onLoadCollectProjects}
  368. onClickCollectProjects={this.props.onClickCollectProjects}
  369. showEditProjectForm={this.showEditProjectForm('edit', lists)}
  370. />
  371. ))
  372. : ''
  373. return (
  374. <div className={styles.listWrapper}>
  375. <Row>
  376. <Col span={16}>
  377. <Input.Search
  378. placeholder="搜索项目"
  379. onChange={this.onSearchProject}
  380. />
  381. </Col>
  382. <Col span={1} offset={7}>
  383. {addButton}
  384. </Col>
  385. </Row>
  386. <Row>
  387. <Col span={24}>{ProjectItems}</Col>
  388. </Row>
  389. <Row type="flex" justify="end" style={{ marginTop: '16px' }}>
  390. <Col>{projectSearchPagination}</Col>
  391. </Row>
  392. <Modal
  393. title={null}
  394. visible={formVisible}
  395. footer={null}
  396. onCancel={this.hideProjectForm}
  397. afterClose={this.afterProjectFormClose}
  398. >
  399. <ProjectForm
  400. type={formType}
  401. modalLoading={modalLoading}
  402. onModalOk={this.onModalOk}
  403. organizations={organizations}
  404. onTransfer={this.onTransfer}
  405. onCheckUniqueName={this.checkUniqueName}
  406. wrappedComponentRef={this.refHandlers.ProjectForm}
  407. />
  408. </Modal>
  409. <Modal
  410. wrapClassName="ant-modal-large ant-modal-center"
  411. title="项目设置"
  412. visible={editFormVisible}
  413. footer={null}
  414. onCancel={this.hideProjectForm}
  415. afterClose={this.afterProjectEditFormClose}
  416. >
  417. <ProjectEditForm
  418. type={formType}
  419. onTabsChange={this.tabsChange}
  420. modalLoading={modalLoading}
  421. onModalOk={this.onModalOk}
  422. deleteProject={this.deleteProject}
  423. currentProject={currentProject}
  424. onCancel={this.hideProjectForm}
  425. onCheckUniqueName={this.checkUniqueName}
  426. showEditProjectForm={this.showProjectForm('transfer')}
  427. wrappedComponentRef={this.refHandlers.ProjectEditForm}
  428. />
  429. </Modal>
  430. <StarUserModal
  431. visible={starModalVisble}
  432. starUser={starUserList}
  433. closeUserListModal={this.onCloseStarModal}
  434. />
  435. </div>
  436. )
  437. }
  438. }
  439. const mapStateToProps = createStructuredSelector({
  440. starUserList: makeSelectStarUserList(),
  441. loginUser: makeSelectLoginUser(),
  442. projectDetail: makeSelectCurrentOrganizationProject(),
  443. organizations: makeSelectOrganizations(),
  444. currentOrganization: makeSelectCurrentOrganizations(),
  445. currentOrganizationProjects: makeSelectCurrentOrganizationProjects(),
  446. currentOrganizationProjectsDetail: makeSelectCurrentOrganizationProjectsDetail(),
  447. currentOrganizationMembers: makeSelectCurrentOrganizationMembers(),
  448. collectProjects: makeSelectCollectProjects()
  449. })
  450. export function mapDispatchToProps(dispatch) {
  451. return {
  452. onLoadVizs: (projectId) => dispatch(ScheduleActions.loadVizs(projectId)),
  453. onSetCurrentProject: (option) =>
  454. dispatch(OrganizationActions.setCurrentProject(option)),
  455. onTransferProject: (id, orgId, resolve) =>
  456. dispatch(ProjectActions.transferProject(id, orgId, resolve)),
  457. onStarProject: (id, resolve) =>
  458. dispatch(ProjectActions.unStarProject(id, resolve)),
  459. onLoadOrganizations: () =>
  460. dispatch(OrganizationActions.loadOrganizations()),
  461. onGetProjectStarUser: (id) =>
  462. dispatch(ProjectActions.getProjectStarUser(id)),
  463. onAddProject: (project, resolve) =>
  464. dispatch(ProjectActions.addProject(project, resolve)),
  465. onEditProject: (project, resolve) =>
  466. dispatch(ProjectActions.editProject(project, resolve)),
  467. onLoadOrganizationProjects: (param) =>
  468. dispatch(OrganizationActions.loadOrganizationProjects(param)),
  469. onDeleteProject: (id, resolve) =>
  470. dispatch(ProjectActions.deleteProject(id, resolve)),
  471. onDeleteOrganizationMember: (id, resolve) =>
  472. dispatch(OrganizationActions.deleteOrganizationMember(id, resolve)),
  473. onChangeOrganizationMemberRole: (id, role, resolve) =>
  474. dispatch(
  475. OrganizationActions.changeOrganizationMemberRole(id, role, resolve)
  476. ),
  477. onClickCollectProjects: (isFavorite, proId, result) =>
  478. dispatch(ProjectActions.clickCollectProjects(isFavorite, proId, result)),
  479. onLoadCollectProjects: () => dispatch(ProjectActions.loadCollectProjects()),
  480. onCheckUniqueName: (pathname, data, resolve, reject) =>
  481. dispatch(checkNameUniqueAction(pathname, data, resolve, reject))
  482. }
  483. }
  484. type MappedStates = ReturnType<typeof mapStateToProps>
  485. type MappedDispatches = ReturnType<typeof mapDispatchToProps>
  486. const withConnect = connect<MappedStates, MappedDispatches, IProjectsProps>(
  487. mapStateToProps,
  488. mapDispatchToProps
  489. )
  490. const withReducerSchedule = injectReducer({
  491. key: 'schedule',
  492. reducer: scheduleReducer
  493. })
  494. const withSagaSchedule = injectSaga({ key: 'schedule', saga: scheduleSaga })
  495. export default compose(
  496. withConnect,
  497. withReducerSchedule,
  498. withSagaSchedule
  499. )(ProjectList)