|
4 | 4 | [malli.core :as m]
|
5 | 5 | [malli.error :as me]
|
6 | 6 | [ajax.core :refer [GET POST]]
|
7 |
| - [reitit-db-fun.validations :as v])) |
| 7 | + [reitit-db-fun.validations :as v] |
8 | 8 |
|
9 |
| -(defonce app-state (atom {:articles [{:title "Tytul artykulu" |
10 |
| - :body "Ciekawa tresc artykulu" |
11 |
| - :author-id 1}]})) |
| 9 | + [reitit-db-fun.db :refer [conn]] |
| 10 | + [datascript.core :as ds])) |
| 11 | + |
| 12 | +(defn entities-for-attr [db attribute] |
| 13 | + (->> (ds/datoms db :aevt attribute) |
| 14 | + (map :e) |
| 15 | + (ds/pull-many db [:*]))) |
| 16 | + |
| 17 | + |
| 18 | +(defn all-articles [db] |
| 19 | + (->> (ds/datoms db :aevt :article/title) |
| 20 | + (map :e) |
| 21 | + (ds/pull-many db [:*]))) |
12 | 22 |
|
13 | 23 |
|
14 | 24 | (rum/defc title < rum/static
|
15 | 25 | [text]
|
16 |
| - [:h1 text]) |
| 26 | + [:h1.title text]) |
17 | 27 |
|
18 | 28 | (rum/defc input < rum/static
|
19 |
| - [{:keys [type name label message value on-change read-only] |
| 29 | + [{:keys [type name label message value on-change read-only options] |
20 | 30 | :or {read-only false}}]
|
21 | 31 | (let [inputs
|
22 | 32 | {:text
|
|
40 | 50 | :value value
|
41 | 51 | :on-change on-change
|
42 | 52 | :read-only read-only}]]
|
| 53 | + [:p.help.is-danger message]] |
| 54 | + |
| 55 | + :select |
| 56 | + [:.field |
| 57 | + [:label.label label] |
| 58 | + [:.control |
| 59 | + [:.select {:name name |
| 60 | + :read-only read-only |
| 61 | + :on-change on-change} |
| 62 | + (into [:select] |
| 63 | + (for [[value text] options] [:option {:value value} text]))]] |
43 | 64 | [:p.help.is-danger message]]}]
|
44 | 65 | (get inputs type)))
|
45 | 66 |
|
46 |
| -(rum/defc articles < rum/static |
47 |
| - [articles] |
| 67 | +(rum/defc articles |
| 68 | + [db] |
48 | 69 | (into [:div]
|
49 |
| - (for [article articles] |
| 70 | + (for [article (all-articles db)] |
50 | 71 | [:<>
|
51 |
| - (input {:type :text :value (:title article) :read-only true}) |
52 |
| - (input {:type :text-area :value (:body article) :read-only true})]))) |
53 |
| - |
54 |
| - |
55 |
| -(defn save-article! [article] |
56 |
| - (swap! app-state update :articles conj article)) |
57 |
| - |
| 72 | + (input {:type :text :value (:article/title article) :read-only true}) |
| 73 | + (input {:type :text-area :value (:article/body article) :read-only true}) |
| 74 | + (input {:type :text :value (->> (:article/author-id article) |
| 75 | + (ds/datoms db :eavt) |
| 76 | + first |
| 77 | + :v) :read-only true})]))) |
| 78 | + |
| 79 | +(defn save-article! |
| 80 | + "TODO na razie zapisuje lokalnie w bazie. Docelowo w backendzie." |
| 81 | + [article] |
| 82 | + (println "saving:" article) |
| 83 | + (ds/transact! conn [(merge article {:db/id -1})])) |
58 | 84 |
|
59 | 85 | ;; dodać lokalny stan z {} i walidować
|
60 | 86 | (rum/defcs article-form < (rum/local
|
61 |
| - {:form-data {:title "" :body ""} |
| 87 | + {:form-data {:article/title "" |
| 88 | + :article/body "" |
| 89 | + :article/author-id nil} |
62 | 90 | :messages {}}
|
63 | 91 | ::article-form)
|
64 |
| - [state] |
65 |
| - (let [local-state (::article-form state) |
66 |
| - {:keys [form-data messages]} @local-state |
67 |
| - {:keys [title body]} form-data] |
| 92 | + [state authors] |
| 93 | + (let [#_ "TODO dodać reaktywną listę autorów.. hmmm" |
| 94 | + #_ " w sumie to bez sensu trochÄ™...." |
| 95 | + |
| 96 | + local-state (::article-form state) |
| 97 | + {:keys [form-data messages]} @local-state] |
68 | 98 | [:div
|
69 |
| - (input {:name :title :type :text :label "Tytuł" :value title |
70 |
| - :message (get messages :title "") |
| 99 | + (input {:name :title :type :text :label "Tytuł" :value (:article/title form-data) |
| 100 | + :message (get messages :article/title "") |
71 | 101 | :on-change (fn [e]
|
72 |
| - (swap! local-state assoc-in [:form-data :title] |
| 102 | + (swap! local-state assoc-in [:form-data :article/title] |
73 | 103 | (-> e .-target .-value)))})
|
74 |
| - (input {:name :body :type :text-area :label "Treść" :value body |
75 |
| - :message (get messages :body "") |
| 104 | + (input {:name :body :type :text-area :label "Treść" :value (:article/body form-data) |
| 105 | + :message (get messages :article/body "") |
76 | 106 | :on-change (fn [e]
|
77 |
| - (swap! local-state assoc-in [:form-data :body] |
| 107 | + (swap! local-state assoc-in [:form-data :article/body] |
78 | 108 | (-> e .-target .-value)))})
|
| 109 | + (input {:name :author-id :type :select :label "Autor" :options authors |
| 110 | + :message (get messages :article/author-id "") |
| 111 | + :on-change (fn [e] |
| 112 | + (swap! local-state assoc-in [:form-data :article/author-id] |
| 113 | + (-> e .-target .-value js/parseInt)))}) |
79 | 114 | [:button.button.is-primary
|
80 | 115 | {:on-click
|
81 | 116 | (fn [_]
|
82 |
| - (if (m/validate v/Article {:title title :body body}) |
| 117 | + (if (m/validate v/Article form-data) |
83 | 118 | (do
|
84 | 119 | (swap! local-state assoc :messages {})
|
85 |
| - (save-article! {:title title :body body}) |
86 |
| - (prn "call to backend" {:title title :body body})) |
| 120 | + (save-article! form-data)) |
87 | 121 | (let [errors (-> v/Article
|
88 |
| - (m/explain {:title title :body body}) |
| 122 | + (m/explain form-data) |
89 | 123 | (me/humanize))]
|
| 124 | + (js/console.log (pr-str errors)) |
90 | 125 | (swap! local-state assoc :messages {})
|
91 | 126 | (doseq [[k v] errors]
|
92 | 127 | (swap! local-state assoc-in [:messages k] v)))))}
|
93 | 128 | "Zapisz"]]))
|
94 | 129 |
|
95 |
| -(rum/defc app [] |
96 |
| - [:.container |
97 |
| - (title "Artukuły") |
98 |
| - (articles (:articles @app-state)) |
99 |
| - (article-form)]) |
| 130 | +(rum/defc app < rum/reactive |
| 131 | + [conn] |
| 132 | + (let [db (rum/react conn)] |
| 133 | + [:.container |
| 134 | + (article-form (mapv (juxt :db/id :author/name) (entities-for-attr db :author/name))) |
| 135 | + (title "Artukuły") |
| 136 | + (articles db) |
| 137 | + ])) |
100 | 138 |
|
101 | 139 |
|
102 | 140 | (defn ^:dev/after-load init []
|
103 |
| - (rum/mount (app) (js/document.getElementById "app"))) |
| 141 | + (rum/mount (app conn) (js/document.getElementById "app"))) |
104 | 142 |
|
105 | 143 | (comment
|
106 | 144 |
|
|
112 | 150 | (assoc ::m/missing-key
|
113 | 151 | {:error/message "Pole wymagane"}))}))
|
114 | 152 |
|
| 153 | + (save-article! {:article/title "title2" :article/body "body2" |
| 154 | + :article/author-id "test"}) |
| 155 | + |
| 156 | + (all-articles @conn) |
| 157 | + (entities-for-attr @conn :article/title) |
| 158 | + (entities-for-attr @conn :author/name) |
| 159 | + |
115 | 160 |
|
| 161 | + (mapv (juxt :db/id :author/name) (entities-for-attr @conn :author/name)) |
| 162 | + (ds/db conn) |
116 | 163 | )
|
0 commit comments