AuthForm.tsx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /*
  2. * <<
  3. * Davinci
  4. * ==
  5. * Copyright (C) 2016 - 2017 EDP
  6. * ==
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. * >>
  19. */
  20. import React, {
  21. useState,
  22. useCallback,
  23. useEffect,
  24. ReactElement,
  25. memo
  26. } from 'react'
  27. import { debounce } from 'lodash'
  28. import BaseForm from './BaseForm'
  29. import { Form, Row, Col, Select, Radio } from 'antd'
  30. import { WrappedFormUtils } from 'antd/lib/form/Form'
  31. import { IProjectRoles } from 'containers/Organizations/component/ProjectRole'
  32. import { IOrganizationMember } from 'containers/Organizations/types'
  33. import { sliceLength } from './util'
  34. import { TCopyType } from '../types'
  35. import styles from '../SharePanel.less'
  36. const FormItem = Form.Item
  37. const SelectOption = Select.Option
  38. const RadioGroup = Radio.Group
  39. interface IAuthFormProps {
  40. form: WrappedFormUtils
  41. projectRoles: IProjectRoles[]
  42. organizationMembers: IOrganizationMember[]
  43. shareUrl: string
  44. loading: boolean
  45. onSetRoles: (roles: number[]) => void
  46. onSetViewers: (viewers: number[]) => void
  47. onCopy: (copytype: TCopyType) => () => void
  48. onGetToken: () => void
  49. }
  50. const AuthForm: React.FC<IAuthFormProps> = ({
  51. form,
  52. projectRoles,
  53. organizationMembers,
  54. shareUrl,
  55. loading,
  56. onSetRoles,
  57. onSetViewers,
  58. onGetToken,
  59. onCopy
  60. }) => {
  61. const [authOptions, setAuthOptions] = useState<ReactElement[]>([])
  62. const { getFieldDecorator } = form
  63. const getRoleOptions = useCallback(
  64. (orgRoles: IProjectRoles[], searchValue: string) => {
  65. return orgRoles
  66. .filter((role: IProjectRoles) =>
  67. searchValue ? role.name.includes(searchValue.trim()) : role
  68. )
  69. .map(({ id, name }) => (
  70. <SelectOption key={id} value={`roles-${id}`}>
  71. <div className={styles.options}>
  72. <strong>角色</strong> -<span className={styles.name}>{name}</span>
  73. </div>
  74. </SelectOption>
  75. ))
  76. },
  77. []
  78. )
  79. const getOrgMemberOptions = useCallback(
  80. (orgMembers: IOrganizationMember[], searchValue: string) => {
  81. return orgMembers
  82. .filter((member: IOrganizationMember) =>
  83. searchValue
  84. ? member.user.username.includes(searchValue.trim())
  85. : member
  86. )
  87. .map(({ id, user }: IOrganizationMember) => (
  88. <SelectOption key={id} value={`viewers-${user.id}`}>
  89. <div className={styles.options}>
  90. <strong>用户</strong> -
  91. <span className={styles.name}>
  92. {user.username}
  93. {user.email}
  94. </span>
  95. </div>
  96. </SelectOption>
  97. ))
  98. },
  99. []
  100. )
  101. const getOptions = useCallback(
  102. (projectRoles, organizationMembers, searchValue) => {
  103. const roles = getRoleOptions(projectRoles, searchValue)
  104. const viewers = getOrgMemberOptions(organizationMembers, searchValue)
  105. return sliceLength(100, roles, viewers)()
  106. },
  107. []
  108. )
  109. const debouncedSearch = useCallback(
  110. debounce((searchValue: string) => {
  111. setAuthOptions(getOptions(projectRoles, organizationMembers, searchValue))
  112. }, 500),
  113. [projectRoles, organizationMembers]
  114. )
  115. useEffect(() => {
  116. setAuthOptions(getOptions(projectRoles, organizationMembers, ''))
  117. }, [projectRoles, organizationMembers])
  118. const resetOptions = useCallback(() => {
  119. setAuthOptions(getOptions(projectRoles, organizationMembers, ''))
  120. }, [projectRoles, organizationMembers])
  121. const change = useCallback(
  122. (val: string[]) => {
  123. const wrapper: { viewers: number[]; roles: number[] } = val.reduce(
  124. (iteratee, target) => {
  125. const [key, value] = target.split('-')
  126. iteratee[key].push(Number(value))
  127. return iteratee
  128. },
  129. { viewers: [], roles: [] }
  130. )
  131. onSetRoles(wrapper.roles)
  132. onSetViewers(wrapper.viewers)
  133. },
  134. [onSetRoles, onSetViewers]
  135. )
  136. const itemStyle = { labelCol: { span: 6 }, wrapperCol: { span: 17 } }
  137. return (
  138. <>
  139. <Row gutter={8}>
  140. <Col span={24}>
  141. <FormItem label="数据权限" {...itemStyle}>
  142. {getFieldDecorator('permission', { initialValue: 'SHARER' })(
  143. <RadioGroup>
  144. <Radio key="SHARER" value="SHARER">
  145. 与分享者一致
  146. </Radio>
  147. <Radio key="VIEWER" value="VIEWER">
  148. 使用被分享者自身权限
  149. </Radio>
  150. </RadioGroup>
  151. )}
  152. </FormItem>
  153. </Col>
  154. </Row>
  155. <Row gutter={8}>
  156. <Col span={24}>
  157. <FormItem label="被授权人" {...itemStyle}>
  158. {getFieldDecorator('authorized', {
  159. rules: [{ required: true, message: '被授权人不能为空' }]
  160. })(
  161. <Select
  162. showSearch
  163. mode="multiple"
  164. onSearch={debouncedSearch}
  165. onBlur={resetOptions}
  166. onChange={change}
  167. placeholder="输入关键字查询角色或用户"
  168. filterOption={false}
  169. >
  170. {authOptions}
  171. </Select>
  172. )}
  173. </FormItem>
  174. </Col>
  175. </Row>
  176. <BaseForm
  177. form={form}
  178. shareUrl={shareUrl}
  179. loading={loading}
  180. onCopy={onCopy}
  181. onGetToken={onGetToken}
  182. />
  183. </>
  184. )
  185. }
  186. export default memo(AuthForm)