0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-10 00:58:26 -05:00

Refactor color collections page.

This commit is contained in:
Andrey Antukh 2016-11-05 19:50:58 +01:00
parent 3002d296c8
commit 6379315e4b
No known key found for this signature in database
GPG key ID: 4DFEBCB8316A8B95
4 changed files with 288 additions and 217 deletions

View file

@ -32,43 +32,28 @@
;; --- Initialize
(declare fetch-collections)
(declare persist-collections)
(declare collections-fetched?)
(declare conditional-fetch)
(defrecord Initialize [type id]
rs/UpdateEvent
(-apply-update [_ state]
(let [type (or type :own)
data {:type type :id id :selected #{}}]
data {:type type
:id id
:selected #{}}]
(-> state
(assoc-in [:dashboard :colors] data)
(assoc-in [:dashboard :section] :dashboard/colors))))
rs/WatchEvent
(-apply-watch [_ state s]
(rx/of (conditional-fetch))))
(rx/of (fetch-collections))))
(defn initialize
[type id]
(Initialize. type id))
;; --- Conditional fetch of Color Collections
(defrecord ConditionalFetch []
rs/WatchEvent
(-apply-watch [_ state s]
(if (nil? (:color-colls-by-id state))
(rx/merge
(rx/of (fetch-collections))
(->> (rx/filter collections-fetched? s)
(rx/take 1)
(rx/ignore)))
(rx/empty))))
(defn conditional-fetch
[]
(ConditionalFetch.))
;; --- Select a Collection
(defrecord SelectCollection [type id]
@ -86,85 +71,81 @@
;; --- Collections Fetched
(defrecord CollectionFetched [items]
(defrecord CollectionsFetched [data]
rs/UpdateEvent
(-apply-update [_ state]
(reduce assoc-collection state items)))
(let [value (:value data)]
(-> state
(assoc-in [:kvstore :color-collections] data)
(update :color-colls-by-id merge value)))))
(defn collections-fetched
[items]
(CollectionFetched. items))
[data]
{:pre [(map? data)]}
(CollectionsFetched. data))
(defn collections-fetched?
[v]
(instance? CollectionFetched v))
(instance? CollectionsFetched v))
;; --- Fetch Collections
(defrecord FetchCollections []
rs/WatchEvent
(-apply-watch [_ state s]
(->> (rp/req :fetch/color-collections)
(->> (rp/req :fetch/kvstore "color-collections")
(rx/map :payload)
(rx/map (fn [payload]
(if (nil? payload)
{:key "color-collections"
:value nil}
payload)))
(rx/map collections-fetched))))
(defn fetch-collections
[]
(FetchCollections.))
;; --- Collection Created
(defrecord CollectionCreated [item]
rs/UpdateEvent
(-apply-update [_ state]
(-> state
(assoc-collection item)
(assoc-in [:dashboard :colors :id] (:id item))
(assoc-in [:dashboard :colors :type] :own))))
(defn collection-created
[item]
(CollectionCreated. item))
;; --- Create Collection
(defrecord CreateCollection []
rs/UpdateEvent
(-apply-update [_ state]
(let [id (uuid/random)
item {:name "Unnamed collection"
:type :own
:id id}]
(-> state
(assoc-in [:color-colls-by-id id] item)
(assoc-in [:dashboard :colors :id] id)
(assoc-in [:dashboard :colors :type] :own))))
rs/WatchEvent
(-apply-watch [_ state s]
(let [coll {:name "Unnamed collection"
:id (uuid/random)}]
(->> (rp/req :create/color-collection coll)
(rx/map :payload)
(rx/map collection-created)))))
(-apply-watch [_ state stream]
(rx/of (persist-collections))))
(defn create-collection
[]
(CreateCollection.))
;; --- Collection Updated
;; --- Persist Collections
(defrecord CollectionUpdated [item]
rs/UpdateEvent
(-apply-update [_ state]
(assoc-collection state item)))
(defn collection-updated
[item]
(CollectionUpdated. item))
;; --- Update Collection
(defrecord UpdateCollection [id]
(defrecord PersistCollections []
rs/WatchEvent
(-apply-watch [_ state s]
(let [item (get-in state [:color-colls-by-id id])]
(->> (rp/req :update/color-collection item)
(rx/map :payload)
(rx/map collection-updated)))))
(-apply-watch [_ state stream]
(let [builtin? #(= :builtin (:type %))
xf (remove (comp builtin? second))
(defn update-collection
[id]
(UpdateCollection. id))
colls (get state :color-colls-by-id)
data (-> (get-in state [:kvstore :color-collections])
(assoc :value (into {} xf colls)))]
(->> (rp/req :update/kvstore data)
(rx/map :payload)
(rx/map collections-fetched)))))
(defn persist-collections
[]
(PersistCollections.))
;; --- Rename Collection
@ -175,7 +156,7 @@
rs/WatchEvent
(-apply-watch [_ state s]
(rx/of (update-collection id))))
(rx/of (persist-collections))))
(defn rename-collection
[item name]
@ -186,12 +167,11 @@
(defrecord DeleteCollection [id]
rs/UpdateEvent
(-apply-update [_ state]
(dissoc-collection state id))
(update state :color-colls-by-id dissoc id))
rs/WatchEvent
(-apply-watch [_ state s]
(->> (rp/req :delete/color-collection id)
(rx/ignore))))
(rx/of (persist-collections))))
(defn delete-collection
[id]
@ -207,11 +187,12 @@
rs/WatchEvent
(-apply-watch [_ state s]
(rx/of (update-collection id))))
(rx/of (persist-collections))))
(defn replace-color
"Add or replace color in a collection."
[{:keys [id from to] :as params}]
(println "replace-color" params)
(ReplaceColor. id from to))
;; --- Remove Color
@ -224,7 +205,7 @@
rs/WatchEvent
(-apply-watch [_ state s]
(rx/of (update-collection id))))
(rx/of (persist-collections))))
(defn remove-colors
"Remove color in a collection."
@ -257,6 +238,43 @@
{:pre [(color/hex? color)]}
(ToggleColorSelection. color))
;; --- Copy Selected Icon
(defrecord CopySelected [id]
rs/UpdateEvent
(-apply-update [_ state]
(let [selected (get-in state [:dashboard :colors :selected])]
(update-in state [:color-colls-by-id id :data] set/union selected)))
rs/WatchEvent
(-apply-watch [_ state stream]
(rx/of (persist-collections))))
(defn copy-selected
[id]
{:pre [(or (uuid? id) (nil? id))]}
(CopySelected. id))
;; --- Move Selected Icon
(defrecord MoveSelected [from to]
rs/UpdateEvent
(-apply-update [_ state]
(let [selected (get-in state [:dashboard :colors :selected])]
(-> state
(update-in [:color-colls-by-id from :data] set/difference selected)
(update-in [:color-colls-by-id to :data] set/union selected))))
rs/WatchEvent
(-apply-watch [_ state stream]
(rx/of (persist-collections))))
(defn move-selected
[from to]
{:pre [(or (uuid? from) (nil? from))
(or (uuid? to) (nil? to))]}
(MoveSelected. from to))
;; --- Delete Selected Colors
(defrecord DeleteSelectedColors []

View file

@ -13,7 +13,7 @@
[uxbox.main.repo.pages]
[uxbox.main.repo.images]
[uxbox.main.repo.icons]
[uxbox.main.repo.colors]
[uxbox.main.repo.kvstore]
[uxbox.main.repo.impl :as impl]))
(defn req

View file

@ -32,19 +32,10 @@
(-> (l/in [:dashboard :colors])
(l/derive st/state)))
(def collections-map-ref
(def collections-ref
(-> (l/key :color-colls-by-id)
(l/derive st/state)))
(def collections-ref
(-> (l/lens vals)
(l/derive collections-map-ref)))
(defn- focus-collection
[id]
(-> (l/key id)
(l/derive collections-map-ref)))
;; --- Page Title
(mx/defcs page-title
@ -56,7 +47,7 @@
edit? (:edit @local)]
(letfn [(save []
(let [dom (mx/ref-node own "input")
name (.-innerText dom)]
name (dom/get-inner-text dom)]
(rs/emit! (dc/rename-collection id (str/trim name)))
(swap! local assoc :edit false)))
(cancel []
@ -85,7 +76,7 @@
[:span.close {:on-click cancel} i/close]]
[:span.dashboard-title-field
{:on-double-click edit}
(:name coll)])]
(:name coll "Storage")])]
(if (and (not own?) coll)
[:div.edition
(if edit?
@ -93,8 +84,178 @@
[:span {:on-click edit} i/pencil])
[:span {:on-click delete-collection} i/trash]])])))
;; --- Nav
(mx/defc nav-item
{:mixins [mx/static]}
[{:keys [id type name] :as coll} selected?]
(letfn [(on-click [event]
(let [type (or type :own)]
(rs/emit! (dc/select-collection type id))))]
(let [colors (count (:data coll))]
[:li {:on-click on-click
:class-name (when selected? "current")}
[:span.element-title
(if coll name "Storage")]
[:span.element-subtitle
(tr "ds.num-elements" (t/c colors))]])))
(def ^:private storage-num-colors-ref
(-> (comp (l/in [:color-colls-by-id nil :data])
(l/lens count))
(l/derive st/state)))
(mx/defc nav-item-storage
{:mixins [mx/static mx/reactive]}
[selected?]
(let [num-colors (mx/react storage-num-colors-ref)
on-click #(rs/emit! (dc/select-collection :own nil))]
[:li {:on-click on-click :class (when selected? "current")}
[:span.element-title "Storage"]
[:span.element-subtitle
(tr "ds.num-elements" (t/c num-colors))]]))
(mx/defc nav-section
{:mixins [mx/static]}
[type selected colls]
(let [own? (= type :own)
builtin? (= type :builtin)
colls (cond->> (vals colls)
own? (filter #(= :own (:type %)))
builtin? (filter #(= :builtin (:type %)))
own? (sort-by :id))]
[:ul.library-elements
(when own?
[:li
[:a.btn-primary
{:on-click #(rs/emit! (dc/create-collection))}
"+ New library"]])
(when own?
(nav-item-storage (nil? selected)))
(for [coll colls
:let [selected? (= (:id coll) selected)
key (str (:id coll))]]
(-> (nav-item coll selected?)
(mx/with-key key)))]))
(mx/defc nav
{:mixins [mx/static mx/reactive]}
[{:keys [id type] :as state} colls]
(let [own? (= type :own)
builtin? (= type :builtin)]
(letfn [(select-tab [type]
(if own?
(rs/emit! (dc/select-collection type))
(let [coll (->> (map second colls)
(filter #(= type (:type %)))
(sort-by :name)
(first))]
(if coll
(rs/emit! (dc/select-collection type (:id coll)))
(rs/emit! (dc/select-collection type))))))]
[:div.library-bar
[:div.library-bar-inside
[:ul.library-tabs
[:li {:class-name (when own? "current")
:on-click (partial select-tab :own)}
"YOUR COLORS"]
[:li {:class-name (when builtin? "current")
:on-click (partial select-tab :builtin)}
"COLORS STORE"]]
(nav-section type id colls)]])))
;; --- Grid
(mx/defc grid-form
[coll-id]
[:div.grid-item.small-item.add-project
{:on-click #(udl/open! :color-form {:coll coll-id})}
[:span "+ New color"]])
(mx/defc grid-options-copy
{:mixins [mx/reactive mx/static]}
[current-coll]
{:pre [(uuid? current-coll)]}
(let [colls (mx/react collections-ref)
colls (->> (vals colls)
(filter #(= :own (:type %)))
(remove #(= current-coll (:id %)))
(sort-by :name colls))
on-select (fn [event id]
(dom/prevent-default event)
(rs/emit! (dc/copy-selected id)))]
[:ul.move-list
[:li.title "Copy to library"]
[:li [:a {:href "#" :on-click #(on-select % nil)} "Storage"]]
(for [coll colls
:let [id (:id coll)
name (:name coll)]]
[:li {:key (str id)}
[:a {:on-click #(on-select % id)} name]])]))
(mx/defc grid-options-move
{:mixins [mx/reactive mx/static]}
[current-coll]
{:pre [(uuid? current-coll)]}
(let [colls (mx/react collections-ref)
colls (->> (vals colls)
(filter #(= :own (:type %)))
(remove #(= current-coll (:id %)))
(sort-by :name colls))
on-select (fn [event id]
(dom/prevent-default event)
(rs/emit! (dc/move-selected current-coll id)))]
[:ul.move-list
[:li.title "Move to library"]
[:li [:a {:href "#" :on-click #(on-select % nil)} "Storage"]]
(for [coll colls
:let [id (:id coll)
name (:name coll)]]
[:li {:key (str id)}
[:a {:on-click #(on-select % id)} name]])]))
(mx/defcs grid-options
{:mixins [mx/static (mx/local)]}
[own {:keys [type id] :as coll}]
(let [editable? (or (= type :own) (nil? id))
local (:rum/local own)]
(letfn [(delete [event]
(rs/emit! (dc/delete-selected-colors)))
(on-delete [event]
(udl/open! :confirm {:on-accept delete}))
(on-toggle-copy [event]
(swap! local assoc
:show-copy-tooltip not
:show-move-tooltip false))
(on-toggle-move [event]
(swap! local assoc
:show-move-tooltip not
:show-copy-tooltip false))]
;; MULTISELECT OPTIONS BAR
[:div.multiselect-bar
(if editable?
[:div.multiselect-nav
[:span.move-item.tooltip.tooltip-top
{:on-click on-toggle-copy}
(when (:show-copy-tooltip @local)
(grid-options-copy id))
i/organize]
[:span.move-item.tooltip.tooltip-top
{:on-click on-toggle-move}
(when (:show-move-tooltip @local)
(grid-options-move id))
i/organize]
[:span.delete.tooltip.tooltip-top
{:alt "Delete"
:on-click on-delete}
i/trash]]
[:div.multiselect-nav
[:span.move-item.tooltip.tooltip-top
{:on-click on-toggle-copy}
(when (:show-copy-tooltip @local)
(grid-options-copy id))
i/organize]])])))
(mx/defc grid-item
[color selected?]
(let [color-rgb (hex->rgb color)]
@ -115,139 +276,28 @@
[:span.color-data color]
[:span.color-data (apply str "RGB " (interpose ", " color-rgb))]])))
(mx/defc grid-options
[coll]
(let [own? (= (:type coll) :own)]
(letfn [(on-delete [event]
(rs/emit! (dc/delete-selected-colors)))]
;; MULTISELECT OPTIONS BAR
[:div.multiselect-bar
(if own?
[:div.multiselect-nav
[:span.move-item.tooltip.tooltip-top
{:alt "Move to"}
i/organize]
[:span.delete.tooltip.tooltip-top
{:alt "Delete"
:on-click on-delete}
i/trash]]
[:div.multiselect-nav
[:span.move-item.tooltip.tooltip-top
{:alt "Copy to"}
[:ul.move-list
[:li.title "Copy to library"]
[:li
[:a {:href "#"} "Red palette"]]
[:li
[:a {:href "#"} "Protoype"]]
[:li
[:a {:href "#"} "Gray scale palette"]]
[:li
[:a {:href "#"} "Current project"]]
[:li
[:a {:href "#"} "Gray scale palette"]]
[:li
[:a {:href "#"} "Current project"]]
[:li
[:a {:href "#"} "Library 3"]]]
i/organize]])])))
(mx/defc grid
{:mixins [mx/static]}
[selected coll]
(let [own? (= (:type coll) :own)
colors (->> (:data coll)
(remove nil?)
[{:keys [id type data] :as coll} selected]
(let [editable? (or (= :own type) (nil? id))
colors (->> (remove nil? data)
(sort-by identity))]
[:div.dashboard-grid-content
[:div.dashboard-grid-row
(when own?
[:div.grid-item.small-item.add-project
{:on-click #(udl/open! :color-form {:coll coll})}
[:span "+ New color"]])
(when editable? (grid-form id))
(for [color colors
:let [selected? (contains? selected color)]]
(-> (grid-item color selected?)
(mx/with-key (str color))))]]))
(mx/defc content
{:mixins [mx/static mx/reactive]}
[]
(let [dashboard (mx/react dashboard-ref)
selected (:selected dashboard)
coll-type (:type dashboard)
coll-id (:id dashboard)
coll (mx/react (focus-collection coll-id))
own? (= coll-type :own)]
(when coll
[:section.dashboard-grid.library
(page-title coll)
(grid selected coll)
(when (and (seq selected))
(grid-options coll))])))
;; --- Nav
(mx/defc nav-item
{:mixins [mx/static]}
[coll selected?]
(letfn [(on-click [event]
(let [type (:type coll)
id (:id coll)]
(rs/emit! (dc/select-collection type id))))]
(let [colors (count (:data coll))]
[:li {:on-click on-click
:class-name (when selected? "current")}
[:span.element-title (:name coll)]
[:span.element-subtitle
(tr "ds.num-elements" (t/c colors))]])))
(mx/defc nav-section
{:mixins [mx/static mx/reactive]}
[type selected]
(let [own? (= type :own)
builtin? (= type :builtin)
colls (cond->> (mx/react collections-ref)
own? (filter #(= :own (:type %)))
builtin? (filter #(= :builtin (:type %)))
own? (sort-by :id))]
[:ul.library-elements
(when own?
[:li
[:a.btn-primary
{:on-click #(rs/emit! (dc/create-collection))}
"+ New library"]])
(for [coll colls
:let [selected? (= (:id coll) selected)
key (str (:id coll))]]
(-> (nav-item coll selected?)
(mx/with-key key)))]))
(mx/defc nav
{:mixins [mx/static mx/reactive]}
[]
(let [dashboard (mx/react dashboard-ref)
colls (mx/react collections-ref)
selected (:id dashboard)
type (:type dashboard)
own? (= type :own)
builtin? (= type :builtin)]
(letfn [(select-tab [type]
(let [xf (filter #(= type (:type %)))
colls (sequence xf colls)]
(if-let [item (first colls)]
(rs/emit! (dc/select-collection type (:id item)))
(rs/emit! (dc/select-collection type)))))]
[:div.library-bar
[:div.library-bar-inside
[:ul.library-tabs
[:li {:class-name (when own? "current")
:on-click (partial select-tab :own)}
"YOUR COLORS"]
[:li {:class-name (when builtin? "current")
:on-click (partial select-tab :builtin)}
"COLORS STORE"]]
(nav-section type selected)]])))
[{:keys [selected] :as state} coll]
[:section.dashboard-grid.library
(page-title coll)
(grid coll selected)
(when (and (seq selected))
(grid-options coll))])
;; --- Colors Page
@ -269,22 +319,25 @@
(mx/defc colors-page
{:will-mount colors-page-will-mount
:did-remount colors-page-did-remount
:mixins [mx/static]}
[type id]
[:main.dashboard-main
(header)
[:section.dashboard-content
(nav)
(content)]])
:mixins [mx/static mx/reactive]}
[_ _]
(let [state (mx/react dashboard-ref)
colls (mx/react collections-ref)
coll (get colls (:id state))]
[:main.dashboard-main
(header)
[:section.dashboard-content
(nav state colls)
(content state coll)]]))
;; --- Colors Lightbox (Component)
(mx/defcs color-lightbox
{:mixins [(mx/local {}) mx/static]}
[own {:keys [coll color]}]
[own {:keys [coll color] :as params}]
(let [local (:rum/local own)]
(letfn [(on-submit [event]
(let [params {:id (:id coll)
(let [params {:id coll
:from color
:to (:hex @local)}]
(rs/emit! (dc/replace-color params))

View file

@ -76,7 +76,7 @@
(defn- colorpalette-will-mount
[own]
(rs/emit! (dc/conditional-fetch))
(rs/emit! (dc/fetch-collections))
own)
(mx/defc colorpalette