user-affiliations.pug 15 KB

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