-
Notifications
You must be signed in to change notification settings - Fork 2
/
ui.cljc
112 lines (100 loc) · 4.37 KB
/
ui.cljc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
(ns sb.app.entity.ui
(:require [inside-out.forms :as io]
[sb.app.asset.ui :as asset.ui]
[sb.app.entity.data :as data]
[sb.app.views.ui :as ui]
[sb.authorize :as az]
[sb.icons :as icons]
[sb.routing :as routing]
[sb.schema :as sch]
[yawn.hooks :as h]
[yawn.view :as v]))
(defn malli-schema [a]
(some-> (get @sch/!schema a) :malli/schema))
(defn throw-no-persistence! [?field]
(throw (ex-info (str "No persistence for " (:sym ?field)) {:where (->> (iterate io/parent ?field)
(take-while identity)
(map :sym))})))
(def persisted-value data/persisted-value)
(defn get-view [?field props]
(or (:view props)
(:view ?field)
(some-> (:attribute ?field) io/global-meta :view)
(throw (ex-info (str "No view declared for field: " (:sym ?field) (:attribute ?field)) {:sym (:sym ?field)
:attribute (:attribute ?field)}))))
(defn view-field [?field & [props]]
[(get-view ?field props)
?field
(merge (:props ?field)
(dissoc props :view))])
(defn add-meta! [?field m]
(swap! (io/!meta ?field) merge
(when-let [attr (:attribute m)]
(io/global-meta attr))
m)
(when-some [init (:init m)] (reset! ?field init))
?field)
(defn use-persisted-attr [e a & {:as props}]
#?(:cljs
(let [persisted-value (get e a)
view (or (:view props) (-> a io/global-meta :view))
make-field (or (:make-?field (meta view))
(fn [init _props] (io/field :init init)))
?field (h/use-memo #(doto (make-field persisted-value props)
(add-meta! {:attribute a
:db/id (sch/wrap-id e)
:field/label (:field/label props)
:field/persisted? true}))
;; create a new field when the persisted value changes
(h/use-deps persisted-value))]
(view-field ?field (assoc props :view view)))))
#?(:cljs
(defn href [{:as e :entity/keys [kind id]} key]
(when e
(let [tag (keyword (name kind) (name key))]
(routing/path-for [tag {(keyword (str (name kind) "-id")) id}])))))
(ui/defview card:compact
{:key :entity/id}
[{:as entity
:keys [entity/title image/avatar]}]
[:a.flex.relative
{:href (routing/path-for (routing/entity-route entity 'ui/show))
:class ["sm:divide-x sm:shadow sm:hover:shadow-md "
"overflow-hidden rounded-lg"
"h-12 sm:h-16 bg-card text-card-txt border border-white"]}
(when avatar
[:div.flex-none
(v/props
(merge {:class ["w-12 sm:w-16"
"bg-no-repeat sm:bg-secondary bg-center bg-contain"]}
(when avatar
{:style {:background-image (asset.ui/css-url (asset.ui/asset-src avatar :avatar))}})))])
[:div.flex.items-center.px-3.leading-snug
[:div.line-clamp-2 title]]])
(ui/defview settings-button [entity]
(let [roles (az/all-roles nil entity)]
(when-let [path (and (or (:role/admin roles)
(:role/org-admin roles))
(some-> (routing/entity-route entity 'admin-ui/settings)
routing/path-for))]
[:a.button
{:href path}
[icons/gear "icon-lg"]])))
(ui/defview row
{:key :entity/id}
[{:as entity
:keys [entity/title member/roles]}]
[:div.flex.hover:bg-gray-100.rounded-lg
[:a.flex.relative.gap-3.items-center.p-2.cursor-default.flex-auto
{:href (routing/entity-path entity 'ui/show)}
[ui/avatar {:size 10} entity]
[:div.line-clamp-2.leading-snug.flex-grow.flex title]]])
(ui/defview show-filtered-results
{:key :title}
[{:keys [q title results]}]
(when-let [results (seq (sequence (ui/filtered q) results))]
[:div.mt-6 {:key title}
(when title [:div.px-body.font-medium title [:hr.mt-2.sm:hidden]])
(into [:div.card-grid]
(map card:compact)
results)]))