settings.pug 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  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. form-messages(for="settingsForm")
  12. .alert.alert-success(ng-show="settingsForm.response.success")
  13. | #{translate("thanks_settings_updated")}
  14. form-messages(for="changePasswordForm")
  15. div
  16. form.row(
  17. ng-controller="UserAffiliationsController"
  18. name="affiliationsForm"
  19. )
  20. .col-md-12
  21. h3 Emails and Affiliations
  22. 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.
  23. table.table.affiliations-table
  24. thead
  25. tr
  26. th.affiliations-table-email Email
  27. th.affiliations-table-institution Institution and role
  28. th.affiliations-table-inline-actions
  29. tbody
  30. tr(
  31. ng-repeat="userEmail in userEmails"
  32. )
  33. td {{ userEmail.email + (userEmail.default ? ' (default)' : '') }}
  34. td {{ userEmail.institution }}
  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(
  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. div(
  100. ng-if="ui.showManualUniversitySelectionUI"
  101. )
  102. .affiliations-form-group
  103. ui-select(
  104. ng-model="newAffiliation.country"
  105. )
  106. ui-select-match(
  107. placeholder="Country"
  108. ) {{ $select.selected.name }}
  109. ui-select-choices(
  110. repeat="country in countries | filter: $select.search"
  111. )
  112. span(
  113. ng-bind="country.name"
  114. s)
  115. .affiliations-form-group
  116. ui-select(
  117. ng-model="newAffiliation.university"
  118. ng-disabled="!newAffiliation.country"
  119. tagging="addUniversityToSelection"
  120. tagging-label="false"
  121. )
  122. ui-select-match(
  123. placeholder="Institution"
  124. ) {{ $select.selected.name }}
  125. ui-select-choices(
  126. repeat="university in universities | filter: $select.search"
  127. )
  128. span(
  129. ng-bind="university.name"
  130. )
  131. .affiliations-form-group(
  132. ng-if="ui.isValidEmail && newAffiliation.university"
  133. )
  134. input.form-control(
  135. type="text"
  136. id="affiliations-role"
  137. placeholder="Role"
  138. ng-model="newAffiliation.role"
  139. s)
  140. .affiliations-form-group(
  141. ng-if="ui.isValidEmail && newAffiliation.university"
  142. )
  143. input.form-control(
  144. type="text"
  145. id="affiliations-department"
  146. placeholder="Department"
  147. ng-model="newAffiliation.department"
  148. ng-if="!newAffiliation.university.departments || newAffiliation.university.departments.length === 0"
  149. )
  150. ui-select(
  151. ng-model="newAffiliation.department"
  152. ng-if="newAffiliation.university.departments.length > 0"
  153. tagging
  154. tagging-label="false"
  155. )
  156. ui-select-match(
  157. placeholder="Department"
  158. ) {{ $select.selected }}
  159. ui-select-choices(
  160. repeat="department in getUniqueUniversityDepartments() | filter: $select.search"
  161. )
  162. span(
  163. ng-bind="department"
  164. )
  165. td
  166. button.btn.btn-primary(
  167. ng-disabled="affiliationsForm.$invalid || ui.isAddingNewEmail"
  168. ng-click="addNewEmail()"
  169. )
  170. span(
  171. ng-if="!ui.isAddingNewEmail"
  172. ) Add new email
  173. span(
  174. ng-if="ui.isAddingNewEmail"
  175. )
  176. i.fa.fa-fw.fa-spin.fa-refresh
  177. |  Adding...
  178. hr
  179. .row
  180. .col-md-5
  181. h3 #{translate("update_account_info")}
  182. form(async-form="settings", name="settingsForm", method="POST", action="/user/settings", novalidate)
  183. input(type="hidden", name="_csrf", value=csrfToken)
  184. if !externalAuthenticationSystemUsed()
  185. .form-group
  186. label(for='email') #{translate("email")}
  187. input.form-control(
  188. type='email',
  189. name='email',
  190. placeholder="email@example.com"
  191. required,
  192. ng-model="email",
  193. ng-init="email = "+JSON.stringify(user.email),
  194. ng-model-options="{ updateOn: 'blur' }"
  195. )
  196. span.small.text-primary(ng-show="settingsForm.email.$invalid && settingsForm.email.$dirty")
  197. | #{translate("must_be_email_address")}
  198. else
  199. // show the email, non-editable
  200. .form-group
  201. label.control-label #{translate("email")}
  202. div.form-control(readonly="true") #{user.email}
  203. if shouldAllowEditingDetails
  204. .form-group
  205. label(for='firstName').control-label #{translate("first_name")}
  206. input.form-control(
  207. type='text',
  208. name='first_name',
  209. value=user.first_name
  210. ng-non-bindable
  211. )
  212. .form-group
  213. label(for='lastName').control-label #{translate("last_name")}
  214. input.form-control(
  215. type='text',
  216. name='last_name',
  217. value=user.last_name
  218. ng-non-bindable
  219. )
  220. .actions
  221. button.btn.btn-primary(
  222. type='submit',
  223. ng-disabled="settingsForm.$invalid"
  224. ) #{translate("update")}
  225. else
  226. .form-group
  227. label.control-label #{translate("first_name")}
  228. div.form-control(readonly="true") #{user.first_name}
  229. .form-group
  230. label.control-label #{translate("last_name")}
  231. div.form-control(readonly="true") #{user.last_name}
  232. if !externalAuthenticationSystemUsed()
  233. .col-md-5.col-md-offset-1
  234. h3 #{translate("change_password")}
  235. form(async-form="changepassword", name="changePasswordForm", action="/user/password/update", method="POST", novalidate)
  236. input(type="hidden", name="_csrf", value=csrfToken)
  237. .form-group
  238. label(for='currentPassword') #{translate("current_password")}
  239. input.form-control(
  240. type='password',
  241. name='currentPassword',
  242. placeholder='*********',
  243. ng-model="currentPassword",
  244. required
  245. )
  246. span.small.text-primary(ng-show="changePasswordForm.currentPassword.$invalid && changePasswordForm.currentPassword.$dirty")
  247. | #{translate("required")}
  248. .form-group
  249. label(for='newPassword1') #{translate("new_password")}
  250. input.form-control(
  251. id='passwordField',
  252. type='password',
  253. name='newPassword1',
  254. placeholder='*********',
  255. ng-model="newPassword1",
  256. required,
  257. complex-password
  258. )
  259. span.small.text-primary(ng-show="changePasswordForm.newPassword1.$error.complexPassword && changePasswordForm.newPassword1.$dirty", ng-bind-html="complexPasswordErrorMessage")
  260. .form-group
  261. label(for='newPassword2') #{translate("confirm_new_password")}
  262. input.form-control(
  263. type='password',
  264. name='newPassword2',
  265. placeholder='*********',
  266. ng-model="newPassword2",
  267. equals="passwordField"
  268. )
  269. span.small.text-primary(ng-show="changePasswordForm.newPassword2.$error.areEqual && changePasswordForm.newPassword2.$dirty")
  270. | #{translate("doesnt_match")}
  271. span.small.text-primary(ng-show="!changePasswordForm.newPassword2.$error.areEqual && changePasswordForm.newPassword2.$invalid && changePasswordForm.newPassword2.$dirty")
  272. | #{translate("invalid_password")}
  273. .actions
  274. button.btn.btn-primary(
  275. type='submit',
  276. ng-disabled="changePasswordForm.$invalid"
  277. ) #{translate("change")}
  278. | !{moduleIncludes("userSettings", locals)}
  279. //- The beta program doesn't make much sense to include while v2 is going
  280. //- but we may want to add it back in later
  281. //- hr
  282. //-
  283. //- h3
  284. //- | #{translate("sharelatex_beta_program")}
  285. //-
  286. //- if (user.betaProgram)
  287. //- p.small
  288. //- | #{translate("beta_program_already_participating")}
  289. //-
  290. //- div
  291. //- a(id="beta-program-participate-link" href="/beta/participate") #{translate("manage_beta_program_membership")}
  292. hr
  293. h3
  294. | #{translate("sessions")}
  295. div
  296. a(id="sessions-link", href="/user/sessions") #{translate("manage_sessions")}
  297. hr
  298. if !externalAuthenticationSystemUsed()
  299. p.small
  300. | #{translate("newsletter_info_and_unsubscribe")}
  301. a(
  302. href,
  303. ng-click="unsubscribe()",
  304. ng-show="subscribed && !unsubscribing"
  305. ) #{translate("unsubscribe")}
  306. span(
  307. ng-show="unsubscribing"
  308. )
  309. i.fa.fa-spin.fa-refresh
  310. | #{translate("unsubscribing")}
  311. span.text-success(
  312. ng-show="!subscribed"
  313. )
  314. i.fa.fa-check
  315. | #{translate("unsubscribed")}
  316. p #{translate("need_to_leave")}
  317. a(href, ng-click="deleteAccount()") #{translate("delete_your_account")}
  318. script(type='text/ng-template', id='deleteAccountModalTemplate')
  319. .modal-header
  320. h3 #{translate("delete_account")}
  321. div.modal-body#delete-account-modal
  322. p !{translate("delete_account_warning_message_3")}
  323. form(novalidate, name="deleteAccountForm")
  324. label #{translate('email')}
  325. input.form-control(
  326. type="text",
  327. autocomplete="off",
  328. placeholder="",
  329. ng-model="state.deleteText",
  330. focus-on="open",
  331. ng-keyup="checkValidation()"
  332. )
  333. label #{translate('password')}
  334. input.form-control(
  335. type="password",
  336. autocomplete="off",
  337. placeholder="",
  338. ng-model="state.password",
  339. ng-keyup="checkValidation()"
  340. )
  341. div(ng-if="state.error")
  342. div.alert.alert-danger
  343. | #{translate('generic_something_went_wrong')}
  344. div(ng-if="state.invalidCredentials")
  345. div.alert.alert-danger
  346. | #{translate('email_or_password_wrong_try_again')}
  347. .modal-footer
  348. button.btn.btn-default(
  349. ng-click="cancel()"
  350. ) #{translate("cancel")}
  351. button.btn.btn-danger(
  352. ng-disabled="!state.isValid || state.inflight"
  353. ng-click="delete()"
  354. )
  355. span(ng-hide="state.inflight") #{translate("delete")}
  356. span(ng-show="state.inflight") #{translate("deleting")}...
  357. script(type='text/javascript').
  358. window.passwordStrengthOptions = !{JSON.stringify(settings.passwordStrengthOptions || {})}