row.tsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. import { useState } from 'react'
  2. import { Trans, useTranslation } from 'react-i18next'
  3. import { UserEmailData } from '../../../../../../types/user-email'
  4. import Email from './email'
  5. import InstitutionAndRole from './institution-and-role'
  6. import EmailCell from './cell'
  7. import Actions from './actions'
  8. import { institutionAlreadyLinked } from '../../utils/selectors'
  9. import { useUserEmailsContext } from '../../context/user-email-context'
  10. import getMeta from '../../../../utils/meta'
  11. import { ssoAvailableForInstitution } from '../../utils/sso'
  12. import ReconfirmationInfo from './reconfirmation-info'
  13. import { useLocation } from '../../../../shared/hooks/use-location'
  14. import OLRow from '@/features/ui/components/ol/ol-row'
  15. import OLCol from '@/features/ui/components/ol/ol-col'
  16. import OLButton from '@/features/ui/components/ol/ol-button'
  17. type EmailsRowProps = {
  18. userEmailData: UserEmailData
  19. }
  20. function EmailsRow({ userEmailData }: EmailsRowProps) {
  21. const hasSSOAffiliation = Boolean(
  22. userEmailData.affiliation &&
  23. ssoAvailableForInstitution(userEmailData.affiliation.institution)
  24. )
  25. return (
  26. <>
  27. <OLRow>
  28. <OLCol lg={4}>
  29. <EmailCell>
  30. <Email userEmailData={userEmailData} />
  31. </EmailCell>
  32. </OLCol>
  33. <OLCol lg={5}>
  34. {userEmailData.affiliation?.institution && (
  35. <EmailCell>
  36. <InstitutionAndRole userEmailData={userEmailData} />
  37. </EmailCell>
  38. )}
  39. </OLCol>
  40. <OLCol lg={3}>
  41. <EmailCell className="text-lg-end">
  42. <Actions userEmailData={userEmailData} />
  43. </EmailCell>
  44. </OLCol>
  45. </OLRow>
  46. {hasSSOAffiliation && (
  47. <SSOAffiliationInfo userEmailData={userEmailData} />
  48. )}
  49. <ReconfirmationInfo userEmailData={userEmailData} />
  50. </>
  51. )
  52. }
  53. type SSOAffiliationInfoProps = {
  54. userEmailData: UserEmailData
  55. }
  56. function SSOAffiliationInfo({ userEmailData }: SSOAffiliationInfoProps) {
  57. const { samlInitPath } = getMeta('ol-ExposedSettings')
  58. const { t } = useTranslation()
  59. const { state } = useUserEmailsContext()
  60. const location = useLocation()
  61. const [linkAccountsButtonDisabled, setLinkAccountsButtonDisabled] =
  62. useState(false)
  63. function handleLinkAccountsButtonClick() {
  64. setLinkAccountsButtonDisabled(true)
  65. location.assign(
  66. `${samlInitPath}?university_id=${userEmailData.affiliation?.institution?.id}&auto=/user/settings&email=${userEmailData.email}`
  67. )
  68. }
  69. if (
  70. !userEmailData.samlProviderId &&
  71. institutionAlreadyLinked(state, userEmailData)
  72. ) {
  73. // if the email is not linked to the institution, but there's another email already linked to that institution
  74. // no SSO affiliation is displayed, since cannot have multiple emails linked to the same institution
  75. return null
  76. }
  77. if (userEmailData.samlProviderId) {
  78. return (
  79. <OLRow>
  80. <OLCol lg={{ span: 8, offset: 4 }}>
  81. <EmailCell>
  82. <p>
  83. <Trans
  84. i18nKey="acct_linked_to_institution_acct_2"
  85. components={
  86. /* eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key */
  87. [<strong />]
  88. }
  89. values={{
  90. institutionName: userEmailData.affiliation?.institution.name,
  91. }}
  92. shouldUnescape
  93. tOptions={{ interpolation: { escapeValue: true } }}
  94. />
  95. </p>
  96. </EmailCell>
  97. </OLCol>
  98. </OLRow>
  99. )
  100. }
  101. return (
  102. <OLRow>
  103. <OLCol lg={{ span: 8, offset: 4 }}>
  104. <div className="horizontal-divider" />
  105. <OLRow>
  106. <OLCol lg={9}>
  107. <EmailCell>
  108. <p className="small">
  109. <Trans
  110. i18nKey="can_link_your_institution_acct_2"
  111. values={{
  112. institutionName:
  113. userEmailData.affiliation?.institution.name,
  114. }}
  115. shouldUnescape
  116. tOptions={{ interpolation: { escapeValue: true } }}
  117. components={
  118. /* eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key */
  119. [<strong />]
  120. }
  121. />
  122. </p>
  123. <p className="small">
  124. <Trans
  125. i18nKey="doing_this_allow_log_in_through_institution_2"
  126. components={
  127. /* eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key */
  128. [<strong />]
  129. }
  130. />{' '}
  131. <a href="/learn/how-to/Institutional_Login" target="_blank">
  132. {t('find_out_more_about_institution_login')}
  133. </a>
  134. </p>
  135. </EmailCell>
  136. </OLCol>
  137. <OLCol lg={3} className="text-lg-end">
  138. <EmailCell>
  139. <OLButton
  140. variant="primary"
  141. className="btn-link-accounts"
  142. disabled={linkAccountsButtonDisabled}
  143. onClick={handleLinkAccountsButtonClick}
  144. size="sm"
  145. >
  146. {t('link_accounts')}
  147. </OLButton>
  148. </EmailCell>
  149. </OLCol>
  150. </OLRow>
  151. </OLCol>
  152. </OLRow>
  153. )
  154. }
  155. export default EmailsRow