settings.pug 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. extends ../layout
  2. block content
  3. .content.content-alt
  4. .container
  5. .row
  6. .col-md-12.col-lg-10.col-lg-offset-1
  7. .card
  8. .page-header
  9. h1 #{translate("account_settings")}
  10. .account-settings(ng-controller="AccountSettingsController", ng-cloak)
  11. if locals.showAffiliationsUI
  12. form.row(
  13. ng-controller="UserAffiliationsController"
  14. name="affiliationsForm"
  15. )
  16. .col-md-12
  17. h3 Emails and Affiliations
  18. p.small Add additional email addresses to your account to access any upgrades your university or institution has, to make it easier for collaborators to find you, and to make sure you can recover your account.
  19. table.table.affiliations-table
  20. thead
  21. tr
  22. th.affiliations-table-email Email
  23. th.affiliations-table-institution Institution and role
  24. th.affiliations-table-inline-actions
  25. tbody
  26. tr(
  27. ng-repeat="userEmail in userEmails"
  28. )
  29. td {{ userEmail.email + (userEmail.default ? ' (default)' : '') }}
  30. td
  31. div(ng-if="userEmail.affiliation.institution") {{ userEmail.affiliation.institution.name }}
  32. div(ng-if="userEmail.affiliation.role || userEmail.affiliation.department")
  33. span(ng-if="userEmail.affiliation.role") {{ userEmail.affiliation.role + ", " }}
  34. span(ng-if="userEmail.affiliation.department") {{ userEmail.affiliation.department }}
  35. td
  36. a(
  37. href
  38. ng-if="!userEmail.default"
  39. ng-click="setDefaultUserEmail(userEmail.email)"
  40. ) Make default
  41. br
  42. a(
  43. href
  44. ng-if="!userEmail.default"
  45. ng-click="removeUserEmail(userEmail.email)"
  46. ) Remove
  47. tr.affiliations-table-highlighted-row(
  48. ng-if="ui.isLoadingEmails"
  49. )
  50. td.text-center(colspan="3")
  51. i.fa.fa-fw.fa-spin.fa-refresh
  52. |  Loading...
  53. tr.affiliations-table-highlighted-row(
  54. ng-if="!ui.showAddEmailUI && !ui.isLoadingEmails"
  55. )
  56. td(colspan="3")
  57. a(
  58. href
  59. ng-click="showAddEmailForm()"
  60. ) Add another email
  61. tr.affiliations-table-highlighted-row(
  62. ng-if="ui.showAddEmailUI"
  63. )
  64. td
  65. .affiliations-form-group
  66. input-suggestions(
  67. ng-model="newAffiliation.email"
  68. ng-model-options="{ allowInvalid: true }"
  69. get-suggestion="getEmailSuggestion(userInput)"
  70. on-blur="handleEmailInputBlur()"
  71. input-id="affilitations-email"
  72. input-name="affilitationsEmail"
  73. input-placeholder="e.g. johndoe@mit.edu"
  74. input-type="email"
  75. input-required="true"
  76. )
  77. td
  78. .affiliations-table-label(
  79. ng-if="newAffiliation.university && !ui.showManualUniversitySelectionUI"
  80. )
  81. | {{ newAffiliation.university.name }} (
  82. a(
  83. href
  84. ng-click="selectUniversityManually();"
  85. ) change
  86. | )
  87. .affiliations-table-label(
  88. ng-if="!newAffiliation.university && !ui.isValidEmail && !ui.showManualUniversitySelectionUI"
  89. ) Start by adding your email address.
  90. .affiliations-table-label(
  91. ng-if="!newAffiliation.university && ui.isValidEmail && !ui.isBlacklistedEmail && !ui.showManualUniversitySelectionUI"
  92. )
  93. | Is your email affiliated with an institution?
  94. br
  95. a(
  96. href
  97. ng-click="selectUniversityManually();"
  98. ) Let us know
  99. .affiliations-form-group(
  100. ng-if="ui.showManualUniversitySelectionUI"
  101. )
  102. ui-select(
  103. ng-model="newAffiliation.country"
  104. )
  105. ui-select-match(
  106. placeholder="Country"
  107. ) {{ $select.selected.name }}
  108. ui-select-choices(
  109. repeat="country in countries | filter: $select.search"
  110. )
  111. span(
  112. ng-bind="country.name"
  113. s)
  114. .affiliations-form-group(
  115. ng-if="ui.showManualUniversitySelectionUI"
  116. )
  117. ui-select(
  118. ng-model="newAffiliation.university"
  119. ng-disabled="!newAffiliation.country"
  120. tagging="addUniversityToSelection"
  121. tagging-label="false"
  122. )
  123. ui-select-match(
  124. placeholder="Institution"
  125. ) {{ $select.selected.name }}
  126. ui-select-choices(
  127. repeat="university in universities | filter: $select.search"
  128. )
  129. span(
  130. ng-bind="university.name"
  131. )
  132. .affiliations-form-group(
  133. ng-if="ui.isValidEmail && newAffiliation.university"
  134. )
  135. input.form-control(
  136. type="text"
  137. id="affiliations-role"
  138. placeholder="Role"
  139. ng-model="newAffiliation.role"
  140. )
  141. .affiliations-form-group(
  142. ng-if="ui.isValidEmail && newAffiliation.university"
  143. )
  144. input.form-control(
  145. type="text"
  146. id="affiliations-department"
  147. placeholder="Department"
  148. ng-model="newAffiliation.department"
  149. ng-if="!newAffiliation.university.departments || newAffiliation.university.departments.length === 0"
  150. )
  151. ui-select(
  152. ng-model="newAffiliation.department"
  153. ng-if="newAffiliation.university.departments.length > 0"
  154. tagging
  155. tagging-label="false"
  156. )
  157. ui-select-match(
  158. placeholder="Department"
  159. ) {{ $select.selected }}
  160. ui-select-choices(
  161. repeat="department in getUniqueUniversityDepartments() | filter: $select.search"
  162. )
  163. span(
  164. ng-bind="department"
  165. )
  166. td
  167. button.btn.btn-primary(
  168. ng-disabled="affiliationsForm.$invalid || ui.isAddingNewEmail"
  169. ng-click="addNewEmail()"
  170. )
  171. span(
  172. ng-if="!ui.isAddingNewEmail"
  173. ) Add new email
  174. span(
  175. ng-if="ui.isAddingNewEmail"
  176. )
  177. i.fa.fa-fw.fa-spin.fa-refresh
  178. |  Adding...
  179. hr
  180. form-messages(for="settingsForm")
  181. .alert.alert-success(ng-show="settingsForm.response.success")
  182. | #{translate("thanks_settings_updated")}
  183. form-messages(for="changePasswordForm")
  184. .row
  185. .col-md-5
  186. h3 #{translate("update_account_info")}
  187. form(async-form="settings", name="settingsForm", method="POST", action="/user/settings", novalidate)
  188. input(type="hidden", name="_csrf", value=csrfToken)
  189. if !externalAuthenticationSystemUsed()
  190. .form-group
  191. label(for='email') #{translate("email")}
  192. input.form-control(
  193. type='email',
  194. name='email',
  195. placeholder="email@example.com"
  196. required,
  197. ng-model="email",
  198. ng-init="email = "+JSON.stringify(user.email),
  199. ng-model-options="{ updateOn: 'blur' }"
  200. )
  201. span.small.text-primary(ng-show="settingsForm.email.$invalid && settingsForm.email.$dirty")
  202. | #{translate("must_be_email_address")}
  203. else
  204. // show the email, non-editable
  205. .form-group
  206. label.control-label #{translate("email")}
  207. div.form-control(readonly="true") #{user.email}
  208. if shouldAllowEditingDetails
  209. .form-group
  210. label(for='firstName').control-label #{translate("first_name")}
  211. input.form-control(
  212. type='text',
  213. name='first_name',
  214. value=user.first_name
  215. ng-non-bindable
  216. )
  217. .form-group
  218. label(for='lastName').control-label #{translate("last_name")}
  219. input.form-control(
  220. type='text',
  221. name='last_name',
  222. value=user.last_name
  223. ng-non-bindable
  224. )
  225. .actions
  226. button.btn.btn-primary(
  227. type='submit',
  228. ng-disabled="settingsForm.$invalid"
  229. ) #{translate("update")}
  230. else
  231. .form-group
  232. label.control-label #{translate("first_name")}
  233. div.form-control(readonly="true") #{user.first_name}
  234. .form-group
  235. label.control-label #{translate("last_name")}
  236. div.form-control(readonly="true") #{user.last_name}
  237. if !externalAuthenticationSystemUsed()
  238. .col-md-5.col-md-offset-1
  239. h3 #{translate("change_password")}
  240. form(async-form="changepassword", name="changePasswordForm", action="/user/password/update", method="POST", novalidate)
  241. input(type="hidden", name="_csrf", value=csrfToken)
  242. .form-group
  243. label(for='currentPassword') #{translate("current_password")}
  244. input.form-control(
  245. type='password',
  246. name='currentPassword',
  247. placeholder='*********',
  248. ng-model="currentPassword",
  249. required
  250. )
  251. span.small.text-primary(ng-show="changePasswordForm.currentPassword.$invalid && changePasswordForm.currentPassword.$dirty")
  252. | #{translate("required")}
  253. .form-group
  254. label(for='newPassword1') #{translate("new_password")}
  255. input.form-control(
  256. id='passwordField',
  257. type='password',
  258. name='newPassword1',
  259. placeholder='*********',
  260. ng-model="newPassword1",
  261. required,
  262. complex-password
  263. )
  264. span.small.text-primary(ng-show="changePasswordForm.newPassword1.$error.complexPassword && changePasswordForm.newPassword1.$dirty", ng-bind-html="complexPasswordErrorMessage")
  265. .form-group
  266. label(for='newPassword2') #{translate("confirm_new_password")}
  267. input.form-control(
  268. type='password',
  269. name='newPassword2',
  270. placeholder='*********',
  271. ng-model="newPassword2",
  272. equals="passwordField"
  273. )
  274. span.small.text-primary(ng-show="changePasswordForm.newPassword2.$error.areEqual && changePasswordForm.newPassword2.$dirty")
  275. | #{translate("doesnt_match")}
  276. span.small.text-primary(ng-show="!changePasswordForm.newPassword2.$error.areEqual && changePasswordForm.newPassword2.$invalid && changePasswordForm.newPassword2.$dirty")
  277. | #{translate("invalid_password")}
  278. .actions
  279. button.btn.btn-primary(
  280. type='submit',
  281. ng-disabled="changePasswordForm.$invalid"
  282. ) #{translate("change")}
  283. | !{moduleIncludes("userSettings", locals)}
  284. //- The beta program doesn't make much sense to include while v2 is going
  285. //- but we may want to add it back in later
  286. //- hr
  287. //-
  288. //- h3
  289. //- | #{translate("sharelatex_beta_program")}
  290. //-
  291. //- if (user.betaProgram)
  292. //- p.small
  293. //- | #{translate("beta_program_already_participating")}
  294. //-
  295. //- div
  296. //- a(id="beta-program-participate-link" href="/beta/participate") #{translate("manage_beta_program_membership")}
  297. hr
  298. h3
  299. | #{translate("sessions")}
  300. div
  301. a(id="sessions-link", href="/user/sessions") #{translate("manage_sessions")}
  302. hr
  303. if !externalAuthenticationSystemUsed()
  304. p.small
  305. | #{translate("newsletter_info_and_unsubscribe")}
  306. a(
  307. href,
  308. ng-click="unsubscribe()",
  309. ng-show="subscribed && !unsubscribing"
  310. ) #{translate("unsubscribe")}
  311. span(
  312. ng-show="unsubscribing"
  313. )
  314. i.fa.fa-spin.fa-refresh
  315. | #{translate("unsubscribing")}
  316. span.text-success(
  317. ng-show="!subscribed"
  318. )
  319. i.fa.fa-check
  320. | #{translate("unsubscribed")}
  321. p #{translate("need_to_leave")}
  322. a(href, ng-click="deleteAccount()") #{translate("delete_your_account")}
  323. script(type='text/ng-template', id='deleteAccountModalTemplate')
  324. .modal-header
  325. h3 #{translate("delete_account")}
  326. div.modal-body#delete-account-modal
  327. p !{translate("delete_account_warning_message_3")}
  328. form(novalidate, name="deleteAccountForm")
  329. label #{translate('email')}
  330. input.form-control(
  331. type="text",
  332. autocomplete="off",
  333. placeholder="",
  334. ng-model="state.deleteText",
  335. focus-on="open",
  336. ng-keyup="checkValidation()"
  337. )
  338. label #{translate('password')}
  339. input.form-control(
  340. type="password",
  341. autocomplete="off",
  342. placeholder="",
  343. ng-model="state.password",
  344. ng-keyup="checkValidation()"
  345. )
  346. div(ng-if="state.error")
  347. div.alert.alert-danger
  348. | #{translate('generic_something_went_wrong')}
  349. div(ng-if="state.invalidCredentials")
  350. div.alert.alert-danger
  351. | #{translate('email_or_password_wrong_try_again')}
  352. .modal-footer
  353. button.btn.btn-default(
  354. ng-click="cancel()"
  355. ) #{translate("cancel")}
  356. button.btn.btn-danger(
  357. ng-disabled="!state.isValid || state.inflight"
  358. ng-click="delete()"
  359. )
  360. span(ng-hide="state.inflight") #{translate("delete")}
  361. span(ng-show="state.inflight") #{translate("deleting")}...
  362. script(type='text/javascript').
  363. window.passwordStrengthOptions = !{JSON.stringify(settings.passwordStrengthOptions || {})}