invite.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import { useCallback } from 'react'
  2. import PropTypes from 'prop-types'
  3. import { useShareProjectContext } from './share-project-modal'
  4. import Icon from '../../../shared/components/icon'
  5. import { Button, Col, Row } from 'react-bootstrap'
  6. import Tooltip from '../../../shared/components/tooltip'
  7. import { Trans, useTranslation } from 'react-i18next'
  8. import MemberPrivileges from './member-privileges'
  9. import { resendInvite, revokeInvite } from '../utils/api'
  10. import { useProjectContext } from '../../../shared/context/project-context'
  11. export default function Invite({ invite, isProjectOwner }) {
  12. return (
  13. <Row className="project-invite">
  14. <Col xs={7}>
  15. <div>{invite.email}</div>
  16. <div className="small">
  17. <Trans i18nKey="invite_not_accepted" />
  18. .&nbsp;
  19. {isProjectOwner && <ResendInvite invite={invite} />}
  20. </div>
  21. </Col>
  22. <Col xs={3} className="text-left">
  23. <MemberPrivileges privileges={invite.privileges} />
  24. </Col>
  25. {isProjectOwner && (
  26. <Col xs={2} className="text-center">
  27. <RevokeInvite invite={invite} />
  28. </Col>
  29. )}
  30. </Row>
  31. )
  32. }
  33. Invite.propTypes = {
  34. invite: PropTypes.object.isRequired,
  35. isProjectOwner: PropTypes.bool.isRequired,
  36. }
  37. function ResendInvite({ invite }) {
  38. const { monitorRequest } = useShareProjectContext()
  39. const { _id: projectId } = useProjectContext()
  40. // const buttonRef = useRef(null)
  41. //
  42. const handleClick = useCallback(
  43. () =>
  44. monitorRequest(() => resendInvite(projectId, invite)).finally(() => {
  45. // NOTE: disabled as react-bootstrap v0.33.1 isn't forwarding the ref to the `button`
  46. // if (buttonRef.current) {
  47. // buttonRef.current.blur()
  48. // }
  49. document.activeElement.blur()
  50. }),
  51. [invite, monitorRequest, projectId]
  52. )
  53. return (
  54. <Button
  55. bsStyle="link"
  56. className="btn-inline-link"
  57. onClick={handleClick}
  58. // ref={buttonRef}
  59. >
  60. <Trans i18nKey="resend" />
  61. </Button>
  62. )
  63. }
  64. ResendInvite.propTypes = {
  65. invite: PropTypes.object.isRequired,
  66. }
  67. function RevokeInvite({ invite }) {
  68. const { t } = useTranslation()
  69. const { updateProject, monitorRequest } = useShareProjectContext()
  70. const { _id: projectId, invites } = useProjectContext()
  71. function handleClick(event) {
  72. event.preventDefault()
  73. monitorRequest(() => revokeInvite(projectId, invite)).then(() => {
  74. updateProject({
  75. invites: invites.filter(existing => existing !== invite),
  76. })
  77. })
  78. }
  79. return (
  80. <Tooltip
  81. id="revoke-invite"
  82. description={<Trans i18nKey="revoke_invite" />}
  83. overlayProps={{ placement: 'bottom' }}
  84. >
  85. <Button
  86. type="button"
  87. bsStyle="link"
  88. onClick={handleClick}
  89. aria-label={t('revoke')}
  90. className="btn-inline-link"
  91. >
  92. <Icon type="times" />
  93. </Button>
  94. </Tooltip>
  95. )
  96. }
  97. RevokeInvite.propTypes = {
  98. invite: PropTypes.object.isRequired,
  99. }