invite.js 2.8 KB

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