Skip to content

Commit

Permalink
manage tags (board-admin)
Browse files Browse the repository at this point in the history
  • Loading branch information
mhuebert committed Jan 9, 2024
1 parent 0519311 commit 49cad81
Show file tree
Hide file tree
Showing 10 changed files with 166 additions and 44 deletions.
2 changes: 2 additions & 0 deletions src/sb/app.cljc
Expand Up @@ -57,6 +57,8 @@
:entity/video {:view field.ui/video-field}
:entity/fields {:view field.admin-ui/fields-editor
:make-field field.admin-ui/make-field:fields}
:entity/member-tags {:view field.admin-ui/tags-editor
:make-field field.admin-ui/make-field:tags}
:entity/field-entries {:view field.ui/entries-field
:make-field field.ui/make-field:entries}
:asset/as-map {:view field.ui/image-field}})
4 changes: 4 additions & 0 deletions src/sb/app/board/admin_ui.cljc
Expand Up @@ -24,6 +24,9 @@
[:<>
(header/entity board nil)

#_[:div {:class "max-w-[600px] mx-auto my-6 flex-v gap-6"}
(use-persisted :entity/member-tags)]

[radix/accordion {:class "max-w-[600px] mx-auto my-6 flex-v gap-6"
:multiple true}

Expand All @@ -38,6 +41,7 @@

[:div.field-label (t :tr/projects-and-members)]
[:div.flex-v.gap-4
(use-persisted :entity/member-tags)
(use-persisted :entity/member-fields)
(use-persisted :entity/project-fields)]

Expand Down
6 changes: 3 additions & 3 deletions src/sb/app/board/data.cljc
Expand Up @@ -30,7 +30,6 @@
:board/max-projects-per-member {s- :int}
:board/sticky-color {:doc "Deprecate - sticky notes can pick their own colors"
s- :html/color}
:board/member-tags {s- [:sequential :tag/as-map]}
:board/invite-email-text {:hint "Text of email sent when inviting a user to a board."
s- :string},
:board/registration-newsletter-field? {:hint "During registration, request permission to send the user an email newsletter"
Expand Down Expand Up @@ -80,7 +79,7 @@
(? :board/max-members-per-project)
(? :board/max-projects-per-member)
(? :entity/member-fields)
(? :board/member-tags)
(? :entity/member-tags)
(? :board/new-projects-require-approval?)
(? :entity/project-fields)
(? :board/project-sharing-buttons)
Expand Down Expand Up @@ -127,7 +126,7 @@
:account/display-name]}
{:member/tags [:entity/id
:tag/label
:tag/background-color]}
:tag/color]}
:entity/field-entries
{:member/entity [:entity/id]}
{:member/custom-tags [:tag/label]}
Expand Down Expand Up @@ -187,6 +186,7 @@
[{:keys [board-id member/roles]}]
(some->
(q/pull `[~@entity.data/entity-keys
:entity/member-tags
{:entity/member-fields ~field.data/field-keys}
{:entity/project-fields ~field.data/field-keys}] board-id)
(merge {:member/roles roles})))
Expand Down
23 changes: 12 additions & 11 deletions src/sb/app/entity/data.cljc
Expand Up @@ -9,17 +9,17 @@

(sch/register!
(merge
{:tag/id unique-uuid
:tag/background-color {s- :html/color},
:tag/label {s- :string},,
:tag/restricted? {:doc "Tag may only be modified by an admin of the owner of this tag"
s- :boolean}
:tag/as-map {:doc "Description of a tag which may be applied to an entity."
s- [:map {:closed true}
:tag/id
:tag/label
(? :tag/background-color)
(? :tag/restricted?)]}}
{:tag/id unique-uuid
:tag/color {s- :html/color},
:tag/label {s- :string},,
:tag/restricted? {:doc "Tag may only be modified by an admin of the owner of this tag"
s- :boolean}
:tag/as-map {:doc "Description of a tag which may be applied to an entity."
s- [:map {:closed true}
:tag/id
:tag/label
(? :tag/color)
(? :tag/restricted?)]}}

{:entity/id unique-uuid
:entity/title {:doc "Title of entity, for card/header display."
Expand Down Expand Up @@ -48,6 +48,7 @@
:chat.message]}
:entity/project-fields {s- :entity/fields}
:entity/member-fields {s- :entity/fields}
:entity/member-tags {s- [:sequential :tag/as-map]}
:entity/draft? {:doc "Entity is not yet published - visible only to creator/team"
s- :boolean}
:entity/description {:doc "Description of an entity (for card/header display)"
Expand Down
127 changes: 117 additions & 10 deletions src/sb/app/field/admin_ui.cljc
@@ -1,13 +1,12 @@
(ns sb.app.field.admin-ui
(:require [applied-science.js-interop :as j]
(:require #?(:cljs ["@radix-ui/react-popover" :as Pop])
[clojure.string :as str]
[inside-out.forms :as io]
[promesa.core :as p]
[re-db.reactive :as r]
[sb.app.entity.ui :as entity.ui :refer [view-field]]
[sb.app.entity.data :as entity.data]
[sb.app.field.ui :as field.ui]
[sb.app.entity.ui :refer [view-field]]
[sb.app.field.data :as data]
[sb.app.field.ui :as field.ui]
[sb.app.form.ui :as form.ui]
[sb.app.views.radix :as radix]
[sb.app.views.ui :as ui]
Expand Down Expand Up @@ -68,7 +67,7 @@
(p/let [result (entity.data/maybe-save-field ?options)]
(reset! ?new (:init ?new))
result)))}
[field.ui/text-field ?new {:placeholder "Option label"
[field.ui/text-field ?new {:placeholder "Option label"
:field/classes {:wrapper "flex-auto"}}]
[:div.btn.bg-white.px-3.py-1.shadow "Add Option"]])
#_[ui/pprinted @?options]]))
Expand Down Expand Up @@ -200,13 +199,121 @@
(reset! !new-field nil)
(entity.data/maybe-save-field ?fields)))}
[:div.h-10.flex.items-center [(:icon (data/field-types @?type)) "icon-lg text-gray-700 mx-2"]]
[field.ui/text-field ?label {:field/label false
:ref !autofocus-ref
:placeholder (:field/label ?label)
:field/classes {:wrapper "flex-auto"}}]
[field.ui/text-field ?label {:field/label false
:ref !autofocus-ref
:placeholder (:field/label ?label)
:field/classes {:wrapper "flex-auto"}}]
[:button.btn.btn-white.h-10 {:type "submit"}
(t :tr/add)]
[:div.flex.items-center.justify-center.icon-light-gray.h-10.w-7
{:on-mouse-down #(reset! !new-field nil)}
[icons/close "w-4 h-4 "]]]
[:div.pl-12.py-2 (form.ui/show-field-messages ?new-field)]])]))
[:div.pl-12.py-2 (form.ui/show-field-messages ?new-field)]])]))

(defn make-field:tags [init props]
(io/field :many (u/prune {:tag/id ?id
:tag/label ?label
:tag/color ?color
:tag/restricted? ?restricted?})
:init init))

(ui/defview tag-form [{:keys [?state
init
on-submit
close!]}]
(let [!ref (h/use-ref)
{:as ?tag :syms [?label ?color ?restricted?]} (h/use-memo #(io/form (u/prune {:tag/id ?id
:tag/label ?label
:tag/color (?color :init "#dddddd")
:tag/restricted? (?restricted? :field/label (t :tr/restricted))})
:required [?label]
:init init)
(h/use-deps init))
submit! #(on-submit ?tag close!)]
[:el.relative Pop/Root {:open true :on-open-change #(close!)}
[:el Pop/Anchor]
[:el Pop/Content {:as-child true}
[:div.p-2.z-10 {:class radix/float-small}
[:form.outline-none.flex-v.gap-2.items-stretch
{:ref !ref
:on-submit (fn [e]
(.preventDefault e)
(submit!))}
[:div.flex.gap-2
[field.ui/text-field ?label {:placeholder (t :tr/label)
:field/keybindings {:Enter submit!}
:field/multi-line? false
:field/can-edit? true
:field/label false}]

[:div.relative.w-10.h-10.overflow-hidden.rounded.outline.outline-black.outline-1 [field.ui/color-field ?color {:field/can-edit? true}]]
[:button.flex.items-center {:type "submit"} [icons/checkmark "w-5 h-5 icon-gray"]]]
[field.ui/checkbox-field ?restricted? {:field/can-edit? true
:field/classes {:wrapper "pl-3"}}]]
(form.ui/show-field-messages ?state)]]]))

(ui/defview show-tag
{:key (fn [_ ?tag] #?(:cljs (goog/getUid ?tag)))}
[{:keys [?tags
!editing
use-order]} ?tag]
(let [{:syms [?label ?color]} ?tag
bg (or (u/some-str @?color) "#dddddd")
color (color/contrasting-text-color bg)
tag (v/x [:div.rounded.bg-badge.text-badge-txt.py-1.px-2.text-sm.inline-flex
{:key @?label
:style {:background-color bg :color color}} @?label])
{:keys [drag-handle-props
drag-subject-props
dragging
dropping]} (use-order ?tag)]
[radix/context-menu {:trigger [:div.transition-all
(v/merge-props drag-handle-props
drag-subject-props
{:class (cond (= dropping :before) "pl-2"
dragging "opacity-20")})
tag
(when (= ?tag @!editing)
[tag-form {:close! #(reset! !editing nil)
:?state ?tags
:init @?tag
:on-submit (fn [?new-tag close!]
(reset! ?tag @?new-tag)
(p/let [res (entity.data/maybe-save-field ?tag)]
(when-not (:error res)
(reset! ?tag @?new-tag)
(close!))))}])]
:items [[radix/context-menu-item
{:on-select (fn []
(io/remove-many! ?tag)
(entity.data/maybe-save-field ?tags))}
(t :tr/remove)]
[radix/context-menu-item
{:on-select (fn [] (p/do (p/delay 0) (reset! !editing ?tag)))}
(t :tr/edit)]]}]))

(ui/defview tags-editor [?tags _]
(let [!editing (h/use-state nil)
use-order (ui/use-orderable-parent ?tags {:axis :x})]
[:div.field-wrapper
(form.ui/show-label ?tags)
[:div.flex.gap-1
(map (partial show-tag {:?tags ?tags
:!editing !editing
:use-order use-order}) ?tags)
(let [!creating-new (h/use-state false)]
[:div.inline-flex.text-sm.gap-1.items-center.rounded.hover:bg-gray-100.p-1
{:on-click #(reset! !creating-new true)}
[:span.cursor-default (t :tr/add-tag)]
[icons/plus "w-4 h-4 icon-gray"]
(when @!creating-new
[tag-form {:?state ?tags
:on-submit (fn [?tag close!]
(io/add-many! ?tags (assoc @?tag :tag/id (random-uuid)))
(p/let [res (entity.data/maybe-save-field ?tags)]
(when-not (:error res)
(io/clear! ?tag)
(close!))
res))
:init {:badge/color "#dddddd"}
:close! #(reset! !creating-new false)}])])]]))
26 changes: 14 additions & 12 deletions src/sb/app/field/ui.cljc
Expand Up @@ -66,6 +66,7 @@
[?field props]
(let [messages (forms/visible-messages ?field)
loading? (:loading? ?field)
{:keys [field/classes]} props
props (-> (v/merge-props (form.ui/?field-props ?field
(merge {:field/event->value (comp boolean (j/get-in [:target :checked]))}
props))
Expand All @@ -83,6 +84,7 @@
(update :checked boolean))
]
[:div.flex.flex-col.gap-1.relative

[:label.relative.flex.items-center
(when loading?
[:div.h-5.w-5.inline-flex.items-center.justify-center.absolute
Expand Down Expand Up @@ -296,19 +298,18 @@
(update :value #(or % "#ffffff"))
(form.ui/pass-props))])

(ui/defview badge-form [{:keys [init
(ui/defview badge-form [{:keys [?state
init
on-submit
close!]}]
;; TODO
;; - color picker should show colors already used in the board?
(let [!ref (h/use-ref)
{:as ?badge :syms [?label ?color]} (h/use-memo #(io/form {:badge/label ?label
:badge/color (?color :init "#dddddd")}
:required [?label ?color]
:init init)
(h/use-deps init))
submit! #(on-submit ?badge close!)]
[:el.relative Pop/Root {:open true :on-open-change #(do (prn :on-open-change %) (close!))}
[:el.relative Pop/Root {:open true :on-open-change #(close!)}
[:el Pop/Anchor]
[:el Pop/Content {:as-child true}
[:div.p-2.z-10 {:class radix/float-small}
Expand All @@ -324,7 +325,7 @@
:field/label false}]
[:div.relative.w-10.h-10.overflow-hidden.rounded.outline.outline-black.outline-1 [color-field ?color {:field/can-edit? true}]]
[:button.flex.items-center {:type "submit"} [icons/checkmark "w-5 h-5 icon-gray"]]]
(form.ui/show-field-messages (or (io/parent ?badge) ?badge))]]]))
(form.ui/show-field-messages ?state)]]]))

(ui/defview badges-field* [?badges {:keys [member/roles]}]
(let [board-admin? (:role/board-admin roles)
Expand All @@ -341,8 +342,8 @@
[radix/context-menu {:trigger [:div
badge
(when (= ?badge @!editing)
[badge-form {:?badge ?badge
:close! #(reset! !editing nil)
[badge-form {:close! #(reset! !editing nil)
:?state ?badges
:init @?badge
:on-submit (fn [?new-badge close!]
(reset! ?badge @?new-badge)
Expand All @@ -367,10 +368,11 @@
(when @!creating-new
[badge-form {:on-submit (fn [?badge close!]
(io/add-many! ?badges @?badge)
(io/clear! ?badge)
(p/let [res (entity.data/maybe-save-field ?badges)]
(when-not (:error res)
(io/clear! ?badge)
(close!))))
:?state ?badges
:init {:badge/color "#dddddd"}
:close! #(reset! !creating-new false)}])]))]))

Expand Down Expand Up @@ -556,17 +558,17 @@
(defn show-select:card [{:keys [field/options]} {:keys [select/value]}]
(let [{:keys [field-option/label
field-option/color]
:or {color "#dddddd"}} (u/find-first options #(= value (:field-option/value %)))]
:or {color "#dddddd"}} (u/find-first options #(= value (:field-option/value %)))]
[:div {:class radix/select-trigger-classes
:style {:background-color color
:color (color/contrasting-text-color color)}}
:color (color/contrasting-text-color color)}}
label]))

(defn show-image-list:card [{:keys [image-list/images]}]
(when-let [{:keys [entity/id]} (first images)]
[:img.max-h-80 {:src (asset.ui/asset-src id :card)}]))

(defn show-prose:card [field {:as m :prose/keys [format string]}]
(ui/defview show-prose:card [field {:as m :prose/keys [format string]}]
(when-not (str/blank? string)
(let [string (u/truncate-string string 140)]
(case format
Expand All @@ -591,7 +593,7 @@
:field.type/video [show-video-url (:video/url entry)]
:field.type/select [show-select:card field entry]
:field.type/link-list [show-link-list:card field entry]
:field.type/image-list [show-image-list:card field entry ]
:field.type/image-list [show-image-list:card field entry]
:field.type/prose [show-prose:card field entry]
(str "no match" field)))

Expand Down
10 changes: 5 additions & 5 deletions src/sb/app/member/ui.cljc
Expand Up @@ -25,16 +25,16 @@
(when-let [tags (seq (concat tags custom-tags))]
[:section [:h3 (t :tr/tags)]
(into [:ul]
(map (fn [{:tag/keys [label background-color]}]
[:li {:style (when background-color {:background-color background-color})} label]))
(map (fn [{:tag/keys [label color]}]
[:li {:style (when color {:background-color color})} label]))
tags)])
(when avatar [:img {:src (asset.ui/asset-src avatar :card)}])]))

(defn show-tag [{:keys [tag/label tag/background-color] :or {background-color "#dddddd"}}]
(defn show-tag [{:keys [tag/label tag/color] :or {color "#dddddd"}}]
[:div.tag-sm
{:key label
:style {:background-color background-color
:color (color/contrasting-text-color background-color)}}
:style {:background-color color
:color (color/contrasting-text-color color)}}
label])

(ui/defview card
Expand Down
2 changes: 1 addition & 1 deletion src/sb/app/views/radix.cljc
Expand Up @@ -230,7 +230,7 @@
(v/defview context-menu [{:keys [trigger
items]}]
[:el ContextMenu/Root
[:el.cursor-context-menu.select-none ContextMenu/Trigger {:as-child true} (v/x trigger)]
[:el.cursor-context-menu ContextMenu/Trigger {:as-child true} (v/x trigger)]
[:el ContextMenu/Content {:style {:z-index 20}
:class [float-small
"p-1 min-w-32"]}
Expand Down

0 comments on commit 49cad81

Please sign in to comment.