settings.cljs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. (ns frontend.components.settings
  2. (:require [rum.core :as rum]
  3. [frontend.ui :as ui]
  4. [frontend.handler.notification :as notification]
  5. [frontend.handler.user :as user-handler]
  6. [frontend.handler.ui :as ui-handler]
  7. [frontend.handler.repo :as repo-handler]
  8. [frontend.handler.config :as config-handler]
  9. [frontend.state :as state]
  10. [frontend.util :as util]
  11. [frontend.config :as config]
  12. [frontend.dicts :as dicts]
  13. [clojure.string :as string]
  14. [goog.object :as gobj]
  15. [frontend.context.i18n :as i18n]))
  16. (rum/defcs set-email < (rum/local "" ::email)
  17. [state]
  18. (let [email (get state ::email)]
  19. [:div.p-8.flex.items-center.justify-center
  20. [:div.w-full.mx-auto
  21. [:div
  22. [:div
  23. [:h1.title.mb-1
  24. "Your email address:"]
  25. [:div.mt-2.mb-4.relative.rounded-md.shadow-sm.max-w-xs
  26. [:input#.form-input.block.w-full.pl-2.sm:text-sm.sm:leading-5
  27. {:autoFocus true
  28. :on-change (fn [e]
  29. (reset! email (util/evalue e)))}]]]]
  30. (ui/button
  31. "Submit"
  32. :on-click
  33. (fn []
  34. (user-handler/set-email! @email)))
  35. [:hr]
  36. [:span.pl-1.opacity-70 "Git commit requires the email address."]]]))
  37. (rum/defcs set-cors < (rum/local "" ::cors)
  38. [state]
  39. (let [cors (get state ::cors)]
  40. [:div.p-8.flex.items-center.justify-center
  41. [:div.w-full.mx-auto
  42. [:div
  43. [:div
  44. [:h1.title.mb-1
  45. "Your cors address:"]
  46. [:div.mt-2.mb-4.relative.rounded-md.shadow-sm.max-w-xs
  47. [:input#.form-input.block.w-full.pl-2.sm:text-sm.sm:leading-5
  48. {:autoFocus true
  49. :on-change (fn [e]
  50. (reset! cors (util/evalue e)))}]]]]
  51. (ui/button
  52. "Submit"
  53. :on-click
  54. (fn []
  55. (user-handler/set-cors! @cors)))
  56. [:hr]
  57. [:span.pl-1.opacity-70 "Git commit requires the cors address."]]]))
  58. (rum/defcs settings < rum/reactive
  59. []
  60. (let [preferred-format (keyword (state/sub [:me :preferred_format]))
  61. preferred-workflow (keyword (state/sub [:me :preferred_workflow]))
  62. preferred-language (state/sub [:preferred-language])
  63. enable-timetracking? (state/enable-timetracking?)
  64. enable-block-time? (state/enable-block-time?)
  65. show-brackets? (state/show-brackets?)
  66. github-token (state/sub [:me :access-token])
  67. cors-proxy (state/sub [:me :cors_proxy])
  68. logged? (state/logged?)
  69. current-repo (state/get-current-repo)
  70. developer-mode? (state/sub [:ui/developer-mode?])
  71. theme (state/sub :ui/theme)
  72. dark? (= "dark" theme)
  73. switch-theme (if dark? "white" "dark")]
  74. (rum/with-context [[t] i18n/*tongue-context*]
  75. [:div#settings
  76. [:h1.title (t :settings)]
  77. [:div.mb-1.sm:grid.sm:grid-cols-3.sm:gap-4.sm:items-start.sm:pt-5.pl-1
  78. [:label.block.text-sm.font-medium.leading-5.sm:mt-px.sm:pt-2.opacity-70
  79. {:for "toggle_theme"}
  80. (t :right-side-bar/switch-theme (string/capitalize switch-theme))]
  81. [:div.flex.flex-row.mt-1.sm:mt-0.sm:col-span-2.pt-2
  82. [:div.max-w-lg.rounded-md.sm:max-w-xs
  83. (ui/toggle dark?
  84. (fn []
  85. (state/set-theme! switch-theme)))]
  86. [:span.ml-4.opacity-50 "t t"]]]
  87. [:div.sm:grid.sm:grid-cols-3.sm:gap-4.sm:items-start.sm:pt-5.pl-1
  88. [:label.block.text-sm.font-medium.leading-5.opacity-70
  89. {:for "show_brackets"}
  90. (t :settings-page/show-brackets)]
  91. [:div.flex.flex-row.mt-1.sm:mt-0.sm:col-span-2
  92. [:div.max-w-lg.rounded-md.sm:max-w-xs
  93. (ui/toggle show-brackets?
  94. config-handler/toggle-ui-show-brackets!)]
  95. [:span.ml-4.opacity-50 "Ctrl-c Ctrl-b"]]]
  96. [:div.mb-6.sm:grid.sm:grid-cols-3.sm:gap-4.sm:items-start.sm:pt-5.pl-1
  97. [:label.block.text-sm.font-medium.leading-5.sm:mt-px.sm:pt-2.opacity-70
  98. {:for "preferred_language"}
  99. (t :language)]
  100. [:div.mt-1.sm:mt-0.sm:col-span-2
  101. [:div.max-w-lg.rounded-md.shadow-sm.sm:max-w-xs
  102. [:select.mt-1.form-select.block.w-full.pl-3.pr-10.py-2.text-base.leading-6.border-gray-300.focus:outline-none.focus:shadow-outline-blue.focus:border-blue-300.sm:text-sm.sm:leading-5
  103. {:on-change (fn [e]
  104. (let [lang (util/evalue e)
  105. lang-val (filter (fn [el] (if (= (:label el) lang) true nil)) dicts/languages)
  106. lang-val (name (:value (first lang-val)))]
  107. (state/set-preferred-language! lang-val)
  108. (ui-handler/re-render-root!)))}
  109. (for [language dicts/languages]
  110. [:option (cond->
  111. {:key (:value language)}
  112. (= (name (:value language)) preferred-language)
  113. (assoc :selected "selected"))
  114. (:label language)])]]]]
  115. [:div.pl-1
  116. ;; config.edn
  117. (when current-repo
  118. [:a {:href (str "/file/" (util/url-encode (str config/app-name "/" config/config-file)))}
  119. (t :settings-page/edit-config-edn)])
  120. [:hr]
  121. [:div.mt-6.sm:mt-5
  122. [:div.sm:grid.sm:grid-cols-3.sm:gap-4.sm:items-start.sm:pt-5
  123. [:label.block.text-sm.font-medium.leading-5.sm:mt-px.sm:pt-2.opacity-70
  124. {:for "preferred_format"}
  125. (t :settings-page/preferred-file-format)]
  126. [:div.mt-1.sm:mt-0.sm:col-span-2
  127. [:div.max-w-lg.rounded-md.shadow-sm.sm:max-w-xs
  128. [:select.mt-1.form-select.block.w-full.pl-3.pr-10.py-2.text-base.leading-6.border-gray-300.focus:outline-none.focus:shadow-outline-blue.focus:border-blue-300.sm:text-sm.sm:leading-5
  129. {:on-change (fn [e]
  130. (let [format (-> (util/evalue e)
  131. (string/lower-case)
  132. keyword)]
  133. (user-handler/set-preferred-format! format)))}
  134. (for [format [:org :markdown]]
  135. [:option (cond->
  136. {:key (name format)}
  137. (= format preferred-format)
  138. (assoc :selected "selected"))
  139. (string/capitalize (name format))])]]]]
  140. [:div.mt-6.sm:grid.sm:grid-cols-3.sm:gap-4.sm:items-start.sm:pt-5
  141. [:label.block.text-sm.font-medium.leading-5.sm:mt-px.sm:pt-2.opacity-70
  142. {:for "preferred_workflow"}
  143. (t :settings-page/preferred-workflow)]
  144. [:div.mt-1.sm:mt-0.sm:col-span-2
  145. [:div.max-w-lg.rounded-md.shadow-sm.sm:max-w-xs
  146. [:select.mt-1.form-select.block.w-full.pl-3.pr-10.py-2.text-base.leading-6.border-gray-300.focus:outline-none.focus:shadow-outline-blue.focus:border-blue-300.sm:text-sm.sm:leading-5
  147. {:on-change (fn [e]
  148. (let [workflow (-> (util/evalue e)
  149. (string/lower-case)
  150. keyword)
  151. workflow (if (= workflow :now/later)
  152. :now
  153. :todo)]
  154. (user-handler/set-preferred-workflow! workflow)))}
  155. (for [workflow [:now :todo]]
  156. [:option (cond->
  157. {:key (name workflow)}
  158. (= workflow preferred-workflow)
  159. (assoc :selected "selected"))
  160. (if (= workflow :now)
  161. "NOW/LATER"
  162. "TODO/DOING")])]]]]
  163. [:div.mt-6.sm:grid.sm:grid-cols-3.sm:gap-4.sm:items-start.sm:pt-5
  164. [:label.block.text-sm.font-medium.leading-5.opacity-70
  165. {:for "enable_timetracking"}
  166. (t :settings-page/enable-timetracking)]
  167. [:div.mt-1.sm:mt-0.sm:col-span-2
  168. [:div.max-w-lg.rounded-md.sm:max-w-xs
  169. (ui/toggle enable-timetracking?
  170. (fn []
  171. (let [value (not enable-timetracking?)]
  172. (config-handler/set-config! :feature/enable-timetracking? value))))]]]
  173. [:div.mt-6.sm:grid.sm:grid-cols-3.sm:gap-4.sm:items-start.sm:pt-5
  174. [:label.block.text-sm.font-medium.leading-5.opacity-70
  175. {:for "enable_block_time"}
  176. (t :settings-page/enable-block-time)]
  177. [:div.mt-1.sm:mt-0.sm:col-span-2
  178. [:div.max-w-lg.rounded-md.sm:max-w-xs
  179. (ui/toggle enable-block-time?
  180. (fn []
  181. (let [value (not enable-block-time?)]
  182. (config-handler/set-config! :feature/enable-block-time? value))))]]]
  183. [:hr]
  184. (when logged?
  185. [:div
  186. (ui/admonition
  187. :important
  188. [:p (t :settings-page/dont-use-other-peoples-proxy-servers)
  189. [:a {:href "https://github.com/isomorphic-git/cors-proxy"
  190. :target "_blank"}
  191. "https://github.com/isomorphic-git/cors-proxy"]])
  192. [:div.mt-6.sm:mt-5.sm:grid.sm:grid-cols-3.sm:gap-4.sm:items-start.sm:pt-5
  193. [:label.block.text-sm.font-medium.leading-5.sm:mt-px.sm:pt-2.opacity-70
  194. {:for "cors"}
  195. (t :settings-page/custom-cors-proxy-server)]
  196. [:div.mt-1.sm:mt-0.sm:col-span-2
  197. [:div.max-w-lg.rounded-md.shadow-sm.sm:max-w-xs
  198. [:input#pat.form-input.block.w-full.transition.duration-150.ease-in-out.sm:text-sm.sm:leading-5
  199. {:default-value cors-proxy
  200. :on-blur (fn [event]
  201. (when-let [server (util/evalue event)]
  202. (user-handler/set-cors! server)
  203. (notification/show! "Custom CORS proxy updated successfully!" :success)))
  204. :on-key-press (fn [event]
  205. (let [k (gobj/get event "key")]
  206. (if (= "Enter" k)
  207. (when-let [server (util/evalue event)]
  208. (user-handler/set-cors! server)
  209. (notification/show! "Custom CORS proxy updated successfully!" :success)))))}]]]]
  210. [:hr]])
  211. [:div.sm:grid.sm:grid-cols-3.sm:gap-4.sm:items-start.sm:pt-5
  212. [:label.block.text-sm.font-medium.leading-5.sm:mt-px.sm:pt-2.opacity-70
  213. {:for "developer_mode"}
  214. (t :settings-page/developer-mode)]
  215. [:div.mt-1.sm:mt-0.sm:col-span-2
  216. [:div.max-w-lg.rounded-md.shadow-sm.sm:max-w-xs
  217. (ui/button (if developer-mode? (t :settings-page/disable-developer-mode) (t :settings-page/enable-developer-mode))
  218. :on-click #(state/set-developer-mode! (not developer-mode?)))]]]
  219. [:br]
  220. (t :settings-page/developer-mode-desc)]]])))