profile.html 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <pstm-uri>/profile</pstm-uri>
  5. <pstm-template>main</pstm-template>
  6. <script>
  7. // The Notifications card (goal 41 task 3): the push-bell
  8. // preference UI moved here from the dashboard's full-width opener
  9. // card. The per-browser engine is shared with the dashboard's
  10. // compact rail strip (window.initPushBell in app.js); it reads
  11. // THIS page's slot (stateType: 'profile'), which carries the same
  12. // VAPID key, endpoint fingerprints and push actions the dashboard
  13. // exposes - the server actions are the existing DTOs, untouched.
  14. if (window.statum && window.initPushBell) {
  15. window.initPushBell({ stateType: 'profile' });
  16. }
  17. </script>
  18. </head>
  19. <body>
  20. <section class="stack">
  21. <h2>Your profile</h2>
  22. <div stm-if="profile == null" class="page-loading" role="status" aria-label="Loading"><span class="spinner spinner-lg"></span></div>
  23. <div stm-if="profile != null" class="stack">
  24. <div class="card">
  25. <h3 stm-text="profile.name_display">name</h3>
  26. <p><span stm-attribute.class="profile.is_admin ? 'badge badge-admin' : 'badge'"
  27. stm-text="profile.is_admin ? 'admin' : 'user'">role</span></p>
  28. <p class="text-muted">Username: <strong stm-text="profile.username">username</strong></p>
  29. <p class="text-muted">Email: <span stm-text="profile.email">email</span></p>
  30. <p class="text-muted">Member since <span stm-text="profile.created_display">when</span></p>
  31. </div>
  32. <div class="card">
  33. <h3>Appearance</h3>
  34. <form stm-action="profile.set_theme" stm-busy-class="is-busy" class="stack">
  35. <div class="field">
  36. <label>Theme</label>
  37. <div class="choices">
  38. <label class="choice"><input type="radio" name="theme" value=""
  39. stm-attribute.checked="profile.theme == '' || profile.theme == 'core'">
  40. Spry (default)</label>
  41. <label class="choice"><input type="radio" name="theme" value="airy"
  42. stm-attribute.checked="profile.theme == 'airy'">
  43. Airy</label>
  44. <label class="choice"><input type="radio" name="theme" value="dwarf"
  45. stm-attribute.checked="profile.theme == 'dwarf'">
  46. Dwarf</label>
  47. <label class="choice"><input type="radio" name="theme" value="formal"
  48. stm-attribute.checked="profile.theme == 'formal'">
  49. Formal</label>
  50. <label class="choice"><input type="radio" name="theme" value="glassy"
  51. stm-attribute.checked="profile.theme == 'glassy'">
  52. Glassy</label>
  53. <label class="choice"><input type="radio" name="theme" value="h2o"
  54. stm-attribute.checked="profile.theme == 'h2o'">
  55. H2O</label>
  56. <label class="choice"><input type="radio" name="theme" value="living-sky"
  57. stm-attribute.checked="profile.theme == 'living-sky'">
  58. Living Sky</label>
  59. <label class="choice"><input type="radio" name="theme" value="modern"
  60. stm-attribute.checked="profile.theme == 'modern'">
  61. Modern</label>
  62. </div>
  63. <p class="hint">The theme repaints the whole interface. Your choice is
  64. remembered for this account on this device and applies immediately.</p>
  65. </div>
  66. <div class="field">
  67. <label>Colour mode</label>
  68. <div class="choices">
  69. <label class="choice"><input type="radio" name="mode" value="auto"
  70. stm-attribute.checked="profile.mode == 'auto'">
  71. Auto (follow system)</label>
  72. <label class="choice"><input type="radio" name="mode" value="light"
  73. stm-attribute.checked="profile.mode == 'light'">
  74. Light</label>
  75. <label class="choice"><input type="radio" name="mode" value="dark"
  76. stm-attribute.checked="profile.mode == 'dark'">
  77. Dark</label>
  78. </div>
  79. <p class="hint">Auto follows your device's light/dark preference.</p>
  80. </div>
  81. <div><button type="submit" class="btn-primary">Save appearance</button></div>
  82. </form>
  83. </div>
  84. <div class="card push-bell-card">
  85. <h3>Notifications</h3>
  86. <p class="text-muted">Be told when an agent asks a question, raises an RFC or
  87. review. The preference is per browser: each one you enable receives the
  88. alerts; per-task "Notify me" adds that task's start, failure and
  89. completion.</p>
  90. <form class="stack">
  91. <button type="button" data-push-bell data-bell-on
  92. hidden>Enable notifications</button>
  93. <button type="button" data-push-bell data-bell-off
  94. hidden>Turn off notifications</button>
  95. <button type="button" data-push-test
  96. hidden>Send test notification</button>
  97. <p class="hint" data-bell-help>— be told when an agent asks a question,
  98. raises an RFC or review</p>
  99. </form>
  100. </div>
  101. <div class="card">
  102. <h3>Change password</h3>
  103. <form stm-action="profile.change_password" stm-busy-class="is-busy" class="stack">
  104. <div class="field"><label for="current-password">Current password</label>
  105. <input id="current-password" type="password" name="current_password"
  106. required autocomplete="current-password"></div>
  107. <div class="field"><label for="new-password">New password</label>
  108. <input id="new-password" type="password" name="new_password"
  109. required autocomplete="new-password"></div>
  110. <div class="field"><label for="confirm-password">Confirm new password</label>
  111. <input id="confirm-password" type="password" name="confirm_password"
  112. required autocomplete="new-password"></div>
  113. <div><button type="submit">Change password</button></div>
  114. </form>
  115. </div>
  116. </div>
  117. </section>
  118. </body>
  119. </html>