Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/braid/core/api.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@
{:pre [(util/valid? braid.core.client.ui.views.user-header/UserHeaderItem config)]}
(swap! braid.core.client.ui.views.user-header/user-header-menu-items conj config))

(defn register-user-profile-item!
"Add a new section on the user profile page
Expects a map with the following keys
:view reagent component
:priority number, for ordering"
[config]
{:pre [(util/valid? braid.core.client.ui.views.pages.me/profile-item-dataspec config)]}
(swap! braid.core.client.ui.views.pages.me/user-profile-items conj config))

(defn register-thread-header-item!
"Adds a new view to a thread's header.
Expects a map with the following keys:
Expand Down
29 changes: 22 additions & 7 deletions src/braid/core/client/ui/views/pages/me.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,18 @@
[braid.core.client.routes :as routes]
[braid.core.client.ui.views.upload :refer [avatar-upload-view]]
[braid.core.common.util :refer [valid-nickname?]]
[braid.core.hooks :as hooks]
[clojure.string :as string]
[re-frame.core :refer [dispatch subscribe]]
[reagent.core :as r]))

(def profile-item-dataspec
{:priority number?
:view fn?})

(defonce user-profile-items
(hooks/register! (atom []) [profile-item-dataspec]))

(defn nickname-view
[]
(let [format-error (r/atom false)
Expand Down Expand Up @@ -102,10 +110,17 @@
[]
[:div.page.me
[:div.title "Me!"]
[:div.content
[nickname-view]
[avatar-view]
[password-view]
[:p
[:a {:href (routes/system-page-path {:page-id "global-settings"})}
"Go to Global Settings"]]]])
(into
[:div.content]
(conj
(->> @user-profile-items
(sort-by :priority)
reverse
(mapv (fn [el]
[(:view el)])))
[nickname-view]
[avatar-view]
[password-view]
[:p
[:a {:href (routes/system-page-path {:page-id "global-settings"})}
"Go to Global Settings"]]))])
2 changes: 2 additions & 0 deletions src/braid/core/modules.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
[braid.notices.core]
[braid.permalinks.core]
[braid.popovers.core]
[braid.profile.core]
[braid.quests.core]
[braid.rss.core]
[braid.search.core]
Expand Down Expand Up @@ -42,6 +43,7 @@
(braid.notices.core/init!)
(braid.permalinks.core/init!)
(braid.popovers.core/init!)
(braid.profile.core/init!)
(braid.quests.core/init!)
(braid.rss.core/init!)
(braid.stars.core/init!)
Expand Down
103 changes: 103 additions & 0 deletions src/braid/profile/core.cljc
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
(ns braid.profile.core
"Allows users to set and update their profile."
(:require
[braid.core.api :as core]
#?@(:cljs
[[reagent.core :as r]
[re-frame.core :refer [subscribe dispatch]]]

:clj
[[datomic.api :as d]
[braid.core.server.db :as db]])))

(defn profile-view
[]
#?(:cljs
(let [format-error (r/atom false)
error (r/atom nil)
set-format-error! (fn [error?] (reset! format-error error?))
set-error! (fn [err] (reset! error err))
profile (subscribe [:braid.profile/user-profile])
new-profile (r/atom "")]
(fn []
[:div.setting
[:h2 "Update profile"]
[:div.profile
(when @profile
[:div.current-profile
{:style {:white-space "pre-wrap"}}
@profile])
(when @error
[:span.error @error])
[:form {:on-submit (fn [e]
(.preventDefault e)
(set-error! nil)
(dispatch [:braid.profile/set-user-profile! @new-profile]))}
[:textarea.new-profile
{:class (when @format-error "error")
:style {:width "50%"}
:rows 8
:on-change (fn [e]
(->> (.. e -target -value)
(reset! new-profile)))}
@profile]
[:div
[:input {:type "submit" :value "Update"}]]]]]))))

(defn init! []
#?(:cljs
(do
(core/register-state!
{:braid.profile/user-profile ""}
{:braid.profile/user-profile string?})

(core/register-events!
{:braid.profile/set-user-profile!
(fn [{db :db} [_ new-profile]]
(when-not (= (db :braid.profile/user-profile) new-profile)
{:db (assoc db :braid.profile/user-profile new-profile)
:websocket-send [[:braid.profile.ws/set-user-profile! new-profile]]}))})

(core/register-subs!
{:braid.profile/user-profile
(fn [db _]
(:braid.profile/user-profile db))})

(core/register-incoming-socket-message-handlers!
{:braid.profile.ws/set-user-profile!
(fn [_ new-profile]
(dispatch [:braid.profile/set-user-profile! new-profile]))})

(core/register-initial-user-data-handler!
(fn
[db data]
(assoc db :braid.profile/user-profile
(data :braid.profile/user-profile))))

(core/register-user-profile-item!
{:priority 10
:view profile-view}))

:clj
(do
(core/register-db-schema!
[{:db/ident :user/profile
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one}])

(core/register-initial-user-data!
(fn [user-id]
{:braid.profile/user-profile
(d/q '[:find ?user-profile .
:in $ ?user-id
:where
[?u :user/id ?user-id]
[?u :user/profile ?user-profile]]
(db/db)
user-id)}))

(core/register-server-message-handlers!
{:braid.profile.ws/set-user-profile!
(fn [{user-id :user-id new-profile :?data}]
{:db-run-txns! [[:db/add [:user/id user-id] :user/profile new-profile]]
:chsk-send! [user-id [:braid.profile.ws/set-user-profile! new-profile]]})}))))