mirror of
https://github.com/penpot/penpot.git
synced 2025-06-03 05:51:38 +02:00
Images dashboard
This commit is contained in:
parent
963d22d930
commit
b3e9e7d1aa
12 changed files with 778 additions and 89 deletions
|
@ -15,6 +15,7 @@
|
||||||
[uxbox.repo :as rp]
|
[uxbox.repo :as rp]
|
||||||
[uxbox.data.projects :as dp]
|
[uxbox.data.projects :as dp]
|
||||||
[uxbox.data.colors :as dc]
|
[uxbox.data.colors :as dc]
|
||||||
|
[uxbox.data.images :as di]
|
||||||
[uxbox.util.data :refer (deep-merge)]))
|
[uxbox.util.data :refer (deep-merge)]))
|
||||||
|
|
||||||
;; --- Events
|
;; --- Events
|
||||||
|
|
299
src/uxbox/data/images.cljs
Normal file
299
src/uxbox/data/images.cljs
Normal file
|
@ -0,0 +1,299 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) 2015-2016 Andrey Antukh <niwi@niwi.nz>
|
||||||
|
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||||
|
|
||||||
|
(ns uxbox.data.images
|
||||||
|
(:require [cuerdas.core :as str]
|
||||||
|
[beicon.core :as rx]
|
||||||
|
[uuid.core :as uuid]
|
||||||
|
[uxbox.rstore :as rs]
|
||||||
|
[uxbox.state :as st]
|
||||||
|
[uxbox.state.images :as sti]
|
||||||
|
[uxbox.repo :as rp]))
|
||||||
|
|
||||||
|
;; --- Initialize
|
||||||
|
|
||||||
|
(declare fetch-collections)
|
||||||
|
(declare collections-fetched?)
|
||||||
|
|
||||||
|
(defrecord Initialize []
|
||||||
|
rs/EffectEvent
|
||||||
|
(-apply-effect [_ state]
|
||||||
|
(when-not (seq (:images-by-id state))
|
||||||
|
(reset! st/loader true)))
|
||||||
|
|
||||||
|
rs/WatchEvent
|
||||||
|
(-apply-watch [_ state s]
|
||||||
|
(let [images (seq (:images-by-id state))]
|
||||||
|
(if images
|
||||||
|
(rx/empty)
|
||||||
|
(rx/merge
|
||||||
|
(rx/of (fetch-collections))
|
||||||
|
(->> (rx/filter collections-fetched? s)
|
||||||
|
(rx/take 1)
|
||||||
|
(rx/do #(reset! st/loader false))
|
||||||
|
(rx/ignore)))))))
|
||||||
|
|
||||||
|
(defn initialize
|
||||||
|
[]
|
||||||
|
(Initialize.))
|
||||||
|
|
||||||
|
;; --- Color Collections Fetched
|
||||||
|
|
||||||
|
(defrecord CollectionFetched [items]
|
||||||
|
rs/UpdateEvent
|
||||||
|
(-apply-update [_ state]
|
||||||
|
(reduce sti/assoc-collection state items)))
|
||||||
|
|
||||||
|
(defn collections-fetched
|
||||||
|
[items]
|
||||||
|
(CollectionFetched. items))
|
||||||
|
|
||||||
|
;; --- Fetch Color Collections
|
||||||
|
|
||||||
|
(defrecord FetchCollections []
|
||||||
|
rs/WatchEvent
|
||||||
|
(-apply-watch [_ state s]
|
||||||
|
(->> (rp/req :fetch/image-collections)
|
||||||
|
(rx/map :payload)
|
||||||
|
(rx/map collections-fetched))))
|
||||||
|
|
||||||
|
(defn fetch-collections
|
||||||
|
[]
|
||||||
|
(FetchCollections.))
|
||||||
|
|
||||||
|
;; --- Collection Created
|
||||||
|
|
||||||
|
(defrecord CollectionCreated [item]
|
||||||
|
rs/UpdateEvent
|
||||||
|
(-apply-update [_ state]
|
||||||
|
(-> state
|
||||||
|
(sti/assoc-collection item)
|
||||||
|
(assoc-in [:dashboard :collection-id] (:id item))
|
||||||
|
(assoc-in [:dashboard :collection-type] :own))))
|
||||||
|
|
||||||
|
(defn collection-created
|
||||||
|
[item]
|
||||||
|
(CollectionCreated. item))
|
||||||
|
|
||||||
|
;; --- Create Collection
|
||||||
|
|
||||||
|
(defrecord CreateCollection []
|
||||||
|
rs/WatchEvent
|
||||||
|
(-apply-watch [_ state s]
|
||||||
|
(let [coll {:name "Unnamed collection"
|
||||||
|
:id (uuid/random)}]
|
||||||
|
(->> (rp/req :create/image-collection coll)
|
||||||
|
(rx/map :payload)
|
||||||
|
(rx/map collection-created)))))
|
||||||
|
|
||||||
|
(defn create-collection
|
||||||
|
[]
|
||||||
|
(CreateCollection.))
|
||||||
|
|
||||||
|
(defn collections-fetched?
|
||||||
|
[v]
|
||||||
|
(instance? CollectionFetched v))
|
||||||
|
|
||||||
|
;; --- Collection Updated
|
||||||
|
|
||||||
|
(defrecord CollectionUpdated [item]
|
||||||
|
rs/UpdateEvent
|
||||||
|
(-apply-update [_ state]
|
||||||
|
(sti/assoc-collection state item)))
|
||||||
|
|
||||||
|
(defn collection-updated
|
||||||
|
[item]
|
||||||
|
(CollectionUpdated. item))
|
||||||
|
|
||||||
|
;; --- Update Collection
|
||||||
|
|
||||||
|
(defrecord UpdateCollection [id]
|
||||||
|
rs/WatchEvent
|
||||||
|
(-apply-watch [_ state s]
|
||||||
|
(let [item (get-in state [:images-by-id id])]
|
||||||
|
(->> (rp/req :update/image-collection item)
|
||||||
|
(rx/map :payload)
|
||||||
|
(rx/map collection-updated)))))
|
||||||
|
|
||||||
|
(defn update-collection
|
||||||
|
[id]
|
||||||
|
(UpdateCollection. id))
|
||||||
|
|
||||||
|
;; --- Rename Collection
|
||||||
|
|
||||||
|
(defrecord RenameCollection [id name]
|
||||||
|
rs/UpdateEvent
|
||||||
|
(-apply-update [_ state]
|
||||||
|
(assoc-in state [:images-by-id id :name] name))
|
||||||
|
|
||||||
|
rs/WatchEvent
|
||||||
|
(-apply-watch [_ state s]
|
||||||
|
(rx/of (update-collection id))))
|
||||||
|
|
||||||
|
(defn rename-collection
|
||||||
|
[item name]
|
||||||
|
(RenameCollection. item name))
|
||||||
|
|
||||||
|
;; --- Delete Collection
|
||||||
|
|
||||||
|
(defrecord DeleteCollection [id]
|
||||||
|
rs/UpdateEvent
|
||||||
|
(-apply-update [_ state]
|
||||||
|
(sti/dissoc-collection state id))
|
||||||
|
|
||||||
|
rs/WatchEvent
|
||||||
|
(-apply-watch [_ state s]
|
||||||
|
(->> (rp/req :delete/image-collection id)
|
||||||
|
(rx/ignore))))
|
||||||
|
|
||||||
|
(defn delete-collection
|
||||||
|
[id]
|
||||||
|
(DeleteCollection. id))
|
||||||
|
|
||||||
|
;; --- Image Created
|
||||||
|
|
||||||
|
(defrecord ImageCreated [item]
|
||||||
|
rs/UpdateEvent
|
||||||
|
(-apply-update [_ state]
|
||||||
|
(update-in state [:images-by-id (:collection item) :images]
|
||||||
|
#(conj % item))))
|
||||||
|
|
||||||
|
(defn image-created
|
||||||
|
[item]
|
||||||
|
(ImageCreated. item))
|
||||||
|
|
||||||
|
;; --- Create Image
|
||||||
|
|
||||||
|
(defrecord CreateImages [coll-id files]
|
||||||
|
rs/WatchEvent
|
||||||
|
(-apply-watch [_ state s]
|
||||||
|
(let [image-data {:coll coll-id
|
||||||
|
:id (uuid/random)
|
||||||
|
:files files}]
|
||||||
|
(->> (rp/req :create/image image-data)
|
||||||
|
(rx/map :payload)
|
||||||
|
(rx/map image-created)))))
|
||||||
|
|
||||||
|
(defn create-images
|
||||||
|
[coll-id files]
|
||||||
|
(CreateImages. coll-id files))
|
||||||
|
|
||||||
|
;; --- Images Loaded
|
||||||
|
|
||||||
|
(defrecord ImagesLoaded [coll-id items]
|
||||||
|
rs/UpdateEvent
|
||||||
|
(-apply-update [_ state]
|
||||||
|
(assoc-in state [:images-by-id coll-id :images] (set items))))
|
||||||
|
|
||||||
|
(defn images-loaded
|
||||||
|
[coll-id items]
|
||||||
|
(ImagesLoaded. coll-id items))
|
||||||
|
|
||||||
|
;; --- Load Images
|
||||||
|
|
||||||
|
(defrecord LoadImages [coll-id]
|
||||||
|
rs/WatchEvent
|
||||||
|
(-apply-watch [_ state s]
|
||||||
|
(let [params {:coll coll-id}]
|
||||||
|
(->> (rp/req :fetch/images params)
|
||||||
|
(rx/map :payload)
|
||||||
|
(rx/map #(images-loaded coll-id %))))))
|
||||||
|
|
||||||
|
(defn load-images
|
||||||
|
[coll-id]
|
||||||
|
(LoadImages. coll-id))
|
||||||
|
|
||||||
|
;; --- Delete Images
|
||||||
|
|
||||||
|
(defrecord DeleteImage [coll-id image]
|
||||||
|
rs/UpdateEvent
|
||||||
|
(-apply-update [_ state]
|
||||||
|
(sti/dissoc-image state coll-id image))
|
||||||
|
|
||||||
|
rs/WatchEvent
|
||||||
|
(-apply-watch [_ state s]
|
||||||
|
(->> (rp/req :delete/image (:id image))
|
||||||
|
(rx/ignore))))
|
||||||
|
|
||||||
|
(defn delete-image
|
||||||
|
[coll-id image]
|
||||||
|
(DeleteImage. coll-id image))
|
||||||
|
|
||||||
|
;; --- Set Collection
|
||||||
|
|
||||||
|
(defrecord SetCollection [id]
|
||||||
|
rs/UpdateEvent
|
||||||
|
(-apply-update [_ state]
|
||||||
|
(assoc-in state [:dashboard :collection-id] id))
|
||||||
|
|
||||||
|
rs/WatchEvent
|
||||||
|
(-apply-watch [_ state s]
|
||||||
|
(rx/of (load-images id))))
|
||||||
|
|
||||||
|
(defn set-collection
|
||||||
|
[id]
|
||||||
|
(SetCollection. id))
|
||||||
|
|
||||||
|
;; --- Set Collection Type
|
||||||
|
|
||||||
|
(defrecord SetCollectionType [type]
|
||||||
|
rs/WatchEvent
|
||||||
|
(-apply-watch [_ state s]
|
||||||
|
(if (= type :builtin)
|
||||||
|
(rx/of (set-collection 1))
|
||||||
|
(let [colls (sort-by :id (vals (:images-by-id state)))]
|
||||||
|
(rx/of (set-collection (:id (first colls)))))))
|
||||||
|
|
||||||
|
rs/UpdateEvent
|
||||||
|
(-apply-update [_ state]
|
||||||
|
(as-> state $
|
||||||
|
(assoc-in $ [:dashboard :collection-type] type))))
|
||||||
|
|
||||||
|
(defn set-collection-type
|
||||||
|
[type]
|
||||||
|
{:pre [(contains? #{:builtin :own} type)]}
|
||||||
|
(SetCollectionType. type))
|
||||||
|
|
||||||
|
;; --- 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
|
||||||
|
rs/UpdateEvent
|
||||||
|
(-apply-update [_ state]
|
||||||
|
(assoc-in state [:dashboard :images-order] order))))
|
||||||
|
|
||||||
|
(defn set-images-filtering
|
||||||
|
[term]
|
||||||
|
(reify
|
||||||
|
rs/UpdateEvent
|
||||||
|
(-apply-update [_ state]
|
||||||
|
(assoc-in state [:dashboard :images-filter] term))))
|
||||||
|
|
||||||
|
(defn clear-images-filtering
|
||||||
|
[]
|
||||||
|
(reify
|
||||||
|
rs/UpdateEvent
|
||||||
|
(-apply-update [_ state]
|
||||||
|
(assoc-in state [:dashboard :images-filter] ""))))
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
(ns uxbox.library
|
(ns uxbox.library
|
||||||
(:require [uxbox.library.colors :as colors]
|
(:require [uxbox.library.colors :as colors]
|
||||||
|
[uxbox.library.images :as images]
|
||||||
[uxbox.library.icons :as icons]
|
[uxbox.library.icons :as icons]
|
||||||
[uxbox.library.fonts :as fonts]
|
[uxbox.library.fonts :as fonts]
|
||||||
[uxbox.util.data :refer (index-by-id)]))
|
[uxbox.util.data :refer (index-by-id)]))
|
||||||
|
@ -31,6 +32,16 @@
|
||||||
(def ^:const +icon-collections-by-id+
|
(def ^:const +icon-collections-by-id+
|
||||||
(index-by-id icons/+collections+))
|
(index-by-id icons/+collections+))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Images
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(def ^:const +image-collections+
|
||||||
|
images/+collections+)
|
||||||
|
|
||||||
|
(def ^:const +image-collections-by-id+
|
||||||
|
(index-by-id images/+collections+))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Fonts
|
;; Fonts
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
65
src/uxbox/library/images.cljs
Normal file
65
src/uxbox/library/images.cljs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) 2015-2016 Andrey Antukh <niwi@niwi.nz>
|
||||||
|
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||||
|
|
||||||
|
(ns uxbox.library.images)
|
||||||
|
|
||||||
|
(def ^:static +collections+
|
||||||
|
[{:name "Generic 1"
|
||||||
|
:id 1
|
||||||
|
:builtin true
|
||||||
|
:images [{:id 1
|
||||||
|
:name "image_name.jpg"
|
||||||
|
:url "https://images.unsplash.com/photo-1455098934982-64c622c5e066?crop=entropy&fit=crop&fm=jpg&h=1025&ixjsv=2.1.0&ixlib=rb-0.3.5&q=80&w=1400"
|
||||||
|
:thumbnail "https://images.unsplash.com/photo-1455098934982-64c622c5e066?crop=entropy&fit=crop&fm=jpg&h=1025&ixjsv=2.1.0&ixlib=rb-0.3.5&q=80&w=1400"}
|
||||||
|
{:id 2
|
||||||
|
:name "image_name_long_name.jpg"
|
||||||
|
:url "https://images.unsplash.com/photo-1422393462206-207b0fbd8d6b?crop=entropy&fit=crop&fm=jpg&h=1025&ixjsv=2.1.0&ixlib=rb-0.3.5&q=80&w=1925"
|
||||||
|
:thumbnail "https://images.unsplash.com/photo-1422393462206-207b0fbd8d6b?crop=entropy&fit=crop&fm=jpg&h=1025&ixjsv=2.1.0&ixlib=rb-0.3.5&q=80&w=1925"}
|
||||||
|
{:id 3
|
||||||
|
:name "image_name.jpg"
|
||||||
|
:url "https://images.unsplash.com/photo-1441986380878-c4248f5b8b5b?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=486f09671860a11e70bdd0a45e7c5014"
|
||||||
|
:thumbnail "https://images.unsplash.com/photo-1441986380878-c4248f5b8b5b?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=486f09671860a11e70bdd0a45e7c5014"}
|
||||||
|
{:id 4
|
||||||
|
:name "image_name_big_long_name.jpg"
|
||||||
|
:url "https://images.unsplash.com/photo-1423768164017-3f27c066407f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=712b919f3a2f6fc34f29040e8082b6d9"
|
||||||
|
:thumbnail "https://images.unsplash.com/photo-1423768164017-3f27c066407f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=712b919f3a2f6fc34f29040e8082b6d9"}
|
||||||
|
{:id 5
|
||||||
|
:name "image_name.jpg"
|
||||||
|
:url "https://images.unsplash.com/photo-1456428199391-a3b1cb5e93ab?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=765abd6dc931b7184e9795d8494966ed"
|
||||||
|
:thumbnail "https://images.unsplash.com/photo-1456428199391-a3b1cb5e93ab?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=765abd6dc931b7184e9795d8494966ed"}
|
||||||
|
{:id 6
|
||||||
|
:name "image_name.jpg"
|
||||||
|
:url "https://images.unsplash.com/photo-1447678523326-1360892abab8?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=91663afcd23da14f76cc8229c1780d47"
|
||||||
|
:thumbnail "https://images.unsplash.com/photo-1447678523326-1360892abab8?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=91663afcd23da14f76cc8229c1780d47"}]}
|
||||||
|
|
||||||
|
{:name "Generic 2"
|
||||||
|
:id 2
|
||||||
|
:builtin true
|
||||||
|
:images [{:id 7
|
||||||
|
:name "image_name.jpg"
|
||||||
|
:url "https://images.unsplash.com/photo-1455098934982-64c622c5e066?crop=entropy&fit=crop&fm=jpg&h=1025&ixjsv=2.1.0&ixlib=rb-0.3.5&q=80&w=1400"
|
||||||
|
:thumbnail "https://images.unsplash.com/photo-1455098934982-64c622c5e066?crop=entropy&fit=crop&fm=jpg&h=1025&ixjsv=2.1.0&ixlib=rb-0.3.5&q=80&w=1400"}
|
||||||
|
{:id 8
|
||||||
|
:name "image_name_long_name.jpg"
|
||||||
|
:url "https://images.unsplash.com/photo-1422393462206-207b0fbd8d6b?crop=entropy&fit=crop&fm=jpg&h=1025&ixjsv=2.1.0&ixlib=rb-0.3.5&q=80&w=1925"
|
||||||
|
:thumbnail "https://images.unsplash.com/photo-1422393462206-207b0fbd8d6b?crop=entropy&fit=crop&fm=jpg&h=1025&ixjsv=2.1.0&ixlib=rb-0.3.5&q=80&w=1925"}
|
||||||
|
{:id 9
|
||||||
|
:name "image_name.jpg"
|
||||||
|
:url "https://images.unsplash.com/photo-1441986380878-c4248f5b8b5b?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=486f09671860a11e70bdd0a45e7c5014"
|
||||||
|
:thumbnail "https://images.unsplash.com/photo-1441986380878-c4248f5b8b5b?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=486f09671860a11e70bdd0a45e7c5014"}
|
||||||
|
{:id 10
|
||||||
|
:name "image_name_big_long_name.jpg"
|
||||||
|
:url "https://images.unsplash.com/photo-1423768164017-3f27c066407f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=712b919f3a2f6fc34f29040e8082b6d9"
|
||||||
|
:thumbnail "https://images.unsplash.com/photo-1423768164017-3f27c066407f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=712b919f3a2f6fc34f29040e8082b6d9"}
|
||||||
|
{:id 11
|
||||||
|
:name "image_name.jpg"
|
||||||
|
:url "https://images.unsplash.com/photo-1456428199391-a3b1cb5e93ab?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=765abd6dc931b7184e9795d8494966ed"
|
||||||
|
:thumbnail "https://images.unsplash.com/photo-1456428199391-a3b1cb5e93ab?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=765abd6dc931b7184e9795d8494966ed"}
|
||||||
|
{:id 12
|
||||||
|
:name "image_name.jpg"
|
||||||
|
:url "https://images.unsplash.com/photo-1447678523326-1360892abab8?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=91663afcd23da14f76cc8229c1780d47"
|
||||||
|
:thumbnail "https://images.unsplash.com/photo-1447678523326-1360892abab8?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=91663afcd23da14f76cc8229c1780d47"}]}])
|
|
@ -15,6 +15,9 @@
|
||||||
"ds.num-colors" ["No colors"
|
"ds.num-colors" ["No colors"
|
||||||
"%s color"
|
"%s color"
|
||||||
"%s colors"]
|
"%s colors"]
|
||||||
|
"ds.num-images" ["No images"
|
||||||
|
"%s image"
|
||||||
|
"%s images"]
|
||||||
"ds.project-ordering" "Sort by"
|
"ds.project-ordering" "Sort by"
|
||||||
"ds.project-ordering.by-name" "name"
|
"ds.project-ordering.by-name" "name"
|
||||||
"ds.project-ordering.by-last-update" "last update"
|
"ds.project-ordering.by-last-update" "last update"
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
[uxbox.repo.projects]
|
[uxbox.repo.projects]
|
||||||
[uxbox.repo.pages]
|
[uxbox.repo.pages]
|
||||||
[uxbox.repo.colors]
|
[uxbox.repo.colors]
|
||||||
|
[uxbox.repo.images]
|
||||||
[httpurr.status :as status]
|
[httpurr.status :as status]
|
||||||
[beicon.core :as rx]))
|
[beicon.core :as rx]))
|
||||||
|
|
||||||
|
|
|
@ -47,14 +47,14 @@
|
||||||
(defn- send!
|
(defn- send!
|
||||||
[{:keys [body headers auth method query url] :or {auth true} :as request}]
|
[{:keys [body headers auth method query url] :or {auth true} :as request}]
|
||||||
(let [headers (merge {}
|
(let [headers (merge {}
|
||||||
(when body +headers+)
|
(when (map? body) +headers+)
|
||||||
headers
|
headers
|
||||||
(when auth (auth-headers)))
|
(when auth (auth-headers)))
|
||||||
request {:method method
|
request {:method method
|
||||||
:url url
|
:url url
|
||||||
:headers headers
|
:headers headers
|
||||||
:query-string (when query (encode-query query))
|
:query-string (when query (encode-query query))
|
||||||
:body (when body (t/encode body))}]
|
:body (if (map? body) (t/encode body) body)}]
|
||||||
(->> (http/send! request)
|
(->> (http/send! request)
|
||||||
(rx/from-promise)
|
(rx/from-promise)
|
||||||
(rx/map conditional-decode)
|
(rx/map conditional-decode)
|
||||||
|
|
80
src/uxbox/repo/images.cljs
Normal file
80
src/uxbox/repo/images.cljs
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz>
|
||||||
|
|
||||||
|
(ns uxbox.repo.images
|
||||||
|
"A main interface for access to remote resources."
|
||||||
|
(:require [beicon.core :as rx]
|
||||||
|
[uxbox.repo.core :refer (request url send!)]
|
||||||
|
[uxbox.state :as ust]
|
||||||
|
[uxbox.util.transit :as t]))
|
||||||
|
|
||||||
|
(defn- decode-image-collection
|
||||||
|
[{:keys [data] :as coll}]
|
||||||
|
coll)
|
||||||
|
;; (merge coll
|
||||||
|
;; (when data {:data (t/decode data)})))
|
||||||
|
|
||||||
|
(defn- decode-payload
|
||||||
|
[{:keys [payload] :as rsp}]
|
||||||
|
rsp)
|
||||||
|
;; (if (sequential? payload)
|
||||||
|
;; (assoc rsp :payload (mapv decode-image-collection payload))
|
||||||
|
;; (assoc rsp :payload (decode-image-collection payload))))
|
||||||
|
|
||||||
|
(defmethod request :fetch/image-collections
|
||||||
|
[_]
|
||||||
|
(let [params {:url (str url "/library/image-collections")
|
||||||
|
:method :get}]
|
||||||
|
(->> (send! params)
|
||||||
|
(rx/map decode-payload))))
|
||||||
|
|
||||||
|
(defmethod request :delete/image-collection
|
||||||
|
[_ id]
|
||||||
|
(let [url (str url "/library/image-collections/" id)]
|
||||||
|
(send! {:url url :method :delete})))
|
||||||
|
|
||||||
|
(defmethod request :create/image-collection
|
||||||
|
[_ {:keys [data] :as body}]
|
||||||
|
(let [body (assoc body :data (t/encode data))
|
||||||
|
params {:url (str url "/library/image-collections")
|
||||||
|
:method :post
|
||||||
|
:body body}]
|
||||||
|
(->> (send! params)
|
||||||
|
(rx/map decode-payload))))
|
||||||
|
|
||||||
|
(defmethod request :update/image-collection
|
||||||
|
[_ {:keys [id data] :as body}]
|
||||||
|
(let [body (assoc body :data (t/encode data))
|
||||||
|
params {:url (str url "/library/image-collections/" id)
|
||||||
|
:method :put
|
||||||
|
:body body}]
|
||||||
|
(->> (send! params)
|
||||||
|
(rx/map decode-payload))))
|
||||||
|
|
||||||
|
(defmethod request :fetch/images
|
||||||
|
[_ {:keys [coll]}]
|
||||||
|
(let [params {:url (str url "/library/images/" coll)
|
||||||
|
:method :get}]
|
||||||
|
(->> (send! params)
|
||||||
|
(rx/map decode-payload))))
|
||||||
|
|
||||||
|
(defmethod request :create/image
|
||||||
|
[_ {:keys [coll id files] :as body}]
|
||||||
|
(let [build-body (fn []
|
||||||
|
(let [data (js/FormData.)]
|
||||||
|
(.append data "file" (aget files 0))
|
||||||
|
(.append data "id" id)
|
||||||
|
data))
|
||||||
|
params {:url (str url "/library/images/" coll)
|
||||||
|
:method :post
|
||||||
|
:body (build-body)}]
|
||||||
|
(->> (send! params)
|
||||||
|
(rx/map decode-payload))))
|
||||||
|
|
||||||
|
(defmethod request :delete/image
|
||||||
|
[_ id]
|
||||||
|
(let [url (str url "/library/images/" id)]
|
||||||
|
(send! {:url url :method :delete})))
|
|
@ -25,7 +25,9 @@
|
||||||
(defn- get-initial-state
|
(defn- get-initial-state
|
||||||
[]
|
[]
|
||||||
{:dashboard {:project-order :name
|
{:dashboard {:project-order :name
|
||||||
:project-filter ""}
|
:project-filter ""
|
||||||
|
:images-order :name
|
||||||
|
:images-filter ""}
|
||||||
:route nil
|
:route nil
|
||||||
:auth (:uxbox/auth storage nil)
|
:auth (:uxbox/auth storage nil)
|
||||||
:clipboard #queue []
|
:clipboard #queue []
|
||||||
|
|
28
src/uxbox/state/images.cljs
Normal file
28
src/uxbox/state/images.cljs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
(ns uxbox.state.images
|
||||||
|
"A collection of functions for manage dashboard data insinde the state.")
|
||||||
|
|
||||||
|
(defn assoc-collection
|
||||||
|
"A reduce function for assoc the image collection
|
||||||
|
to the state map."
|
||||||
|
[state coll]
|
||||||
|
(let [id (:id coll)]
|
||||||
|
(assoc-in state [:images-by-id id] coll)))
|
||||||
|
|
||||||
|
(defn dissoc-collection
|
||||||
|
"A reduce function for dissoc the image collection
|
||||||
|
to the state map."
|
||||||
|
[state id]
|
||||||
|
(update state :images-by-id dissoc id))
|
||||||
|
|
||||||
|
(defn select-first-collection
|
||||||
|
"A reduce function for select the first image collection
|
||||||
|
to the state map."
|
||||||
|
[state]
|
||||||
|
(let [colls (sort-by :id (vals (:images-by-id state)))]
|
||||||
|
(assoc-in state [:dashboard :collection-id] (:id (first colls)))))
|
||||||
|
|
||||||
|
(defn dissoc-image
|
||||||
|
"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))
|
|
@ -8,116 +8,300 @@
|
||||||
(ns uxbox.ui.dashboard.images
|
(ns uxbox.ui.dashboard.images
|
||||||
(:require [sablono.core :as html :refer-macros [html]]
|
(:require [sablono.core :as html :refer-macros [html]]
|
||||||
[rum.core :as rum]
|
[rum.core :as rum]
|
||||||
|
[lentes.core :as l]
|
||||||
|
[uxbox.locales :as t :refer (tr)]
|
||||||
|
[uxbox.state :as st]
|
||||||
[uxbox.rstore :as rs]
|
[uxbox.rstore :as rs]
|
||||||
|
[uxbox.library :as library]
|
||||||
[uxbox.data.dashboard :as dd]
|
[uxbox.data.dashboard :as dd]
|
||||||
[uxbox.data.lightbox :as udl]
|
[uxbox.data.lightbox :as udl]
|
||||||
|
[uxbox.data.images :as di]
|
||||||
[uxbox.ui.icons :as i]
|
[uxbox.ui.icons :as i]
|
||||||
[uxbox.ui.mixins :as mx]
|
[uxbox.ui.mixins :as mx]
|
||||||
[uxbox.ui.lightbox :as lbx]
|
[uxbox.ui.lightbox :as lbx]
|
||||||
|
[uxbox.ui.keyboard :as k]
|
||||||
[uxbox.ui.library-bar :as ui.library-bar]
|
[uxbox.ui.library-bar :as ui.library-bar]
|
||||||
[uxbox.ui.dashboard.header :refer (header)]
|
[uxbox.ui.dashboard.header :refer (header)]
|
||||||
|
[uxbox.util.lens :as ul]
|
||||||
[uxbox.util.dom :as dom]))
|
[uxbox.util.dom :as dom]))
|
||||||
|
|
||||||
|
;; --- Helpers & Constants
|
||||||
|
|
||||||
|
(def +ordering-options+
|
||||||
|
{:name "ds.project-ordering.by-name"
|
||||||
|
:created "ds.project-ordering.by-creation-date"})
|
||||||
|
|
||||||
|
;; --- Lenses
|
||||||
|
|
||||||
|
(def ^:const ^:private dashboard-l
|
||||||
|
(-> (l/key :dashboard)
|
||||||
|
(l/focus-atom st/state)))
|
||||||
|
|
||||||
|
(def ^:const ^: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)))
|
||||||
|
|
||||||
|
|
||||||
|
(defn- focus-collection
|
||||||
|
[collid]
|
||||||
|
(-> (l/key collid)
|
||||||
|
(l/focus-atom collections-by-id-l)))
|
||||||
|
|
||||||
|
|
||||||
;; --- Page Title
|
;; --- Page Title
|
||||||
|
|
||||||
(defn page-title-render
|
(defn page-title-render
|
||||||
[]
|
[own coll]
|
||||||
(html
|
(let [local (:rum/local own)
|
||||||
[:div.dashboard-title
|
dashboard (rum/react dashboard-l)
|
||||||
[:h2 "Element library name"]
|
own? (:builtin coll false)]
|
||||||
[:div.edition
|
(letfn [(on-title-save [e]
|
||||||
[:span i/pencil]
|
(rs/emit! (di/rename-collection (:id coll) (:coll-name @local)))
|
||||||
[:span i/trash]]]))
|
(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)
|
||||||
|
:else (let [content (dom/event->inner-text e)]
|
||||||
|
(swap! local assoc :coll-name content))))
|
||||||
|
(on-title-edit [e]
|
||||||
|
(swap! local assoc :edit true :coll-name (:name coll)))
|
||||||
|
(on-delete [e]
|
||||||
|
(rs/emit! (di/delete-collection (:id coll))))]
|
||||||
|
(html
|
||||||
|
[:div.dashboard-title {}
|
||||||
|
[:h2 {}
|
||||||
|
(if (:edit @local)
|
||||||
|
[:div.dashboard-title-field
|
||||||
|
[:span.edit
|
||||||
|
{:content-editable ""
|
||||||
|
:on-key-up on-title-edited}
|
||||||
|
(:name coll)]
|
||||||
|
[:span.close
|
||||||
|
{:on-click #(swap! local assoc :edit false)}
|
||||||
|
i/close]]
|
||||||
|
[:span.dashboard-title-field
|
||||||
|
(:name coll)])]
|
||||||
|
(if (and (not own?) coll)
|
||||||
|
[:div.edition
|
||||||
|
(if (:edit @local)
|
||||||
|
[:span {:on-click on-title-save} i/save]
|
||||||
|
[:span {:on-click on-title-edit} i/pencil])
|
||||||
|
[:span {:on-click on-delete} i/trash]])]))))
|
||||||
|
|
||||||
(def ^:const ^:private page-title
|
(def ^:private page-title
|
||||||
(mx/component
|
(mx/component
|
||||||
{:render page-title-render
|
{:render page-title-render
|
||||||
:name "page-title"
|
:name "page-title"
|
||||||
:mixins [mx/static]}))
|
:mixins [(rum/local {}) mx/static rum/reactive]}))
|
||||||
|
|
||||||
|
;; --- Nav
|
||||||
|
|
||||||
|
(defn nav-render
|
||||||
|
[own]
|
||||||
|
(let [dashboard (rum/react dashboard-l)
|
||||||
|
collections-by-id (rum/react collections-by-id-l)
|
||||||
|
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 $)))]
|
||||||
|
(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))}
|
||||||
|
"STANDARD"]
|
||||||
|
[:li {:class-name (when own? "current")
|
||||||
|
:on-click #(rs/emit! (di/set-collection-type :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)]
|
||||||
|
[:span.element-subtitle
|
||||||
|
(tr "ds.num-elements" (t/c num))]])]]])))
|
||||||
|
|
||||||
|
(def ^:const ^:private nav
|
||||||
|
(mx/component
|
||||||
|
{:render nav-render
|
||||||
|
:name "nav"
|
||||||
|
:mixins [rum/reactive]}))
|
||||||
|
|
||||||
|
|
||||||
;; --- Grid
|
;; --- Grid
|
||||||
|
|
||||||
(defn grid-render
|
(defn grid-render
|
||||||
[own]
|
[own]
|
||||||
(html
|
(let [local (:rum/local own)
|
||||||
[:div.dashboard-grid-content
|
dashboard (rum/react dashboard-l)
|
||||||
[:div.dashboard-grid-row
|
coll-type (:collection-type dashboard)
|
||||||
[:div.grid-item.add-project
|
coll-id (:collection-id dashboard)
|
||||||
{on-click #(udl/open! :new-element)}
|
own? (= coll-type :own)
|
||||||
[:span "+ New image"]]
|
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 %)))}]])
|
||||||
|
|
||||||
[:div.grid-item.images-th
|
(for [image coll-images]
|
||||||
[:div.grid-item-th
|
[:div.grid-item.images-th
|
||||||
{:style
|
{:key (:id image) :on-click #(when (k/shift? %) (toggle-image-check image))}
|
||||||
{:background-image "url('https://images.unsplash.com/photo-1455098934982-64c622c5e066?crop=entropy&fit=crop&fm=jpg&h=1025&ixjsv=2.1.0&ixlib=rb-0.3.5&q=80&w=1400')"}}
|
[:div.grid-item-th
|
||||||
[:div.input-checkbox.check-primary
|
{:style
|
||||||
[:input {:type "checkbox" :id "item-1" :value "Yes"}]
|
{:background-image (str "url('" (:thumbnail image) "')")}}
|
||||||
[:label {:for "item-1"}]]]
|
[:div.input-checkbox.check-primary
|
||||||
[:span "image_name.jpg"]]
|
[:input {:type "checkbox"
|
||||||
|
:id (:id image)
|
||||||
|
:on-click #(toggle-image-check image)
|
||||||
|
:checked ((:selected @local) image)}]
|
||||||
|
[:label {:for (:id image)}]]]
|
||||||
|
[:span (:name image)]])]
|
||||||
|
|
||||||
[:div.grid-item.images-th
|
(when (not (empty? (:selected @local)))
|
||||||
[:div.grid-item-th
|
;; MULTISELECT OPTIONS BAR
|
||||||
{:style
|
[:div.multiselect-bar
|
||||||
{:background-image "url('https://images.unsplash.com/photo-1422393462206-207b0fbd8d6b?crop=entropy&fit=crop&fm=jpg&h=1025&ixjsv=2.1.0&ixlib=rb-0.3.5&q=80&w=1925')"}}
|
[:div.multiselect-nav
|
||||||
[:div.input-checkbox.check-primary
|
[:span.move-item.tooltip.tooltip-top
|
||||||
[:input {:type "checkbox" :id "item-2" :value "Yes"}]
|
{:alt "Copy to"}
|
||||||
[:label {:for "item-2"}]]]
|
i/organize]
|
||||||
[:span "image_name_long_name.jpg"]]
|
(if own?
|
||||||
|
[:span.copy.tooltip.tooltip-top
|
||||||
[:div.grid-item.images-th
|
{:alt "Duplicate"}
|
||||||
[:div.grid-item-th
|
i/copy])
|
||||||
{:style
|
(if own?
|
||||||
{:background-image "url('https://images.unsplash.com/photo-1441986380878-c4248f5b8b5b?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=486f09671860a11e70bdd0a45e7c5014')"}}
|
[:span.delete.tooltip.tooltip-top
|
||||||
[:div.input-checkbox.check-primary
|
{:alt "Delete"
|
||||||
[:input {:type "checkbox" :id "item-3" :value "Yes"}]
|
:on-click #(delete-selected-images)}
|
||||||
[:label {:for "item-3"}]]]
|
i/trash])]])]]))))
|
||||||
[:span "image_name.jpg"]]
|
|
||||||
|
|
||||||
[:div.grid-item.images-th
|
|
||||||
[:div.grid-item-th
|
|
||||||
{:style
|
|
||||||
{:background-image "url('https://images.unsplash.com/photo-1423768164017-3f27c066407f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=712b919f3a2f6fc34f29040e8082b6d9')"}}
|
|
||||||
[:div.input-checkbox.check-primary
|
|
||||||
[:input {:type "checkbox" :id "item-4" :value "Yes"}]
|
|
||||||
[:label {:for "item-4"}]]]
|
|
||||||
[:span "image_name_big_long_name.jpg"]]
|
|
||||||
|
|
||||||
[:div.grid-item.images-th
|
|
||||||
[:div.grid-item-th
|
|
||||||
{:style
|
|
||||||
{:background-image "url('https://images.unsplash.com/photo-1456428199391-a3b1cb5e93ab?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=765abd6dc931b7184e9795d8494966ed')"}}
|
|
||||||
[:div.input-checkbox.check-primary
|
|
||||||
[:input {:type "checkbox" :id "item-5" :value "Yes"}]
|
|
||||||
[:label {:for "item-5"}]]]
|
|
||||||
[:span "image_name.jpg"]]
|
|
||||||
|
|
||||||
[:div.grid-item.images-th
|
|
||||||
[:div.grid-item-th
|
|
||||||
{:style
|
|
||||||
{:background-image "url('https://images.unsplash.com/photo-1447678523326-1360892abab8?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=91663afcd23da14f76cc8229c1780d47')"}}
|
|
||||||
[:div.input-checkbox.check-primary
|
|
||||||
[:input {:type "checkbox" :id "item-6" :value "Yes"}]
|
|
||||||
[:label {:for "item-6"}]]]
|
|
||||||
[:span "image_name.jpg"]]]
|
|
||||||
|
|
||||||
;; MULTISELECT OPTIONS BAR
|
|
||||||
[:div.multiselect-bar
|
|
||||||
[:div.multiselect-nav
|
|
||||||
[:span.move-item.tooltip.tooltip-top
|
|
||||||
{:alt "Move to"}
|
|
||||||
i/organize]
|
|
||||||
[:span.copy.tooltip.tooltip-top
|
|
||||||
{:alt "Duplicate"}
|
|
||||||
i/copy]
|
|
||||||
[:span.delete.tooltip.tooltip-top
|
|
||||||
{:alt "Delete"}
|
|
||||||
i/trash]]]]))
|
|
||||||
|
|
||||||
(def ^:const ^:private grid
|
(def ^:const ^:private grid
|
||||||
(mx/component
|
(mx/component
|
||||||
{:render grid-render
|
{:render grid-render
|
||||||
:name "grid"
|
:name "grid"
|
||||||
:mixins [mx/static]}))
|
:mixins [(rum/local {:selected #{}})
|
||||||
|
mx/static
|
||||||
|
rum/reactive]}))
|
||||||
|
|
||||||
|
;; --- Sort Widget
|
||||||
|
|
||||||
|
(defn sort-widget-render
|
||||||
|
[]
|
||||||
|
(let [ordering (rum/react images-ordering-l)
|
||||||
|
on-change #(rs/emit! (di/set-images-ordering
|
||||||
|
(keyword (.-value (.-target %)))))]
|
||||||
|
(html
|
||||||
|
[:div
|
||||||
|
[:span (tr "ds.project-ordering")]
|
||||||
|
[:select.input-select
|
||||||
|
{:on-change on-change
|
||||||
|
:value (:name ordering)}
|
||||||
|
(for [option (keys +ordering-options+)
|
||||||
|
:let [option-id (get +ordering-options+ option)
|
||||||
|
option-value (:name option)
|
||||||
|
option-text (tr option-id)]]
|
||||||
|
[:option
|
||||||
|
{:key option-id
|
||||||
|
:value option-value}
|
||||||
|
option-text])]])))
|
||||||
|
|
||||||
|
(def ^:private sort-widget
|
||||||
|
(mx/component
|
||||||
|
{:render sort-widget-render
|
||||||
|
:name "sort-widget-render"
|
||||||
|
:mixins [rum/reactive mx/static]}))
|
||||||
|
|
||||||
|
;; --- Filtering Widget
|
||||||
|
|
||||||
|
(defn search-widget-render
|
||||||
|
[]
|
||||||
|
(letfn [(on-term-change [event]
|
||||||
|
(-> (dom/get-target event)
|
||||||
|
(dom/get-value)
|
||||||
|
(di/set-images-filtering)
|
||||||
|
(rs/emit!)))
|
||||||
|
(on-clear [event]
|
||||||
|
(rs/emit! (di/clear-images-filtering)))]
|
||||||
|
(html
|
||||||
|
[:form.dashboard-search
|
||||||
|
[:input.input-text
|
||||||
|
{:key :images-search-box
|
||||||
|
:type "text"
|
||||||
|
:on-change on-term-change
|
||||||
|
:auto-focus true
|
||||||
|
:placeholder (tr "ds.project-search.placeholder")
|
||||||
|
:value (rum/react images-filtering-l)}]
|
||||||
|
[:div.clear-search
|
||||||
|
{:on-click on-clear}
|
||||||
|
i/close]])))
|
||||||
|
|
||||||
|
(def ^:private search-widget
|
||||||
|
(mx/component
|
||||||
|
{:render search-widget-render
|
||||||
|
:name "search-widget"
|
||||||
|
:mixins [rum/reactive mx/static]}))
|
||||||
|
|
||||||
|
|
||||||
|
;; --- Menu
|
||||||
|
|
||||||
|
(defn menu-render
|
||||||
|
[]
|
||||||
|
(let [dashboard (rum/react dashboard-l)
|
||||||
|
coll-id (:collection-id dashboard)
|
||||||
|
coll (rum/react (focus-collection coll-id))
|
||||||
|
icount (count (:images coll)) ]
|
||||||
|
(html
|
||||||
|
[:section.dashboard-bar.library-gap
|
||||||
|
[:div.dashboard-info
|
||||||
|
[:span.dashboard-images (tr "ds.num-images" (t/c icount))]
|
||||||
|
(sort-widget)
|
||||||
|
(search-widget)]])))
|
||||||
|
|
||||||
|
(def menu
|
||||||
|
(mx/component
|
||||||
|
{:render menu-render
|
||||||
|
:name "menu"
|
||||||
|
:mixins [rum/reactive mx/static]}))
|
||||||
|
|
||||||
|
|
||||||
;; --- Images Page
|
;; --- Images Page
|
||||||
|
|
||||||
|
@ -127,14 +311,14 @@
|
||||||
[:main.dashboard-main
|
[:main.dashboard-main
|
||||||
(header)
|
(header)
|
||||||
[:section.dashboard-content
|
[:section.dashboard-content
|
||||||
(ui.library-bar/library-bar)
|
(nav)
|
||||||
[:section.dashboard-grid.library
|
(menu)
|
||||||
(page-title)
|
(grid)]]))
|
||||||
(grid)]]]))
|
|
||||||
|
|
||||||
(defn images-page-will-mount
|
(defn images-page-will-mount
|
||||||
[own]
|
[own]
|
||||||
(rs/emit! (dd/initialize :dashboard/images))
|
(rs/emit! (dd/initialize :dashboard/images)
|
||||||
|
(di/initialize))
|
||||||
own)
|
own)
|
||||||
|
|
||||||
(defn images-page-transfer-state
|
(defn images-page-transfer-state
|
||||||
|
|
|
@ -50,6 +50,16 @@
|
||||||
[node]
|
[node]
|
||||||
(.-value node))
|
(.-value node))
|
||||||
|
|
||||||
|
(defn click
|
||||||
|
"Click a node"
|
||||||
|
[node]
|
||||||
|
(.click node))
|
||||||
|
|
||||||
|
(defn get-files
|
||||||
|
"Extract the files from dom node."
|
||||||
|
[node]
|
||||||
|
(.-files node))
|
||||||
|
|
||||||
(defn checked?
|
(defn checked?
|
||||||
"Check if the node that reprsents a radio
|
"Check if the node that reprsents a radio
|
||||||
or checkbox is checked or not."
|
or checkbox is checked or not."
|
||||||
|
@ -59,3 +69,8 @@
|
||||||
(defn ^boolean equals?
|
(defn ^boolean equals?
|
||||||
[node-a node-b]
|
[node-a node-b]
|
||||||
(.isEqualNode node-a node-b))
|
(.isEqualNode node-a node-b))
|
||||||
|
|
||||||
|
(defn get-event-files
|
||||||
|
"Extract the files from event instance."
|
||||||
|
[event]
|
||||||
|
(get-files (get-target event)))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue