user-affiliations.pug 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. include ../../_mixins/saml
  2. mixin aboutInstitutionLink()
  3. a(href="/learn/how-to/Institutional_Login") #{translate("find_out_more_about_institution_login")}.
  4. mixin btnMakePrimaryDisabled(tooltip)
  5. div(
  6. tooltip=tooltip
  7. tooltip-enable="!ui.isMakingRequest"
  8. ng-if="!userEmail.default && (!userEmail.confirmedAt || ui.isMakingRequest) && !institutionAlreadyLinked(userEmail)"
  9. )
  10. button.btn.btn-sm.btn-success.affiliations-table-inline-action(
  11. disabled
  12. type="button"
  13. ) #{translate("make_primary")}
  14. form.row(
  15. ng-controller="UserAffiliationsController"
  16. name="affiliationsForm"
  17. )
  18. .col-md-12
  19. h3 #{translate("emails_and_affiliations_title")}
  20. p.small #{translate("emails_and_affiliations_explanation")}
  21. table.table.affiliations-table
  22. thead
  23. tr
  24. th.affiliations-table-email #{translate("email")}
  25. th.affiliations-table-institution #{translate("institution_and_role")}
  26. th.affiliations-table-inline-actions
  27. tbody
  28. tr(
  29. ng-repeat-start="userEmail in userEmails"
  30. )
  31. td
  32. | {{ userEmail.email + (userEmail.default ? ' (primary)' : '') }}
  33. div(ng-if="!userEmail.confirmedAt").small
  34. strong #{translate('unconfirmed')}.
  35. span(ng-if="!userEmail.ssoAvailable")  #{translate('please_check_your_inbox')}.
  36. br
  37. a(
  38. href,
  39. ng-click="resendConfirmationEmail(userEmail)",
  40. ng-if="!userEmail.ssoAvailable"
  41. ) #{translate('resend_confirmation_email')}
  42. div(ng-if="userEmail.confirmedAt && userEmail.affiliation.institution && userEmail.affiliation.institution.confirmed && userEmail.affiliation.licence && userEmail.affiliation.licence != 'free'").small
  43. span.label.label-primary #{translate("professional")}
  44. td
  45. div(ng-if="userEmail.affiliation.institution")
  46. div {{ userEmail.affiliation.institution.name }}
  47. span.small
  48. a(
  49. href
  50. ng-if="!isChangingAffiliation(userEmail.email) && !userEmail.affiliation.role && !userEmail.affiliation.department"
  51. ng-click="changeAffiliation(userEmail);"
  52. ) #{translate("add_role_and_department")}
  53. div.small(
  54. ng-if="!isChangingAffiliation(userEmail.email) && (userEmail.affiliation.role || userEmail.affiliation.department)"
  55. )
  56. span(ng-if="userEmail.affiliation.role") {{ userEmail.affiliation.role }}
  57. span(ng-if="userEmail.affiliation.role && userEmail.affiliation.department") , 
  58. span(ng-if="userEmail.affiliation.department") {{ userEmail.affiliation.department }}
  59. br
  60. a(
  61. href
  62. ng-click="changeAffiliation(userEmail);"
  63. ) #{translate("change")}
  64. .affiliation-change-container(
  65. ng-if="isChangingAffiliation(userEmail.email)"
  66. )
  67. affiliation-form(
  68. affiliation-data="affiliationToChange"
  69. show-university-and-country="false"
  70. show-role-and-department="true"
  71. )
  72. .affiliation-change-actions.small
  73. button.btn.btn-sm.btn-success(
  74. ng-click="saveAffiliationChange(userEmail);"
  75. ng-disabled="!(affiliationToChange.role && affiliationToChange.department)"
  76. type="button"
  77. ) #{translate("save_or_cancel-save")}
  78. |  #{translate("save_or_cancel-or" )} 
  79. a(
  80. href
  81. ng-click="cancelAffiliationChange();"
  82. ) #{translate("save_or_cancel-cancel")}
  83. td.affiliations-table-inline-actions
  84. // Disabled buttons don't work with tooltips, due to pointer-events: none,
  85. // so create a wrapper for the tooltip
  86. .affiliations-table-inline-action-disabled-wrapper(ng-if="userEmail.ssoAvailable")
  87. +btnMakePrimaryDisabled("Please confirm your email by linking to your institutional account before making it the primary email.")
  88. .affiliations-table-inline-action-disabled-wrapper(ng-if="!userEmail.ssoAvailable")
  89. +btnMakePrimaryDisabled(translate("please_confirm_your_email_before_making_it_default"))
  90. button.btn.btn-sm.btn-success.affiliations-table-inline-action(
  91. tooltip=translate("make_email_primary_description")
  92. ng-if="!userEmail.default && (userEmail.confirmedAt && !ui.isMakingRequest)"
  93. ng-click="setDefaultUserEmail(userEmail)"
  94. type="button"
  95. ) #{translate("make_primary")}
  96. |  
  97. button.btn.btn-sm.btn-danger.affiliations-table-inline-action(
  98. ng-if="!userEmail.default"
  99. ng-click="removeUserEmail(userEmail)"
  100. ng-disabled="ui.isMakingRequest"
  101. tooltip=translate("remove")
  102. type="button"
  103. )
  104. i.fa.fa-fw.fa-trash(aria-hidden="true")
  105. span.sr-only #{translate("remove")}
  106. tr.affiliations-table-saml-row(ng-repeat-end ng-if="userEmail.affiliation && userEmail.affiliation && userEmail.ssoAvailable")
  107. td
  108. td(ng-attr-colspan="{{userEmail.samlProviderId ? '2' : '1'}}" ng-class="institutionAlreadyLinked(userEmail) ? '' : 'with-border'")
  109. p.small(ng-if="userEmail.samlProviderId")
  110. | !{translate("acct_linked_to_institution_acct", {institutionName: '{{userEmail.affiliation.institution.name}}'})}
  111. div(ng-if="!userEmail.samlProviderId && !institutionAlreadyLinked(userEmail)")
  112. //- this email is not linked to institution login but
  113. //- cannot have multiple emails at same institution linked for "institution login"
  114. //- so check if institution is already linked
  115. p.small
  116. | !{translate("can_link_your_institution_acct", {institutionName: '{{userEmail.affiliation.institution.name}}'})}
  117. p.small
  118. | !{translate("doing_this_allow_log_in_through_institution")} 
  119. +aboutInstitutionLink()
  120. td.with-border.affiliations-table-inline-actions(ng-if="!userEmail.samlProviderId && !institutionAlreadyLinked(userEmail)")
  121. button.btn-sm.btn.btn-info(
  122. ng-click="linkInstitutionAcct(userEmail.email, userEmail.affiliation.institution.id)"
  123. ng-disabled="ui.isMakingRequest"
  124. type="button"
  125. )
  126. | #{translate("link_accounts")}
  127. tr.affiliations-table-highlighted-row(
  128. ng-if="!ui.showAddEmailUI && !ui.isMakingRequest"
  129. )
  130. td(colspan="3")
  131. a(
  132. href
  133. ng-click="showAddEmailForm()"
  134. ) #{translate("add_another_email")}
  135. tr.affiliations-table-highlighted-row(
  136. ng-if="ui.showAddEmailUI && !ui.isLoadingEmails"
  137. )
  138. td
  139. .affiliations-form-group
  140. input-suggestions(
  141. ng-model="newAffiliation.email"
  142. ng-model-options="{ allowInvalid: true }"
  143. get-suggestion="getEmailSuggestion(userInput)"
  144. on-blur="handleEmailInputBlur()"
  145. input-id="affilitations-email"
  146. input-name="affilitationsEmail"
  147. input-placeholder="e.g. johndoe@mit.edu"
  148. input-type="email"
  149. input-required="true"
  150. )
  151. td(
  152. colspan="2"
  153. ng-if="newAffiliation.ssoAvailable"
  154. )
  155. p.affiliations-table-label {{ newAffiliation.university.name }}
  156. p !{translate("to_add_email_accounts_need_to_be_linked", {institutionName: "{{newAffiliation.university.name}}"})}
  157. p !{translate("doing_this_will_verify_affiliation_and_allow_log_in", {institutionName: "{{newAffiliation.university.name}}"})} 
  158. +aboutInstitutionLink()
  159. button.btn-sm.btn.btn-primary.btn-link-accounts(
  160. ng-click="linkInstitutionAcct(newAffiliation.email, newAffiliation.university.id)"
  161. ng-disabled="ui.isMakingRequest"
  162. type="button"
  163. )
  164. | #{translate("link_accounts_and_add_email")}
  165. td(
  166. ng-if="!newAffiliation.ssoAvailable"
  167. )
  168. p.affiliations-table-label(
  169. ng-if="newAffiliation.university && !ui.showManualUniversitySelectionUI"
  170. )
  171. | {{ newAffiliation.university.name }}
  172. span.small
  173. | (
  174. a(
  175. href
  176. ng-click="selectUniversityManually();"
  177. ) #{translate("change")}
  178. | )
  179. .affiliations-table-label(
  180. ng-if="!newAffiliation.university && !ui.isValidEmail && !ui.showManualUniversitySelectionUI"
  181. ) #{translate("start_by_adding_your_email")}
  182. .affiliations-table-label(
  183. ng-if="!newAffiliation.university && ui.isValidEmail && !ui.isBlacklistedEmail && !ui.showManualUniversitySelectionUI"
  184. )
  185. | #{translate("is_email_affiliated")}
  186. br
  187. a(
  188. href
  189. ng-click="selectUniversityManually();"
  190. ) #{translate("let_us_know")}
  191. affiliation-form(
  192. affiliation-data="newAffiliation"
  193. show-university-and-country="ui.showManualUniversitySelectionUI"
  194. show-role-and-department="ui.isValidEmail && newAffiliation.university"
  195. )
  196. td(
  197. ng-if="!newAffiliation.ssoAvailable"
  198. )
  199. button.btn.btn-sm.btn-primary(
  200. ng-disabled="affiliationsForm.$invalid || ui.isMakingRequest"
  201. ng-click="addNewEmail()"
  202. )
  203. | #{translate("add_new_email")}
  204. tr.affiliations-table-highlighted-row(
  205. ng-if="ui.isMakingRequest"
  206. )
  207. td.text-center(colspan="3", ng-if="ui.isLoadingEmails")
  208. i.fa.fa-fw.fa-spin.fa-refresh(aria-hidden="true")
  209. |  #{translate("loading")}…
  210. td.text-center(colspan="3", ng-if="ui.isResendingConfirmation")
  211. i.fa.fa-fw.fa-spin.fa-refresh(aria-hidden="true")
  212. |  #{translate("sending")}…
  213. td.text-center.text-capitalize(colspan="3", ng-if="ui.isProcessing")
  214. i.fa.fa-fw.fa-spin.fa-refresh(aria-hidden="true")
  215. |  #{translate("processing")}
  216. td.text-center(colspan="3", ng-if="!ui.isLoadingEmails && !ui.isResendingConfirmation && !ui.isProcessing")
  217. i.fa.fa-fw.fa-spin.fa-refresh(aria-hidden="true")
  218. |  #{translate("saving")}
  219. tr.affiliations-table-error-row(
  220. ng-if="ui.hasError"
  221. )
  222. td.text-center(colspan="3")
  223. div
  224. i.fa.fa-fw.fa-exclamation-triangle(aria-hidden="true")
  225. span(ng-if="!ui.errorMessage")  #{translate("error_performing_request")}
  226. span(ng-if="ui.errorMessage")  {{ui.errorMessage}}
  227. if institutionLinked
  228. tr.affiliations-table-info-row(ng-if="!hideInstitutionNotifications.info")
  229. td.text-center(aria-live="assertive" colspan="3")
  230. button.close(
  231. type="button"
  232. data-dismiss="modal"
  233. ng-click="closeInstitutionNotification('info')"
  234. aria-label=translate("close")
  235. )
  236. span(aria-hidden="true") ×
  237. .small !{translate("institution_acct_successfully_linked", {institutionName: institutionLinked.universityName})}
  238. if institutionLinked.hasEntitlement
  239. .small !{translate("this_grants_access_to_features", {featureType: translate("professional")})}
  240. if institutionEmailNonCanonical
  241. tr.affiliations-table-warning-row(ng-if="!hideInstitutionNotifications.warning")
  242. td.text-center(aria-live="assertive" colspan="3")
  243. button.close(
  244. type="button"
  245. data-dismiss="modal"
  246. ng-click="closeInstitutionNotification('warning')"
  247. aria-label=translate("close")
  248. )
  249. span(aria-hidden="true") ×
  250. .small
  251. i.fa.fa-exclamation-triangle(aria-hidden="true")
  252. |  
  253. | !{translate("in_order_to_match_institutional_metadata", {email: institutionEmailNonCanonical})}
  254. if institutionLinkedToAnother
  255. tr.affiliations-table-error-row(ng-if="!hideInstitutionNotifications.error")
  256. td.text-center(aria-live="assertive" colspan="3")
  257. button.close(
  258. type="button"
  259. data-dismiss="modal"
  260. ng-click="closeInstitutionNotification('error')"
  261. aria-label=translate("close")
  262. )
  263. span(aria-hidden="true") ×
  264. .small
  265. i.fa.fa-exclamation-triangle(aria-hidden="true")
  266. |  
  267. | !{translate("institution_account_tried_to_add_already_registered")}
  268. if institutionLinkingError
  269. tr.affiliations-table-error-row(ng-if="!hideInstitutionNotifications.linkError")
  270. td.text-center(aria-live="assertive" colspan="3")
  271. button.close(
  272. type="button"
  273. data-dismiss="modal"
  274. ng-click="closeInstitutionNotification('linkError')"
  275. aria-label=translate("close")
  276. )
  277. span(aria-hidden="true") ×
  278. .small
  279. +samlErrorLoggedIn(institutionLinkingError)
  280. hr
  281. script(type="text/ng-template", id="affiliationFormTpl")
  282. .affiliations-form-group(
  283. ng-if="$ctrl.showUniversityAndCountry"
  284. )
  285. ui-select(
  286. ng-model="$ctrl.affiliationData.country"
  287. )
  288. ui-select-match(
  289. placeholder="Country"
  290. ) {{ $select.selected.name }}
  291. ui-select-choices(
  292. repeat="country in $ctrl.countries | filter: $select.search"
  293. )
  294. span(
  295. ng-bind="country.name"
  296. )
  297. .affiliations-form-group(
  298. ng-if="$ctrl.showUniversityAndCountry"
  299. )
  300. ui-select(
  301. ng-model="$ctrl.affiliationData.university"
  302. ng-disabled="!$ctrl.affiliationData.country"
  303. tagging="$ctrl.addUniversityToSelection"
  304. tagging-label="false"
  305. )
  306. ui-select-match(
  307. placeholder="Institution"
  308. ) {{ $select.selected.name }}
  309. ui-select-choices(
  310. repeat="university in $ctrl.universities | filter: $select.search"
  311. refresh="$ctrl.handleFreeformInputChange($select, 'name');"
  312. refresh-delay="10"
  313. )
  314. span(
  315. ng-bind="university.name"
  316. )
  317. .affiliations-form-group(
  318. ng-if="$ctrl.showRoleAndDepartment"
  319. )
  320. ui-select(
  321. ng-model="$ctrl.affiliationData.role"
  322. tagging
  323. tagging-label="false"
  324. )
  325. ui-select-match(
  326. placeholder="Role"
  327. ) {{ $select.selected }}
  328. ui-select-choices(
  329. repeat="role in $ctrl.roles | filter: $select.search"
  330. refresh="$ctrl.handleFreeformInputChange($select);"
  331. refresh-delay="10"
  332. )
  333. span(
  334. ng-bind="role"
  335. )
  336. .affiliations-form-group(
  337. ng-if="$ctrl.showRoleAndDepartment"
  338. )
  339. ui-select(
  340. ng-model="$ctrl.affiliationData.department"
  341. tagging
  342. tagging-label="false"
  343. )
  344. ui-select-match(
  345. placeholder="Department"
  346. ) {{ $select.selected }}
  347. ui-select-choices(
  348. repeat="department in $ctrl.departments | filter: $select.search"
  349. refresh="$ctrl.handleFreeformInputChange($select);"
  350. refresh-delay="10"
  351. )
  352. span(
  353. ng-bind="department"
  354. )