index.tsx 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. import React from 'react'
  2. import { connect } from 'react-redux'
  3. import { Icon, Row, Col, Modal, Breadcrumb } from 'antd'
  4. import FormType from 'antd/lib/form/Form'
  5. import { Link } from 'react-router-dom'
  6. import Box from 'components/Box'
  7. import { compose } from 'redux'
  8. import { makeSelectLoginUser } from '../App/selectors'
  9. import { OrganizationActions } from './actions'
  10. const { addOrganization, loadOrganizations } = OrganizationActions
  11. import { createStructuredSelector } from 'reselect'
  12. import { makeSelectOrganizations } from './selectors'
  13. const styles = require('./Organization.less')
  14. import OrganizationForm from './component/OrganizationForm'
  15. const utilStyles = require('assets/less/util.less')
  16. import Avatar from 'components/Avatar'
  17. import { checkNameUniqueAction } from '../App/actions'
  18. import { RouteComponentWithParams } from 'utils/types'
  19. interface IOrganizationsState {
  20. formVisible: boolean
  21. modalLoading: boolean
  22. }
  23. interface IOrganizationsProps {
  24. organizations: IOrganization[]
  25. onLoadOrganizations: () => any
  26. onAddOrganization: (organization: any, resolve: () => any) => any
  27. onCheckUniqueName: (pathname: string, data: any, resolve: () => any, reject: (error: string) => any) => any
  28. }
  29. interface IOrganization {
  30. id?: number
  31. name?: string
  32. description?: string
  33. avatar?: any
  34. role?: number
  35. }
  36. export class Organizations extends React.PureComponent<IOrganizationsProps & RouteComponentWithParams, IOrganizationsState> {
  37. constructor (props) {
  38. super(props)
  39. this.state = {
  40. formVisible: false,
  41. modalLoading: false
  42. }
  43. }
  44. private checkNameUnique = (rule, value = '', callback) => {
  45. const { onCheckUniqueName } = this.props
  46. const { getFieldsValue } = this.OrganizationForm.props.form
  47. const id = getFieldsValue()['id']
  48. const data = {
  49. name: value,
  50. id
  51. }
  52. onCheckUniqueName('organization', data,
  53. () => {
  54. callback()
  55. }, (err) => {
  56. callback(err)
  57. })
  58. }
  59. private toOrganization = (organization) => () => {
  60. this.props.history.push(`/account/organization/${organization.id}`)
  61. }
  62. private OrganizationForm: FormType
  63. private refHandles = {
  64. OrganizationForm: (ref) => this.OrganizationForm = ref
  65. }
  66. private showOrganizationForm = () => (e) => {
  67. e.stopPropagation()
  68. this.setState({
  69. formVisible: true
  70. })
  71. }
  72. public componentWillMount () {
  73. const { onLoadOrganizations } = this.props
  74. onLoadOrganizations()
  75. }
  76. private onModalOk = () => {
  77. this.OrganizationForm.props.form.validateFieldsAndScroll((err, values) => {
  78. if (!err) {
  79. this.setState({ modalLoading: true })
  80. this.props.onAddOrganization({
  81. ...values,
  82. config: '{}'
  83. }, () => { this.hideOrganizationForm() })
  84. }
  85. })
  86. }
  87. private hideOrganizationForm = () => {
  88. this.setState({
  89. formVisible: false,
  90. modalLoading: false
  91. })
  92. }
  93. private afterOrganizationFormClose = () => {
  94. this.OrganizationForm.props.form.resetFields()
  95. }
  96. public render () {
  97. const { formVisible, modalLoading } = this.state
  98. const { organizations } = this.props
  99. const organizationArr = organizations ? organizations.map((org) => (
  100. <div className={styles.groupList} key={org.id} onClick={this.toOrganization(org)}>
  101. <div className={styles.orgHeader}>
  102. <div className={styles.avatar}>
  103. <Avatar path={org.avatar} enlarge={false} border size="small"/>
  104. <div className={styles.name}>
  105. <div className={styles.title}>
  106. {org.name}
  107. {org.role === 1 ? <span className={styles.nameTag}>Owner</span> : null}
  108. </div>
  109. <div className={styles.desc}>{org.description}</div>
  110. </div>
  111. </div>
  112. </div>
  113. <div className={styles.setting}>
  114. <Icon type="setting"/>
  115. </div>
  116. </div>
  117. )
  118. ) : ''
  119. return (
  120. <Box>
  121. <Box.Header>
  122. <Box.Title>
  123. <Row>
  124. <Col span={20}>
  125. <Breadcrumb className={utilStyles.breadcrumb}>
  126. <Breadcrumb.Item>
  127. <Link to="/account/organizations">
  128. <Icon type="bars" />我的组织
  129. </Link>
  130. </Breadcrumb.Item>
  131. </Breadcrumb>
  132. </Col>
  133. <Col span={1} offset={3}>
  134. <Icon type="plus-circle-o" className={styles.create} onClick={this.showOrganizationForm()}/>
  135. </Col>
  136. </Row>
  137. </Box.Title>
  138. </Box.Header>
  139. {organizationArr}
  140. <Modal
  141. title={null}
  142. visible={formVisible}
  143. footer={null}
  144. onCancel={this.hideOrganizationForm}
  145. afterClose={this.afterOrganizationFormClose}
  146. >
  147. <OrganizationForm
  148. modalLoading={modalLoading}
  149. onModalOk={this.onModalOk}
  150. onCheckUniqueName={this.checkNameUnique}
  151. wrappedComponentRef={this.refHandles.OrganizationForm}
  152. />
  153. </Modal>
  154. </Box>
  155. )
  156. }
  157. }
  158. const mapStateToProps = createStructuredSelector({
  159. organizations: makeSelectOrganizations(),
  160. loginUser: makeSelectLoginUser()
  161. })
  162. export function mapDispatchToProps (dispatch) {
  163. return {
  164. onLoadOrganizations: () => dispatch(loadOrganizations()),
  165. onAddOrganization: (organization, resolve) => dispatch(addOrganization(organization, resolve)),
  166. onCheckUniqueName: (pathname, data, resolve, reject) => dispatch(checkNameUniqueAction(pathname, data, resolve, reject))
  167. }
  168. }
  169. const withConnect = connect(mapStateToProps, mapDispatchToProps)
  170. export default compose(
  171. withConnect
  172. )(Organizations)