mirror of
https://github.com/penpot/penpot.git
synced 2026-09-06 20:18:39 +00:00
Major images page refactor.
This commit is contained in:
parent
5b995f78aa
commit
2143bb6e04
@ -2,8 +2,7 @@
|
|||||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
;; 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/.
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
;;
|
;;
|
||||||
;; Copyright (c) 2015-2016 Andrey Antukh <niwi@niwi.nz>
|
;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz>
|
||||||
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
|
||||||
|
|
||||||
(ns uxbox.main.data.images
|
(ns uxbox.main.data.images
|
||||||
(:require [cuerdas.core :as str]
|
(:require [cuerdas.core :as str]
|
||||||
@ -26,10 +25,8 @@
|
|||||||
(defrecord Initialize [type id]
|
(defrecord Initialize [type id]
|
||||||
rs/UpdateEvent
|
rs/UpdateEvent
|
||||||
(-apply-update [_ state]
|
(-apply-update [_ state]
|
||||||
(let [type (or type :builtin)
|
(let [type (or type :own)
|
||||||
id (or id (if (= type :builtin) 1 nil))
|
|
||||||
data {:type type :id id :selected #{}}]
|
data {:type type :id id :selected #{}}]
|
||||||
(println "initialize:" data)
|
|
||||||
(-> state
|
(-> state
|
||||||
(assoc-in [:dashboard :images] data)
|
(assoc-in [:dashboard :images] data)
|
||||||
(assoc-in [:dashboard :section] :dashboard/images))))
|
(assoc-in [:dashboard :section] :dashboard/images))))
|
||||||
@ -159,8 +156,8 @@
|
|||||||
(rx/of (update-collection id))))
|
(rx/of (update-collection id))))
|
||||||
|
|
||||||
(defn rename-collection
|
(defn rename-collection
|
||||||
[item name]
|
[id name]
|
||||||
(RenameCollection. item name))
|
(RenameCollection. id name))
|
||||||
|
|
||||||
;; --- Delete Collection
|
;; --- Delete Collection
|
||||||
|
|
||||||
@ -193,7 +190,7 @@
|
|||||||
|
|
||||||
(def allowed-file-types #{"image/jpeg" "image/png"})
|
(def allowed-file-types #{"image/jpeg" "image/png"})
|
||||||
|
|
||||||
(defrecord CreateImages [coll-id files]
|
(defrecord CreateImages [id files]
|
||||||
rs/WatchEvent
|
rs/WatchEvent
|
||||||
(-apply-watch [_ state s]
|
(-apply-watch [_ state s]
|
||||||
(letfn [(image-size [file]
|
(letfn [(image-size [file]
|
||||||
@ -202,7 +199,7 @@
|
|||||||
(allowed-file? [file]
|
(allowed-file? [file]
|
||||||
(contains? allowed-file-types (.-type file)))
|
(contains? allowed-file-types (.-type file)))
|
||||||
(prepare [[file [width height]]]
|
(prepare [[file [width height]]]
|
||||||
{:coll coll-id
|
{:collection id
|
||||||
:mimetype (.-type file)
|
:mimetype (.-type file)
|
||||||
:id (uuid/random)
|
:id (uuid/random)
|
||||||
:file file
|
:file file
|
||||||
@ -217,12 +214,13 @@
|
|||||||
(rx/map image-created)))))
|
(rx/map image-created)))))
|
||||||
|
|
||||||
(defn create-images
|
(defn create-images
|
||||||
[coll-id files]
|
[id files]
|
||||||
(CreateImages. coll-id files))
|
{:pre [(or (uuid? id) (nil? id))]}
|
||||||
|
(CreateImages. id files))
|
||||||
|
|
||||||
;; --- Images Fetched
|
;; --- Images Fetched
|
||||||
|
|
||||||
(defrecord ImagesFetched [coll-id items]
|
(defrecord ImagesFetched [items]
|
||||||
rs/UpdateEvent
|
rs/UpdateEvent
|
||||||
(-apply-update [_ state]
|
(-apply-update [_ state]
|
||||||
(reduce (fn [state {:keys [id] :as image}]
|
(reduce (fn [state {:keys [id] :as image}]
|
||||||
@ -231,58 +229,77 @@
|
|||||||
items)))
|
items)))
|
||||||
|
|
||||||
(defn images-fetched
|
(defn images-fetched
|
||||||
[coll-id items]
|
[items]
|
||||||
(ImagesFetched. coll-id items))
|
(ImagesFetched. items))
|
||||||
|
|
||||||
;; --- Fetch Images
|
;; --- Fetch Images
|
||||||
|
|
||||||
(defrecord FetchImages [coll-id]
|
(defrecord FetchImages [id]
|
||||||
rs/WatchEvent
|
rs/WatchEvent
|
||||||
(-apply-watch [_ state s]
|
(-apply-watch [_ state s]
|
||||||
(let [params {:coll coll-id}]
|
(let [params {:coll id}]
|
||||||
(->> (rp/req :fetch/images params)
|
(->> (rp/req :fetch/images params)
|
||||||
(rx/map :payload)
|
(rx/map :payload)
|
||||||
(rx/map #(images-fetched coll-id %))))))
|
(rx/map images-fetched)))))
|
||||||
|
|
||||||
(defn fetch-images
|
(defn fetch-images
|
||||||
[coll-id]
|
"Fetch a list of images of the selected collection"
|
||||||
(FetchImages. coll-id))
|
[id]
|
||||||
|
{:pre [(or (uuid? id) (nil? id))]}
|
||||||
|
(FetchImages. id))
|
||||||
|
|
||||||
|
;; --- Fetch Image
|
||||||
|
|
||||||
|
(declare image-fetched)
|
||||||
|
|
||||||
|
(defrecord FetchImage [id]
|
||||||
|
rs/WatchEvent
|
||||||
|
(-apply-watch [_ state stream]
|
||||||
|
(let [existing (get-in state [:images-by-id id])]
|
||||||
|
(if existing
|
||||||
|
(rx/empty)
|
||||||
|
(->> (rp/req :fetch/image {:id id})
|
||||||
|
(rx/map :payload)
|
||||||
|
(rx/map image-fetched))))))
|
||||||
|
|
||||||
|
(defn fetch-image
|
||||||
|
"Conditionally fetch image by its id. If image
|
||||||
|
is already loaded, this event is noop."
|
||||||
|
[id]
|
||||||
|
{:pre [(uuid? id)]}
|
||||||
|
(FetchImage. id))
|
||||||
|
|
||||||
|
;; --- Image Fetched
|
||||||
|
|
||||||
|
(defrecord ImageFetched [image]
|
||||||
|
rs/UpdateEvent
|
||||||
|
(-apply-update [_ state]
|
||||||
|
(let [id (:id image)]
|
||||||
|
(update state :images-by-id assoc id image))))
|
||||||
|
|
||||||
|
(defn image-fetched
|
||||||
|
[image]
|
||||||
|
{:pre [(map? image)]}
|
||||||
|
(ImageFetched. image))
|
||||||
|
|
||||||
;; --- Delete Images
|
;; --- Delete Images
|
||||||
|
|
||||||
(defrecord DeleteImage [coll-id image-id]
|
(defrecord DeleteImage [id]
|
||||||
rs/UpdateEvent
|
rs/UpdateEvent
|
||||||
(-apply-update [_ state]
|
(-apply-update [_ state]
|
||||||
(update state [:images-by-id] dissoc image-id))
|
(-> state
|
||||||
|
(update :images-by-id dissoc id)
|
||||||
|
(update-in [:dashboard :images :selected] disj id)))
|
||||||
|
|
||||||
rs/WatchEvent
|
rs/WatchEvent
|
||||||
(-apply-watch [_ state s]
|
(-apply-watch [_ state s]
|
||||||
(->> (rp/req :delete/image image-id)
|
(->> (rp/req :delete/image id)
|
||||||
(rx/ignore))))
|
(rx/ignore))))
|
||||||
|
|
||||||
(defn delete-image
|
(defn delete-image
|
||||||
[coll-id image-id]
|
[id]
|
||||||
{:pre [(uuid? coll-id)
|
{:pre [(uuid? id)]}
|
||||||
(uuid? image-id)]}
|
(DeleteImage. id))
|
||||||
(DeleteImage. coll-id image-id))
|
|
||||||
|
|
||||||
;; --- Remove Image
|
|
||||||
|
|
||||||
(defrecord RemoveImages [id images]
|
|
||||||
rs/UpdateEvent
|
|
||||||
(-apply-update [_ state]
|
|
||||||
#_(update-in state [:image-colls-by-id id :data]
|
|
||||||
#(set/difference % images)))
|
|
||||||
|
|
||||||
rs/WatchEvent
|
|
||||||
(-apply-watch [_ state s]
|
|
||||||
(rx/of (update-collection id))))
|
|
||||||
|
|
||||||
(defn remove-images
|
|
||||||
"Remove image in a collection."
|
|
||||||
[id images]
|
|
||||||
(RemoveImages. id images))
|
|
||||||
|
|
||||||
|
|
||||||
;; --- Select image
|
;; --- Select image
|
||||||
|
|
||||||
@ -314,9 +331,9 @@
|
|||||||
(defrecord DeleteSelected []
|
(defrecord DeleteSelected []
|
||||||
rs/WatchEvent
|
rs/WatchEvent
|
||||||
(-apply-watch [_ state stream]
|
(-apply-watch [_ state stream]
|
||||||
(let [{:keys [id selected]} (get-in state [:dashboard :images])]
|
(let [selected (get-in state [:dashboard :images :selected])]
|
||||||
(rx/of (remove-images id selected)
|
(->> (rx/from-coll selected)
|
||||||
#(assoc-in % [:dashboard :images :selected] #{})))))
|
(rx/map delete-image)))))
|
||||||
|
|
||||||
(defn delete-selected
|
(defn delete-selected
|
||||||
[]
|
[]
|
||||||
|
|||||||
@ -40,20 +40,28 @@
|
|||||||
|
|
||||||
(defmethod request :fetch/images
|
(defmethod request :fetch/images
|
||||||
[_ {:keys [coll]}]
|
[_ {:keys [coll]}]
|
||||||
(let [params {:url (str url "/library/image-collections/" coll "/images")
|
(let [url (if coll
|
||||||
|
(str url "/library/image-collections/" coll "/images")
|
||||||
|
(str url "/library/image-collections/images"))
|
||||||
|
params {:url url :method :get}]
|
||||||
|
(send! params)))
|
||||||
|
|
||||||
|
(defmethod request :fetch/image
|
||||||
|
[_ {:keys [id]}]
|
||||||
|
(let [params {:url (str url "/library/images/" id)
|
||||||
:method :get}]
|
:method :get}]
|
||||||
(send! params)))
|
(send! params)))
|
||||||
|
|
||||||
(defmethod request :create/image
|
(defmethod request :create/image
|
||||||
[_ {:keys [coll id file width height mimetype] :as body}]
|
[_ {:keys [collection id file width height mimetype] :as body}]
|
||||||
(let [body (doto (js/FormData.)
|
(let [body (doto (js/FormData.)
|
||||||
(.append "mimetype" mimetype)
|
(.append "mimetype" mimetype)
|
||||||
;; (.append "collection" (str coll))
|
(.append "collection" (str collection))
|
||||||
(.append "file" file)
|
(.append "file" file)
|
||||||
(.append "width" width)
|
(.append "width" width)
|
||||||
(.append "height" height)
|
(.append "height" height)
|
||||||
(.append "id" id))
|
(.append "id" id))
|
||||||
params {:url (str url "/library/image-collections/" coll "/images")
|
params {:url (str url "/library/images/")
|
||||||
:method :post
|
:method :post
|
||||||
:body body}]
|
:body body}]
|
||||||
(send! params)))
|
(send! params)))
|
||||||
|
|||||||
@ -166,19 +166,148 @@
|
|||||||
(defn- new-element-lightbox-render
|
(defn- new-element-lightbox-render
|
||||||
[own]
|
[own]
|
||||||
(html
|
(html
|
||||||
[:div.lightbox-body
|
;;------Element lightbox
|
||||||
[:h3 "New element"]
|
|
||||||
[:div.row-flex
|
;;[:div.lightbox-body
|
||||||
[:div.lightbox-big-btn
|
;;[:h3 "New element"]
|
||||||
[:span.big-svg i/shapes]
|
;;[:div.row-flex
|
||||||
[:span.text "Go to workspace"]]
|
;;[:div.lightbox-big-btn
|
||||||
[:div.lightbox-big-btn
|
;;[:span.big-svg i/shapes]
|
||||||
[:span.big-svg.upload i/exit]
|
;;[:span.text "Go to workspace"]]
|
||||||
[:span.text "Upload file"]]]
|
;;[:div.lightbox-big-btn
|
||||||
|
;;[:span.big-svg.upload i/exit]
|
||||||
|
;;[:span.text "Upload file"]]]
|
||||||
|
;;[:a.close {:href "#"
|
||||||
|
;;:on-click #(do (dom/prevent-default %)
|
||||||
|
;;(udl/close!))}
|
||||||
|
;;i/close]]
|
||||||
|
|
||||||
|
;;------Upload image lightbox
|
||||||
|
|
||||||
|
;;[:div.lightbox-body
|
||||||
|
;;[:h3 "Import image"]
|
||||||
|
;;[:div.row-flex
|
||||||
|
;;[:div.lightbox-big-btn
|
||||||
|
;;[:span.big-svg i/image]
|
||||||
|
;;[:span.text "Select from library"]]
|
||||||
|
;;[:div.lightbox-big-btn
|
||||||
|
;;[:span.big-svg.upload i/exit]
|
||||||
|
;;[:span.text "Upload file"]]]
|
||||||
|
;;[:a.close {:href "#"
|
||||||
|
;;:on-click #(do (dom/prevent-default %)
|
||||||
|
;;(udl/close!))}
|
||||||
|
;;i/close]]
|
||||||
|
|
||||||
|
;;------Upload image library lightbox
|
||||||
|
|
||||||
|
[:div.lightbox-body.big-lightbox
|
||||||
|
[:h3 "Import image from library"]
|
||||||
|
[:div.import-img-library
|
||||||
|
[:div.library-actions
|
||||||
|
[:ul.toggle-library
|
||||||
|
[:li.standard.current "STANDARD"]
|
||||||
|
[:li.your-images "YOUR IMAGES"]]
|
||||||
|
[:select.input-select
|
||||||
|
[:option "Library 1"]
|
||||||
|
[:option "Library 2"]
|
||||||
|
[:option "Library 3"]
|
||||||
|
[:option "Library 4"]
|
||||||
|
[:option "Library 5"]
|
||||||
|
[:option "Library 6"]]]
|
||||||
|
|
||||||
|
[:div.library-content
|
||||||
|
|
||||||
|
[:div.library-item
|
||||||
|
[:div.library-item-th
|
||||||
|
{:style
|
||||||
|
{: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 "image_name.jpg"]]
|
||||||
|
|
||||||
|
[:div.library-item
|
||||||
|
[:div.library-item-th
|
||||||
|
{:style
|
||||||
|
{: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 "image_name.jpg"]]
|
||||||
|
|
||||||
|
[:div.library-item
|
||||||
|
[:div.library-item-th
|
||||||
|
{:style
|
||||||
|
{: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 "image_name.jpg"]]
|
||||||
|
|
||||||
|
[:div.library-item
|
||||||
|
[:div.library-item-th
|
||||||
|
{:style
|
||||||
|
{: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 "image_name.jpg"]]
|
||||||
|
|
||||||
|
[:div.library-item
|
||||||
|
[:div.library-item-th
|
||||||
|
{:style
|
||||||
|
{: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 "image_name.jpg"]]
|
||||||
|
|
||||||
|
[:div.library-item
|
||||||
|
[:div.library-item-th
|
||||||
|
{:style
|
||||||
|
{: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 "image_name.jpg"]]
|
||||||
|
|
||||||
|
[:div.library-item
|
||||||
|
[:div.library-item-th
|
||||||
|
{:style
|
||||||
|
{: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 "image_name.jpg"]]
|
||||||
|
|
||||||
|
[:div.library-item
|
||||||
|
[:div.library-item-th
|
||||||
|
{:style
|
||||||
|
{: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 "image_name.jpg"]]
|
||||||
|
|
||||||
|
[:div.library-item
|
||||||
|
[:div.library-item-th
|
||||||
|
{:style
|
||||||
|
{: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 "image_name.jpg"]]
|
||||||
|
|
||||||
|
[:div.library-item
|
||||||
|
[:div.library-item-th
|
||||||
|
{:style
|
||||||
|
{: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 "image_name.jpg"]]
|
||||||
|
|
||||||
|
[:div.library-item
|
||||||
|
[:div.library-item-th
|
||||||
|
{:style
|
||||||
|
{: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 "image_name.jpg"]]
|
||||||
|
|
||||||
|
[:div.library-item
|
||||||
|
[:div.library-item-th
|
||||||
|
{:style
|
||||||
|
{: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 "image_name.jpg"]]
|
||||||
|
|
||||||
|
[:div.library-item
|
||||||
|
[:div.library-item-th
|
||||||
|
{:style
|
||||||
|
{: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 "image_name.jpg"]]
|
||||||
|
|
||||||
|
[:div.library-item
|
||||||
|
[:div.library-item-th
|
||||||
|
{:style
|
||||||
|
{: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 "image_name.jpg"]]
|
||||||
|
|
||||||
|
]]
|
||||||
[:a.close {:href "#"
|
[:a.close {:href "#"
|
||||||
:on-click #(do (dom/prevent-default %)
|
:on-click #(do (dom/prevent-default %)
|
||||||
(udl/close!))}
|
(udl/close!))}
|
||||||
i/close]]))
|
i/close]]
|
||||||
|
|
||||||
|
))
|
||||||
|
|
||||||
(def ^:private new-element-lightbox
|
(def ^:private new-element-lightbox
|
||||||
(mx/component
|
(mx/component
|
||||||
|
|||||||
@ -6,25 +6,19 @@
|
|||||||
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||||
|
|
||||||
(ns uxbox.main.ui.dashboard.images
|
(ns uxbox.main.ui.dashboard.images
|
||||||
(:require [sablono.core :as html :refer-macros [html]]
|
(:require [cuerdas.core :as str]
|
||||||
[rum.core :as rum]
|
|
||||||
[cuerdas.core :as str]
|
|
||||||
[lentes.core :as l]
|
[lentes.core :as l]
|
||||||
[uxbox.util.i18n :as t :refer (tr)]
|
[uxbox.util.i18n :as t :refer (tr)]
|
||||||
[uxbox.main.state :as st]
|
[uxbox.main.state :as st]
|
||||||
[uxbox.util.rstore :as rs]
|
[uxbox.util.rstore :as rs]
|
||||||
[uxbox.main.library :as library]
|
|
||||||
[uxbox.main.data.dashboard :as dd]
|
|
||||||
[uxbox.main.data.lightbox :as udl]
|
[uxbox.main.data.lightbox :as udl]
|
||||||
[uxbox.main.data.images :as di]
|
[uxbox.main.data.images :as di]
|
||||||
[uxbox.main.ui.icons :as i]
|
[uxbox.main.ui.icons :as i]
|
||||||
[uxbox.util.mixins :as mx :include-macros true]
|
[uxbox.util.mixins :as mx :include-macros true]
|
||||||
[uxbox.main.ui.lightbox :as lbx]
|
[uxbox.main.ui.lightbox :as lbx]
|
||||||
[uxbox.main.ui.keyboard :as kbd]
|
[uxbox.main.ui.keyboard :as kbd]
|
||||||
[uxbox.main.ui.library-bar :as ui.library-bar]
|
|
||||||
[uxbox.main.ui.dashboard.header :refer (header)]
|
[uxbox.main.ui.dashboard.header :refer (header)]
|
||||||
[uxbox.util.data :as data :refer (read-string)]
|
[uxbox.util.data :as data :refer (read-string)]
|
||||||
[uxbox.util.lens :as ul]
|
|
||||||
[uxbox.util.dom :as dom]))
|
[uxbox.util.dom :as dom]))
|
||||||
|
|
||||||
;; --- Helpers & Constants
|
;; --- Helpers & Constants
|
||||||
@ -65,15 +59,6 @@
|
|||||||
(-> (l/key :images-by-id)
|
(-> (l/key :images-by-id)
|
||||||
(l/derive st/state)))
|
(l/derive st/state)))
|
||||||
|
|
||||||
;; (def ^:private collections-ref
|
|
||||||
;; (-> (l/lens vals)
|
|
||||||
;; (l/derive collections-map-ref)))
|
|
||||||
|
|
||||||
;; (defn- focus-collection
|
|
||||||
;; [id]
|
|
||||||
;; (-> (l/key id)
|
|
||||||
;; (l/derive collections-map-ref)))
|
|
||||||
|
|
||||||
;; --- Page Title
|
;; --- Page Title
|
||||||
|
|
||||||
(mx/defcs page-title
|
(mx/defcs page-title
|
||||||
@ -117,7 +102,7 @@
|
|||||||
[:span.close {:on-click on-cancel} i/close]]
|
[:span.close {:on-click on-cancel} i/close]]
|
||||||
[:span.dashboard-title-field
|
[:span.dashboard-title-field
|
||||||
{:on-double-click on-edit}
|
{:on-double-click on-edit}
|
||||||
(:name coll)])]
|
(:name coll "Storage")])]
|
||||||
(if (and (not own?) coll)
|
(if (and (not own?) coll)
|
||||||
[:div.edition
|
[:div.edition
|
||||||
(if edit?
|
(if edit?
|
||||||
@ -127,19 +112,26 @@
|
|||||||
|
|
||||||
;; --- Nav
|
;; --- Nav
|
||||||
|
|
||||||
|
(defn react-count-images
|
||||||
|
[id]
|
||||||
|
(->> (mx/react images-ref)
|
||||||
|
(vals)
|
||||||
|
(filter #(= id (:collection %)))
|
||||||
|
(count)))
|
||||||
|
|
||||||
(mx/defc nav-item
|
(mx/defc nav-item
|
||||||
{:mixins [mx/static]}
|
{:mixins [mx/static mx/reactive]}
|
||||||
[collection selected?]
|
[{:keys [id type name] :as coll} selected?]
|
||||||
(letfn [(on-click [event]
|
(letfn [(on-click [event]
|
||||||
(let [type (:type collection)
|
(let [type (or type :own)]
|
||||||
id (:id collection)]
|
|
||||||
(rs/emit! (di/select-collection type id))))]
|
(rs/emit! (di/select-collection type id))))]
|
||||||
(let [images (count (:images collection []))]
|
(let [num-images (react-count-images id)]
|
||||||
[:li {:on-click on-click
|
[:li {:on-click on-click
|
||||||
:class-name (when selected? "current")}
|
:class-name (when selected? "current")}
|
||||||
[:span.element-title (:name collection)]
|
[:span.element-title
|
||||||
|
(if coll name "Storage")]
|
||||||
[:span.element-subtitle
|
[:span.element-subtitle
|
||||||
(tr "ds.num-elements" (t/c images))]])))
|
(tr "ds.num-elements" (t/c num-images))]])))
|
||||||
|
|
||||||
(mx/defc nav-section
|
(mx/defc nav-section
|
||||||
{:mixins [mx/static mx/reactive]}
|
{:mixins [mx/static mx/reactive]}
|
||||||
@ -156,6 +148,8 @@
|
|||||||
[:a.btn-primary
|
[:a.btn-primary
|
||||||
{:on-click #(rs/emit! (di/create-collection))}
|
{:on-click #(rs/emit! (di/create-collection))}
|
||||||
"+ New library"]])
|
"+ New library"]])
|
||||||
|
(when own?
|
||||||
|
(nav-item nil (nil? selected)))
|
||||||
(for [coll collections
|
(for [coll collections
|
||||||
:let [selected? (= (:id coll) selected)
|
:let [selected? (= (:id coll) selected)
|
||||||
key (str (:id coll))]]
|
key (str (:id coll))]]
|
||||||
@ -179,12 +173,13 @@
|
|||||||
[:div.library-bar
|
[:div.library-bar
|
||||||
[:div.library-bar-inside
|
[:div.library-bar-inside
|
||||||
[:ul.library-tabs
|
[:ul.library-tabs
|
||||||
[:li {:class-name (when builtin? "current")
|
|
||||||
:on-click (partial select-tab :builtin)}
|
|
||||||
"STANDARD"]
|
|
||||||
[:li {:class-name (when own? "current")
|
[:li {:class-name (when own? "current")
|
||||||
:on-click (partial select-tab :own)}
|
:on-click (partial select-tab :own)}
|
||||||
"YOUR LIBRARIES"]]
|
"YOUR IMAGES"]
|
||||||
|
[:li {:class-name (when builtin? "current")
|
||||||
|
:on-click (partial select-tab :builtin)}
|
||||||
|
"IMAGES STORE"]]
|
||||||
|
|
||||||
(nav-section type id colls)]])))
|
(nav-section type id colls)]])))
|
||||||
|
|
||||||
;; --- Grid
|
;; --- Grid
|
||||||
@ -208,15 +203,15 @@
|
|||||||
:on-change on-file-selected}]]))
|
:on-change on-file-selected}]]))
|
||||||
|
|
||||||
(mx/defc grid-options
|
(mx/defc grid-options
|
||||||
[coll]
|
[{:keys [type] :as coll}]
|
||||||
(let [own? (= (:type coll) :own)]
|
(let [editable? (or (= type :own) (nil? coll))]
|
||||||
(letfn [(delete []
|
(letfn [(delete []
|
||||||
(rs/emit! (di/delete-selected)))
|
(rs/emit! (di/delete-selected)))
|
||||||
(on-delete [event]
|
(on-delete [event]
|
||||||
(udl/open! :confirm {:on-accept delete}))]
|
(udl/open! :confirm {:on-accept delete}))]
|
||||||
;; MULTISELECT OPTIONS BAR
|
;; MULTISELECT OPTIONS BAR
|
||||||
[:div.multiselect-bar
|
[:div.multiselect-bar
|
||||||
(if own?
|
(if editable?
|
||||||
[:div.multiselect-nav
|
[:div.multiselect-nav
|
||||||
#_[:span.move-item.tooltip.tooltip-top
|
#_[:span.move-item.tooltip.tooltip-top
|
||||||
{:alt "Move to"}
|
{:alt "Move to"}
|
||||||
@ -251,19 +246,18 @@
|
|||||||
|
|
||||||
(mx/defc grid
|
(mx/defc grid
|
||||||
{:mixins [mx/static mx/reactive]}
|
{:mixins [mx/static mx/reactive]}
|
||||||
[{:keys [id type selected] :as state}]
|
[{:keys [id type selected] :as state}]
|
||||||
(let [filtering (:filter state)
|
(let [editable? (or (= type :own) (nil? id))
|
||||||
|
filtering (:filter state)
|
||||||
ordering (:order state)
|
ordering (:order state)
|
||||||
own? (= type :own)
|
images (mx/react images-ref)
|
||||||
images (rum/react images-ref)
|
|
||||||
images (->> (vals images)
|
images (->> (vals images)
|
||||||
(filter #(= id (:collection %)))
|
(filter #(= id (:collection %)))
|
||||||
(filter-images-by filtering)
|
(filter-images-by filtering)
|
||||||
(sort-images-by ordering))]
|
(sort-images-by ordering))]
|
||||||
[:div.dashboard-grid-content
|
[:div.dashboard-grid-content
|
||||||
[:div.dashboard-grid-row
|
[:div.dashboard-grid-row
|
||||||
(when own?
|
(when editable? (grid-form id))
|
||||||
(grid-form id))
|
|
||||||
(for [image images
|
(for [image images
|
||||||
:let [id (:id image)
|
:let [id (:id image)
|
||||||
selected? (contains? selected id)]]
|
selected? (contains? selected id)]]
|
||||||
@ -273,13 +267,11 @@
|
|||||||
(mx/defc content
|
(mx/defc content
|
||||||
{:mixins [mx/static]}
|
{:mixins [mx/static]}
|
||||||
[{:keys [type id selected] :as state} coll]
|
[{:keys [type id selected] :as state} coll]
|
||||||
(let [own? (= type :own)]
|
[:section.dashboard-grid.library
|
||||||
(when coll
|
(page-title coll)
|
||||||
[:section.dashboard-grid.library
|
(grid state)
|
||||||
(page-title coll)
|
(when (seq selected)
|
||||||
(grid state)
|
(grid-options coll))])
|
||||||
(when (seq selected)
|
|
||||||
(grid-options coll))])))
|
|
||||||
|
|
||||||
;; --- Menu
|
;; --- Menu
|
||||||
|
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
[uxbox.main.ui.shapes.circle :as circle]
|
[uxbox.main.ui.shapes.circle :as circle]
|
||||||
[uxbox.main.ui.shapes.text :as text]
|
[uxbox.main.ui.shapes.text :as text]
|
||||||
[uxbox.main.ui.shapes.path :as path]
|
[uxbox.main.ui.shapes.path :as path]
|
||||||
|
[uxbox.main.ui.shapes.image :as image]
|
||||||
[uxbox.main.geom :as geom]))
|
[uxbox.main.geom :as geom]))
|
||||||
|
|
||||||
;; --- Helpers
|
;; --- Helpers
|
||||||
@ -34,6 +35,7 @@
|
|||||||
:icon (icon/icon-component shape)
|
:icon (icon/icon-component shape)
|
||||||
:rect (rect/rect-component shape)
|
:rect (rect/rect-component shape)
|
||||||
:path (path/path-component shape)
|
:path (path/path-component shape)
|
||||||
|
:image (image/image-component shape)
|
||||||
:circle (circle/circle-component shape)))
|
:circle (circle/circle-component shape)))
|
||||||
|
|
||||||
(mx/defc component-container
|
(mx/defc component-container
|
||||||
|
|||||||
73
src/uxbox/main/ui/shapes/image.cljs
Normal file
73
src/uxbox/main/ui/shapes/image.cljs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
;; 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.main.ui.shapes.image
|
||||||
|
(:require [beicon.core :as rx]
|
||||||
|
[lentes.core :as l]
|
||||||
|
[uxbox.util.mixins :as mx :include-macros true]
|
||||||
|
[uxbox.util.http :as http]
|
||||||
|
[uxbox.util.rstore :as rs]
|
||||||
|
[uxbox.main.state :as st]
|
||||||
|
[uxbox.main.ui.shapes.common :as common]
|
||||||
|
[uxbox.main.ui.shapes.attrs :as attrs]
|
||||||
|
[uxbox.main.data.images :as udi]
|
||||||
|
[uxbox.main.geom :as geom]))
|
||||||
|
|
||||||
|
;; --- Refs
|
||||||
|
|
||||||
|
(defn image-ref
|
||||||
|
[id]
|
||||||
|
(-> (l/in [:images-by-id id])
|
||||||
|
(l/derive st/state)))
|
||||||
|
|
||||||
|
;; --- Image Component
|
||||||
|
|
||||||
|
(declare image-shape)
|
||||||
|
|
||||||
|
(defn- will-mount
|
||||||
|
[own]
|
||||||
|
(let [{:keys [image-id]} (first (:rum/args own))]
|
||||||
|
(rs/emit! (udi/fetch-image image-id))
|
||||||
|
own))
|
||||||
|
|
||||||
|
(mx/defcs image-component
|
||||||
|
{:mixins [mx/static mx/reactive]
|
||||||
|
:will-mount will-mount}
|
||||||
|
[own {:keys [id image-id] :as shape}]
|
||||||
|
(let [selected (mx/react common/selected-ref)
|
||||||
|
image (mx/react (image-ref image-id))
|
||||||
|
selected? (contains? selected id)
|
||||||
|
local (:rum/local own)
|
||||||
|
on-mouse-down #(common/on-mouse-down % shape selected)]
|
||||||
|
(when image
|
||||||
|
[:g.shape {:class (when selected? "selected")
|
||||||
|
:on-mouse-down on-mouse-down}
|
||||||
|
(image-shape (assoc shape :image image))])))
|
||||||
|
|
||||||
|
;; --- Image Shape
|
||||||
|
|
||||||
|
(mx/defc image-shape
|
||||||
|
{:mixins [mx/static]}
|
||||||
|
[{:keys [id x1 y1 image] :as shape}]
|
||||||
|
(let [key (str "shape-" id)
|
||||||
|
;; rfm (geom/transformation-matrix shape)
|
||||||
|
size (geom/size shape)
|
||||||
|
props {:x x1 :y y1 :id key :key key
|
||||||
|
:preserve-aspect-ratio "none"
|
||||||
|
:xlink-href (:url image)}
|
||||||
|
attrs (-> (attrs/extract-style-attrs shape)
|
||||||
|
(merge props size))]
|
||||||
|
[:image attrs]))
|
||||||
|
|
||||||
|
;; --- Image SVG
|
||||||
|
|
||||||
|
(mx/defc image-svg
|
||||||
|
{:mixins [mx/static]}
|
||||||
|
[{:keys [data id view-box] :as shape}]
|
||||||
|
(let [key (str "image-svg-" id)
|
||||||
|
view-box (apply str (interpose " " view-box))
|
||||||
|
props {:view-box view-box :id key :key key}]
|
||||||
|
[:svg props data]))
|
||||||
Loading…
x
Reference in New Issue
Block a user