mirror of
https://github.com/penpot/penpot.git
synced 2025-01-10 17:00:36 -05:00
Minor readability and consistency fixes on images.
This commit is contained in:
parent
57c53ba6a1
commit
a60fbca002
4 changed files with 135 additions and 123 deletions
|
@ -43,14 +43,14 @@
|
|||
|
||||
;; --- Color Collections Fetched
|
||||
|
||||
(defrecord CollectionFetched [items]
|
||||
(defrecord CollectionsFetched [items]
|
||||
rs/UpdateEvent
|
||||
(-apply-update [_ state]
|
||||
(reduce sti/assoc-collection state items)))
|
||||
|
||||
(defn collections-fetched
|
||||
[items]
|
||||
(CollectionFetched. items))
|
||||
(CollectionsFetched. items))
|
||||
|
||||
;; --- Fetch Color Collections
|
||||
|
||||
|
@ -260,23 +260,6 @@
|
|||
|
||||
;; --- Helpers
|
||||
|
||||
(defn sort-images-by
|
||||
[ordering projs]
|
||||
(case ordering
|
||||
:name (sort-by :name projs)
|
||||
:created (reverse (sort-by :created-at projs))
|
||||
projs))
|
||||
|
||||
(defn contains-term?
|
||||
[phrase term]
|
||||
(str/contains? (str/lower phrase) (str/trim (str/lower term))))
|
||||
|
||||
(defn filter-images-by
|
||||
[term projs]
|
||||
(if (str/blank? term)
|
||||
projs
|
||||
(filter #(contains-term? (:name %) term) projs)))
|
||||
|
||||
(defn set-images-ordering
|
||||
[order]
|
||||
(reify
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
(ns uxbox.state.images
|
||||
"A collection of functions for manage dashboard data insinde the state.")
|
||||
(ns uxbox.state.images)
|
||||
|
||||
(defn assoc-collection
|
||||
"A reduce function for assoc the image collection
|
||||
|
@ -25,4 +24,6 @@
|
|||
"A reduce function for dissoc the image collection
|
||||
to the state map."
|
||||
[state coll-id image]
|
||||
(update-in state [:images-by-id coll-id :images] disj image))
|
||||
(let [images (get-in state [:images-by-id coll-id :images])
|
||||
images (filterv #(not= (:id image) (:id %)) images)]
|
||||
(assoc-in state [:images-by-id coll-id images] images)))
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
(ns uxbox.ui.dashboard.images
|
||||
(:require [sablono.core :as html :refer-macros [html]]
|
||||
[rum.core :as rum]
|
||||
[cuerdas.core :as str]
|
||||
[lentes.core :as l]
|
||||
[uxbox.locales :as t :refer (tr)]
|
||||
[uxbox.state :as st]
|
||||
|
@ -19,9 +20,10 @@
|
|||
[uxbox.ui.icons :as i]
|
||||
[uxbox.ui.mixins :as mx]
|
||||
[uxbox.ui.lightbox :as lbx]
|
||||
[uxbox.ui.keyboard :as k]
|
||||
[uxbox.ui.keyboard :as kbd]
|
||||
[uxbox.ui.library-bar :as ui.library-bar]
|
||||
[uxbox.ui.dashboard.header :refer (header)]
|
||||
[uxbox.util.data :as data]
|
||||
[uxbox.util.lens :as ul]
|
||||
[uxbox.util.dom :as dom]))
|
||||
|
||||
|
@ -31,32 +33,47 @@
|
|||
{:name "ds.project-ordering.by-name"
|
||||
:created "ds.project-ordering.by-creation-date"})
|
||||
|
||||
(defn- sort-images-by
|
||||
[ordering projs]
|
||||
(case ordering
|
||||
:name (sort-by :name projs)
|
||||
:created (reverse (sort-by :created-at projs))
|
||||
projs))
|
||||
|
||||
(defn- contains-term?
|
||||
[phrase term]
|
||||
(str/contains? (str/lower phrase) (str/trim (str/lower term))))
|
||||
|
||||
(defn- filter-images-by
|
||||
[term projs]
|
||||
(if (str/blank? term)
|
||||
projs
|
||||
(filter #(contains-term? (:name %) term) projs)))
|
||||
|
||||
;; --- Lenses
|
||||
|
||||
(def ^:const ^:private dashboard-l
|
||||
(def ^:private dashboard-l
|
||||
(-> (l/key :dashboard)
|
||||
(l/focus-atom st/state)))
|
||||
|
||||
(def ^:const ^:private collections-by-id-l
|
||||
(def ^:private collections-by-id-l
|
||||
(-> (comp (l/key :images-by-id)
|
||||
(ul/merge library/+image-collections-by-id+))
|
||||
(l/focus-atom st/state)))
|
||||
|
||||
(def images-ordering-l
|
||||
(as-> (l/in [:dashboard :images-order]) $
|
||||
(l/focus-atom $ st/state)))
|
||||
|
||||
(def images-filtering-l
|
||||
(as-> (l/in [:dashboard :images-filter]) $
|
||||
(l/focus-atom $ st/state)))
|
||||
(def ^:private images-ordering-l
|
||||
(-> (l/in [:dashboard :images-order])
|
||||
(l/focus-atom st/state)))
|
||||
|
||||
(def ^:private images-filtering-l
|
||||
(-> (l/in [:dashboard :images-filter])
|
||||
(l/focus-atom st/state)))
|
||||
|
||||
(defn- focus-collection
|
||||
[collid]
|
||||
(-> (l/key collid)
|
||||
(l/focus-atom collections-by-id-l)))
|
||||
|
||||
|
||||
;; --- Page Title
|
||||
|
||||
(defn page-title-render
|
||||
|
@ -69,8 +86,8 @@
|
|||
(swap! local assoc :edit false))
|
||||
(on-title-edited [e]
|
||||
(cond
|
||||
(k/esc? e) (swap! local assoc :edit false)
|
||||
(k/enter? e) (on-title-save e)
|
||||
(kbd/esc? e) (swap! local assoc :edit false)
|
||||
(kbd/enter? e) (on-title-save e)
|
||||
:else (let [content (dom/event->inner-text e)]
|
||||
(swap! local assoc :coll-name content))))
|
||||
(on-title-edit [e]
|
||||
|
@ -78,8 +95,8 @@
|
|||
(on-delete [e]
|
||||
(rs/emit! (di/delete-collection (:id coll))))]
|
||||
(html
|
||||
[:div.dashboard-title {}
|
||||
[:h2 {}
|
||||
[:div.dashboard-title
|
||||
[:h2
|
||||
(if (:edit @local)
|
||||
[:div.dashboard-title-field
|
||||
[:span.edit
|
||||
|
@ -102,7 +119,7 @@
|
|||
(mx/component
|
||||
{:render page-title-render
|
||||
:name "page-title"
|
||||
:mixins [(rum/local {}) mx/static rum/reactive]}))
|
||||
:mixins [(mx/local) mx/static rum/reactive]}))
|
||||
|
||||
;; --- Nav
|
||||
|
||||
|
@ -113,45 +130,45 @@
|
|||
collid (:collection-id dashboard)
|
||||
own? (= (:collection-type dashboard) :own)
|
||||
builtin? (= (:collection-type dashboard) :builtin)
|
||||
collections (as-> (vals collections-by-id) $
|
||||
(if own?
|
||||
(filter (comp not :builtin) $)
|
||||
(filter :builtin $)))]
|
||||
collections (cond->> (vals collections-by-id)
|
||||
(true? own?) (filter (comp not :builtin))
|
||||
(false? own?) (filter :builtin))
|
||||
show-builtin #(rs/emit! (di/set-collection-type :builtin))
|
||||
show-own #(rs/emit! (di/set-collection-type :own))
|
||||
new-coll #(rs/emit! (di/create-collection))
|
||||
select-coll #(rs/emit! (di/set-collection %))]
|
||||
(html
|
||||
[:div.library-bar
|
||||
[:div.library-bar-inside
|
||||
[:ul.library-tabs
|
||||
[:li {:class-name (when builtin? "current")
|
||||
:on-click #(rs/emit! (di/set-collection-type :builtin))}
|
||||
:on-click show-builtin}
|
||||
"STANDARD"]
|
||||
[:li {:class-name (when own? "current")
|
||||
:on-click #(rs/emit! (di/set-collection-type :own))}
|
||||
:on-click show-own}
|
||||
"YOUR LIBRARIES"]]
|
||||
[:ul.library-elements
|
||||
(when own?
|
||||
[:li
|
||||
[:a.btn-primary
|
||||
{:on-click #(rs/emit! (di/create-collection))}
|
||||
"+ New library"]])
|
||||
(for [props collections
|
||||
:let [num (count (:images props))]]
|
||||
[:li {:key (str (:id props))
|
||||
:on-click #(rs/emit! (di/set-collection (:id props)))
|
||||
:class-name (when (= (:id props) collid) "current")}
|
||||
[:span.element-title (:name props)]
|
||||
[:a.btn-primary {:on-click new-coll} "+ New library"]])
|
||||
(for [{:keys [id images name]} collections
|
||||
:let [num (count images)]]
|
||||
[:li {:key (str id)
|
||||
:on-click (partial select-coll id)
|
||||
:class (when (= id collid) "current")}
|
||||
[:span.element-title name]
|
||||
[:span.element-subtitle
|
||||
(tr "ds.num-elements" (t/c num))]])]]])))
|
||||
|
||||
(def ^:const ^:private nav
|
||||
(def ^:private nav
|
||||
(mx/component
|
||||
{:render nav-render
|
||||
:name "nav"
|
||||
:mixins [rum/reactive]}))
|
||||
|
||||
:mixins [rum/reactive mx/static]}))
|
||||
|
||||
;; --- Grid
|
||||
|
||||
(defn grid-render
|
||||
(defn- grid-render
|
||||
[own]
|
||||
(let [local (:rum/local own)
|
||||
dashboard (rum/react dashboard-l)
|
||||
|
@ -161,70 +178,76 @@
|
|||
coll (rum/react (focus-collection coll-id))
|
||||
images-filtering (rum/react images-filtering-l)
|
||||
images-ordering (rum/react images-ordering-l)
|
||||
coll-images (->> (:images coll)
|
||||
(remove nil?)
|
||||
(di/filter-images-by images-filtering)
|
||||
(di/sort-images-by images-ordering))
|
||||
toggle-image-check (fn [image]
|
||||
(swap! local update :selected #(if (% image) (disj % image) (conj % image))))
|
||||
delete-selected-images #(doseq [image (:selected @local)]
|
||||
(rs/emit! (di/delete-image coll-id image)))]
|
||||
(when coll
|
||||
(html
|
||||
[:section.dashboard-grid.library
|
||||
(page-title coll)
|
||||
[:div.dashboard-grid-content
|
||||
[:div.dashboard-grid-row
|
||||
(if own?
|
||||
[:div.grid-item.add-project
|
||||
{:on-click #(dom/click (dom/get-element-by-class "upload-image-input"))}
|
||||
[:span "+ New image"]
|
||||
[:input.upload-image-input {:style {:display "none"}
|
||||
:type "file"
|
||||
:on-change #(rs/emit! (di/create-images coll-id (dom/get-event-files %)))}]])
|
||||
images (->> (:images coll)
|
||||
(remove nil?)
|
||||
(filter-images-by images-filtering)
|
||||
(sort-images-by images-ordering))
|
||||
show-menu? (not (empty? (:selected @local)))]
|
||||
(letfn [(toggle-check [image]
|
||||
(swap! local update :selected #(data/conj-or-disj % image)))
|
||||
(toggle-check-card [image event]
|
||||
(when (kbd/shift? event)
|
||||
(toggle-check image)))
|
||||
(forward-click [event]
|
||||
(dom/click (mx/get-ref-dom own "file-input")))
|
||||
(delete-selected []
|
||||
(->> (:selected @local)
|
||||
(run! #(rs/emit! (di/delete-image coll-id %)))))
|
||||
(on-file-selected [event]
|
||||
(let [files (dom/get-event-files event)]
|
||||
(rs/emit! (di/create-images coll-id files))))]
|
||||
(when coll
|
||||
(html
|
||||
[:section.dashboard-grid.library
|
||||
(page-title coll)
|
||||
[:div.dashboard-grid-content
|
||||
[:div.dashboard-grid-row
|
||||
(if own?
|
||||
[:div.grid-item.add-project {:on-click forward-click}
|
||||
[:span "+ New image"]
|
||||
[:input.upload-image-input
|
||||
{:style {:display "none"}
|
||||
:ref "file-input"
|
||||
:type "file"
|
||||
:on-change on-file-selected}]])
|
||||
|
||||
(for [image coll-images]
|
||||
[:div.grid-item.images-th
|
||||
{:key (:id image) :on-click #(when (k/shift? %) (toggle-image-check image))}
|
||||
[:div.grid-item-th
|
||||
{:style
|
||||
{:background-image (str "url('" (:thumbnail image) "')")}}
|
||||
[:div.input-checkbox.check-primary
|
||||
[:input {:type "checkbox"
|
||||
:id (:id image)
|
||||
:on-click #(toggle-image-check image)
|
||||
:checked ((:selected @local) image)}]
|
||||
[:label {:for (:id image)}]]]
|
||||
[:span (:name image)]])]
|
||||
(for [image images
|
||||
:let [selected? (contains? (:selected @local) image)]]
|
||||
[:div.grid-item.images-th
|
||||
{:key (:id image)
|
||||
:on-click (partial toggle-check-card image)}
|
||||
[:div.grid-item-th
|
||||
{:style {:background-image (str "url('" (:thumbnail image) "')")}}
|
||||
[:div.input-checkbox.check-primary
|
||||
[:input {:type "checkbox"
|
||||
:id (:id image)
|
||||
:on-click (partial toggle-check image)
|
||||
:checked selected?}]
|
||||
[:label {:for (:id image)}]]]
|
||||
[:span (:name image)]])]
|
||||
|
||||
(when (not (empty? (:selected @local)))
|
||||
;; MULTISELECT OPTIONS BAR
|
||||
[:div.multiselect-bar
|
||||
[:div.multiselect-nav
|
||||
[:span.move-item.tooltip.tooltip-top
|
||||
{:alt "Copy to"}
|
||||
i/organize]
|
||||
(if own?
|
||||
[:span.copy.tooltip.tooltip-top
|
||||
{:alt "Duplicate"}
|
||||
i/copy])
|
||||
(if own?
|
||||
[:span.delete.tooltip.tooltip-top
|
||||
{:alt "Delete"
|
||||
:on-click #(delete-selected-images)}
|
||||
i/trash])]])]]))))
|
||||
(when show-menu?
|
||||
;; MULTISELECT OPTIONS BAR
|
||||
[:div.multiselect-bar
|
||||
[:div.multiselect-nav
|
||||
[:span.move-item.tooltip.tooltip-top {:alt "Copy to"} i/organize]
|
||||
(if own?
|
||||
[:span.copy.tooltip.tooltip-top {:alt "Duplicate"} i/copy])
|
||||
(if own?
|
||||
[:span.delete.tooltip.tooltip-top
|
||||
{:alt "Delete"
|
||||
:on-click delete-selected}
|
||||
i/trash])]])]])))))
|
||||
|
||||
(def ^:const ^:private grid
|
||||
(def ^:private grid
|
||||
(mx/component
|
||||
{:render grid-render
|
||||
:name "grid"
|
||||
:mixins [(rum/local {:selected #{}})
|
||||
mx/static
|
||||
rum/reactive]}))
|
||||
:mixins [(rum/local {:selected #{}}) mx/static rum/reactive]}))
|
||||
|
||||
;; --- Sort Widget
|
||||
|
||||
(defn sort-widget-render
|
||||
(defn- sort-widget-render
|
||||
[]
|
||||
(let [ordering (rum/react images-ordering-l)
|
||||
on-change #(rs/emit! (di/set-images-ordering
|
||||
|
@ -234,7 +257,7 @@
|
|||
[:span (tr "ds.project-ordering")]
|
||||
[:select.input-select
|
||||
{:on-change on-change
|
||||
:value (:name ordering)}
|
||||
:value (:name ordering "")}
|
||||
(for [option (keys +ordering-options+)
|
||||
:let [option-id (get +ordering-options+ option)
|
||||
option-value (:name option)
|
||||
|
@ -252,7 +275,7 @@
|
|||
|
||||
;; --- Filtering Widget
|
||||
|
||||
(defn search-widget-render
|
||||
(defn- search-widget-render
|
||||
[]
|
||||
(letfn [(on-term-change [event]
|
||||
(-> (dom/get-target event)
|
||||
|
@ -270,9 +293,7 @@
|
|||
:auto-focus true
|
||||
:placeholder (tr "ds.project-search.placeholder")
|
||||
:value (rum/react images-filtering-l)}]
|
||||
[:div.clear-search
|
||||
{:on-click on-clear}
|
||||
i/close]])))
|
||||
[:div.clear-search {:on-click on-clear} i/close]])))
|
||||
|
||||
(def ^:private search-widget
|
||||
(mx/component
|
||||
|
@ -280,10 +301,9 @@
|
|||
:name "search-widget"
|
||||
:mixins [rum/reactive mx/static]}))
|
||||
|
||||
|
||||
;; --- Menu
|
||||
|
||||
(defn menu-render
|
||||
(defn- menu-render
|
||||
[]
|
||||
(let [dashboard (rum/react dashboard-l)
|
||||
coll-id (:collection-id dashboard)
|
||||
|
@ -296,7 +316,7 @@
|
|||
(sort-widget)
|
||||
(search-widget)]])))
|
||||
|
||||
(def menu
|
||||
(def ^:private menu
|
||||
(mx/component
|
||||
{:render menu-render
|
||||
:name "menu"
|
||||
|
@ -305,7 +325,7 @@
|
|||
|
||||
;; --- Images Page
|
||||
|
||||
(defn images-page-render
|
||||
(defn- images-page-render
|
||||
[own]
|
||||
(html
|
||||
[:main.dashboard-main
|
||||
|
@ -315,13 +335,13 @@
|
|||
(menu)
|
||||
(grid)]]))
|
||||
|
||||
(defn images-page-will-mount
|
||||
(defn- images-page-will-mount
|
||||
[own]
|
||||
(rs/emit! (dd/initialize :dashboard/images)
|
||||
(di/initialize))
|
||||
own)
|
||||
|
||||
(defn images-page-transfer-state
|
||||
(defn- images-page-transfer-state
|
||||
[old-state state]
|
||||
(rs/emit! (dd/initialize :dashboard/images))
|
||||
state)
|
||||
|
|
|
@ -61,6 +61,14 @@
|
|||
(apply merge-with deep-merge maps)
|
||||
(last maps)))
|
||||
|
||||
(defn conj-or-disj
|
||||
"Given a set, and an element remove that element from set
|
||||
if it exists or add it if it does not exists."
|
||||
[s v]
|
||||
(if (contains? s v)
|
||||
(disj s v)
|
||||
(conj s v)))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Numbers Parsing
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
|
Loading…
Reference in a new issue