mirror of
https://github.com/penpot/penpot.git
synced 2025-04-04 19:11:20 -05:00
❄️ integration with new items
This commit is contained in:
parent
b2474fc3fb
commit
5b7182fac6
14 changed files with 1549 additions and 1332 deletions
|
@ -1125,5 +1125,8 @@
|
|||
"translations" : {
|
||||
"en" : "Click to close the path"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"modal.create-color.new-color": "New Color",
|
||||
"modal.create-color.edit-color": "Edit Color"
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ body {
|
|||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
transition: all .4s ease;
|
||||
// transition: all .4s ease;
|
||||
}
|
||||
|
||||
.global-zeroclipboard-container {
|
||||
|
|
|
@ -285,3 +285,53 @@
|
|||
top: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.modal-create-color {
|
||||
position: relative;
|
||||
background-color: $color-white;
|
||||
padding: 4rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
& .sketch-picker {
|
||||
box-shadow: none !important;
|
||||
border: 1px solid $color-gray-lighter !important;
|
||||
border-radius: 0 !important;
|
||||
|
||||
& input {
|
||||
background-color: $color-white;
|
||||
}
|
||||
}
|
||||
|
||||
& .close {
|
||||
position: absolute;
|
||||
right: 1rem;
|
||||
transform: rotate(45deg);
|
||||
top: 1rem;
|
||||
|
||||
svg {
|
||||
fill: $color-black;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
|
||||
&:hover {
|
||||
fill: $color-danger;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
& .btn-primary {
|
||||
width: 10rem;
|
||||
padding: 0.5rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-create-color-title {
|
||||
color: $color-black;
|
||||
font-size: 24px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
|
|
@ -19,230 +19,230 @@
|
|||
[uxbox.util.time :as dt]
|
||||
[uxbox.util.uuid :as uuid]))
|
||||
|
||||
;; TODO: need a good refactor
|
||||
|
||||
;; --- Initialize
|
||||
|
||||
(declare fetch-collections)
|
||||
(declare persist-collections)
|
||||
(declare collections-fetched?)
|
||||
|
||||
;; --- Collections Fetched
|
||||
|
||||
(defrecord CollectionsFetched [data]
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [{:keys [version value]} data]
|
||||
(-> state
|
||||
(update :colors-collections merge value)
|
||||
(assoc ::version version)))))
|
||||
|
||||
(defn collections-fetched
|
||||
[data]
|
||||
{:pre [(map? data)]}
|
||||
(CollectionsFetched. data))
|
||||
|
||||
(defn collections-fetched?
|
||||
[v]
|
||||
(instance? CollectionsFetched v))
|
||||
|
||||
;; --- Fetch Collections
|
||||
|
||||
(defrecord FetchCollections []
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(->> (rp/query! :user-attr {:key "color-collections"})
|
||||
(rx/map collections-fetched)
|
||||
(rx/catch (fn [{:keys [type] :as error}]
|
||||
(if (= type :not-found)
|
||||
(rx/empty)
|
||||
(rx/throw error)))))))
|
||||
|
||||
(defn fetch-collections
|
||||
[]
|
||||
(FetchCollections.))
|
||||
|
||||
;; --- Create Collection
|
||||
|
||||
(defrecord CreateCollection [id]
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [item {:name (tr "ds.default-library-title" (gensym "c"))
|
||||
:id id
|
||||
:created-at (dt/now)
|
||||
:type :own
|
||||
:colors #{}}]
|
||||
(assoc-in state [:colors-collections id] item)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(rx/of (persist-collections)
|
||||
(rt/nav :dashboard/colors nil {:type :own :id id}))))
|
||||
|
||||
(defn create-collection
|
||||
[]
|
||||
(let [id (uuid/next)]
|
||||
(CreateCollection. id)))
|
||||
|
||||
;; --- Persist Collections
|
||||
|
||||
(defrecord PersistCollections []
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [builtin? #(= :builtin (:type %))
|
||||
xform (remove (comp builtin? second))
|
||||
version (or (get state ::version) -1)
|
||||
value (->> (get state :colors-collections)
|
||||
(into {} xform))
|
||||
data {:key "color-collections"
|
||||
:val value}]
|
||||
(->> (rp/mutation! :upsert-user-attr data)
|
||||
(rx/map collections-fetched)))))
|
||||
|
||||
(defn persist-collections
|
||||
[]
|
||||
(PersistCollections.))
|
||||
|
||||
;; --- Rename Collection
|
||||
|
||||
(defrecord RenameCollection [id name]
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:colors-collections id :name] name))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(rx/of (persist-collections))))
|
||||
|
||||
(defn rename-collection
|
||||
[item name]
|
||||
(RenameCollection. item name))
|
||||
|
||||
;; --- Delete Collection
|
||||
|
||||
(defrecord DeleteCollection [id]
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :colors-collections dissoc id))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(rx/of (persist-collections))))
|
||||
|
||||
(defn delete-collection
|
||||
[id]
|
||||
(DeleteCollection. id))
|
||||
|
||||
;; --- Replace Color
|
||||
|
||||
(defrecord AddColor [coll-id color]
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update-in state [:colors-collections coll-id :colors] set/union #{color}))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(rx/of (persist-collections))))
|
||||
|
||||
(defn add-color
|
||||
"Add or replace color in a collection."
|
||||
[coll-id color]
|
||||
(AddColor. coll-id color))
|
||||
|
||||
;; --- Remove Color
|
||||
|
||||
(defrecord RemoveColors [id colors]
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update-in state [:colors-collections id :colors]
|
||||
#(set/difference % colors)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(rx/of (persist-collections))))
|
||||
|
||||
(defn remove-colors
|
||||
"Remove color in a collection."
|
||||
[id colors]
|
||||
(RemoveColors. id colors))
|
||||
|
||||
;; --- Select color
|
||||
|
||||
(defrecord SelectColor [color]
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update-in state [:dashboard :colors :selected] conj color)))
|
||||
|
||||
(defrecord DeselectColor [color]
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update-in state [:dashboard :colors :selected] disj color)))
|
||||
|
||||
(defrecord ToggleColorSelection [color]
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [selected (get-in state [:dashboard :colors :selected])]
|
||||
(rx/of
|
||||
(if (selected color)
|
||||
(DeselectColor. color)
|
||||
(SelectColor. color))))))
|
||||
|
||||
(defn toggle-color-selection
|
||||
[color]
|
||||
{:pre [(color/hex? color)]}
|
||||
(ToggleColorSelection. color))
|
||||
|
||||
;; --- Copy Selected Color
|
||||
|
||||
(defrecord CopySelected [id]
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [selected (get-in state [:dashboard :colors :selected])]
|
||||
(update-in state [:colors-collections id :colors] set/union selected)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(rx/of (persist-collections))))
|
||||
|
||||
(defn copy-selected
|
||||
[id]
|
||||
{:pre [(or (uuid? id) (nil? id))]}
|
||||
(CopySelected. id))
|
||||
|
||||
;; --- Move Selected Color
|
||||
|
||||
(defrecord MoveSelected [from to]
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [selected (get-in state [:dashboard :colors :selected])]
|
||||
(-> state
|
||||
(update-in [:colors-collections from :colors] set/difference selected)
|
||||
(update-in [:colors-collections to :colors] set/union selected))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(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 Colors
|
||||
|
||||
(defrecord DeleteColors [coll-id colors]
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:dashboard :colors :selected] #{}))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(rx/of (remove-colors coll-id colors))))
|
||||
|
||||
(defn delete-colors
|
||||
[coll-id colors]
|
||||
(DeleteColors. coll-id colors))
|
||||
;; ;; TODO: need a good refactor
|
||||
;;
|
||||
;; ;; --- Initialize
|
||||
;;
|
||||
;; (declare fetch-collections)
|
||||
;; (declare persist-collections)
|
||||
;; (declare collections-fetched?)
|
||||
;;
|
||||
;; ;; --- Collections Fetched
|
||||
;;
|
||||
;; (defrecord CollectionsFetched [data]
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (let [{:keys [version value]} data]
|
||||
;; (-> state
|
||||
;; (update :colors-collections merge value)
|
||||
;; (assoc ::version version)))))
|
||||
;;
|
||||
;; (defn collections-fetched
|
||||
;; [data]
|
||||
;; {:pre [(map? data)]}
|
||||
;; (CollectionsFetched. data))
|
||||
;;
|
||||
;; (defn collections-fetched?
|
||||
;; [v]
|
||||
;; (instance? CollectionsFetched v))
|
||||
;;
|
||||
;; ;; --- Fetch Collections
|
||||
;;
|
||||
;; (defrecord FetchCollections []
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state s]
|
||||
;; (->> (rp/query! :user-attr {:key "color-collections"})
|
||||
;; (rx/map collections-fetched)
|
||||
;; (rx/catch (fn [{:keys [type] :as error}]
|
||||
;; (if (= type :not-found)
|
||||
;; (rx/empty)
|
||||
;; (rx/throw error)))))))
|
||||
;;
|
||||
;; (defn fetch-collections
|
||||
;; []
|
||||
;; (FetchCollections.))
|
||||
;;
|
||||
;; ;; --- Create Collection
|
||||
;;
|
||||
;; (defrecord CreateCollection [id]
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (let [item {:name (tr "ds.default-library-title" (gensym "c"))
|
||||
;; :id id
|
||||
;; :created-at (dt/now)
|
||||
;; :type :own
|
||||
;; :colors #{}}]
|
||||
;; (assoc-in state [:colors-collections id] item)))
|
||||
;;
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state stream]
|
||||
;; (rx/of (persist-collections)
|
||||
;; (rt/nav :dashboard/colors nil {:type :own :id id}))))
|
||||
;;
|
||||
;; (defn create-collection
|
||||
;; []
|
||||
;; (let [id (uuid/next)]
|
||||
;; (CreateCollection. id)))
|
||||
;;
|
||||
;; ;; --- Persist Collections
|
||||
;;
|
||||
;; (defrecord PersistCollections []
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state stream]
|
||||
;; (let [builtin? #(= :builtin (:type %))
|
||||
;; xform (remove (comp builtin? second))
|
||||
;; version (or (get state ::version) -1)
|
||||
;; value (->> (get state :colors-collections)
|
||||
;; (into {} xform))
|
||||
;; data {:key "color-collections"
|
||||
;; :val value}]
|
||||
;; (->> (rp/mutation! :upsert-user-attr data)
|
||||
;; (rx/map collections-fetched)))))
|
||||
;;
|
||||
;; (defn persist-collections
|
||||
;; []
|
||||
;; (PersistCollections.))
|
||||
;;
|
||||
;; ;; --- Rename Collection
|
||||
;;
|
||||
;; (defrecord RenameCollection [id name]
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (assoc-in state [:colors-collections id :name] name))
|
||||
;;
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state s]
|
||||
;; (rx/of (persist-collections))))
|
||||
;;
|
||||
;; (defn rename-collection
|
||||
;; [item name]
|
||||
;; (RenameCollection. item name))
|
||||
;;
|
||||
;; ;; --- Delete Collection
|
||||
;;
|
||||
;; (defrecord DeleteCollection [id]
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (update state :colors-collections dissoc id))
|
||||
;;
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state s]
|
||||
;; (rx/of (persist-collections))))
|
||||
;;
|
||||
;; (defn delete-collection
|
||||
;; [id]
|
||||
;; (DeleteCollection. id))
|
||||
;;
|
||||
;; ;; --- Replace Color
|
||||
;;
|
||||
;; (defrecord AddColor [coll-id color]
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (update-in state [:colors-collections coll-id :colors] set/union #{color}))
|
||||
;;
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state s]
|
||||
;; (rx/of (persist-collections))))
|
||||
;;
|
||||
;; (defn add-color
|
||||
;; "Add or replace color in a collection."
|
||||
;; [coll-id color]
|
||||
;; (AddColor. coll-id color))
|
||||
;;
|
||||
;; ;; --- Remove Color
|
||||
;;
|
||||
;; (defrecord RemoveColors [id colors]
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (update-in state [:colors-collections id :colors]
|
||||
;; #(set/difference % colors)))
|
||||
;;
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state s]
|
||||
;; (rx/of (persist-collections))))
|
||||
;;
|
||||
;; (defn remove-colors
|
||||
;; "Remove color in a collection."
|
||||
;; [id colors]
|
||||
;; (RemoveColors. id colors))
|
||||
;;
|
||||
;; ;; --- Select color
|
||||
;;
|
||||
;; (defrecord SelectColor [color]
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (update-in state [:dashboard :colors :selected] conj color)))
|
||||
;;
|
||||
;; (defrecord DeselectColor [color]
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (update-in state [:dashboard :colors :selected] disj color)))
|
||||
;;
|
||||
;; (defrecord ToggleColorSelection [color]
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state stream]
|
||||
;; (let [selected (get-in state [:dashboard :colors :selected])]
|
||||
;; (rx/of
|
||||
;; (if (selected color)
|
||||
;; (DeselectColor. color)
|
||||
;; (SelectColor. color))))))
|
||||
;;
|
||||
;; (defn toggle-color-selection
|
||||
;; [color]
|
||||
;; {:pre [(color/hex? color)]}
|
||||
;; (ToggleColorSelection. color))
|
||||
;;
|
||||
;; ;; --- Copy Selected Color
|
||||
;;
|
||||
;; (defrecord CopySelected [id]
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (let [selected (get-in state [:dashboard :colors :selected])]
|
||||
;; (update-in state [:colors-collections id :colors] set/union selected)))
|
||||
;;
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state stream]
|
||||
;; (rx/of (persist-collections))))
|
||||
;;
|
||||
;; (defn copy-selected
|
||||
;; [id]
|
||||
;; {:pre [(or (uuid? id) (nil? id))]}
|
||||
;; (CopySelected. id))
|
||||
;;
|
||||
;; ;; --- Move Selected Color
|
||||
;;
|
||||
;; (defrecord MoveSelected [from to]
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (let [selected (get-in state [:dashboard :colors :selected])]
|
||||
;; (-> state
|
||||
;; (update-in [:colors-collections from :colors] set/difference selected)
|
||||
;; (update-in [:colors-collections to :colors] set/union selected))))
|
||||
;;
|
||||
;; ptk/WatchEvent
|
||||
;; (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 Colors
|
||||
;;
|
||||
;; (defrecord DeleteColors [coll-id colors]
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (assoc-in state [:dashboard :colors :selected] #{}))
|
||||
;;
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state stream]
|
||||
;; (rx/of (remove-colors coll-id colors))))
|
||||
;;
|
||||
;; (defn delete-colors
|
||||
;; [coll-id colors]
|
||||
;; (DeleteColors. coll-id colors))
|
||||
|
||||
|
||||
;;;; NEW
|
||||
|
@ -287,3 +287,43 @@
|
|||
(update [_ state]
|
||||
(-> state
|
||||
(assoc-in [:library :selected-items] data)))))
|
||||
|
||||
(declare create-color-library-result)
|
||||
|
||||
(defn create-color-library
|
||||
[team-id name]
|
||||
(ptk/reify ::create-color-library
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(->> (rp/mutation! :create-color-library {:team-id team-id
|
||||
:name name})
|
||||
(rx/map create-color-library-result)))))
|
||||
|
||||
(defn create-color-library-result [result]
|
||||
(ptk/reify ::create-color-library-result
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(update-in [:library :color-libraries] #(into [result] %))))))
|
||||
|
||||
(declare create-color-result)
|
||||
|
||||
(defn create-color
|
||||
[library-id color]
|
||||
(s/assert (s/nilable uuid?) library-id)
|
||||
(ptk/reify ::create-color
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
|
||||
(->> (rp/mutation! :create-color {:library-id library-id
|
||||
:content color
|
||||
:name color})
|
||||
(rx/map create-color-result)))))
|
||||
|
||||
(defn create-color-result
|
||||
[item]
|
||||
(ptk/reify ::create-color-result
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(update-in [:library :selected-items] #(into [item] %) )))))
|
||||
|
|
|
@ -76,6 +76,26 @@
|
|||
(-> state
|
||||
(assoc-in [:library :selected-items] data)))))
|
||||
|
||||
(declare create-icon-library-result)
|
||||
|
||||
(defn create-icon-library
|
||||
[team-id name]
|
||||
(ptk/reify ::create-icon-library
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(->> (rp/mutation! :create-icon-library {:team-id team-id
|
||||
:name name})
|
||||
(rx/map create-icon-library-result)))))
|
||||
|
||||
(defn create-icon-library-result [result]
|
||||
(ptk/reify ::create-icon-library-result
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(update-in [:library :icon-libraries] #(into [result] %))))))
|
||||
|
||||
|
||||
|
||||
;; (declare fetch-icons)
|
||||
;;
|
||||
;; (defn initialize
|
||||
|
@ -92,32 +112,32 @@
|
|||
;;
|
||||
;; --- Fetch Collections
|
||||
|
||||
(declare collections-fetched)
|
||||
|
||||
(def fetch-collections
|
||||
(ptk/reify ::fetch-collections
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(->> (rp/query! :icons-collections)
|
||||
(rx/map collections-fetched)))))
|
||||
|
||||
;; --- Collections Fetched
|
||||
|
||||
(defn collections-fetched
|
||||
[items]
|
||||
(s/assert (s/every ::collection) items)
|
||||
(ptk/reify ::collections-fetched
|
||||
cljs.core/IDeref
|
||||
(-deref [_] items)
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(reduce (fn [state {:keys [id user] :as item}]
|
||||
(let [type (if (uuid/zero? (:user-id item)) :builtin :own)
|
||||
item (assoc item :type type)]
|
||||
(assoc-in state [:icons-collections id] item)))
|
||||
state
|
||||
items))))
|
||||
;; (declare collections-fetched)
|
||||
;;
|
||||
;; (def fetch-collections
|
||||
;; (ptk/reify ::fetch-collections
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state s]
|
||||
;; (->> (rp/query! :icons-collections)
|
||||
;; (rx/map collections-fetched)))))
|
||||
;;
|
||||
;; ;; --- Collections Fetched
|
||||
;;
|
||||
;; (defn collections-fetched
|
||||
;; [items]
|
||||
;; (s/assert (s/every ::collection) items)
|
||||
;; (ptk/reify ::collections-fetched
|
||||
;; cljs.core/IDeref
|
||||
;; (-deref [_] items)
|
||||
;;
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (reduce (fn [state {:keys [id user] :as item}]
|
||||
;; (let [type (if (uuid/zero? (:user-id item)) :builtin :own)
|
||||
;; item (assoc item :type type)]
|
||||
;; (assoc-in state [:icons-collections id] item)))
|
||||
;; state
|
||||
;; items))))
|
||||
|
||||
|
||||
;; ;; --- Create Collection
|
||||
|
@ -175,77 +195,75 @@
|
|||
;; (rx/tap on-success)
|
||||
;; (rx/ignore)))))
|
||||
;;
|
||||
;; ;; --- Icon Created
|
||||
;;
|
||||
;; (defrecord IconCreated [item]
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (let [{:keys [id] :as item} (assoc item :type :icon)]
|
||||
;; (update state :icons assoc id item))))
|
||||
;;
|
||||
;; (defn icon-created
|
||||
;; [item]
|
||||
;; (IconCreated. item))
|
||||
;;
|
||||
;; ;; --- Create Icon
|
||||
;;
|
||||
;; (declare icon-created)
|
||||
;;
|
||||
;; (defn- parse-svg
|
||||
;; [data]
|
||||
;; (s/assert ::us/string data)
|
||||
;; (let [valid-tags #{"defs" "path" "circle" "rect" "metadata" "g"
|
||||
;; "radialGradient" "stop"}
|
||||
;; div (dom/create-element "div")
|
||||
;; gc (dom/create-element "div")
|
||||
;; g (dom/create-element "http://www.w3.org/2000/svg" "g")
|
||||
;; _ (dom/set-html! div data)
|
||||
;; svg (dom/query div "svg")]
|
||||
;; (loop [child (dom/get-first-child svg)]
|
||||
;; (if child
|
||||
;; (let [tagname (dom/get-tag-name child)]
|
||||
;; (if (contains? valid-tags tagname)
|
||||
;; (dom/append-child! g child)
|
||||
;; (dom/append-child! gc child))
|
||||
;; (recur (dom/get-first-child svg)))
|
||||
;; (let [width (.. svg -width -baseVal -value)
|
||||
;; height (.. svg -height -baseVal -value)
|
||||
;; view-box [(.. svg -viewBox -baseVal -x)
|
||||
;; (.. svg -viewBox -baseVal -y)
|
||||
;; (.. svg -viewBox -baseVal -width)
|
||||
;; (.. svg -viewBox -baseVal -height)]
|
||||
;; props {:width width
|
||||
;; :mimetype "image/svg+xml"
|
||||
;; :height height
|
||||
;; :view-box view-box}]
|
||||
;; [(dom/get-outer-html g) props])))))
|
||||
;;
|
||||
;;
|
||||
;; (defn create-icons
|
||||
;; [id files]
|
||||
;; (s/assert (s/nilable uuid?) id)
|
||||
;; (ptk/reify ::create-icons
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state s]
|
||||
;; (letfn [(parse [file]
|
||||
;; (->> (wapi/read-file-as-text file)
|
||||
;; (rx/map parse-svg)))
|
||||
;; (allowed? [file]
|
||||
;; (= (.-type file) "image/svg+xml"))
|
||||
;; (prepare [[content metadata]]
|
||||
;; {:collection-id id
|
||||
;; :content content
|
||||
;; :id (uuid/next)
|
||||
;; ;; TODO Keep the name of the original icon
|
||||
;; :name (str "Icon " (gensym "i"))
|
||||
;; :metadata metadata})]
|
||||
;; (->> (rx/from files)
|
||||
;; (rx/filter allowed?)
|
||||
;; (rx/merge-map parse)
|
||||
;; (rx/map prepare)
|
||||
;; (rx/flat-map #(rp/mutation! :create-icon %))
|
||||
;; (rx/map icon-created))))))
|
||||
;;
|
||||
;; --- Icon Created
|
||||
|
||||
;; --- Create Icon
|
||||
(defn- parse-svg
|
||||
[data]
|
||||
(s/assert ::us/string data)
|
||||
(let [valid-tags #{"defs" "path" "circle" "rect" "metadata" "g"
|
||||
"radialGradient" "stop"}
|
||||
div (dom/create-element "div")
|
||||
gc (dom/create-element "div")
|
||||
g (dom/create-element "http://www.w3.org/2000/svg" "g")
|
||||
_ (dom/set-html! div data)
|
||||
svg (dom/query div "svg")]
|
||||
(loop [child (dom/get-first-child svg)]
|
||||
(if child
|
||||
(let [tagname (dom/get-tag-name child)]
|
||||
(if (contains? valid-tags tagname)
|
||||
(dom/append-child! g child)
|
||||
(dom/append-child! gc child))
|
||||
(recur (dom/get-first-child svg)))
|
||||
(let [width (.. svg -width -baseVal -value)
|
||||
height (.. svg -height -baseVal -value)
|
||||
view-box [(.. svg -viewBox -baseVal -x)
|
||||
(.. svg -viewBox -baseVal -y)
|
||||
(.. svg -viewBox -baseVal -width)
|
||||
(.. svg -viewBox -baseVal -height)]
|
||||
props {:width width
|
||||
:mimetype "image/svg+xml"
|
||||
:height height
|
||||
:view-box view-box}]
|
||||
[(dom/get-outer-html g) props])))))
|
||||
|
||||
|
||||
(declare create-icon-result)
|
||||
|
||||
(defn create-icons
|
||||
[library-id files]
|
||||
(s/assert (s/nilable uuid?) library-id)
|
||||
(ptk/reify ::create-icons
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(letfn [(parse [file]
|
||||
(->> (wapi/read-file-as-text file)
|
||||
(rx/map parse-svg)))
|
||||
(allowed? [file]
|
||||
(= (.-type file) "image/svg+xml"))
|
||||
(prepare [[content metadata]]
|
||||
{:library-id library-id
|
||||
:content content
|
||||
:id (uuid/next)
|
||||
;; TODO Keep the name of the original icon
|
||||
:name (str "Icon " (gensym "i"))
|
||||
:metadata metadata})]
|
||||
(->> (rx/from files)
|
||||
(rx/filter allowed?)
|
||||
(rx/merge-map parse)
|
||||
(rx/map prepare)
|
||||
(rx/flat-map #(rp/mutation! :create-icon %))
|
||||
(rx/map create-icon-result))))))
|
||||
|
||||
(defn create-icon-result
|
||||
[item]
|
||||
(ptk/reify ::create-icon-result
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [{:keys [id] :as item} (assoc item :type :icon)]
|
||||
(-> state
|
||||
(update-in [:library :selected-items] #(into [item] %)))))))
|
||||
|
||||
;; ;; --- Icon Persisted
|
||||
;;
|
||||
;; (defrecord IconPersisted [id data]
|
||||
|
@ -272,27 +290,27 @@
|
|||
;;
|
||||
;; --- Load Icons
|
||||
|
||||
(declare icons-fetched)
|
||||
|
||||
(defn fetch-icons
|
||||
[id]
|
||||
(ptk/reify ::fetch-icons
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(let [params (cond-> {} id (assoc :collection-id id))]
|
||||
(->> (rp/query! :icons-by-collection params)
|
||||
(rx/map icons-fetched))))))
|
||||
|
||||
;; --- Icons Fetched
|
||||
|
||||
(defn icons-fetched
|
||||
[items]
|
||||
;; TODO: specs
|
||||
(ptk/reify ::icons-fetched
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [icons (d/index-by :id items)]
|
||||
(assoc state :icons icons)))))
|
||||
;; (declare icons-fetched)
|
||||
;;
|
||||
;; (defn fetch-icons
|
||||
;; [id]
|
||||
;; (ptk/reify ::fetch-icons
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state s]
|
||||
;; (let [params (cond-> {} id (assoc :collection-id id))]
|
||||
;; (->> (rp/query! :icons-by-collection params)
|
||||
;; (rx/map icons-fetched))))))
|
||||
;;
|
||||
;; ;; --- Icons Fetched
|
||||
;;
|
||||
;; (defn icons-fetched
|
||||
;; [items]
|
||||
;; ;; TODO: specs
|
||||
;; (ptk/reify ::icons-fetched
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (let [icons (d/index-by :id items)]
|
||||
;; (assoc state :icons icons)))))
|
||||
|
||||
;; ;; --- Rename Icon
|
||||
;;
|
||||
|
|
|
@ -55,305 +55,254 @@
|
|||
::thumb-uri
|
||||
::user-id]))
|
||||
|
||||
;; --- Initialize Collection Page
|
||||
|
||||
(declare fetch-images)
|
||||
|
||||
(defn initialize
|
||||
[collection-id]
|
||||
(us/verify ::us/uuid collection-id)
|
||||
(ptk/reify ::initialize
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:dashboard-images :selected] #{}))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(rx/of (fetch-images collection-id)))))
|
||||
|
||||
;; --- Fetch Collections
|
||||
|
||||
(declare collections-fetched)
|
||||
|
||||
(def fetch-collections
|
||||
(ptk/reify ::fetch-collections
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(->> (rp/query! :image-collections)
|
||||
(rx/map collections-fetched)))))
|
||||
|
||||
|
||||
;; --- Collections Fetched
|
||||
|
||||
(defn collections-fetched
|
||||
[items]
|
||||
(us/verify (s/every ::collection) items)
|
||||
(ptk/reify ::collections-fetched
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(reduce (fn [state {:keys [id user] :as item}]
|
||||
(let [type (if (uuid/zero? (:user-id item)) :builtin :own)
|
||||
item (assoc item :type type)]
|
||||
(assoc-in state [:images-collections id] item)))
|
||||
state
|
||||
items))))
|
||||
|
||||
|
||||
;; --- Create Collection
|
||||
|
||||
(declare collection-created)
|
||||
|
||||
(def create-collection
|
||||
(ptk/reify ::create-collection
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(let [data {:name (tr "ds.default-library-title" (gensym "c"))}]
|
||||
(->> (rp/mutation! :create-image-collection data)
|
||||
(rx/map collection-created))))))
|
||||
|
||||
;; --- Collection Created
|
||||
|
||||
(defn collection-created
|
||||
[item]
|
||||
(us/verify ::collection item)
|
||||
(ptk/reify ::collection-created
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [{:keys [id] :as item} (assoc item :type :own)]
|
||||
(update state :images-collections assoc id item)))))
|
||||
|
||||
;; --- Rename Collection
|
||||
|
||||
(defn rename-collection
|
||||
[id name]
|
||||
(ptk/reify ::rename-collection
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:images-collections id :name] name))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(let [params {:id id :name name}]
|
||||
(->> (rp/mutation! :rename-image-collection params)
|
||||
(rx/ignore))))))
|
||||
|
||||
;; --- Delete Collection
|
||||
|
||||
(defn delete-collection
|
||||
[id on-success]
|
||||
(ptk/reify ::delete-collection
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :images-collections dissoc id))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(->> (rp/mutation! :delete-image-collection {:id id})
|
||||
(rx/tap on-success)
|
||||
(rx/ignore)))))
|
||||
|
||||
;; --- Create Image
|
||||
|
||||
(declare image-created)
|
||||
(def allowed-file-types #{"image/jpeg" "image/png"})
|
||||
|
||||
(defn create-images
|
||||
([id files] (create-images id files identity))
|
||||
([id files on-uploaded]
|
||||
(us/verify (s/nilable ::us/uuid) id)
|
||||
(us/verify fn? on-uploaded)
|
||||
(ptk/reify ::create-images
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:dashboard-images :uploading] true))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(letfn [(allowed-file? [file]
|
||||
(contains? allowed-file-types (.-type file)))
|
||||
(finalize-upload [state]
|
||||
(assoc-in state [:dashboard-images :uploading] false))
|
||||
(on-success [_]
|
||||
(st/emit! finalize-upload)
|
||||
(on-uploaded))
|
||||
(on-error [e]
|
||||
(st/emit! finalize-upload)
|
||||
(rx/throw e))
|
||||
(prepare [file]
|
||||
{:name (.-name file)
|
||||
:collection-id id
|
||||
:content file})]
|
||||
(->> (rx/from files)
|
||||
(rx/filter allowed-file?)
|
||||
(rx/map prepare)
|
||||
(rx/mapcat #(rp/mutation! :upload-image %))
|
||||
(rx/reduce conj [])
|
||||
(rx/do on-success)
|
||||
(rx/mapcat identity)
|
||||
(rx/map image-created)
|
||||
(rx/catch on-error)))))))
|
||||
|
||||
;; --- Image Created
|
||||
|
||||
(defn image-created
|
||||
[item]
|
||||
(us/verify ::image item)
|
||||
(ptk/reify ::image-created
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :images assoc (:id item) item))))
|
||||
|
||||
;; --- Update Image
|
||||
|
||||
(defn persist-image
|
||||
[id]
|
||||
(us/verify ::us/uuid id)
|
||||
(ptk/reify ::persist-image
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [data (get-in state [:images id])]
|
||||
(->> (rp/mutation! :update-image data)
|
||||
(rx/ignore))))))
|
||||
|
||||
;; --- Fetch Images
|
||||
|
||||
(declare images-fetched)
|
||||
|
||||
(defn fetch-images
|
||||
"Fetch a list of images of the selected collection"
|
||||
[id]
|
||||
(us/verify ::us/uuid id)
|
||||
(ptk/reify ::fetch-images
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(let [params {:collection-id id}]
|
||||
(->> (rp/query! :images-by-collection params)
|
||||
(rx/map (partial images-fetched id)))))))
|
||||
|
||||
;; --- Images Fetched
|
||||
|
||||
(s/def ::images (s/every ::image))
|
||||
|
||||
(defn images-fetched
|
||||
[collection-id items]
|
||||
(us/verify ::us/uuid collection-id)
|
||||
(us/verify ::images items)
|
||||
(ptk/reify ::images-fetched
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [images (d/index-by :id items)]
|
||||
(assoc state :images images)))))
|
||||
|
||||
;; --- Fetch Image
|
||||
|
||||
(declare image-fetched)
|
||||
|
||||
(defrecord FetchImage [id]
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [existing (get-in state [:images id])]
|
||||
(if existing
|
||||
(rx/empty)
|
||||
(->> (rp/query! :image-by-id {:id id})
|
||||
(rx/map image-fetched)
|
||||
(rx/catch rp/client-error? #(rx/empty)))))))
|
||||
|
||||
(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]
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [id (:id image)]
|
||||
(update state :images assoc id image))))
|
||||
|
||||
(defn image-fetched
|
||||
[image]
|
||||
{:pre [(map? image)]}
|
||||
(ImageFetched. image))
|
||||
|
||||
;; --- Rename Image
|
||||
|
||||
(defn rename-image
|
||||
[id name]
|
||||
(us/verify ::us/uuid id)
|
||||
(us/verify ::us/string name)
|
||||
(ptk/reify ::rename-image
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:images id :name] name))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(rx/of (persist-image id)))))
|
||||
|
||||
;; --- Image Selection
|
||||
|
||||
(defn select-image
|
||||
[id]
|
||||
(ptk/reify ::select-image
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update-in state [:dashboard-images :selected] (fnil conj #{}) id))))
|
||||
|
||||
(defn deselect-image
|
||||
[id]
|
||||
(ptk/reify ::deselect-image
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update-in state [:dashboard-images :selected] (fnil disj #{}) id))))
|
||||
|
||||
(def deselect-all-images
|
||||
(ptk/reify ::deselect-all-images
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:dashboard-images :selected] #{}))))
|
||||
|
||||
;; --- Delete Images
|
||||
|
||||
(defn delete-image
|
||||
[id]
|
||||
(us/verify ::us/uuid id)
|
||||
(ptk/reify ::delete-image
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :images dissoc id))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(rx/merge
|
||||
(rx/of deselect-all-images)
|
||||
(->> (rp/mutation! :delete-image {:id id})
|
||||
(rx/ignore))))))
|
||||
|
||||
;; --- Delete Selected
|
||||
|
||||
(def delete-selected
|
||||
(ptk/reify ::delete-selected
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [selected (get-in state [:dashboard-images :selected])]
|
||||
(->> (rx/from selected)
|
||||
(rx/map delete-image))))))
|
||||
|
||||
;; --- Update Opts (Filtering & Ordering)
|
||||
|
||||
(defn update-opts
|
||||
[& {:keys [order filter edition]
|
||||
:or {edition false}}]
|
||||
(ptk/reify ::update-opts
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :dashboard-images merge
|
||||
{:edition edition}
|
||||
(when order {:order order})
|
||||
(when filter {:filter filter})))))
|
||||
;; ;; --- Initialize Collection Page
|
||||
;;
|
||||
;; (declare fetch-images)
|
||||
;;
|
||||
;; (defn initialize
|
||||
;; [collection-id]
|
||||
;; (us/verify ::us/uuid collection-id)
|
||||
;; (ptk/reify ::initialize
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (assoc-in state [:dashboard-images :selected] #{}))
|
||||
;;
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state stream]
|
||||
;; (rx/of (fetch-images collection-id)))))
|
||||
;;
|
||||
;; ;; --- Fetch Collections
|
||||
;;
|
||||
;; (declare collections-fetched)
|
||||
;;
|
||||
;; (def fetch-collections
|
||||
;; (ptk/reify ::fetch-collections
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state s]
|
||||
;; (->> (rp/query! :image-collections)
|
||||
;; (rx/map collections-fetched)))))
|
||||
;;
|
||||
;;
|
||||
;; ;; --- Collections Fetched
|
||||
;;
|
||||
;; (defn collections-fetched
|
||||
;; [items]
|
||||
;; (us/verify (s/every ::collection) items)
|
||||
;; (ptk/reify ::collections-fetched
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (reduce (fn [state {:keys [id user] :as item}]
|
||||
;; (let [type (if (uuid/zero? (:user-id item)) :builtin :own)
|
||||
;; item (assoc item :type type)]
|
||||
;; (assoc-in state [:images-collections id] item)))
|
||||
;; state
|
||||
;; items))))
|
||||
;;
|
||||
;;
|
||||
;; ;; --- Create Collection
|
||||
;;
|
||||
;; (declare collection-created)
|
||||
;;
|
||||
;; (def create-collection
|
||||
;; (ptk/reify ::create-collection
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state s]
|
||||
;; (let [data {:name (tr "ds.default-library-title" (gensym "c"))}]
|
||||
;; (->> (rp/mutation! :create-image-collection data)
|
||||
;; (rx/map collection-created))))))
|
||||
;;
|
||||
;; ;; --- Collection Created
|
||||
;;
|
||||
;; (defn collection-created
|
||||
;; [item]
|
||||
;; (us/verify ::collection item)
|
||||
;; (ptk/reify ::collection-created
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (let [{:keys [id] :as item} (assoc item :type :own)]
|
||||
;; (update state :images-collections assoc id item)))))
|
||||
;;
|
||||
;; ;; --- Rename Collection
|
||||
;;
|
||||
;; (defn rename-collection
|
||||
;; [id name]
|
||||
;; (ptk/reify ::rename-collection
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (assoc-in state [:images-collections id :name] name))
|
||||
;;
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state s]
|
||||
;; (let [params {:id id :name name}]
|
||||
;; (->> (rp/mutation! :rename-image-collection params)
|
||||
;; (rx/ignore))))))
|
||||
;;
|
||||
;; ;; --- Delete Collection
|
||||
;;
|
||||
;; (defn delete-collection
|
||||
;; [id on-success]
|
||||
;; (ptk/reify ::delete-collection
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (update state :images-collections dissoc id))
|
||||
;;
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state s]
|
||||
;; (->> (rp/mutation! :delete-image-collection {:id id})
|
||||
;; (rx/tap on-success)
|
||||
;; (rx/ignore)))))
|
||||
;;
|
||||
;; ;; --- Update Image
|
||||
;;
|
||||
;; (defn persist-image
|
||||
;; [id]
|
||||
;; (us/verify ::us/uuid id)
|
||||
;; (ptk/reify ::persist-image
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state stream]
|
||||
;; (let [data (get-in state [:images id])]
|
||||
;; (->> (rp/mutation! :update-image data)
|
||||
;; (rx/ignore))))))
|
||||
;;
|
||||
;; ;; --- Fetch Images
|
||||
;;
|
||||
;; (declare images-fetched)
|
||||
;;
|
||||
;; (defn fetch-images
|
||||
;; "Fetch a list of images of the selected collection"
|
||||
;; [id]
|
||||
;; (us/verify ::us/uuid id)
|
||||
;; (ptk/reify ::fetch-images
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state s]
|
||||
;; (let [params {:collection-id id}]
|
||||
;; (->> (rp/query! :images-by-collection params)
|
||||
;; (rx/map (partial images-fetched id)))))))
|
||||
;;
|
||||
;; ;; --- Images Fetched
|
||||
;;
|
||||
;; (s/def ::images (s/every ::image))
|
||||
;;
|
||||
;; (defn images-fetched
|
||||
;; [collection-id items]
|
||||
;; (us/verify ::us/uuid collection-id)
|
||||
;; (us/verify ::images items)
|
||||
;; (ptk/reify ::images-fetched
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (let [images (d/index-by :id items)]
|
||||
;; (assoc state :images images)))))
|
||||
;;
|
||||
;; ;; --- Fetch Image
|
||||
;;
|
||||
;; (declare image-fetched)
|
||||
;;
|
||||
;; (defrecord FetchImage [id]
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state stream]
|
||||
;; (let [existing (get-in state [:images id])]
|
||||
;; (if existing
|
||||
;; (rx/empty)
|
||||
;; (->> (rp/query! :image-by-id {:id id})
|
||||
;; (rx/map image-fetched)
|
||||
;; (rx/catch rp/client-error? #(rx/empty)))))))
|
||||
;;
|
||||
;; (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]
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (let [id (:id image)]
|
||||
;; (update state :images assoc id image))))
|
||||
;;
|
||||
;; (defn image-fetched
|
||||
;; [image]
|
||||
;; {:pre [(map? image)]}
|
||||
;; (ImageFetched. image))
|
||||
;;
|
||||
;; ;; --- Rename Image
|
||||
;;
|
||||
;; (defn rename-image
|
||||
;; [id name]
|
||||
;; (us/verify ::us/uuid id)
|
||||
;; (us/verify ::us/string name)
|
||||
;; (ptk/reify ::rename-image
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (assoc-in state [:images id :name] name))
|
||||
;;
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state stream]
|
||||
;; (rx/of (persist-image id)))))
|
||||
;;
|
||||
;; ;; --- Image Selection
|
||||
;;
|
||||
;; (defn select-image
|
||||
;; [id]
|
||||
;; (ptk/reify ::select-image
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (update-in state [:dashboard-images :selected] (fnil conj #{}) id))))
|
||||
;;
|
||||
;; (defn deselect-image
|
||||
;; [id]
|
||||
;; (ptk/reify ::deselect-image
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (update-in state [:dashboard-images :selected] (fnil disj #{}) id))))
|
||||
;;
|
||||
;; (def deselect-all-images
|
||||
;; (ptk/reify ::deselect-all-images
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (assoc-in state [:dashboard-images :selected] #{}))))
|
||||
;;
|
||||
;; ;; --- Delete Images
|
||||
;;
|
||||
;; (defn delete-image
|
||||
;; [id]
|
||||
;; (us/verify ::us/uuid id)
|
||||
;; (ptk/reify ::delete-image
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (update state :images dissoc id))
|
||||
;;
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state s]
|
||||
;; (rx/merge
|
||||
;; (rx/of deselect-all-images)
|
||||
;; (->> (rp/mutation! :delete-image {:id id})
|
||||
;; (rx/ignore))))))
|
||||
;;
|
||||
;; ;; --- Delete Selected
|
||||
;;
|
||||
;; (def delete-selected
|
||||
;; (ptk/reify ::delete-selected
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state stream]
|
||||
;; (let [selected (get-in state [:dashboard-images :selected])]
|
||||
;; (->> (rx/from selected)
|
||||
;; (rx/map delete-image))))))
|
||||
;;
|
||||
;; ;; --- Update Opts (Filtering & Ordering)
|
||||
;;
|
||||
;; (defn update-opts
|
||||
;; [& {:keys [order filter edition]
|
||||
;; :or {edition false}}]
|
||||
;; (ptk/reify ::update-opts
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (update state :dashboard-images merge
|
||||
;; {:edition edition}
|
||||
;; (when order {:order order})
|
||||
;; (when filter {:filter filter})))))
|
||||
|
||||
;; --- Copy Selected Image
|
||||
|
||||
|
@ -431,7 +380,7 @@
|
|||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(->> (rp/query! :image {:library-id library-id})
|
||||
(->> (rp/query! :images {:library-id library-id})
|
||||
(rx/map fetch-image-library-result)))))
|
||||
|
||||
(defn fetch-image-library-result
|
||||
|
@ -441,3 +390,71 @@
|
|||
(update [_ state]
|
||||
(-> state
|
||||
(assoc-in [:library :selected-items] data)))))
|
||||
|
||||
(declare create-image-library-result)
|
||||
|
||||
(defn create-image-library
|
||||
[team-id name]
|
||||
(ptk/reify ::create-image-library
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(->> (rp/mutation! :create-image-library {:team-id team-id
|
||||
:name name})
|
||||
(rx/map create-image-library-result)))))
|
||||
|
||||
(defn create-image-library-result [result]
|
||||
(ptk/reify ::create-image-library-result
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(update-in [:library :image-libraries] #(into [result] %))))))
|
||||
|
||||
|
||||
|
||||
;; --- Create Image
|
||||
(declare create-images-result)
|
||||
(def allowed-file-types #{"image/jpeg" "image/png"})
|
||||
|
||||
(defn create-images
|
||||
([library-id files] (create-images library-id files identity))
|
||||
([library-id files on-uploaded]
|
||||
(us/verify (s/nilable ::us/uuid) library-id)
|
||||
(us/verify fn? on-uploaded)
|
||||
(ptk/reify ::create-images
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(letfn [(allowed-file? [file]
|
||||
(contains? allowed-file-types (.-type file)))
|
||||
#_(finalize-upload [state]
|
||||
(assoc-in state [:dashboard-images :uploading] false))
|
||||
(on-success [_]
|
||||
#_(st/emit! finalize-upload)
|
||||
(on-uploaded))
|
||||
(on-error [e]
|
||||
#_(st/emit! finalize-upload)
|
||||
(rx/throw e))
|
||||
(prepare [file]
|
||||
{:name (.-name file)
|
||||
:library-id library-id
|
||||
:content file})]
|
||||
(->> (rx/from files)
|
||||
(rx/filter allowed-file?)
|
||||
(rx/map prepare)
|
||||
(rx/mapcat #(rp/mutation! :upload-image %))
|
||||
(rx/reduce conj [])
|
||||
(rx/do on-success)
|
||||
(rx/mapcat identity)
|
||||
(rx/map create-images-result)
|
||||
(rx/catch on-error)))))))
|
||||
|
||||
;; --- Image Created
|
||||
|
||||
(defn create-images-result
|
||||
[item]
|
||||
#_(us/verify ::image item)
|
||||
(ptk/reify ::create-images-result
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(update-in [:library :selected-items] #(into [item] %))))))
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
(ns uxbox.main.ui.colorpicker
|
||||
(:require
|
||||
[lentes.core :as l]
|
||||
[uxbox.main.store :as st]
|
||||
[goog.object :as gobj]
|
||||
[rumext.alpha :as mf]
|
||||
[vendor.react-color]))
|
||||
|
@ -16,5 +18,21 @@
|
|||
[:> js/SketchPicker {:color value
|
||||
:disableAlpha true
|
||||
:presetColors colors
|
||||
:onChangeComplete on-change-complete}]))
|
||||
:onChangeComplete on-change-complete
|
||||
:style {:box-shadow "none"}}]))
|
||||
|
||||
(defn- lookup-colors
|
||||
[state]
|
||||
(as-> {} $
|
||||
(reduce (fn [acc shape]
|
||||
(-> acc
|
||||
(update (:fill-color shape) (fnil inc 0))
|
||||
(update (:stroke-color shape) (fnil inc 0))))
|
||||
$ (vals (:shapes state)))
|
||||
(reverse (sort-by second $))
|
||||
(map first $)
|
||||
(remove nil? $)))
|
||||
|
||||
(def most-used-colors
|
||||
(-> (l/lens lookup-colors)
|
||||
(l/derive st/state)))
|
||||
|
|
|
@ -24,272 +24,272 @@
|
|||
[uxbox.util.i18n :as t :refer [tr]]
|
||||
[uxbox.util.router :as rt]))
|
||||
|
||||
;; --- Refs
|
||||
|
||||
(def collections-iref
|
||||
(-> (l/key :colors-collections)
|
||||
(l/derive st/state)))
|
||||
|
||||
(def selected-colors-iref
|
||||
(-> (l/in [:dashboard :colors :selected])
|
||||
(l/derive st/state)))
|
||||
|
||||
;; --- Colors Modal (Component)
|
||||
|
||||
(mf/defc color-modal
|
||||
[{:keys [on-submit value] :as props}]
|
||||
(let [local (mf/use-var value)]
|
||||
[:div.lightbox-body
|
||||
[:h3 (tr "ds.color-lightbox.title" )]
|
||||
[:form
|
||||
[:div.row-flex.center
|
||||
[:& colorpicker {:value (or @local "#00ccff")
|
||||
:on-change #(reset! local %)}]]
|
||||
[:input#project-btn.btn-primary
|
||||
{:value (tr "ds.color-lightbox.add")
|
||||
:on-click #(on-submit @local)
|
||||
:type "button"}]]]))
|
||||
|
||||
;; --- Page Title
|
||||
|
||||
|
||||
(mf/defc grid-header
|
||||
[{:keys [coll] :as props}]
|
||||
(letfn [(on-change [name]
|
||||
(st/emit! (dc/rename-collection (:id coll) name)))
|
||||
|
||||
(delete []
|
||||
(st/emit!
|
||||
(dc/delete-collection (:id coll))
|
||||
(rt/nav :dashboard-colors nil {:type (:type coll)})))
|
||||
|
||||
(on-delete []
|
||||
(modal/show! confirm-dialog {:on-accept delete}))]
|
||||
[:& common/grid-header {:value (:name coll)
|
||||
:on-change on-change
|
||||
:on-delete on-delete}]))
|
||||
|
||||
;; --- Nav
|
||||
|
||||
(mf/defc nav-item
|
||||
[{:keys [coll selected?] :as props}]
|
||||
(let [local (mf/use-state {})
|
||||
{:keys [id type name]} coll
|
||||
colors (count (:colors coll))
|
||||
editable? (= type :own)]
|
||||
(letfn [(on-click [event]
|
||||
(let [type (or type :own)]
|
||||
(st/emit! (rt/nav :dashboard-colors nil {:type type :id id}))))
|
||||
(on-input-change [event]
|
||||
(let [value (dom/get-target event)
|
||||
value (dom/get-value value)]
|
||||
(swap! local assoc :name value)))
|
||||
(on-cancel [event]
|
||||
(swap! local dissoc :name)
|
||||
(swap! local dissoc :edit))
|
||||
(on-double-click [event]
|
||||
(when editable?
|
||||
(swap! local assoc :edit true)))
|
||||
(on-input-keyup [event]
|
||||
(when (k/enter? event)
|
||||
(let [value (dom/get-target event)
|
||||
value (dom/get-value value)]
|
||||
(st/emit! (dc/rename-collection id (str/trim (:name @local))))
|
||||
(swap! local assoc :edit false))))]
|
||||
[:li {:on-click on-click
|
||||
:on-double-click on-double-click
|
||||
:class-name (when selected? "current")}
|
||||
(if (:edit @local)
|
||||
[:div
|
||||
[:input.element-title
|
||||
{:value (if (:name @local) (:name @local) name)
|
||||
:on-change on-input-change
|
||||
:on-key-down on-input-keyup}]
|
||||
[:span.close {:on-click on-cancel} i/close]]
|
||||
[:span.element-title name])
|
||||
#_[:span.element-subtitle
|
||||
(tr "ds.num-elements" (t/c colors))]])))
|
||||
|
||||
(mf/defc nav
|
||||
[{:keys [id type colls selected-coll] :as props}]
|
||||
(let [own? (= type :own)
|
||||
builtin? (= type :builtin)
|
||||
select-tab #(st/emit! (rt/nav :dashboard-colors nil {:type %}))]
|
||||
[:div.library-bar
|
||||
[:div.library-bar-inside
|
||||
[:ul.library-tabs
|
||||
[:li {:class-name (when own? "current")
|
||||
:on-click (partial select-tab :own)}
|
||||
(tr "ds.your-colors-title")]
|
||||
[:li {:class-name (when builtin? "current")
|
||||
:on-click (partial select-tab :builtin)}
|
||||
(tr "ds.store-colors-title")]]
|
||||
[:ul.library-elements
|
||||
(when own?
|
||||
[:li
|
||||
[:a.btn-primary {:on-click #(st/emit! (dc/create-collection))}
|
||||
(tr "ds.colors-collection.new")]])
|
||||
(for [item colls]
|
||||
(let [selected? (= (:id item) (:id selected-coll))]
|
||||
[:& nav-item {:coll item :selected? selected? :key (:id item)}]))]]]))
|
||||
|
||||
;; --- Grid
|
||||
|
||||
(mf/defc grid-form
|
||||
[{:keys [id] :as props}]
|
||||
(letfn [(on-submit [val]
|
||||
(st/emit! (dc/add-color id val))
|
||||
(modal/hide!))
|
||||
(on-click [event]
|
||||
(modal/show! color-modal {:on-submit on-submit}))]
|
||||
[:div.grid-item.small-item.add-project {:on-click on-click}
|
||||
[:span (tr "ds.color-new")]]))
|
||||
|
||||
(mf/defc grid-options-tooltip
|
||||
[{:keys [selected on-select title] :as props}]
|
||||
{:pre [(uuid? selected)
|
||||
(fn? on-select)
|
||||
(string? title)]}
|
||||
(let [colls (mf/deref collections-iref)
|
||||
colls (->> (vals colls)
|
||||
(filter #(= :own (:type %)))
|
||||
(remove #(= selected (:id %)))
|
||||
(sort-by :name colls))
|
||||
on-select (fn [event id]
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(on-select id))]
|
||||
[:ul.move-list
|
||||
[:li.title title]
|
||||
(for [{:keys [id name] :as coll} colls]
|
||||
[:li {:key (str id)}
|
||||
[:a {:on-click #(on-select % id)} name]])]))
|
||||
|
||||
(mf/defc grid-options
|
||||
[{:keys [id type coll selected] :as props}]
|
||||
(let [local (mf/use-state {})]
|
||||
(letfn [(delete [event]
|
||||
(st/emit! (dc/delete-colors id selected)))
|
||||
(on-delete [event]
|
||||
(modal/show! confirm-dialog {:on-accept delete}))
|
||||
(on-toggle-copy [event]
|
||||
(swap! local update :show-copy-tooltip not)
|
||||
(swap! local assoc :show-move-tooltip false))
|
||||
(on-toggle-move [event]
|
||||
(swap! local update :show-move-tooltip not)
|
||||
(swap! local assoc :show-copy-tooltip false))
|
||||
(on-copy [selected]
|
||||
(swap! local assoc
|
||||
:show-move-tooltip false
|
||||
:show-copy-tooltip false)
|
||||
(st/emit! (dc/copy-selected selected)))
|
||||
(on-move [selected]
|
||||
(swap! local assoc
|
||||
:show-move-tooltip false
|
||||
:show-copy-tooltip false)
|
||||
(st/emit! (dc/move-selected id selected)))]
|
||||
|
||||
;; MULTISELECT OPTIONS BAR
|
||||
[:div.multiselect-bar
|
||||
(if (or (= type :own) (nil? id))
|
||||
;; if editable
|
||||
[:div.multiselect-nav
|
||||
[:span.move-item.tooltip.tooltip-top
|
||||
{:alt (tr "ds.multiselect-bar.copy")
|
||||
:on-click on-toggle-copy}
|
||||
(when (:show-copy-tooltip @local)
|
||||
[:& grid-options-tooltip {:selected id
|
||||
:title (tr "ds.multiselect-bar.copy-to-library")
|
||||
:on-select on-copy}])
|
||||
i/copy]
|
||||
[:span.move-item.tooltip.tooltip-top
|
||||
{:alt (tr "ds.multiselect-bar.move")
|
||||
:on-click on-toggle-move}
|
||||
(when (:show-move-tooltip @local)
|
||||
[:& grid-options-tooltip {:selected id
|
||||
:title (tr "ds.multiselect-bar.move-to-library")
|
||||
:on-select on-move}])
|
||||
i/move]
|
||||
[:span.delete.tooltip.tooltip-top
|
||||
{:alt (tr "ds.multiselect-bar.delete")
|
||||
:on-click on-delete}
|
||||
i/trash]]
|
||||
|
||||
;; if not editable
|
||||
[:div.multiselect-nav
|
||||
[:span.move-item.tooltip.tooltip-top
|
||||
{:alt (tr "ds.multiselect-bar.copy")
|
||||
:on-click on-toggle-copy}
|
||||
(when (:show-copy-tooltip @local)
|
||||
[:& grid-options-tooltip {:selected id
|
||||
:title (tr "ds.multiselect-bar.copy-to-library")
|
||||
:on-select on-copy}])
|
||||
i/organize]])])))
|
||||
|
||||
(mf/defc grid-item
|
||||
[{:keys [color selected?] :as props}]
|
||||
(letfn [(toggle-selection [event]
|
||||
(st/emit! (dc/toggle-color-selection color)))]
|
||||
[:div.grid-item.small-item.project-th {:on-click toggle-selection}
|
||||
[:span.color-swatch {:style {:background-color color}}]
|
||||
[:div.input-checkbox.check-primary
|
||||
[:input {:type "checkbox"
|
||||
:id color
|
||||
:on-change toggle-selection
|
||||
:checked selected?}]
|
||||
[:label {:for color}]]
|
||||
[:span.color-data color]
|
||||
[:span.color-data (apply str "RGB " (interpose ", " (hex->rgb color)))]]))
|
||||
|
||||
(mf/defc grid
|
||||
[{:keys [id type coll selected] :as props}]
|
||||
(let [{:keys [colors]} coll
|
||||
editable? (= :own type)
|
||||
colors (->> (remove nil? colors)
|
||||
(sort-by identity))]
|
||||
[:div.dashboard-grid-content
|
||||
[:div.dashboard-grid-row
|
||||
(when (and editable? id)
|
||||
[:& grid-form {:id id}])
|
||||
(for [color colors]
|
||||
(let [selected? (contains? selected color)]
|
||||
[:& grid-item {:color color :selected? selected? :key color}]))]]))
|
||||
|
||||
(mf/defc content
|
||||
[{:keys [id type coll] :as props}]
|
||||
(let [selected (mf/deref selected-colors-iref)]
|
||||
[:section.dashboard-grid.library
|
||||
(when coll
|
||||
[:& grid-header {:coll coll}])
|
||||
[:& grid {:coll coll :id id :type type :selected selected}]
|
||||
(when (seq selected)
|
||||
[:& grid-options {:id id :type type
|
||||
:selected selected
|
||||
:coll coll}])]))
|
||||
|
||||
;; --- Colors Page
|
||||
|
||||
(mf/defc colors-page
|
||||
[{:keys [id type] :as props}]
|
||||
(let [type (or type :own)
|
||||
|
||||
colls (mf/deref collections-iref)
|
||||
colls (cond->> (vals colls)
|
||||
(= type :own) (filter #(= :own (:type %)))
|
||||
(= type :builtin) (filter #(= :builtin (:type %)))
|
||||
true (sort-by :created-at))
|
||||
selected-coll (if id
|
||||
(seek #(= id (:id %)) colls)
|
||||
(first colls))
|
||||
id (:id selected-coll)]
|
||||
|
||||
(mf/use-effect #(st/emit! (dc/fetch-collections)))
|
||||
|
||||
[:section.dashboard-content
|
||||
[:& nav {:type type
|
||||
:id id
|
||||
:colls colls}]
|
||||
[:& content {:type type
|
||||
:id id
|
||||
:coll selected-coll}]]))
|
||||
|
||||
;; ;; --- Refs
|
||||
;;
|
||||
;; (def collections-iref
|
||||
;; (-> (l/key :colors-collections)
|
||||
;; (l/derive st/state)))
|
||||
;;
|
||||
;; (def selected-colors-iref
|
||||
;; (-> (l/in [:dashboard :colors :selected])
|
||||
;; (l/derive st/state)))
|
||||
;;
|
||||
;; ;; --- Colors Modal (Component)
|
||||
;;
|
||||
;; (mf/defc color-modal
|
||||
;; [{:keys [on-submit value] :as props}]
|
||||
;; (let [local (mf/use-var value)]
|
||||
;; [:div.lightbox-body
|
||||
;; [:h3 (tr "ds.color-lightbox.title" )]
|
||||
;; [:form
|
||||
;; [:div.row-flex.center
|
||||
;; [:& colorpicker {:value (or @local "#00ccff")
|
||||
;; :on-change #(reset! local %)}]]
|
||||
;; [:input#project-btn.btn-primary
|
||||
;; {:value (tr "ds.color-lightbox.add")
|
||||
;; :on-click #(on-submit @local)
|
||||
;; :type "button"}]]]))
|
||||
;;
|
||||
;; ;; --- Page Title
|
||||
;;
|
||||
;;
|
||||
;; (mf/defc grid-header
|
||||
;; [{:keys [coll] :as props}]
|
||||
;; (letfn [(on-change [name]
|
||||
;; (st/emit! (dc/rename-collection (:id coll) name)))
|
||||
;;
|
||||
;; (delete []
|
||||
;; (st/emit!
|
||||
;; (dc/delete-collection (:id coll))
|
||||
;; (rt/nav :dashboard-colors nil {:type (:type coll)})))
|
||||
;;
|
||||
;; (on-delete []
|
||||
;; (modal/show! confirm-dialog {:on-accept delete}))]
|
||||
;; [:& common/grid-header {:value (:name coll)
|
||||
;; :on-change on-change
|
||||
;; :on-delete on-delete}]))
|
||||
;;
|
||||
;; ;; --- Nav
|
||||
;;
|
||||
;; (mf/defc nav-item
|
||||
;; [{:keys [coll selected?] :as props}]
|
||||
;; (let [local (mf/use-state {})
|
||||
;; {:keys [id type name]} coll
|
||||
;; colors (count (:colors coll))
|
||||
;; editable? (= type :own)]
|
||||
;; (letfn [(on-click [event]
|
||||
;; (let [type (or type :own)]
|
||||
;; (st/emit! (rt/nav :dashboard-colors nil {:type type :id id}))))
|
||||
;; (on-input-change [event]
|
||||
;; (let [value (dom/get-target event)
|
||||
;; value (dom/get-value value)]
|
||||
;; (swap! local assoc :name value)))
|
||||
;; (on-cancel [event]
|
||||
;; (swap! local dissoc :name)
|
||||
;; (swap! local dissoc :edit))
|
||||
;; (on-double-click [event]
|
||||
;; (when editable?
|
||||
;; (swap! local assoc :edit true)))
|
||||
;; (on-input-keyup [event]
|
||||
;; (when (k/enter? event)
|
||||
;; (let [value (dom/get-target event)
|
||||
;; value (dom/get-value value)]
|
||||
;; (st/emit! (dc/rename-collection id (str/trim (:name @local))))
|
||||
;; (swap! local assoc :edit false))))]
|
||||
;; [:li {:on-click on-click
|
||||
;; :on-double-click on-double-click
|
||||
;; :class-name (when selected? "current")}
|
||||
;; (if (:edit @local)
|
||||
;; [:div
|
||||
;; [:input.element-title
|
||||
;; {:value (if (:name @local) (:name @local) name)
|
||||
;; :on-change on-input-change
|
||||
;; :on-key-down on-input-keyup}]
|
||||
;; [:span.close {:on-click on-cancel} i/close]]
|
||||
;; [:span.element-title name])
|
||||
;; #_[:span.element-subtitle
|
||||
;; (tr "ds.num-elements" (t/c colors))]])))
|
||||
;;
|
||||
;; (mf/defc nav
|
||||
;; [{:keys [id type colls selected-coll] :as props}]
|
||||
;; (let [own? (= type :own)
|
||||
;; builtin? (= type :builtin)
|
||||
;; select-tab #(st/emit! (rt/nav :dashboard-colors nil {:type %}))]
|
||||
;; [:div.library-bar
|
||||
;; [:div.library-bar-inside
|
||||
;; [:ul.library-tabs
|
||||
;; [:li {:class-name (when own? "current")
|
||||
;; :on-click (partial select-tab :own)}
|
||||
;; (tr "ds.your-colors-title")]
|
||||
;; [:li {:class-name (when builtin? "current")
|
||||
;; :on-click (partial select-tab :builtin)}
|
||||
;; (tr "ds.store-colors-title")]]
|
||||
;; [:ul.library-elements
|
||||
;; (when own?
|
||||
;; [:li
|
||||
;; [:a.btn-primary {:on-click #(st/emit! (dc/create-collection))}
|
||||
;; (tr "ds.colors-collection.new")]])
|
||||
;; (for [item colls]
|
||||
;; (let [selected? (= (:id item) (:id selected-coll))]
|
||||
;; [:& nav-item {:coll item :selected? selected? :key (:id item)}]))]]]))
|
||||
;;
|
||||
;; ;; --- Grid
|
||||
;;
|
||||
;; (mf/defc grid-form
|
||||
;; [{:keys [id] :as props}]
|
||||
;; (letfn [(on-submit [val]
|
||||
;; (st/emit! (dc/add-color id val))
|
||||
;; (modal/hide!))
|
||||
;; (on-click [event]
|
||||
;; (modal/show! color-modal {:on-submit on-submit}))]
|
||||
;; [:div.grid-item.small-item.add-project {:on-click on-click}
|
||||
;; [:span (tr "ds.color-new")]]))
|
||||
;;
|
||||
;; (mf/defc grid-options-tooltip
|
||||
;; [{:keys [selected on-select title] :as props}]
|
||||
;; {:pre [(uuid? selected)
|
||||
;; (fn? on-select)
|
||||
;; (string? title)]}
|
||||
;; (let [colls (mf/deref collections-iref)
|
||||
;; colls (->> (vals colls)
|
||||
;; (filter #(= :own (:type %)))
|
||||
;; (remove #(= selected (:id %)))
|
||||
;; (sort-by :name colls))
|
||||
;; on-select (fn [event id]
|
||||
;; (dom/prevent-default event)
|
||||
;; (dom/stop-propagation event)
|
||||
;; (on-select id))]
|
||||
;; [:ul.move-list
|
||||
;; [:li.title title]
|
||||
;; (for [{:keys [id name] :as coll} colls]
|
||||
;; [:li {:key (str id)}
|
||||
;; [:a {:on-click #(on-select % id)} name]])]))
|
||||
;;
|
||||
;; (mf/defc grid-options
|
||||
;; [{:keys [id type coll selected] :as props}]
|
||||
;; (let [local (mf/use-state {})]
|
||||
;; (letfn [(delete [event]
|
||||
;; (st/emit! (dc/delete-colors id selected)))
|
||||
;; (on-delete [event]
|
||||
;; (modal/show! confirm-dialog {:on-accept delete}))
|
||||
;; (on-toggle-copy [event]
|
||||
;; (swap! local update :show-copy-tooltip not)
|
||||
;; (swap! local assoc :show-move-tooltip false))
|
||||
;; (on-toggle-move [event]
|
||||
;; (swap! local update :show-move-tooltip not)
|
||||
;; (swap! local assoc :show-copy-tooltip false))
|
||||
;; (on-copy [selected]
|
||||
;; (swap! local assoc
|
||||
;; :show-move-tooltip false
|
||||
;; :show-copy-tooltip false)
|
||||
;; (st/emit! (dc/copy-selected selected)))
|
||||
;; (on-move [selected]
|
||||
;; (swap! local assoc
|
||||
;; :show-move-tooltip false
|
||||
;; :show-copy-tooltip false)
|
||||
;; (st/emit! (dc/move-selected id selected)))]
|
||||
;;
|
||||
;; ;; MULTISELECT OPTIONS BAR
|
||||
;; [:div.multiselect-bar
|
||||
;; (if (or (= type :own) (nil? id))
|
||||
;; ;; if editable
|
||||
;; [:div.multiselect-nav
|
||||
;; [:span.move-item.tooltip.tooltip-top
|
||||
;; {:alt (tr "ds.multiselect-bar.copy")
|
||||
;; :on-click on-toggle-copy}
|
||||
;; (when (:show-copy-tooltip @local)
|
||||
;; [:& grid-options-tooltip {:selected id
|
||||
;; :title (tr "ds.multiselect-bar.copy-to-library")
|
||||
;; :on-select on-copy}])
|
||||
;; i/copy]
|
||||
;; [:span.move-item.tooltip.tooltip-top
|
||||
;; {:alt (tr "ds.multiselect-bar.move")
|
||||
;; :on-click on-toggle-move}
|
||||
;; (when (:show-move-tooltip @local)
|
||||
;; [:& grid-options-tooltip {:selected id
|
||||
;; :title (tr "ds.multiselect-bar.move-to-library")
|
||||
;; :on-select on-move}])
|
||||
;; i/move]
|
||||
;; [:span.delete.tooltip.tooltip-top
|
||||
;; {:alt (tr "ds.multiselect-bar.delete")
|
||||
;; :on-click on-delete}
|
||||
;; i/trash]]
|
||||
;;
|
||||
;; ;; if not editable
|
||||
;; [:div.multiselect-nav
|
||||
;; [:span.move-item.tooltip.tooltip-top
|
||||
;; {:alt (tr "ds.multiselect-bar.copy")
|
||||
;; :on-click on-toggle-copy}
|
||||
;; (when (:show-copy-tooltip @local)
|
||||
;; [:& grid-options-tooltip {:selected id
|
||||
;; :title (tr "ds.multiselect-bar.copy-to-library")
|
||||
;; :on-select on-copy}])
|
||||
;; i/organize]])])))
|
||||
;;
|
||||
;; (mf/defc grid-item
|
||||
;; [{:keys [color selected?] :as props}]
|
||||
;; (letfn [(toggle-selection [event]
|
||||
;; (st/emit! (dc/toggle-color-selection color)))]
|
||||
;; [:div.grid-item.small-item.project-th {:on-click toggle-selection}
|
||||
;; [:span.color-swatch {:style {:background-color color}}]
|
||||
;; [:div.input-checkbox.check-primary
|
||||
;; [:input {:type "checkbox"
|
||||
;; :id color
|
||||
;; :on-change toggle-selection
|
||||
;; :checked selected?}]
|
||||
;; [:label {:for color}]]
|
||||
;; [:span.color-data color]
|
||||
;; [:span.color-data (apply str "RGB " (interpose ", " (hex->rgb color)))]]))
|
||||
;;
|
||||
;; (mf/defc grid
|
||||
;; [{:keys [id type coll selected] :as props}]
|
||||
;; (let [{:keys [colors]} coll
|
||||
;; editable? (= :own type)
|
||||
;; colors (->> (remove nil? colors)
|
||||
;; (sort-by identity))]
|
||||
;; [:div.dashboard-grid-content
|
||||
;; [:div.dashboard-grid-row
|
||||
;; (when (and editable? id)
|
||||
;; [:& grid-form {:id id}])
|
||||
;; (for [color colors]
|
||||
;; (let [selected? (contains? selected color)]
|
||||
;; [:& grid-item {:color color :selected? selected? :key color}]))]]))
|
||||
;;
|
||||
;; (mf/defc content
|
||||
;; [{:keys [id type coll] :as props}]
|
||||
;; (let [selected (mf/deref selected-colors-iref)]
|
||||
;; [:section.dashboard-grid.library
|
||||
;; (when coll
|
||||
;; [:& grid-header {:coll coll}])
|
||||
;; [:& grid {:coll coll :id id :type type :selected selected}]
|
||||
;; (when (seq selected)
|
||||
;; [:& grid-options {:id id :type type
|
||||
;; :selected selected
|
||||
;; :coll coll}])]))
|
||||
;;
|
||||
;; ;; --- Colors Page
|
||||
;;
|
||||
;; (mf/defc colors-page
|
||||
;; [{:keys [id type] :as props}]
|
||||
;; (let [type (or type :own)
|
||||
;;
|
||||
;; colls (mf/deref collections-iref)
|
||||
;; colls (cond->> (vals colls)
|
||||
;; (= type :own) (filter #(= :own (:type %)))
|
||||
;; (= type :builtin) (filter #(= :builtin (:type %)))
|
||||
;; true (sort-by :created-at))
|
||||
;; selected-coll (if id
|
||||
;; (seek #(= id (:id %)) colls)
|
||||
;; (first colls))
|
||||
;; id (:id selected-coll)]
|
||||
;;
|
||||
;; (mf/use-effect #(st/emit! (dc/fetch-collections)))
|
||||
;;
|
||||
;; [:section.dashboard-content
|
||||
;; [:& nav {:type type
|
||||
;; :id id
|
||||
;; :colls colls}]
|
||||
;; [:& content {:type type
|
||||
;; :id id
|
||||
;; :coll selected-coll}]]))
|
||||
;;
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
(ns uxbox.main.ui.dashboard.components.context-menu
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.util.uuid :as uuid]))
|
||||
|
||||
(mf/defc context-menu
|
||||
[{ :keys [ is-open options ]}]
|
||||
[:div.context-menu
|
||||
{ :class-name (when is-open "is-open")}
|
||||
[:ul.context-menu-items
|
||||
(for [[action-name action-handler] options]
|
||||
[:li.context-menu-item
|
||||
{ :key (uuid/next)}
|
||||
[:a.context-menu-action {:on-click action-handler} action-name]])]])
|
||||
|
|
@ -28,360 +28,360 @@
|
|||
[uxbox.util.router :as rt]
|
||||
[uxbox.util.time :as dt]))
|
||||
|
||||
;; --- Page Title
|
||||
|
||||
(mf/defc grid-header
|
||||
[{:keys [collection] :as props}]
|
||||
(let [{:keys [id type]} collection
|
||||
on-change #(st/emit! (di/rename-collection id %))
|
||||
on-deleted #(st/emit! (rt/nav :dashboard-images nil {:type type}))
|
||||
delete #(st/emit! (di/delete-collection id on-deleted))
|
||||
on-delete #(modal/show! confirm-dialog {:on-accept delete})]
|
||||
[:& common/grid-header {:value (:name collection)
|
||||
:on-change on-change
|
||||
:on-delete on-delete}]))
|
||||
|
||||
;; --- Nav
|
||||
|
||||
(mf/defc nav-item
|
||||
[{:keys [coll selected?] :as props}]
|
||||
(let [local (mf/use-state {})
|
||||
{:keys [id type name num-images]} coll
|
||||
editable? (= type :own)
|
||||
|
||||
on-click
|
||||
(fn [event]
|
||||
(let [type (or type :own)]
|
||||
(st/emit! (rt/nav :dashboard-images {} {:type type :id id}))))
|
||||
|
||||
on-cancel-edition #(swap! local dissoc :edit)
|
||||
on-double-click #(when editable? (swap! local assoc :edit true))
|
||||
|
||||
on-input-keyup
|
||||
(fn [event]
|
||||
(when (kbd/enter? event)
|
||||
(let [value (-> (dom/get-target event)
|
||||
(dom/get-value)
|
||||
(str/trim))]
|
||||
(st/emit! (di/rename-collection id value))
|
||||
(swap! local assoc :edit false))))]
|
||||
|
||||
[:li {:on-click on-click
|
||||
:on-double-click on-double-click
|
||||
:class-name (when selected? "current")}
|
||||
(if (:edit @local)
|
||||
[:div
|
||||
[:input.element-title {:default-value name
|
||||
:on-key-down on-input-keyup}]
|
||||
[:span.close {:on-click on-cancel-edition} i/close]]
|
||||
[:span.element-title (if id name "Storage")])]))
|
||||
|
||||
(mf/defc nav
|
||||
[{:keys [id type collections] :as props}]
|
||||
(let [locale (i18n/use-locale)
|
||||
own? (= type :own)
|
||||
builtin? (= type :builtin)
|
||||
create-collection #(st/emit! di/create-collection)
|
||||
select-own-tab #(st/emit! (rt/nav :dashboard-images nil {:type :own}))
|
||||
select-buitin-tab #(st/emit! (rt/nav :dashboard-images nil {:type :builtin}))]
|
||||
[:div.library-bar
|
||||
[:div.library-bar-inside
|
||||
|
||||
;; Tabs
|
||||
[:ul.library-tabs
|
||||
[:li {:class (when own? "current")
|
||||
:on-click select-own-tab}
|
||||
(t locale "ds.your-images-title")]
|
||||
|
||||
[:li {:class (when builtin? "current")
|
||||
:on-click select-buitin-tab}
|
||||
(t locale "ds.store-images-title")]]
|
||||
|
||||
;; Collections List
|
||||
[:ul.library-elements
|
||||
(when own?
|
||||
[:li
|
||||
[:a.btn-primary {:on-click create-collection}
|
||||
(t locale "ds.images-collection.new")]])
|
||||
|
||||
(for [item collections]
|
||||
[:& nav-item {:coll item
|
||||
:selected? (= (:id item) id)
|
||||
:key (:id item)}])]]]))
|
||||
|
||||
;; --- Grid
|
||||
|
||||
;; (mf/defc grid-options-tooltip
|
||||
;; [{:keys [selected on-select title] :as props}]
|
||||
;; {:pre [(uuid? selected)
|
||||
;; (fn? on-select)
|
||||
;; (string? title)]}
|
||||
;; (let [colls (mf/deref collections-iref)
|
||||
;; colls (->> (vals colls)
|
||||
;; (filter #(= :own (:type %)))
|
||||
;; (remove #(= selected (:id %)))
|
||||
;; #_(sort-by :name colls))
|
||||
;; on-select (fn [event id]
|
||||
;; (dom/prevent-default event)
|
||||
;; (dom/stop-propagation event)
|
||||
;; (on-select id))]
|
||||
;; [:ul.move-list
|
||||
;; [:li.title title]
|
||||
;; [:li
|
||||
;; (when (not (nil? selected))
|
||||
;; [:a {:href "#" :on-click #(on-select % nil)} "Storage"])]
|
||||
;; (for [{:keys [id name] :as coll} colls]
|
||||
;; [:li {:key (pr-str id)}
|
||||
;; [:a {:on-click #(on-select % id)} name]])]))
|
||||
|
||||
(mf/defc grid-options
|
||||
[{:keys [id type selected] :as props}]
|
||||
(let [local (mf/use-state {})
|
||||
delete #(st/emit! di/delete-selected)
|
||||
on-delete #(modal/show! confirm-dialog {:on-accept delete})
|
||||
|
||||
;; (on-toggle-copy [event]
|
||||
;; (swap! local update :show-copy-tooltip not))
|
||||
;; (on-toggle-move [event]
|
||||
;; (swap! local update :show-move-tooltip not))
|
||||
;; (on-copy [selected]
|
||||
;; (swap! local assoc
|
||||
;; :show-move-tooltip false
|
||||
;; :show-copy-tooltip false)
|
||||
;; (st/emit! (di/copy-selected selected)))
|
||||
;; (on-move [selected]
|
||||
;; (swap! local assoc
|
||||
;; :show-move-tooltip false
|
||||
;; :show-copy-tooltip false)
|
||||
;; (st/emit! (di/move-selected selected)))
|
||||
;; (on-rename [event]
|
||||
;; (let [selected (first selected)]
|
||||
;; (st/emit! (di/update-opts :edition selected))))
|
||||
]
|
||||
;; MULTISELECT OPTIONS BAR
|
||||
[:div.multiselect-bar
|
||||
(when (= type :own)
|
||||
;; If editable
|
||||
[:div.multiselect-nav
|
||||
;; [:span.move-item.tooltip.tooltip-top
|
||||
;; {:alt (tr "ds.multiselect-bar.copy")
|
||||
;; :on-click on-toggle-copy}
|
||||
;; (when (:show-copy-tooltip @local)
|
||||
;; [:& grid-options-tooltip {:selected id
|
||||
;; :title (tr "ds.multiselect-bar.copy-to-library")
|
||||
;; :on-select on-copy}])
|
||||
;; i/copy]
|
||||
;; [:span.move-item.tooltip.tooltip-top
|
||||
;; {:alt (tr "ds.multiselect-bar.move")
|
||||
;; :on-click on-toggle-move}
|
||||
;; (when (:show-move-tooltip @local)
|
||||
;; [:& grid-options-tooltip {:selected id
|
||||
;; :title (tr "ds.multiselect-bar.move-to-library")
|
||||
;; :on-select on-move}])
|
||||
;; i/move]
|
||||
;; (when (= 1 (count selected))
|
||||
;; [:span.move-item.tooltip.tooltip-top {:alt (tr "ds.multiselect-bar.rename")
|
||||
;; :on-click on-rename}
|
||||
;; i/pencil])
|
||||
[:span.delete.tooltip.tooltip-top
|
||||
{:alt (tr "ds.multiselect-bar.delete")
|
||||
:on-click on-delete}
|
||||
i/trash]]
|
||||
|
||||
;; If not editable
|
||||
;; [:div.multiselect-nav
|
||||
;; [:span.move-item.tooltip.tooltip-top {:alt (tr "ds.multiselect-bar.copy")
|
||||
;; :on-click on-toggle-copy}
|
||||
;; (when (:show-copy-tooltip @local)
|
||||
;; [:& grid-options-tooltip {:selected id
|
||||
;; :title (tr "ds.multiselect-bar.copy-to-library")
|
||||
;; :on-select on-copy}])
|
||||
;; i/organize]]
|
||||
)]))
|
||||
|
||||
|
||||
;; --- Grid Form
|
||||
|
||||
(mf/defc grid-form
|
||||
[{:keys [id type uploading?] :as props}]
|
||||
(let [input (mf/use-ref nil)
|
||||
on-click #(dom/click (mf/ref-node input))
|
||||
on-select #(st/emit! (->> (dom/get-target %)
|
||||
(dom/get-files)
|
||||
(array-seq)
|
||||
(di/create-images id)))]
|
||||
[:div.grid-item.add-project {:on-click on-click}
|
||||
(if uploading?
|
||||
[:div i/loader-pencil]
|
||||
[:span (tr "ds.image-new")])
|
||||
[:input.upload-image-input
|
||||
{:style {:display "none"}
|
||||
:multiple true
|
||||
:ref input
|
||||
:value ""
|
||||
:accept "image/jpeg,image/png,image/webp"
|
||||
:type "file"
|
||||
:on-change on-select}]]))
|
||||
|
||||
;; --- Grid Item
|
||||
|
||||
(mf/defc grid-item
|
||||
[{:keys [image selected? edition?] :as props}]
|
||||
(let [toggle-selection #(st/emit! (if selected?
|
||||
(di/deselect-image (:id image))
|
||||
(di/select-image (:id image))))
|
||||
on-blur
|
||||
(fn [event]
|
||||
(let [target (dom/get-target event)
|
||||
name (dom/get-value target)]
|
||||
(st/emit! (di/update-opts :edition false)
|
||||
(di/rename-image (:id image) name))))
|
||||
|
||||
on-key-down
|
||||
(fn [event]
|
||||
(when (kbd/enter? event)
|
||||
(on-blur event)))
|
||||
|
||||
on-edit
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (di/update-opts :edition (:id image))))
|
||||
|
||||
background (str "url('" (:thumb-uri image) "')")]
|
||||
|
||||
[:div.grid-item.images-th
|
||||
[:div.grid-item-th {:style {:background-image background}}
|
||||
[:div.input-checkbox.check-primary
|
||||
[:input {:type "checkbox"
|
||||
:id (:id image)
|
||||
:on-change toggle-selection
|
||||
:checked selected?}]
|
||||
[:label {:for (:id image)}]]]
|
||||
|
||||
[:div.item-info
|
||||
(if edition?
|
||||
[:input.element-name {:type "text"
|
||||
:auto-focus true
|
||||
:on-key-down on-key-down
|
||||
:on-blur on-blur
|
||||
:on-click on-edit
|
||||
:default-value (:name image)}]
|
||||
[:h3 {:on-double-click on-edit} (:name image)])
|
||||
[:span.date (tr "ds.uploaded-at" (dt/format (:created-at image) "dd/MM/yyyy"))]]]))
|
||||
|
||||
;; --- Grid
|
||||
|
||||
;; (defn- make-images-iref
|
||||
;; [collection-id]
|
||||
;; (letfn [(selector [state]
|
||||
;; (->> (vals (:images state))
|
||||
;; (filterv #(= (:collection-id %) collection-id))))]
|
||||
;; (-> (l/lens selector)
|
||||
;; (l/derive st/state))))
|
||||
|
||||
(def images-iref
|
||||
(-> (comp (l/key :images) (l/lens vals))
|
||||
(l/derive st/state)))
|
||||
|
||||
(mf/defc grid
|
||||
[{:keys [id type collection opts] :as props}]
|
||||
(let [editable? (= type :own)
|
||||
;; images-iref (mf/use-memo {:fn #(make-images-iref id)
|
||||
;; :deps (mf/deps id)})
|
||||
images (->> (mf/deref images-iref)
|
||||
(sort-by :created-at))]
|
||||
[:div.dashboard-grid-content
|
||||
[:div.dashboard-grid-row
|
||||
(when editable?
|
||||
[:& grid-form {:id id :type type :uploading? (:uploading opts)}])
|
||||
(for [item images]
|
||||
[:& grid-item {:image item
|
||||
:key (:id item)
|
||||
:selected? (contains? (:selected opts) (:id item))
|
||||
:edition? (= (:edition opts) (:id item))}])]]))
|
||||
|
||||
;; --- Menu
|
||||
|
||||
;; (mf/defc menu
|
||||
;; [{:keys [opts coll] :as props}]
|
||||
;; (let [ordering (:order opts :name)
|
||||
;; filtering (:filter opts "")
|
||||
;; icount (count (:images coll))]
|
||||
;; (letfn [(on-term-change [event]
|
||||
;; (let [term (-> (dom/get-target event)
|
||||
;; (dom/get-value))]
|
||||
;; (st/emit! (di/update-opts :filter term))))
|
||||
;; (on-ordering-change [event]
|
||||
;; (let [value (dom/event->value event)
|
||||
;; value (read-string value)]
|
||||
;; (st/emit! (di/update-opts :order value))))
|
||||
;; (on-clear [event]
|
||||
;; (st/emit! (di/update-opts :filter "")))]
|
||||
;; [:section.dashboard-bar.library-gap
|
||||
;; [:div.dashboard-info
|
||||
|
||||
;; ;; Counter
|
||||
;; [:span.dashboard-images (tr "ds.num-images" (t/c icount))]
|
||||
|
||||
;; ;; Sorting
|
||||
;; [:div
|
||||
;; [:span (tr "ds.ordering")]
|
||||
;; [:select.input-select {:on-change on-ordering-change
|
||||
;; :value (pr-str ordering)}
|
||||
;; (for [[key value] (seq +ordering-options+)]
|
||||
;; [:option {:key key :value (pr-str key)} (tr value)])]]
|
||||
|
||||
;; ;; Search
|
||||
;; [:form.dashboard-search
|
||||
;; [:input.input-text {:key :images-search-box
|
||||
;; :type "text"
|
||||
;; :on-change on-term-change
|
||||
;; :auto-focus true
|
||||
;; :placeholder (tr "ds.search.placeholder")
|
||||
;; :value filtering}]
|
||||
;; [:div.clear-search {:on-click on-clear} i/close]]]])))
|
||||
|
||||
(def opts-iref
|
||||
(-> (l/key :dashboard-images)
|
||||
(l/derive st/state)))
|
||||
|
||||
(mf/defc content
|
||||
[{:keys [id type collection] :as props}]
|
||||
(let [{:keys [selected] :as opts} (mf/deref opts-iref)]
|
||||
[:section.dashboard-grid.library
|
||||
(when collection
|
||||
[:& grid-header {:collection collection}])
|
||||
(if collection
|
||||
[:& grid {:id id :type type :collection collection :opts opts}]
|
||||
[:span "EMPTY STATE TODO"])
|
||||
(when-not (empty? selected)
|
||||
[:& grid-options {:id id :type type :selected selected}])]))
|
||||
|
||||
;; --- Images Page
|
||||
|
||||
(def collections-iref
|
||||
(-> (l/key :images-collections)
|
||||
(l/derive st/state)))
|
||||
|
||||
(mf/defc images-page
|
||||
[{:keys [id type] :as props}]
|
||||
(let [collections (mf/deref collections-iref)
|
||||
collections (cond->> (vals collections)
|
||||
(= type :own) (filter #(= :own (:type %)))
|
||||
(= type :builtin) (filter #(= :builtin (:type %)))
|
||||
true (sort-by :created-at))
|
||||
|
||||
collection (cond
|
||||
(uuid? id) (d/seek #(= id (:id %)) collections)
|
||||
:else (first collections))
|
||||
id (:id collection)]
|
||||
|
||||
(mf/use-effect #(st/emit! di/fetch-collections))
|
||||
(mf/use-effect
|
||||
{:fn #(when id (st/emit! (di/initialize id)))
|
||||
:deps (mf/deps id)})
|
||||
|
||||
[:section.dashboard-content
|
||||
[:& nav {:type type :id id :collections collections}]
|
||||
[:& content {:type type :id id :collection collection}]]))
|
||||
;; ;; --- Page Title
|
||||
;;
|
||||
;; (mf/defc grid-header
|
||||
;; [{:keys [collection] :as props}]
|
||||
;; (let [{:keys [id type]} collection
|
||||
;; on-change #(st/emit! (di/rename-collection id %))
|
||||
;; on-deleted #(st/emit! (rt/nav :dashboard-images nil {:type type}))
|
||||
;; delete #(st/emit! (di/delete-collection id on-deleted))
|
||||
;; on-delete #(modal/show! confirm-dialog {:on-accept delete})]
|
||||
;; [:& common/grid-header {:value (:name collection)
|
||||
;; :on-change on-change
|
||||
;; :on-delete on-delete}]))
|
||||
;;
|
||||
;; ;; --- Nav
|
||||
;;
|
||||
;; (mf/defc nav-item
|
||||
;; [{:keys [coll selected?] :as props}]
|
||||
;; (let [local (mf/use-state {})
|
||||
;; {:keys [id type name num-images]} coll
|
||||
;; editable? (= type :own)
|
||||
;;
|
||||
;; on-click
|
||||
;; (fn [event]
|
||||
;; (let [type (or type :own)]
|
||||
;; (st/emit! (rt/nav :dashboard-images {} {:type type :id id}))))
|
||||
;;
|
||||
;; on-cancel-edition #(swap! local dissoc :edit)
|
||||
;; on-double-click #(when editable? (swap! local assoc :edit true))
|
||||
;;
|
||||
;; on-input-keyup
|
||||
;; (fn [event]
|
||||
;; (when (kbd/enter? event)
|
||||
;; (let [value (-> (dom/get-target event)
|
||||
;; (dom/get-value)
|
||||
;; (str/trim))]
|
||||
;; (st/emit! (di/rename-collection id value))
|
||||
;; (swap! local assoc :edit false))))]
|
||||
;;
|
||||
;; [:li {:on-click on-click
|
||||
;; :on-double-click on-double-click
|
||||
;; :class-name (when selected? "current")}
|
||||
;; (if (:edit @local)
|
||||
;; [:div
|
||||
;; [:input.element-title {:default-value name
|
||||
;; :on-key-down on-input-keyup}]
|
||||
;; [:span.close {:on-click on-cancel-edition} i/close]]
|
||||
;; [:span.element-title (if id name "Storage")])]))
|
||||
;;
|
||||
;; (mf/defc nav
|
||||
;; [{:keys [id type collections] :as props}]
|
||||
;; (let [locale (i18n/use-locale)
|
||||
;; own? (= type :own)
|
||||
;; builtin? (= type :builtin)
|
||||
;; create-collection #(st/emit! di/create-collection)
|
||||
;; select-own-tab #(st/emit! (rt/nav :dashboard-images nil {:type :own}))
|
||||
;; select-buitin-tab #(st/emit! (rt/nav :dashboard-images nil {:type :builtin}))]
|
||||
;; [:div.library-bar
|
||||
;; [:div.library-bar-inside
|
||||
;;
|
||||
;; ;; Tabs
|
||||
;; [:ul.library-tabs
|
||||
;; [:li {:class (when own? "current")
|
||||
;; :on-click select-own-tab}
|
||||
;; (t locale "ds.your-images-title")]
|
||||
;;
|
||||
;; [:li {:class (when builtin? "current")
|
||||
;; :on-click select-buitin-tab}
|
||||
;; (t locale "ds.store-images-title")]]
|
||||
;;
|
||||
;; ;; Collections List
|
||||
;; [:ul.library-elements
|
||||
;; (when own?
|
||||
;; [:li
|
||||
;; [:a.btn-primary {:on-click create-collection}
|
||||
;; (t locale "ds.images-collection.new")]])
|
||||
;;
|
||||
;; (for [item collections]
|
||||
;; [:& nav-item {:coll item
|
||||
;; :selected? (= (:id item) id)
|
||||
;; :key (:id item)}])]]]))
|
||||
;;
|
||||
;; ;; --- Grid
|
||||
;;
|
||||
;; ;; (mf/defc grid-options-tooltip
|
||||
;; ;; [{:keys [selected on-select title] :as props}]
|
||||
;; ;; {:pre [(uuid? selected)
|
||||
;; ;; (fn? on-select)
|
||||
;; ;; (string? title)]}
|
||||
;; ;; (let [colls (mf/deref collections-iref)
|
||||
;; ;; colls (->> (vals colls)
|
||||
;; ;; (filter #(= :own (:type %)))
|
||||
;; ;; (remove #(= selected (:id %)))
|
||||
;; ;; #_(sort-by :name colls))
|
||||
;; ;; on-select (fn [event id]
|
||||
;; ;; (dom/prevent-default event)
|
||||
;; ;; (dom/stop-propagation event)
|
||||
;; ;; (on-select id))]
|
||||
;; ;; [:ul.move-list
|
||||
;; ;; [:li.title title]
|
||||
;; ;; [:li
|
||||
;; ;; (when (not (nil? selected))
|
||||
;; ;; [:a {:href "#" :on-click #(on-select % nil)} "Storage"])]
|
||||
;; ;; (for [{:keys [id name] :as coll} colls]
|
||||
;; ;; [:li {:key (pr-str id)}
|
||||
;; ;; [:a {:on-click #(on-select % id)} name]])]))
|
||||
;;
|
||||
;; (mf/defc grid-options
|
||||
;; [{:keys [id type selected] :as props}]
|
||||
;; (let [local (mf/use-state {})
|
||||
;; delete #(st/emit! di/delete-selected)
|
||||
;; on-delete #(modal/show! confirm-dialog {:on-accept delete})
|
||||
;;
|
||||
;; ;; (on-toggle-copy [event]
|
||||
;; ;; (swap! local update :show-copy-tooltip not))
|
||||
;; ;; (on-toggle-move [event]
|
||||
;; ;; (swap! local update :show-move-tooltip not))
|
||||
;; ;; (on-copy [selected]
|
||||
;; ;; (swap! local assoc
|
||||
;; ;; :show-move-tooltip false
|
||||
;; ;; :show-copy-tooltip false)
|
||||
;; ;; (st/emit! (di/copy-selected selected)))
|
||||
;; ;; (on-move [selected]
|
||||
;; ;; (swap! local assoc
|
||||
;; ;; :show-move-tooltip false
|
||||
;; ;; :show-copy-tooltip false)
|
||||
;; ;; (st/emit! (di/move-selected selected)))
|
||||
;; ;; (on-rename [event]
|
||||
;; ;; (let [selected (first selected)]
|
||||
;; ;; (st/emit! (di/update-opts :edition selected))))
|
||||
;; ]
|
||||
;; ;; MULTISELECT OPTIONS BAR
|
||||
;; [:div.multiselect-bar
|
||||
;; (when (= type :own)
|
||||
;; ;; If editable
|
||||
;; [:div.multiselect-nav
|
||||
;; ;; [:span.move-item.tooltip.tooltip-top
|
||||
;; ;; {:alt (tr "ds.multiselect-bar.copy")
|
||||
;; ;; :on-click on-toggle-copy}
|
||||
;; ;; (when (:show-copy-tooltip @local)
|
||||
;; ;; [:& grid-options-tooltip {:selected id
|
||||
;; ;; :title (tr "ds.multiselect-bar.copy-to-library")
|
||||
;; ;; :on-select on-copy}])
|
||||
;; ;; i/copy]
|
||||
;; ;; [:span.move-item.tooltip.tooltip-top
|
||||
;; ;; {:alt (tr "ds.multiselect-bar.move")
|
||||
;; ;; :on-click on-toggle-move}
|
||||
;; ;; (when (:show-move-tooltip @local)
|
||||
;; ;; [:& grid-options-tooltip {:selected id
|
||||
;; ;; :title (tr "ds.multiselect-bar.move-to-library")
|
||||
;; ;; :on-select on-move}])
|
||||
;; ;; i/move]
|
||||
;; ;; (when (= 1 (count selected))
|
||||
;; ;; [:span.move-item.tooltip.tooltip-top {:alt (tr "ds.multiselect-bar.rename")
|
||||
;; ;; :on-click on-rename}
|
||||
;; ;; i/pencil])
|
||||
;; [:span.delete.tooltip.tooltip-top
|
||||
;; {:alt (tr "ds.multiselect-bar.delete")
|
||||
;; :on-click on-delete}
|
||||
;; i/trash]]
|
||||
;;
|
||||
;; ;; If not editable
|
||||
;; ;; [:div.multiselect-nav
|
||||
;; ;; [:span.move-item.tooltip.tooltip-top {:alt (tr "ds.multiselect-bar.copy")
|
||||
;; ;; :on-click on-toggle-copy}
|
||||
;; ;; (when (:show-copy-tooltip @local)
|
||||
;; ;; [:& grid-options-tooltip {:selected id
|
||||
;; ;; :title (tr "ds.multiselect-bar.copy-to-library")
|
||||
;; ;; :on-select on-copy}])
|
||||
;; ;; i/organize]]
|
||||
;; )]))
|
||||
;;
|
||||
;;
|
||||
;; ;; --- Grid Form
|
||||
;;
|
||||
;; (mf/defc grid-form
|
||||
;; [{:keys [id type uploading?] :as props}]
|
||||
;; (let [input (mf/use-ref nil)
|
||||
;; on-click #(dom/click (mf/ref-node input))
|
||||
;; on-select #(st/emit! (->> (dom/get-target %)
|
||||
;; (dom/get-files)
|
||||
;; (array-seq)
|
||||
;; (di/create-images id)))]
|
||||
;; [:div.grid-item.add-project {:on-click on-click}
|
||||
;; (if uploading?
|
||||
;; [:div i/loader-pencil]
|
||||
;; [:span (tr "ds.image-new")])
|
||||
;; [:input.upload-image-input
|
||||
;; {:style {:display "none"}
|
||||
;; :multiple true
|
||||
;; :ref input
|
||||
;; :value ""
|
||||
;; :accept "image/jpeg,image/png,image/webp"
|
||||
;; :type "file"
|
||||
;; :on-change on-select}]]))
|
||||
;;
|
||||
;; ;; --- Grid Item
|
||||
;;
|
||||
;; (mf/defc grid-item
|
||||
;; [{:keys [image selected? edition?] :as props}]
|
||||
;; (let [toggle-selection #(st/emit! (if selected?
|
||||
;; (di/deselect-image (:id image))
|
||||
;; (di/select-image (:id image))))
|
||||
;; on-blur
|
||||
;; (fn [event]
|
||||
;; (let [target (dom/get-target event)
|
||||
;; name (dom/get-value target)]
|
||||
;; (st/emit! (di/update-opts :edition false)
|
||||
;; (di/rename-image (:id image) name))))
|
||||
;;
|
||||
;; on-key-down
|
||||
;; (fn [event]
|
||||
;; (when (kbd/enter? event)
|
||||
;; (on-blur event)))
|
||||
;;
|
||||
;; on-edit
|
||||
;; (fn [event]
|
||||
;; (dom/stop-propagation event)
|
||||
;; (dom/prevent-default event)
|
||||
;; (st/emit! (di/update-opts :edition (:id image))))
|
||||
;;
|
||||
;; background (str "url('" (:thumb-uri image) "')")]
|
||||
;;
|
||||
;; [:div.grid-item.images-th
|
||||
;; [:div.grid-item-th {:style {:background-image background}}
|
||||
;; [:div.input-checkbox.check-primary
|
||||
;; [:input {:type "checkbox"
|
||||
;; :id (:id image)
|
||||
;; :on-change toggle-selection
|
||||
;; :checked selected?}]
|
||||
;; [:label {:for (:id image)}]]]
|
||||
;;
|
||||
;; [:div.item-info
|
||||
;; (if edition?
|
||||
;; [:input.element-name {:type "text"
|
||||
;; :auto-focus true
|
||||
;; :on-key-down on-key-down
|
||||
;; :on-blur on-blur
|
||||
;; :on-click on-edit
|
||||
;; :default-value (:name image)}]
|
||||
;; [:h3 {:on-double-click on-edit} (:name image)])
|
||||
;; [:span.date (tr "ds.uploaded-at" (dt/format (:created-at image) "dd/MM/yyyy"))]]]))
|
||||
;;
|
||||
;; ;; --- Grid
|
||||
;;
|
||||
;; ;; (defn- make-images-iref
|
||||
;; ;; [collection-id]
|
||||
;; ;; (letfn [(selector [state]
|
||||
;; ;; (->> (vals (:images state))
|
||||
;; ;; (filterv #(= (:collection-id %) collection-id))))]
|
||||
;; ;; (-> (l/lens selector)
|
||||
;; ;; (l/derive st/state))))
|
||||
;;
|
||||
;; (def images-iref
|
||||
;; (-> (comp (l/key :images) (l/lens vals))
|
||||
;; (l/derive st/state)))
|
||||
;;
|
||||
;; (mf/defc grid
|
||||
;; [{:keys [id type collection opts] :as props}]
|
||||
;; (let [editable? (= type :own)
|
||||
;; ;; images-iref (mf/use-memo {:fn #(make-images-iref id)
|
||||
;; ;; :deps (mf/deps id)})
|
||||
;; images (->> (mf/deref images-iref)
|
||||
;; (sort-by :created-at))]
|
||||
;; [:div.dashboard-grid-content
|
||||
;; [:div.dashboard-grid-row
|
||||
;; (when editable?
|
||||
;; [:& grid-form {:id id :type type :uploading? (:uploading opts)}])
|
||||
;; (for [item images]
|
||||
;; [:& grid-item {:image item
|
||||
;; :key (:id item)
|
||||
;; :selected? (contains? (:selected opts) (:id item))
|
||||
;; :edition? (= (:edition opts) (:id item))}])]]))
|
||||
;;
|
||||
;; ;; --- Menu
|
||||
;;
|
||||
;; ;; (mf/defc menu
|
||||
;; ;; [{:keys [opts coll] :as props}]
|
||||
;; ;; (let [ordering (:order opts :name)
|
||||
;; ;; filtering (:filter opts "")
|
||||
;; ;; icount (count (:images coll))]
|
||||
;; ;; (letfn [(on-term-change [event]
|
||||
;; ;; (let [term (-> (dom/get-target event)
|
||||
;; ;; (dom/get-value))]
|
||||
;; ;; (st/emit! (di/update-opts :filter term))))
|
||||
;; ;; (on-ordering-change [event]
|
||||
;; ;; (let [value (dom/event->value event)
|
||||
;; ;; value (read-string value)]
|
||||
;; ;; (st/emit! (di/update-opts :order value))))
|
||||
;; ;; (on-clear [event]
|
||||
;; ;; (st/emit! (di/update-opts :filter "")))]
|
||||
;; ;; [:section.dashboard-bar.library-gap
|
||||
;; ;; [:div.dashboard-info
|
||||
;;
|
||||
;; ;; ;; Counter
|
||||
;; ;; [:span.dashboard-images (tr "ds.num-images" (t/c icount))]
|
||||
;;
|
||||
;; ;; ;; Sorting
|
||||
;; ;; [:div
|
||||
;; ;; [:span (tr "ds.ordering")]
|
||||
;; ;; [:select.input-select {:on-change on-ordering-change
|
||||
;; ;; :value (pr-str ordering)}
|
||||
;; ;; (for [[key value] (seq +ordering-options+)]
|
||||
;; ;; [:option {:key key :value (pr-str key)} (tr value)])]]
|
||||
;;
|
||||
;; ;; ;; Search
|
||||
;; ;; [:form.dashboard-search
|
||||
;; ;; [:input.input-text {:key :images-search-box
|
||||
;; ;; :type "text"
|
||||
;; ;; :on-change on-term-change
|
||||
;; ;; :auto-focus true
|
||||
;; ;; :placeholder (tr "ds.search.placeholder")
|
||||
;; ;; :value filtering}]
|
||||
;; ;; [:div.clear-search {:on-click on-clear} i/close]]]])))
|
||||
;;
|
||||
;; (def opts-iref
|
||||
;; (-> (l/key :dashboard-images)
|
||||
;; (l/derive st/state)))
|
||||
;;
|
||||
;; (mf/defc content
|
||||
;; [{:keys [id type collection] :as props}]
|
||||
;; (let [{:keys [selected] :as opts} (mf/deref opts-iref)]
|
||||
;; [:section.dashboard-grid.library
|
||||
;; (when collection
|
||||
;; [:& grid-header {:collection collection}])
|
||||
;; (if collection
|
||||
;; [:& grid {:id id :type type :collection collection :opts opts}]
|
||||
;; [:span "EMPTY STATE TODO"])
|
||||
;; (when-not (empty? selected)
|
||||
;; [:& grid-options {:id id :type type :selected selected}])]))
|
||||
;;
|
||||
;; ;; --- Images Page
|
||||
;;
|
||||
;; (def collections-iref
|
||||
;; (-> (l/key :images-collections)
|
||||
;; (l/derive st/state)))
|
||||
;;
|
||||
;; (mf/defc images-page
|
||||
;; [{:keys [id type] :as props}]
|
||||
;; (let [collections (mf/deref collections-iref)
|
||||
;; collections (cond->> (vals collections)
|
||||
;; (= type :own) (filter #(= :own (:type %)))
|
||||
;; (= type :builtin) (filter #(= :builtin (:type %)))
|
||||
;; true (sort-by :created-at))
|
||||
;;
|
||||
;; collection (cond
|
||||
;; (uuid? id) (d/seek #(= id (:id %)) collections)
|
||||
;; :else (first collections))
|
||||
;; id (:id collection)]
|
||||
;;
|
||||
;; (mf/use-effect #(st/emit! di/fetch-collections))
|
||||
;; (mf/use-effect
|
||||
;; {:fn #(when id (st/emit! (di/initialize id)))
|
||||
;; :deps (mf/deps id)})
|
||||
;;
|
||||
;; [:section.dashboard-content
|
||||
;; [:& nav {:type type :id id :collections collections}]
|
||||
;; [:& content {:type type :id id :collection collection}]]))
|
||||
|
|
|
@ -16,13 +16,77 @@
|
|||
[uxbox.util.router :as rt]
|
||||
[uxbox.util.i18n :as i18n :refer [t tr]]
|
||||
[uxbox.util.color :as uc]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.main.data.icons :as dico]
|
||||
[uxbox.main.data.images :as dimg]
|
||||
[uxbox.main.data.colors :as dcol]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.ui.dashboard.components.context-menu :refer [context-menu]]))
|
||||
[uxbox.main.ui.components.context-menu :refer [context-menu]]
|
||||
[uxbox.main.ui.modal :as modal]
|
||||
[uxbox.main.ui.confirm :refer [confirm-dialog]]
|
||||
[uxbox.main.ui.colorpicker :refer [colorpicker most-used-colors]]
|
||||
))
|
||||
|
||||
(mf/defc modal-create-color
|
||||
[{:keys [on-accept on-cancel] :as ctx}]
|
||||
(let [state (mf/use-state { :current-color "#406280" })]
|
||||
(letfn [(accept [event]
|
||||
(dom/prevent-default event)
|
||||
(modal/hide!)
|
||||
(when on-accept (on-accept (:current-color @state))))
|
||||
|
||||
(cancel [event]
|
||||
(dom/prevent-default event)
|
||||
(modal/hide!)
|
||||
(when on-cancel (on-cancel)))]
|
||||
[:div.modal-create-color
|
||||
[:h3.modal-create-color-title (tr "modal.create-color.new-color")]
|
||||
[:& colorpicker {:value (:current-color @state)
|
||||
:colors (into-array @most-used-colors)
|
||||
:on-change #(swap! state assoc :current-color %)}]
|
||||
|
||||
[:input.btn-primary {:type "button"
|
||||
:value (tr "ds.button.save")
|
||||
:on-click accept}]
|
||||
|
||||
[:a.close {:href "#" :on-click cancel} i/close]])))
|
||||
|
||||
|
||||
(defmulti create-library (fn [x _] x))
|
||||
(defmethod create-library :icons [_ team-id]
|
||||
(let [name (str "Icon Library "(gensym "l"))]
|
||||
(st/emit! (dico/create-icon-library team-id name))))
|
||||
|
||||
(defmethod create-library :images [_ team-id]
|
||||
(let [name (str "Image Library "(gensym "l"))]
|
||||
(st/emit! (dimg/create-image-library team-id name))))
|
||||
|
||||
(defmethod create-library :palettes [_ team-id]
|
||||
(let [name (str "Image Library "(gensym "l"))]
|
||||
(st/emit! (dcol/create-color-library team-id name))))
|
||||
|
||||
(defmulti create-item (fn [x _ _] x))
|
||||
|
||||
(defmethod create-item :icons [_ library-id data]
|
||||
(let [files (->> data
|
||||
(dom/get-target)
|
||||
(dom/get-files)
|
||||
(array-seq))]
|
||||
(st/emit! (dico/create-icons library-id files))))
|
||||
|
||||
(defmethod create-item :images [_ library-id data]
|
||||
(let [files (->> data
|
||||
(dom/get-target)
|
||||
(dom/get-files)
|
||||
(array-seq))]
|
||||
(st/emit! (dimg/create-images library-id files))))
|
||||
|
||||
(defmethod create-item :palettes [_ library-id]
|
||||
(letfn [(dispatch-color [color]
|
||||
(st/emit! (dcol/create-color library-id color)))]
|
||||
(modal/show! modal-create-color {:on-accept dispatch-color})))
|
||||
|
||||
(mf/defc library-header
|
||||
[{:keys [section team-id] :as props}]
|
||||
|
@ -51,22 +115,23 @@
|
|||
(let [locale (i18n/use-locale)]
|
||||
[:aside.library-sidebar
|
||||
[:button.library-sidebar-add-item
|
||||
{:type "button"}
|
||||
{:type "button"
|
||||
:on-click #(create-library section team-id)}
|
||||
(t locale (str "dashboard.library.add-library." (name section)))]
|
||||
[:ul.library-sidebar-list
|
||||
(for [item items]
|
||||
[:li.library-sidebar-list-element
|
||||
{:key (:id item)
|
||||
:class-name (when (= library-id (:id item)) "current")
|
||||
:on-click (fn [] (let [path (keyword (str "dashboard-library-" (name section)))
|
||||
route (rt/nav path {:team-id team-id
|
||||
:library-id (:id item)})]
|
||||
(dico/fetch-icon-library (:id item))
|
||||
(st/emit! route)))}
|
||||
:on-click
|
||||
(fn []
|
||||
(let [path (keyword (str "dashboard-library-" (name section)))]
|
||||
(dico/fetch-icon-library (:id item))
|
||||
(st/emit! (rt/nav path {:team-id team-id :library-id (:id item)}))))}
|
||||
[:a (:name item)]])]]))
|
||||
|
||||
(mf/defc library-top-menu
|
||||
[{:keys [selected section]}]
|
||||
[{:keys [selected section library-id]}]
|
||||
(let [state (mf/use-state {:is-open false})
|
||||
locale (i18n/use-locale)]
|
||||
[:header.library-top-menu
|
||||
|
@ -75,13 +140,27 @@
|
|||
[:a.library-top-menu-current-action
|
||||
{ :on-click #(swap! state update :is-open not)}
|
||||
[:span i/arrow-down]]
|
||||
[:& context-menu {:is-open (:is-open @state)
|
||||
:options [[(t locale "ds.button.rename") #(println "Rename")]
|
||||
[(t locale "ds.button.delete") #(println "Delete")]]}]]
|
||||
[:& context-menu
|
||||
{:show (:is-open @state)
|
||||
:on-close #(swap! state update :is-open not)
|
||||
:options [[(t locale "ds.button.rename") #(println "Rename")]
|
||||
[(t locale "ds.button.delete") #(println "Delete")]]}]]
|
||||
|
||||
[:div.library-top-menu-actions
|
||||
[:a i/trash]
|
||||
[:a.btn-dashboard (t locale (str "dashboard.library.add-item." (name section)))]]]))
|
||||
|
||||
(if (= section :palettes)
|
||||
[:button.btn-dashboard
|
||||
{:on-click #(create-item section library-id)}
|
||||
(t locale (str "dashboard.library.add-item." (name section)))]
|
||||
|
||||
[:*
|
||||
[:label {:for "file-upload" :class-name "btn-dashboard"}
|
||||
(t locale (str "dashboard.library.add-item." (name section)))]
|
||||
[:input {:on-change #(create-item section library-id %)
|
||||
:id "file-upload" :type "file" :style {:display "none"}}]]
|
||||
|
||||
)]]))
|
||||
|
||||
(mf/defc library-icon-card
|
||||
[{:keys [id name url content metadata]}]
|
||||
|
@ -107,11 +186,13 @@
|
|||
[:div.library-card-footer-menu
|
||||
{ :on-click #(swap! state update :is-open not) }
|
||||
i/actions]
|
||||
[:& context-menu {:is-open (:is-open @state)
|
||||
:options [[(t locale "ds.button.delete") #(println "Delete")]]}]]]))
|
||||
[:& context-menu
|
||||
{:show (:is-open @state)
|
||||
:on-close #(swap! state update :is-open not)
|
||||
:options [[(t locale "ds.button.delete") #(println "Delete")]]}]]]))
|
||||
|
||||
(mf/defc library-image-card
|
||||
[{:keys [id name url]}]
|
||||
[{:keys [id name thumb-uri]}]
|
||||
(let [locale (i18n/use-locale)
|
||||
state (mf/use-state {:is-open false})]
|
||||
[:div.library-card.library-image
|
||||
|
@ -122,39 +203,44 @@
|
|||
#_(:checked false)}]
|
||||
[:label {:for (str "image-" id)}]]
|
||||
[:div.library-card-image
|
||||
[:img {:src url}]]
|
||||
[:img {:src thumb-uri}]]
|
||||
[:div.library-card-footer
|
||||
[:div.library-card-footer-name name]
|
||||
[:div.library-card-footer-timestamp "Less than 5 seconds ago"]
|
||||
[:div.library-card-footer-menu
|
||||
{ :on-click #(swap! state update :is-open not) }
|
||||
i/actions]
|
||||
[:& context-menu {:is-open (:is-open @state)
|
||||
:options [[(t locale "ds.button.delete") #(println "Delete")]]}]]]))
|
||||
[:& context-menu
|
||||
{:show (:is-open @state)
|
||||
:on-close #(swap! state update :is-open not)
|
||||
:options [[(t locale "ds.button.delete") #(println "Delete")]]}]]]))
|
||||
|
||||
(mf/defc library-color-card
|
||||
[{ :keys [ id content ] }]
|
||||
(let [locale (i18n/use-locale)
|
||||
state (mf/use-state {:is-open false})]
|
||||
[:div.library-card.library-color
|
||||
[:div.input-checkbox.check-primary
|
||||
[:input {:type "checkbox"
|
||||
:id (str "color-" id)
|
||||
:on-change #(println "toggle-selection")
|
||||
#_(:checked false)}]
|
||||
[:label {:for (str "color-" id)}]]
|
||||
[:div.library-card-image
|
||||
{ :style { :background-color content }}]
|
||||
[:div.library-card-footer
|
||||
[:div.library-card-footer-name content ]
|
||||
[:div.library-card-footer-color
|
||||
[:span.library-card-footer-color-label "RGB"]
|
||||
[:span.library-card-footer-color-rgb (str/join " " (uc/hex->rgb content))]]
|
||||
[:div.library-card-footer-menu
|
||||
{ :on-click #(swap! state update :is-open not) }
|
||||
i/actions]
|
||||
[:& context-menu {:is-open (:is-open @state)
|
||||
:options [[(t locale "ds.button.delete") #(println "Delete")]]}]]]))
|
||||
(when content
|
||||
(let [locale (i18n/use-locale)
|
||||
state (mf/use-state {:is-open false})]
|
||||
[:div.library-card.library-color
|
||||
[:div.input-checkbox.check-primary
|
||||
[:input {:type "checkbox"
|
||||
:id (str "color-" id)
|
||||
:on-change #(println "toggle-selection")
|
||||
#_(:checked false)}]
|
||||
[:label {:for (str "color-" id)}]]
|
||||
[:div.library-card-image
|
||||
{ :style { :background-color content }}]
|
||||
[:div.library-card-footer
|
||||
[:div.library-card-footer-name content ]
|
||||
[:div.library-card-footer-color
|
||||
[:span.library-card-footer-color-label "RGB"]
|
||||
[:span.library-card-footer-color-rgb (str/join " " (uc/hex->rgb content))]]
|
||||
[:div.library-card-footer-menu
|
||||
{ :on-click #(swap! state update :is-open not) }
|
||||
i/actions]
|
||||
[:& context-menu
|
||||
{:show (:is-open @state)
|
||||
:on-close #(swap! state update :is-open not)
|
||||
:options [[(t locale "ds.button.delete") #(println "Delete")]]}]]])))
|
||||
|
||||
(def icon-libraries-ref
|
||||
(-> (comp (l/key :library) (l/key :icon-libraries))
|
||||
|
@ -197,11 +283,11 @@
|
|||
|
||||
(when library-id
|
||||
[:section.library-content
|
||||
[:& library-top-menu {:selected selected-library :section section}]
|
||||
[:& library-top-menu {:selected selected-library :section section :library-id library-id}]
|
||||
[:div.library-page-cards-container
|
||||
(for [item items]
|
||||
(let [item (assoc item :key (:id item))]
|
||||
(case section
|
||||
:icons [:& library-icon-card item]
|
||||
:images [:& library-image-card { :name "Nicolas Cage" :url "https://www.placecage.com/200/200" }]
|
||||
:images [:& library-image-card item]
|
||||
:palettes [:& library-color-card item ])))]])]))
|
||||
|
|
|
@ -125,5 +125,5 @@
|
|||
(mf/defc colorpalette
|
||||
[props]
|
||||
(let [colls (mf/deref collections-iref)]
|
||||
(mf/use-effect #(st/emit! (udc/fetch-collections)))
|
||||
#_(mf/use-effect #(st/emit! (udc/fetch-collections)))
|
||||
[:& palette {:colls (vals colls)}]))
|
||||
|
|
|
@ -160,8 +160,8 @@
|
|||
(d/read-string)
|
||||
(swap! local assoc :collection-id))]
|
||||
|
||||
(mf/use-effect #(st/emit! udi/fetch-collections))
|
||||
(mf/use-effect
|
||||
#_(mf/use-effect #(st/emit! udi/fetch-collections))
|
||||
#_(mf/use-effect
|
||||
{:deps (mf/deps collection-id)
|
||||
:fn #(when collection-id
|
||||
(st/emit! (udi/fetch-images collection-id)))})
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
(fn [event data]
|
||||
(st/emit! (dw/select-for-drawing :icon data)))]
|
||||
|
||||
(mf/use-effect
|
||||
#_(mf/use-effect
|
||||
{:fn #(st/emit! (di/fetch-icons collection-id))
|
||||
:deps (mf/deps collection-id)})
|
||||
|
||||
|
@ -79,7 +79,7 @@
|
|||
(st/emit! (dw/select-for-drawing nil))
|
||||
(reset! selected val))]
|
||||
|
||||
(mf/use-effect
|
||||
#_(mf/use-effect
|
||||
{:fn #(st/emit! di/fetch-collections)})
|
||||
|
||||
[:div#form-figures.tool-window
|
||||
|
|
Loading…
Add table
Reference in a new issue