:neckbeard: retrieve data from backend

This commit is contained in:
alonso.torres 2020-03-16 15:52:02 +01:00
parent e700f937db
commit b2474fc3fb
15 changed files with 1022 additions and 687 deletions

View file

@ -23,6 +23,8 @@
{:http-server-port 6060 {:http-server-port 6060
:http-server-cors "http://localhost:3449" :http-server-cors "http://localhost:3449"
:database-uri "postgresql://127.0.0.1/uxbox" :database-uri "postgresql://127.0.0.1/uxbox"
:database-username "uxbox"
:database-password "uxbox"
:media-directory "resources/public/media" :media-directory "resources/public/media"
:assets-directory "resources/public/static" :assets-directory "resources/public/static"
:media-uri "http://localhost:6060/media/" :media-uri "http://localhost:6060/media/"

View file

@ -66,9 +66,20 @@
values ($1, $2, $3, $4, $5, $6) values ($1, $2, $3, $4, $5, $6)
returning id;") returning id;")
(def sql:create-icon-library
"insert into icon_library (team_id, name)
values ($1, $2)
returning id;")
(def sql:create-icon
"insert into icon_library (library_id, name, content, metadata)
values ($1, $2, $3, $4)
returning id;")
(def preset-small (def preset-small
{:num-teams 50 {:num-teams 5
:num-profiles 50 :num-profiles 5
:num-profiles-per-team 5 :num-profiles-per-team 5
:num-projects-per-team 5 :num-projects-per-team 5
:num-files-per-project 5 :num-files-per-project 5

View file

@ -31,6 +31,7 @@
(s/def ::name ::us/string) (s/def ::name ::us/string)
(s/def ::profile-id ::us/uuid) (s/def ::profile-id ::us/uuid)
(s/def ::library-id ::us/uuid) (s/def ::library-id ::us/uuid)
(s/def ::team-id ::us/uuid)
(defn decode-row (defn decode-row
[{:keys [metadata] :as row}] [{:keys [metadata] :as row}]

View file

@ -21,6 +21,7 @@
(s/def ::id ::us/uuid) (s/def ::id ::us/uuid)
(s/def ::name ::us/string) (s/def ::name ::us/string)
(s/def ::profile-id ::us/uuid) (s/def ::profile-id ::us/uuid)
(s/def ::team-id ::us/uuid)
(s/def ::library-id ::us/uuid) (s/def ::library-id ::us/uuid)
;; --- Query: Image Librarys ;; --- Query: Image Librarys

View file

@ -78,14 +78,68 @@
"en" : "Type to search results" "en" : "Type to search results"
} }
}, },
"dashboard.library.add-item.icons" : {
"translations" : {
"en" : "+ New icon"
},
"unused" : true
},
"dashboard.library.add-item.images" : {
"translations" : {
"en" : "+ New image"
},
"unused" : true
},
"dashboard.library.add-item.palettes" : {
"translations" : {
"en" : "+ New color"
},
"unused" : true
},
"dashboard.library.add-library.icons" : {
"translations" : {
"en" : "+ New icon library"
},
"unused" : true
},
"dashboard.library.add-library.images" : {
"translations" : {
"en" : "+ New image library"
},
"unused" : true
},
"dashboard.library.add-library.palettes" : {
"translations" : {
"en" : "+ New palette"
},
"unused" : true
},
"dashboard.library.menu.icons" : {
"used-in" : [ "src/uxbox/main/ui/dashboard/library.cljs:39" ],
"translations" : {
"en" : "Icons"
}
},
"dashboard.library.menu.images" : {
"used-in" : [ "src/uxbox/main/ui/dashboard/library.cljs:43" ],
"translations" : {
"en" : "Images"
}
},
"dashboard.library.menu.palettes" : {
"used-in" : [ "src/uxbox/main/ui/dashboard/library.cljs:47" ],
"translations" : {
"en" : "Palettes"
}
},
"dashboard.sidebar.drafts" : { "dashboard.sidebar.drafts" : {
"used-in" : [ "src/uxbox/main/ui/dashboard/sidebar.cljs:113" ], "used-in" : [ "src/uxbox/main/ui/dashboard/sidebar.cljs:112" ],
"translations" : { "translations" : {
"en" : "Drafts" "en" : "Drafts"
} }
}, },
"dashboard.sidebar.libraries" : { "dashboard.sidebar.libraries" : {
"used-in" : [ "src/uxbox/main/ui/dashboard/sidebar.cljs:118" ], "used-in" : [ "src/uxbox/main/ui/dashboard/sidebar.cljs:117" ],
"translations" : { "translations" : {
"en" : "Libraries" "en" : "Libraries"
} }
@ -97,7 +151,7 @@
"unused" : true "unused" : true
}, },
"dashboard.sidebar.recent" : { "dashboard.sidebar.recent" : {
"used-in" : [ "src/uxbox/main/ui/dashboard/sidebar.cljs:106" ], "used-in" : [ "src/uxbox/main/ui/dashboard/sidebar.cljs:105" ],
"translations" : { "translations" : {
"en" : "Recent" "en" : "Recent"
} }
@ -109,6 +163,24 @@
"fr" : "Accepter" "fr" : "Accepter"
} }
}, },
"ds.button.delete" : {
"used-in" : [ "src/uxbox/main/ui/dashboard/library.cljs:80", "src/uxbox/main/ui/dashboard/library.cljs:111", "src/uxbox/main/ui/dashboard/library.cljs:133", "src/uxbox/main/ui/dashboard/library.cljs:157" ],
"translations" : {
"en" : "Delete"
}
},
"ds.button.rename" : {
"used-in" : [ "src/uxbox/main/ui/dashboard/library.cljs:79" ],
"translations" : {
"en" : "Rename"
}
},
"ds.button.save" : {
"translations" : {
"en" : "Save"
},
"unused" : true
},
"ds.cancel" : { "ds.cancel" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/history.cljs:114" ], "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/history.cljs:114" ],
"translations" : { "translations" : {
@ -166,7 +238,7 @@
} }
}, },
"ds.default-library-title" : { "ds.default-library-title" : {
"used-in" : [ "src/uxbox/main/data/icons.cljs:90", "src/uxbox/main/data/colors.cljs:68", "src/uxbox/main/data/images.cljs:110" ], "used-in" : [ "src/uxbox/main/data/colors.cljs:68", "src/uxbox/main/data/icons.cljs:90", "src/uxbox/main/data/images.cljs:110" ],
"translations" : { "translations" : {
"en" : "Unnamed Collection (%s)", "en" : "Unnamed Collection (%s)",
"fr" : "Collection sans nom (%s)" "fr" : "Collection sans nom (%s)"
@ -244,7 +316,7 @@
} }
}, },
"ds.multiselect-bar.delete" : { "ds.multiselect-bar.delete" : {
"used-in" : [ "src/uxbox/main/ui/dashboard/icons.cljs:221", "src/uxbox/main/ui/dashboard/colors.cljs:214", "src/uxbox/main/ui/dashboard/images.cljs:187" ], "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:214", "src/uxbox/main/ui/dashboard/images.cljs:187", "src/uxbox/main/ui/dashboard/icons.cljs:221" ],
"translations" : { "translations" : {
"en" : "Delete", "en" : "Delete",
"fr" : "Supprimer" "fr" : "Supprimer"
@ -300,7 +372,7 @@
"unused" : true "unused" : true
}, },
"ds.search.placeholder" : { "ds.search.placeholder" : {
"used-in" : [ "src/uxbox/main/ui/dashboard/sidebar.cljs:168" ], "used-in" : [ "src/uxbox/main/ui/dashboard/sidebar.cljs:140" ],
"translations" : { "translations" : {
"en" : "Search...", "en" : "Search...",
"fr" : "Rechercher..." "fr" : "Rechercher..."
@ -356,7 +428,7 @@
} }
}, },
"ds.uploaded-at" : { "ds.uploaded-at" : {
"used-in" : [ "src/uxbox/main/ui/dashboard/icons.cljs:309", "src/uxbox/main/ui/dashboard/images.cljs:271" ], "used-in" : [ "src/uxbox/main/ui/dashboard/images.cljs:271", "src/uxbox/main/ui/dashboard/icons.cljs:309" ],
"translations" : { "translations" : {
"en" : "Uploaded at %s", "en" : "Uploaded at %s",
"fr" : "Mise en ligne : %s" "fr" : "Mise en ligne : %s"
@ -426,14 +498,14 @@
} }
}, },
"errors.generic" : { "errors.generic" : {
"used-in" : [ "src/uxbox/main/ui.cljs:135" ], "used-in" : [ "src/uxbox/main/ui.cljs:131" ],
"translations" : { "translations" : {
"en" : "Something wrong has happened.", "en" : "Something wrong has happened.",
"fr" : "Quelque chose c'est mal passé." "fr" : "Quelque chose c'est mal passé."
} }
}, },
"errors.network" : { "errors.network" : {
"used-in" : [ "src/uxbox/main/ui.cljs:129" ], "used-in" : [ "src/uxbox/main/ui.cljs:125" ],
"translations" : { "translations" : {
"en" : "Unable to connect to backend server.", "en" : "Unable to connect to backend server.",
"fr" : "Impossible de se connecter au serveur principal." "fr" : "Impossible de se connecter au serveur principal."
@ -538,7 +610,7 @@
} }
}, },
"profile.recovery.go-to-login" : { "profile.recovery.go-to-login" : {
"used-in" : [ "src/uxbox/main/ui/profile/recovery_request.cljs:65", "src/uxbox/main/ui/profile/recovery.cljs:81" ], "used-in" : [ "src/uxbox/main/ui/profile/recovery.cljs:81", "src/uxbox/main/ui/profile/recovery_request.cljs:65" ],
"translations" : { "translations" : {
"en" : "Go back!", "en" : "Go back!",
"fr" : "Retour!" "fr" : "Retour!"
@ -895,7 +967,7 @@
} }
}, },
"workspace.options.color" : { "workspace.options.color" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:124", "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:47", "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:81" ], "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:47", "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:124", "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:81" ],
"translations" : { "translations" : {
"en" : "Color", "en" : "Color",
"fr" : "Couleur" "fr" : "Couleur"
@ -937,7 +1009,7 @@
} }
}, },
"workspace.options.measures" : { "workspace.options.measures" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:69", "src/uxbox/main/ui/workspace/sidebar/options/icon.cljs:66", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:62", "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:64", "src/uxbox/main/ui/workspace/sidebar/options/frame.cljs:55", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:66" ], "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:64", "src/uxbox/main/ui/workspace/sidebar/options/frame.cljs:55", "src/uxbox/main/ui/workspace/sidebar/options/icon.cljs:66", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:62", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:66", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:69" ],
"translations" : { "translations" : {
"en" : "Size, position & rotation", "en" : "Size, position & rotation",
"fr" : "Taille, position et rotation" "fr" : "Taille, position et rotation"
@ -951,21 +1023,21 @@
} }
}, },
"workspace.options.position" : { "workspace.options.position" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:98", "src/uxbox/main/ui/workspace/sidebar/options/icon.cljs:95", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:91", "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:92", "src/uxbox/main/ui/workspace/sidebar/options/frame.cljs:84", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:95" ], "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:92", "src/uxbox/main/ui/workspace/sidebar/options/frame.cljs:84", "src/uxbox/main/ui/workspace/sidebar/options/icon.cljs:95", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:91", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:95", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:98" ],
"translations" : { "translations" : {
"en" : "Position", "en" : "Position",
"fr" : "Position" "fr" : "Position"
} }
}, },
"workspace.options.rotation-radius" : { "workspace.options.rotation-radius" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:115", "src/uxbox/main/ui/workspace/sidebar/options/icon.cljs:112", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:108", "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:107", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:112" ], "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:107", "src/uxbox/main/ui/workspace/sidebar/options/icon.cljs:112", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:108", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:112", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:115" ],
"translations" : { "translations" : {
"en" : "Rotation & Radius", "en" : "Rotation & Radius",
"fr" : "TODO" "fr" : "TODO"
} }
}, },
"workspace.options.size" : { "workspace.options.size" : {
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:114", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:71", "src/uxbox/main/ui/workspace/sidebar/options/icon.cljs:68", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:64", "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:68", "src/uxbox/main/ui/workspace/sidebar/options/frame.cljs:57", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:68" ], "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:68", "src/uxbox/main/ui/workspace/sidebar/options/frame.cljs:57", "src/uxbox/main/ui/workspace/sidebar/options/icon.cljs:68", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:64", "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:114", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:68", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:71" ],
"translations" : { "translations" : {
"en" : "Size", "en" : "Size",
"fr" : "Taille" "fr" : "Taille"

View file

@ -47,6 +47,8 @@
.library-sidebar { .library-sidebar {
background-color: $color-white; background-color: $color-white;
padding: $size-2; padding: $size-2;
height: 100%;
overflow: hidden;
} }
.library-sidebar-add-item { .library-sidebar-add-item {
@ -66,11 +68,17 @@
.library-sidebar-list { .library-sidebar-list {
margin-top: $size-4; margin-top: $size-4;
overflow: scroll;
height: 100%;
padding-bottom: 4rem;
} }
.library-sidebar-list-element { .library-sidebar-list-element {
padding: $size-4 $size-2; padding: $size-4 $size-2;
cursor: pointer; cursor: pointer;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
& a { & a {
color: $color-black; color: $color-black;
@ -138,17 +146,19 @@
} }
.library-page-cards-container { .library-page-cards-container {
padding: $size-2; align-content: flex-start;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
overflow: scroll;
height: 100%; height: 100%;
align-content: flex-start; overflow: scroll;
padding: $size-2;
padding-bottom: 4rem;
} }
.library-card { .library-card {
margin: $size-2; margin: $size-2;
background: $color-white; background: $color-white;
border: 2px solid transparent;
&.library-icon, &.library-color { &.library-icon, &.library-color {
width: 200px; width: 200px;
@ -168,6 +178,10 @@
opacity: 0; opacity: 0;
} }
&:hover {
border: 2px solid $color-primary;
}
&:hover .library-card-footer-menu { &:hover .library-card-footer-menu {
visibility: visible; visibility: visible;
opacity: 1; opacity: 1;
@ -204,7 +218,7 @@
text-align: center; text-align: center;
display: flex; display: flex;
& svg, & img { & object, & svg, & img {
margin: auto; margin: auto;
width: auto; width: auto;
height: auto; height: auto;

View file

@ -6,9 +6,11 @@
(ns uxbox.main.data.colors (ns uxbox.main.data.colors
(:require (:require
[cljs.spec.alpha :as s]
[beicon.core :as rx] [beicon.core :as rx]
[clojure.set :as set] [clojure.set :as set]
[potok.core :as ptk] [potok.core :as ptk]
[uxbox.common.spec :as us]
[uxbox.main.repo :as rp] [uxbox.main.repo :as rp]
[uxbox.main.store :as st] [uxbox.main.store :as st]
[uxbox.util.color :as color] [uxbox.util.color :as color]
@ -241,3 +243,47 @@
(defn delete-colors (defn delete-colors
[coll-id colors] [coll-id colors]
(DeleteColors. coll-id colors)) (DeleteColors. coll-id colors))
;;;; NEW
(declare fetch-color-libraries-result)
(defn fetch-color-libraries
[team-id]
(s/assert ::us/uuid team-id)
(ptk/reify ::fetch-color-libraries
ptk/WatchEvent
(watch [_ state stream]
(->> (rp/query! :color-libraries {:team-id team-id})
(rx/map fetch-color-libraries-result)))))
(defn fetch-color-libraries-result [result]
(ptk/reify ::fetch-color-libraries-result
ptk/UpdateEvent
(update [_ state]
(-> state
(assoc-in [:library :color-libraries] result)))))
(declare fetch-color-library-result)
(defn fetch-color-library
[library-id]
(ptk/reify ::fetch-color-library
ptk/UpdateEvent
(update [_ state]
(-> state
(assoc-in [:library :selected-items] nil)))
ptk/WatchEvent
(watch [_ state stream]
(->> (rp/query! :colors {:library-id library-id})
(rx/map fetch-color-library-result)))))
(defn fetch-color-library-result
[data]
(ptk/reify ::fetch-color-library
ptk/UpdateEvent
(update [_ state]
(-> state
(assoc-in [:library :selected-items] data)))))

View file

@ -35,20 +35,61 @@
::user-id])) ::user-id]))
(declare fetch-icons) (declare fetch-icon-libraries-result)
(defn initialize (defn fetch-icon-libraries
[collection-id] [team-id]
(s/assert ::us/uuid collection-id) (s/assert ::us/uuid team-id)
(ptk/reify ::initialize (ptk/reify ::fetch-icon-libraries
ptk/WatchEvent
(watch [_ state stream]
(->> (rp/query! :icon-libraries {:team-id team-id})
(rx/map fetch-icon-libraries-result)))))
(defn fetch-icon-libraries-result [result]
(ptk/reify ::fetch-icon-libraries-result
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
(assoc-in state [:dashboard-icons :selected] #{})) (-> state
(assoc-in [:library :icon-libraries] result)))))
(declare fetch-icon-library-result)
(defn fetch-icon-library
[library-id]
(ptk/reify ::fetch-icon-library
ptk/UpdateEvent
(update [_ state]
(-> state
(assoc-in [:library :selected-items] nil)))
ptk/WatchEvent ptk/WatchEvent
(watch [_ state stream] (watch [_ state stream]
(rx/of (fetch-icons collection-id))))) (->> (rp/query! :icons {:library-id library-id})
(rx/map fetch-icon-library-result)))))
(defn fetch-icon-library-result
[data]
(ptk/reify ::fetch-icon-library
ptk/UpdateEvent
(update [_ state]
(-> state
(assoc-in [:library :selected-items] data)))))
;; (declare fetch-icons)
;;
;; (defn initialize
;; [collection-id]
;; (s/assert ::us/uuid collection-id)
;; (ptk/reify ::initialize
;; ptk/UpdateEvent
;; (update [_ state]
;; (assoc-in state [:dashboard-icons :selected] #{}))
;;
;; ptk/WatchEvent
;; (watch [_ state stream]
;; (rx/of (fetch-icons collection-id)))))
;;
;; --- Fetch Collections ;; --- Fetch Collections
(declare collections-fetched) (declare collections-fetched)
@ -79,156 +120,156 @@
items)))) items))))
;; --- Create Collection ;; ;; --- Create Collection
;;
(declare collection-created) ;; (declare collection-created)
;;
(def create-collection ;; (def create-collection
(ptk/reify ::create-collection ;; (ptk/reify ::create-collection
ptk/WatchEvent ;; ptk/WatchEvent
(watch [_ state s] ;; (watch [_ state s]
(let [name (tr "ds.default-library-title" (gensym "c")) ;; (let [name (tr "ds.default-library-title" (gensym "c"))
data {:name name}] ;; data {:name name}]
(->> (rp/mutation! :create-icons-collection data) ;; (->> (rp/mutation! :create-icons-collection data)
(rx/map collection-created)))))) ;; (rx/map collection-created))))))
;;
;;
;; --- Collection Created ;; ;; --- Collection Created
;;
(defn collection-created ;; (defn collection-created
[item] ;; [item]
(s/assert ::collection item) ;; (s/assert ::collection item)
(ptk/reify ::collection-created ;; (ptk/reify ::collection-created
ptk/UpdateEvent ;; ptk/UpdateEvent
(update [_ state] ;; (update [_ state]
(let [{:keys [id] :as item} (assoc item :type :own)] ;; (let [{:keys [id] :as item} (assoc item :type :own)]
(update state :icons-collections assoc id item))))) ;; (update state :icons-collections assoc id item)))))
;;
;; --- Rename Collection ;; ;; --- Rename Collection
;;
(defn rename-collection ;; (defn rename-collection
[id name] ;; [id name]
(ptk/reify ::rename-collection ;; (ptk/reify ::rename-collection
ptk/UpdateEvent ;; ptk/UpdateEvent
(update [_ state] ;; (update [_ state]
(assoc-in state [:icons-collections id :name] name)) ;; (assoc-in state [:icons-collections id :name] name))
;;
ptk/WatchEvent ;; ptk/WatchEvent
(watch [_ state s] ;; (watch [_ state s]
(let [params {:id id :name name}] ;; (let [params {:id id :name name}]
(->> (rp/mutation! :rename-icons-collection params) ;; (->> (rp/mutation! :rename-icons-collection params)
(rx/ignore)))))) ;; (rx/ignore))))))
;;
;; --- Delete Collection ;; ;; --- Delete Collection
;;
(defn delete-collection ;; (defn delete-collection
[id on-success] ;; [id on-success]
(ptk/reify ::delete-collection ;; (ptk/reify ::delete-collection
ptk/UpdateEvent ;; ptk/UpdateEvent
(update [_ state] ;; (update [_ state]
(update state :icons-collections dissoc id)) ;; (update state :icons-collections dissoc id))
;;
ptk/WatchEvent ;; ptk/WatchEvent
(watch [_ state s] ;; (watch [_ state s]
(->> (rp/mutation! :delete-icons-collection {:id id}) ;; (->> (rp/mutation! :delete-icons-collection {:id id})
(rx/tap on-success) ;; (rx/tap on-success)
(rx/ignore))))) ;; (rx/ignore)))))
;;
;; --- Icon Created ;; ;; --- Icon Created
;;
(defrecord IconCreated [item] ;; (defrecord IconCreated [item]
ptk/UpdateEvent ;; ptk/UpdateEvent
(update [_ state] ;; (update [_ state]
(let [{:keys [id] :as item} (assoc item :type :icon)] ;; (let [{:keys [id] :as item} (assoc item :type :icon)]
(update state :icons assoc id item)))) ;; (update state :icons assoc id item))))
;;
(defn icon-created ;; (defn icon-created
[item] ;; [item]
(IconCreated. item)) ;; (IconCreated. item))
;;
;; --- Create Icon ;; ;; --- Create Icon
;;
(declare icon-created) ;; (declare icon-created)
;;
(defn- parse-svg ;; (defn- parse-svg
[data] ;; [data]
(s/assert ::us/string data) ;; (s/assert ::us/string data)
(let [valid-tags #{"defs" "path" "circle" "rect" "metadata" "g" ;; (let [valid-tags #{"defs" "path" "circle" "rect" "metadata" "g"
"radialGradient" "stop"} ;; "radialGradient" "stop"}
div (dom/create-element "div") ;; div (dom/create-element "div")
gc (dom/create-element "div") ;; gc (dom/create-element "div")
g (dom/create-element "http://www.w3.org/2000/svg" "g") ;; g (dom/create-element "http://www.w3.org/2000/svg" "g")
_ (dom/set-html! div data) ;; _ (dom/set-html! div data)
svg (dom/query div "svg")] ;; svg (dom/query div "svg")]
(loop [child (dom/get-first-child svg)] ;; (loop [child (dom/get-first-child svg)]
(if child ;; (if child
(let [tagname (dom/get-tag-name child)] ;; (let [tagname (dom/get-tag-name child)]
(if (contains? valid-tags tagname) ;; (if (contains? valid-tags tagname)
(dom/append-child! g child) ;; (dom/append-child! g child)
(dom/append-child! gc child)) ;; (dom/append-child! gc child))
(recur (dom/get-first-child svg))) ;; (recur (dom/get-first-child svg)))
(let [width (.. svg -width -baseVal -value) ;; (let [width (.. svg -width -baseVal -value)
height (.. svg -height -baseVal -value) ;; height (.. svg -height -baseVal -value)
view-box [(.. svg -viewBox -baseVal -x) ;; view-box [(.. svg -viewBox -baseVal -x)
(.. svg -viewBox -baseVal -y) ;; (.. svg -viewBox -baseVal -y)
(.. svg -viewBox -baseVal -width) ;; (.. svg -viewBox -baseVal -width)
(.. svg -viewBox -baseVal -height)] ;; (.. svg -viewBox -baseVal -height)]
props {:width width ;; props {:width width
:mimetype "image/svg+xml" ;; :mimetype "image/svg+xml"
:height height ;; :height height
:view-box view-box}] ;; :view-box view-box}]
[(dom/get-outer-html g) props]))))) ;; [(dom/get-outer-html g) props])))))
;;
;;
(defn create-icons ;; (defn create-icons
[id files] ;; [id files]
(s/assert (s/nilable uuid?) id) ;; (s/assert (s/nilable uuid?) id)
(ptk/reify ::create-icons ;; (ptk/reify ::create-icons
ptk/WatchEvent ;; ptk/WatchEvent
(watch [_ state s] ;; (watch [_ state s]
(letfn [(parse [file] ;; (letfn [(parse [file]
(->> (wapi/read-file-as-text file) ;; (->> (wapi/read-file-as-text file)
(rx/map parse-svg))) ;; (rx/map parse-svg)))
(allowed? [file] ;; (allowed? [file]
(= (.-type file) "image/svg+xml")) ;; (= (.-type file) "image/svg+xml"))
(prepare [[content metadata]] ;; (prepare [[content metadata]]
{:collection-id id ;; {:collection-id id
:content content ;; :content content
:id (uuid/next) ;; :id (uuid/next)
;; TODO Keep the name of the original icon ;; ;; TODO Keep the name of the original icon
:name (str "Icon " (gensym "i")) ;; :name (str "Icon " (gensym "i"))
:metadata metadata})] ;; :metadata metadata})]
(->> (rx/from files) ;; (->> (rx/from files)
(rx/filter allowed?) ;; (rx/filter allowed?)
(rx/merge-map parse) ;; (rx/merge-map parse)
(rx/map prepare) ;; (rx/map prepare)
(rx/flat-map #(rp/mutation! :create-icon %)) ;; (rx/flat-map #(rp/mutation! :create-icon %))
(rx/map icon-created)))))) ;; (rx/map icon-created))))))
;;
;; --- Icon Persisted ;; ;; --- Icon Persisted
;;
(defrecord IconPersisted [id data] ;; (defrecord IconPersisted [id data]
ptk/UpdateEvent ;; ptk/UpdateEvent
(update [_ state] ;; (update [_ state]
(assoc-in state [:icons id] data))) ;; (assoc-in state [:icons id] data)))
;;
(defn icon-persisted ;; (defn icon-persisted
[{:keys [id] :as data}] ;; [{:keys [id] :as data}]
{:pre [(map? data)]} ;; {:pre [(map? data)]}
(IconPersisted. id data)) ;; (IconPersisted. id data))
;;
;; --- Persist Icon ;; ;; --- Persist Icon
;;
(defn persist-icon ;; (defn persist-icon
[id] ;; [id]
(s/assert ::us/uuid id) ;; (s/assert ::us/uuid id)
(ptk/reify ::persist-icon ;; (ptk/reify ::persist-icon
ptk/WatchEvent ;; ptk/WatchEvent
(watch [_ state stream] ;; (watch [_ state stream]
(let [data (get-in state [:icons id])] ;; (let [data (get-in state [:icons id])]
(->> (rp/mutation! :update-icon data) ;; (->> (rp/mutation! :update-icon data)
(rx/ignore)))))) ;; (rx/ignore))))))
;;
;; --- Load Icons ;; --- Load Icons
(declare icons-fetched) (declare icons-fetched)
@ -253,80 +294,80 @@
(let [icons (d/index-by :id items)] (let [icons (d/index-by :id items)]
(assoc state :icons icons))))) (assoc state :icons icons)))))
;; --- Rename Icon ;; ;; --- Rename Icon
;;
(defn rename-icon ;; (defn rename-icon
[id name] ;; [id name]
(s/assert ::us/uuid id) ;; (s/assert ::us/uuid id)
(s/assert ::us/string name) ;; (s/assert ::us/string name)
(ptk/reify ::rename-icon ;; (ptk/reify ::rename-icon
ptk/UpdateEvent ;; ptk/UpdateEvent
(update [_ state] ;; (update [_ state]
(assoc-in state [:icons id :name] name)) ;; (assoc-in state [:icons id :name] name))
;;
ptk/WatchEvent ;; ptk/WatchEvent
(watch [_ state stream] ;; (watch [_ state stream]
(rx/of (persist-icon id))))) ;; (rx/of (persist-icon id)))))
;;
;; --- Icon Selection ;; ;; --- Icon Selection
;;
(defn select-icon ;; (defn select-icon
[id] ;; [id]
(ptk/reify ::select-icon ;; (ptk/reify ::select-icon
ptk/UpdateEvent ;; ptk/UpdateEvent
(update [_ state] ;; (update [_ state]
(update-in state [:dashboard-icons :selected] (fnil conj #{}) id)))) ;; (update-in state [:dashboard-icons :selected] (fnil conj #{}) id))))
;;
(defn deselect-icon ;; (defn deselect-icon
[id] ;; [id]
(ptk/reify ::deselect-icon ;; (ptk/reify ::deselect-icon
ptk/UpdateEvent ;; ptk/UpdateEvent
(update [_ state] ;; (update [_ state]
(update-in state [:dashboard-icons :selected] (fnil disj #{}) id)))) ;; (update-in state [:dashboard-icons :selected] (fnil disj #{}) id))))
;;
(def deselect-all-icons ;; (def deselect-all-icons
(ptk/reify ::deselect-all-icons ;; (ptk/reify ::deselect-all-icons
ptk/UpdateEvent ;; ptk/UpdateEvent
(update [_ state] ;; (update [_ state]
(assoc-in state [:dashboard-icons :selected] #{})))) ;; (assoc-in state [:dashboard-icons :selected] #{}))))
;;
;; --- Delete Icons ;; ;; --- Delete Icons
;;
(defn delete-icon ;; (defn delete-icon
[id] ;; [id]
(ptk/reify ::delete-icon ;; (ptk/reify ::delete-icon
ptk/UpdateEvent ;; ptk/UpdateEvent
(update [_ state] ;; (update [_ state]
(update state :icons dissoc id)) ;; (update state :icons dissoc id))
;;
ptk/WatchEvent ;; ptk/WatchEvent
(watch [_ state s] ;; (watch [_ state s]
(rx/merge ;; (rx/merge
(rx/of deselect-all-icons) ;; (rx/of deselect-all-icons)
(->> (rp/mutation! :delete-icon {:id id}) ;; (->> (rp/mutation! :delete-icon {:id id})
(rx/ignore)))))) ;; (rx/ignore))))))
;;
;; --- Delete Selected ;; ;; --- Delete Selected
;;
(def delete-selected ;; (def delete-selected
(ptk/reify ::delete-selected ;; (ptk/reify ::delete-selected
ptk/WatchEvent ;; ptk/WatchEvent
(watch [_ state stream] ;; (watch [_ state stream]
(let [selected (get-in state [:dashboard-icons :selected])] ;; (let [selected (get-in state [:dashboard-icons :selected])]
(->> (rx/from selected) ;; (->> (rx/from selected)
(rx/map delete-icon)))))) ;; (rx/map delete-icon))))))
;; --- Update Opts (Filtering & Ordering) ;; ;; --- Update Opts (Filtering & Ordering)
;;
(defn update-opts ;; (defn update-opts
[& {:keys [order filter edition] ;; [& {:keys [order filter edition]
:or {edition false}}] ;; :or {edition false}}]
(ptk/reify ::update-opts ;; (ptk/reify ::update-opts
ptk/UpdateEvent ;; ptk/UpdateEvent
(update [_ state] ;; (update [_ state]
(update state :dashboard-icons merge ;; (update state :dashboard-icons merge
{:edition edition} ;; {:edition edition}
(when order {:order order}) ;; (when order {:order order})
(when filter {:filter filter}))))) ;; (when filter {:filter filter})))))
;; --- Copy Selected Icon ;; --- Copy Selected Icon

View file

@ -398,3 +398,46 @@
;; {:pre [(or (uuid? id) (nil? id))]} ;; {:pre [(or (uuid? id) (nil? id))]}
;; (MoveSelected. id)) ;; (MoveSelected. id))
;;;;;;; NEW
(declare fetch-image-libraries-result)
(defn fetch-image-libraries
[team-id]
(s/assert ::us/uuid team-id)
(ptk/reify ::fetch-image-libraries
ptk/WatchEvent
(watch [_ state stream]
(->> (rp/query! :image-libraries {:team-id team-id})
(rx/map fetch-image-libraries-result)))))
(defn fetch-image-libraries-result [result]
(ptk/reify ::fetch-image-libraries-result
ptk/UpdateEvent
(update [_ state]
(-> state
(assoc-in [:library :image-libraries] result)))))
(declare fetch-image-library-result)
(defn fetch-image-library
[library-id]
(ptk/reify ::fetch-image-library
ptk/UpdateEvent
(update [_ state]
(-> state
(assoc-in [:library :selected-items] nil)))
ptk/WatchEvent
(watch [_ state stream]
(->> (rp/query! :image {:library-id library-id})
(rx/map fetch-image-library-result)))))
(defn fetch-image-library-result
[data]
(ptk/reify ::fetch-image-library
ptk/UpdateEvent
(update [_ state]
(-> state
(assoc-in [:library :selected-items] data)))))

View file

@ -56,7 +56,20 @@
["/" :dashboard-team] ["/" :dashboard-team]
["/search" :dashboard-search] ["/search" :dashboard-search]
["/project/:project-id" :dashboard-project] ["/project/:project-id" :dashboard-project]
["/library" :dashboard-library]]] ["/library"
["/icons"
["" { :name :dashboard-library-icons-index :section :icons}]
["/:library-id" { :name :dashboard-library-icons :section :icons}]]
["/images"
["" { :name :dashboard-library-images-index :section :images}]
["/:library-id" { :name :dashboard-library-images :section :images}]]
["/palettes"
["" { :name :dashboard-library-palettes-index :section :palettes}]
["/:library-id" { :name :dashboard-library-palettes :section :palettes }]]
]]]
["/workspace/:file-id" :workspace]]) ["/workspace/:file-id" :workspace]])
@ -91,7 +104,12 @@
(:dashboard-search (:dashboard-search
:dashboard-team :dashboard-team
:dashboard-project :dashboard-project
:dashboard-library) :dashboard-library-icons
:dashboard-library-icons-index
:dashboard-library-images
:dashboard-library-images-index
:dashboard-library-palettes
:dashboard-library-palettes-index)
(mf/element dashboard #js {:route route}) (mf/element dashboard #js {:route route})
:workspace :workspace

View file

@ -32,8 +32,10 @@
(defn- parse-params (defn- parse-params
[route profile] [route profile]
(let [search-term (get-in route [:params :query :search-term]) (let [search-term (get-in route [:params :query :search-term])
route-name (get-in route [:data :name])
team-id (get-in route [:params :path :team-id]) team-id (get-in route [:params :path :team-id])
project-id (get-in route [:params :path :project-id])] project-id (get-in route [:params :path :project-id])
library-id (get-in route [:params :path :library-id])]
(cond-> (cond->
{:search-term search-term} {:search-term search-term}
@ -48,14 +50,21 @@
(and (= "drafts" project-id) (and (= "drafts" project-id)
(= "self" team-id)) (= "self" team-id))
(assoc :project-id (:default-project-id profile))))) (assoc :project-id (:default-project-id profile))
(str/starts-with? (name route-name) "dashboard-library")
(assoc :library-section (get-in route [:data :section]))
(uuid-str? library-id)
(assoc :library-id (uuid library-id)))))
(mf/defc dashboard (mf/defc dashboard
[{:keys [route] :as props}] [{:keys [route] :as props}]
(let [profile (mf/deref refs/profile) (let [profile (mf/deref refs/profile)
section (get-in route [:data :name]) page (get-in route [:data :name])
{:keys [search-term team-id project-id]} (parse-params route profile)] {:keys [search-term team-id project-id library-id library-section] :as params}
(parse-params route profile)]
[:main.dashboard-main [:main.dashboard-main
[:& messages-widget] [:& messages-widget]
[:section.dashboard-layout [:section.dashboard-layout
@ -63,18 +72,24 @@
[:& profile-section {:profile profile}] [:& profile-section {:profile profile}]
[:& sidebar {:team-id team-id [:& sidebar {:team-id team-id
:project-id project-id :project-id project-id
:search-term search-term :section page}]
:section section}]
[:div.dashboard-content [:div.dashboard-content
(case section (case page
:dashboard-search :dashboard-search
(mf/element search-page #js {:team-id team-id :search-term search-term}) (mf/element search-page #js {:team-id team-id :search-term search-term})
:dashboard-team :dashboard-team
(mf/element recent-files-page #js {:team-id team-id}) (mf/element recent-files-page #js {:team-id team-id})
:dashboard-library (:dashboard-library-icons
(mf/element library-page #js {:team-id team-id}) :dashboard-library-icons-index
:dashboard-library-images
:dashboard-library-images-index
:dashboard-library-palettes
:dashboard-library-palettes-index)
(mf/element library-page #js {:team-id team-id
:library-id library-id
:section library-section})
:dashboard-project :dashboard-project
(mf/element project-page #js {:team-id team-id (mf/element project-page #js {:team-id team-id

View file

@ -28,357 +28,357 @@
[uxbox.util.router :as rt] [uxbox.util.router :as rt]
[uxbox.util.time :as dt])) [uxbox.util.time :as dt]))
;; --- Helpers & Constants ;; ;; --- Helpers & Constants
;;
(def +ordering-options+ ;; (def +ordering-options+
{:name "ds.ordering.by-name" ;; {:name "ds.ordering.by-name"
:created "ds.ordering.by-creation-date"}) ;; :created "ds.ordering.by-creation-date"})
;;
(defn- sort-icons-by ;; (defn- sort-icons-by
[ordering icons] ;; [ordering icons]
(case ordering ;; (case ordering
:name (sort-by :name icons) ;; :name (sort-by :name icons)
:created (reverse (sort-by :created-at icons)) ;; :created (reverse (sort-by :created-at icons))
icons)) ;; icons))
;;
(defn- contains-term? ;; (defn- contains-term?
[phrase term] ;; [phrase term]
{:pre [(string? phrase) ;; {:pre [(string? phrase)
(string? term)]} ;; (string? term)]}
(let [term (name term)] ;; (let [term (name term)]
(str/includes? (str/lower phrase) (str/trim (str/lower term))))) ;; (str/includes? (str/lower phrase) (str/trim (str/lower term)))))
;;
(defn- filter-icons-by ;; (defn- filter-icons-by
[term icons] ;; [term icons]
(if (str/blank? term) ;; (if (str/blank? term)
icons ;; icons
(filter #(contains-term? (:name %) term) icons))) ;; (filter #(contains-term? (:name %) term) icons)))
;;
;; --- Component: Grid Header ;; ;; --- Component: Grid Header
;;
(mf/defc grid-header ;; (mf/defc grid-header
[{:keys [collection] :as props}] ;; [{:keys [collection] :as props}]
(let [{:keys [id type]} collection ;; (let [{:keys [id type]} collection
on-change #(st/emit! (di/rename-collection id %)) ;; on-change #(st/emit! (di/rename-collection id %))
on-deleted #(st/emit! (rt/nav :dashboard-icons nil {:type type})) ;; on-deleted #(st/emit! (rt/nav :dashboard-icons nil {:type type}))
delete #(st/emit! (di/delete-collection id on-deleted)) ;; delete #(st/emit! (di/delete-collection id on-deleted))
on-delete #(modal/show! confirm-dialog {:on-accept delete})] ;; on-delete #(modal/show! confirm-dialog {:on-accept delete})]
[:& common/grid-header {:value (:name collection) ;; [:& common/grid-header {:value (:name collection)
:on-change on-change ;; :on-change on-change
:on-delete on-delete}])) ;; :on-delete on-delete}]))
;;
;; --- Nav ;; ;; --- Nav
;;
(mf/defc nav-item ;; (mf/defc nav-item
[{:keys [collection selected?] :as props}] ;; [{:keys [collection selected?] :as props}]
(let [local (mf/use-state {}) ;; (let [local (mf/use-state {})
{:keys [id type name]} collection ;; {:keys [id type name]} collection
editable? (= type :own) ;; editable? (= type :own)
;;
on-click ;; on-click
(fn [event] ;; (fn [event]
(let [type (or type :own)] ;; (let [type (or type :own)]
(st/emit! (rt/nav :dashboard-icons {} {:type type :id id})))) ;; (st/emit! (rt/nav :dashboard-icons {} {:type type :id id}))))
;;
;;
on-input-change ;; on-input-change
(fn [event] ;; (fn [event]
(-> (dom/get-target event) ;; (-> (dom/get-target event)
(dom/get-value) ;; (dom/get-value)
(swap! local assoc :name))) ;; (swap! local assoc :name)))
;;
on-cancel #(swap! local dissoc :name :edit) ;; on-cancel #(swap! local dissoc :name :edit)
on-double-click #(when editable? (swap! local assoc :edit true)) ;; on-double-click #(when editable? (swap! local assoc :edit true))
;;
on-input-keyup ;; on-input-keyup
(fn [event] ;; (fn [event]
(when (kbd/enter? event) ;; (when (kbd/enter? event)
(let [value (-> (dom/get-target event) (dom/get-value))] ;; (let [value (-> (dom/get-target event) (dom/get-value))]
(st/emit! (di/rename-collection id (str/trim (:name @local)))) ;; (st/emit! (di/rename-collection id (str/trim (:name @local))))
(swap! local assoc :edit false))))] ;; (swap! local assoc :edit false))))]
;;
[:li {:on-click on-click ;; [:li {:on-click on-click
:on-double-click on-double-click ;; :on-double-click on-double-click
:class-name (when selected? "current")} ;; :class-name (when selected? "current")}
(if (:edit @local) ;; (if (:edit @local)
[:div ;; [:div
[:input.element-title {:value (or (:name @local) name) ;; [:input.element-title {:value (or (:name @local) name)
:on-change on-input-change ;; :on-change on-input-change
:on-key-down on-input-keyup}] ;; :on-key-down on-input-keyup}]
[:span.close {:on-click on-cancel} i/close]] ;; [:span.close {:on-click on-cancel} i/close]]
[:span.element-title name])])) ;; [:span.element-title name])]))
;;
;;
(mf/defc nav ;; (mf/defc nav
[{:keys [id type collections] :as props}] ;; [{:keys [id type collections] :as props}]
(let [locale (i18n/use-locale) ;; (let [locale (i18n/use-locale)
own? (= type :own) ;; own? (= type :own)
builtin? (= type :builtin) ;; builtin? (= type :builtin)
create-collection #(st/emit! di/create-collection) ;; create-collection #(st/emit! di/create-collection)
select-own-tab #(st/emit! (rt/nav :dashboard-icons nil {:type :own})) ;; select-own-tab #(st/emit! (rt/nav :dashboard-icons nil {:type :own}))
select-buitin-tab #(st/emit! (rt/nav :dashboard-icons nil {:type :builtin}))] ;; select-buitin-tab #(st/emit! (rt/nav :dashboard-icons nil {:type :builtin}))]
;;
[:div.library-bar ;; [:div.library-bar
[:div.library-bar-inside ;; [:div.library-bar-inside
;; Tabs ;; ;; Tabs
[:ul.library-tabs ;; [:ul.library-tabs
[:li {:class (when own? "current") ;; [:li {:class (when own? "current")
:on-click select-own-tab} ;; :on-click select-own-tab}
(t locale "ds.your-icons-title")] ;; (t locale "ds.your-icons-title")]
;;
[:li {:class (when builtin? "current") ;; [:li {:class (when builtin? "current")
:on-click select-buitin-tab} ;; :on-click select-buitin-tab}
(t locale "ds.store-icons-title")]] ;; (t locale "ds.store-icons-title")]]
;;
;;
;; Collections List ;; ;; Collections List
[:ul.library-elements ;; [:ul.library-elements
(when own? ;; (when own?
[:li
[:a.btn-primary {:on-click #(st/emit! di/create-collection)}
(tr "ds.icons-collection.new")]])
(for [item collections]
[:& nav-item {:collection item
:selected? (= (:id item) id)
:key (:id item)}])]]]))
;; (mf/def grid-options-tooltip
;; :mixins [mf/reactive mf/memo]
;; :render
;; (fn [own {:keys [selected on-select title]}]
;; {:pre [(uuid? selected)
;; (fn? on-select)
;; (string? title)]}
;; (let [colls (mf/react 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 ;; [:li
;; [:a {:href "#" :on-click #(on-select % nil)} "Storage"]] ;; [:a.btn-primary {:on-click #(st/emit! di/create-collection)}
;; (for [{:keys [id name] :as coll} colls] ;; (tr "ds.icons-collection.new")]])
;; [:li {:key (pr-str id)} ;; (for [item collections]
;; [:a {:on-click #(on-select % id)} name]])]))) ;; [:& nav-item {:collection item
;; :selected? (= (:id item) id)
(mf/defc grid-options ;; :key (:id item)}])]]]))
[{:keys [id type selected] :as props}] ;;
(let [local (mf/use-state {}) ;;
delete #(st/emit! di/delete-selected) ;; ;; (mf/def grid-options-tooltip
on-delete #(modal/show! confirm-dialog {:on-accept delete}) ;; ;; :mixins [mf/reactive mf/memo]
;;
;; (on-toggle-copy [event] ;; ;; :render
;; (swap! local update :show-copy-tooltip not)) ;; ;; (fn [own {:keys [selected on-select title]}]
;; (on-toggle-move [event] ;; ;; {:pre [(uuid? selected)
;; (swap! local update :show-move-tooltip not)) ;; ;; (fn? on-select)
;; (on-copy [selected] ;; ;; (string? title)]}
;; (swap! local assoc ;; ;; (let [colls (mf/react collections-iref)
;; :show-move-tooltip false ;; ;; colls (->> (vals colls)
;; :show-copy-tooltip false) ;; ;; (filter #(= :own (:type %)))
;; (st/emit! (di/copy-selected selected))) ;; ;; (remove #(= selected (:id %)))
;; (on-move [selected] ;; ;; (sort-by :name colls))
;; (swap! local assoc ;; ;; on-select (fn [event id]
;; :show-move-tooltip false ;; ;; (dom/prevent-default event)
;; :show-copy-tooltip false) ;; ;; (dom/stop-propagation event)
;; (st/emit! (di/move-selected selected))) ;; ;; (on-select id))]
;; (on-rename [event] ;; ;; [:ul.move-list
;; (let [selected (first selected)] ;; ;; [:li.title title]
;; (st/emit! (di/update-opts :edition selected)))) ;; ;; [:li
] ;; ;; [:a {:href "#" :on-click #(on-select % nil)} "Storage"]]
;; MULTISELECT OPTIONS BAR ;; ;; (for [{:keys [id name] :as coll} colls]
[:div.multiselect-bar ;; ;; [:li {:key (pr-str id)}
(when (= type :own) ;; ;; [:a {:on-click #(on-select % id)} name]])])))
;; If editable ;;
[:div.multiselect-nav ;; (mf/defc grid-options
;; [:span.move-item.tooltip.tooltip-top ;; [{:keys [id type selected] :as props}]
;; {:alt (tr "ds.multiselect-bar.copy") ;; (let [local (mf/use-state {})
;; :on-click on-toggle-copy} ;; delete #(st/emit! di/delete-selected)
;; (when (:show-copy-tooltip @local) ;; on-delete #(modal/show! confirm-dialog {:on-accept delete})
;; [:& grid-options-tooltip {:selected id ;;
;; :title (tr "ds.multiselect-bar.copy-to-library") ;; ;; (on-toggle-copy [event]
;; :on-select on-copy}]) ;; ;; (swap! local update :show-copy-tooltip not))
;; i/copy] ;; ;; (on-toggle-move [event]
;; [:span.move-item.tooltip.tooltip-top ;; ;; (swap! local update :show-move-tooltip not))
;; {:alt (tr "ds.multiselect-bar.move") ;; ;; (on-copy [selected]
;; :on-click on-toggle-move} ;; ;; (swap! local assoc
;; (when (:show-move-tooltip @local) ;; ;; :show-move-tooltip false
;; [:& grid-options-tooltip {:selected id ;; ;; :show-copy-tooltip false)
;; :title (tr "ds.multiselect-bar.move-to-library") ;; ;; (st/emit! (di/copy-selected selected)))
;; :on-select on-move}]) ;; ;; (on-move [selected]
;; i/move] ;; ;; (swap! local assoc
;; (when (= 1 (count selected)) ;; ;; :show-move-tooltip false
;; [:span.move-item.tooltip.tooltip-top {:alt (tr "ds.multiselect-bar.rename") ;; ;; :show-copy-tooltip false)
;; :on-click on-rename} ;; ;; (st/emit! (di/move-selected selected)))
;; i/pencil]) ;; ;; (on-rename [event]
[:span.delete.tooltip.tooltip-top ;; ;; (let [selected (first selected)]
{:alt (tr "ds.multiselect-bar.delete") ;; ;; (st/emit! (di/update-opts :edition selected))))
:on-click on-delete} ;; ]
i/trash]] ;; ;; MULTISELECT OPTIONS BAR
;; [:div.multiselect-bar
;; If not editable ;; (when (= type :own)
;; [:div.multiselect-nav ;; ;; If editable
;; [:span.move-item.tooltip.tooltip-top {:alt (tr "ds.multiselect-bar.copy") ;; [:div.multiselect-nav
;; :on-click on-toggle-copy} ;; ;; [:span.move-item.tooltip.tooltip-top
;; (when (:show-copy-tooltip @local) ;; ;; {:alt (tr "ds.multiselect-bar.copy")
;; [:& grid-options-tooltip {:selected id ;; ;; :on-click on-toggle-copy}
;; :title (tr "ds.multiselect-bar.copy-to-library") ;; ;; (when (:show-copy-tooltip @local)
;; :on-select on-copy}]) ;; ;; [:& grid-options-tooltip {:selected id
;; i/organize]] ;; ;; :title (tr "ds.multiselect-bar.copy-to-library")
)])) ;; ;; :on-select on-copy}])
;; ;; i/copy]
;; --- Grid Form ;; ;; [:span.move-item.tooltip.tooltip-top
;; ;; {:alt (tr "ds.multiselect-bar.move")
(mf/defc grid-form ;; ;; :on-click on-toggle-move}
[{:keys [id type uploading?] :as props}] ;; ;; (when (:show-move-tooltip @local)
(let [locale (i18n/use-locale) ;; ;; [:& grid-options-tooltip {:selected id
input (mf/use-ref nil) ;; ;; :title (tr "ds.multiselect-bar.move-to-library")
on-click #(dom/click (mf/ref-node input)) ;; ;; :on-select on-move}])
on-select #(st/emit! (->> (dom/get-target %) ;; ;; i/move]
(dom/get-files) ;; ;; (when (= 1 (count selected))
(array-seq) ;; ;; [:span.move-item.tooltip.tooltip-top {:alt (tr "ds.multiselect-bar.rename")
(di/create-icons id)))] ;; ;; :on-click on-rename}
[:div.grid-item.add-project {:on-click on-click} ;; ;; i/pencil])
(if uploading? ;; [:span.delete.tooltip.tooltip-top
[:div i/loader-pencil] ;; {:alt (tr "ds.multiselect-bar.delete")
[:span (t locale "ds.icon-new")]) ;; :on-click on-delete}
[:input.upload-icon-input ;; i/trash]]
{:style {:display "none"} ;;
:multiple true ;; ;; If not editable
:ref input ;; ;; [:div.multiselect-nav
:value "" ;; ;; [:span.move-item.tooltip.tooltip-top {:alt (tr "ds.multiselect-bar.copy")
:accept "icon/svg+xml" ;; ;; :on-click on-toggle-copy}
:type "file" ;; ;; (when (:show-copy-tooltip @local)
:on-change on-select}]])) ;; ;; [:& grid-options-tooltip {:selected id
;; ;; :title (tr "ds.multiselect-bar.copy-to-library")
;; --- Grid Item ;; ;; :on-select on-copy}])
;; ;; i/organize]]
(mf/defc grid-item ;; )]))
[{:keys [icon selected? edition?] :as props}] ;;
(let [toggle-selection #(st/emit! (if selected? ;; ;; --- Grid Form
(di/deselect-icon (:id icon)) ;;
(di/select-icon (:id icon)))) ;; (mf/defc grid-form
on-blur ;; [{:keys [id type uploading?] :as props}]
(fn [event] ;; (let [locale (i18n/use-locale)
(let [target (dom/get-target event) ;; input (mf/use-ref nil)
name (dom/get-value target)] ;; on-click #(dom/click (mf/ref-node input))
(st/emit! (di/update-opts :edition false) ;; on-select #(st/emit! (->> (dom/get-target %)
(di/rename-icon (:id icon) name)))) ;; (dom/get-files)
;; (array-seq)
on-key-down ;; (di/create-icons id)))]
(fn [event] ;; [:div.grid-item.add-project {:on-click on-click}
(when (kbd/enter? event) ;; (if uploading?
(on-blur event))) ;; [:div i/loader-pencil]
;; [:span (t locale "ds.icon-new")])
ignore-click ;; [:input.upload-icon-input
(fn [event] ;; {:style {:display "none"}
(dom/stop-propagation event) ;; :multiple true
(dom/prevent-default event)) ;; :ref input
;; :value ""
on-edit ;; :accept "icon/svg+xml"
(fn [event] ;; :type "file"
(dom/stop-propagation event) ;; :on-change on-select}]]))
(dom/prevent-default event) ;;
(st/emit! (di/update-opts :edition (:id icon))))] ;; ;; --- Grid Item
;;
[:div.grid-item.small-item.project-th ;; (mf/defc grid-item
[:div.input-checkbox.check-primary ;; [{:keys [icon selected? edition?] :as props}]
[:input {:type "checkbox" ;; (let [toggle-selection #(st/emit! (if selected?
:id (:id icon) ;; (di/deselect-icon (:id icon))
:on-change toggle-selection ;; (di/select-icon (:id icon))))
:checked selected?}] ;; on-blur
[:label {:for (:id icon)}]] ;; (fn [event]
[:span.grid-item-icon ;; (let [target (dom/get-target event)
[:& icon/icon-svg {:shape icon}]] ;; name (dom/get-value target)]
[:div.item-info {:on-click ignore-click} ;; (st/emit! (di/update-opts :edition false)
(if edition? ;; (di/rename-icon (:id icon) name))))
[:input.element-name {:type "text" ;;
:auto-focus true ;; on-key-down
:on-key-down on-key-down ;; (fn [event]
:on-blur on-blur ;; (when (kbd/enter? event)
:on-click on-edit ;; (on-blur event)))
:default-value (:name icon)}] ;;
[:h3 {:on-double-click on-edit} ;; ignore-click
(:name icon)]) ;; (fn [event]
(str (tr "ds.uploaded-at" (dt/format (:created-at icon) "dd/MM/yyyy")))]])) ;; (dom/stop-propagation event)
;; (dom/prevent-default event))
;; --- Grid ;;
;; on-edit
(def icons-iref ;; (fn [event]
(-> (comp (l/key :icons) (l/lens vals)) ;; (dom/stop-propagation event)
(l/derive st/state))) ;; (dom/prevent-default event)
;; (st/emit! (di/update-opts :edition (:id icon))))]
(mf/defc grid ;;
[{:keys [id type collection opts] :as props}] ;; [:div.grid-item.small-item.project-th
(let [editable? (= type :own) ;; [:div.input-checkbox.check-primary
icons (->> (mf/deref icons-iref) ;; [:input {:type "checkbox"
(filter-icons-by (:filter opts "")) ;; :id (:id icon)
(sort-icons-by (:order opts :name)))] ;; :on-change toggle-selection
[:div.dashboard-grid-content ;; :checked selected?}]
[:div.dashboard-grid-row ;; [:label {:for (:id icon)}]]
(when editable? ;; [:span.grid-item-icon
[:& grid-form {:id id :type type :uploading? (:uploading opts)}]) ;; [:& icon/icon-svg {:shape icon}]]
;; [:div.item-info {:on-click ignore-click}
[:& chunked-list {:items icons ;; (if edition?
:initial-size 30 ;; [:input.element-name {:type "text"
:chunk-size 30 ;; :auto-focus true
:key (str type id (count icons))} ;; :on-key-down on-key-down
(fn [icon] ;; :on-blur on-blur
[:& grid-item {:icon icon ;; :on-click on-edit
:key (:id icon) ;; :default-value (:name icon)}]
:selected (contains? (:selected opts) (:id icon)) ;; [:h3 {:on-double-click on-edit}
:edition? (= (:edition opts) (:id icon))}])]]])) ;; (:name icon)])
;; (str (tr "ds.uploaded-at" (dt/format (:created-at icon) "dd/MM/yyyy")))]]))
;; --- Content ;;
;; ;; --- Grid
(def opts-iref ;;
(-> (l/key :dashboard-icons) ;; (def icons-iref
(l/derive st/state))) ;; (-> (comp (l/key :icons) (l/lens vals))
;; (l/derive st/state)))
(mf/defc content ;;
[{:keys [id type collection] :as props}] ;; (mf/defc grid
(let [{:keys [selected] :as opts} (mf/deref opts-iref)] ;; [{:keys [id type collection opts] :as props}]
[:section.dashboard-grid.library ;; (let [editable? (= type :own)
(when collection ;; icons (->> (mf/deref icons-iref)
[:& grid-header {:collection collection}]) ;; (filter-icons-by (:filter opts ""))
(if collection ;; (sort-icons-by (:order opts :name)))]
[:& grid {:id id :type type :collection collection :opts opts}] ;; [:div.dashboard-grid-content
[:span "EMPTY STATE TODO"]) ;; [:div.dashboard-grid-row
(when-not (empty? selected) ;; (when editable?
#_[:& grid-options {:id id :type type :selected (:selected opts)}])])) ;; [:& grid-form {:id id :type type :uploading? (:uploading opts)}])
;;
;; --- Icons Page ;; [:& chunked-list {:items icons
;; :initial-size 30
(def collections-iref ;; :chunk-size 30
(-> (l/key :icons-collections) ;; :key (str type id (count icons))}
(l/derive st/state))) ;; (fn [icon]
;; [:& grid-item {:icon icon
(mf/defc icons-page ;; :key (:id icon)
[{:keys [id type] :as props}] ;; :selected (contains? (:selected opts) (:id icon))
(let [type (or type :own) ;; :edition? (= (:edition opts) (:id icon))}])]]]))
collections (mf/deref collections-iref) ;;
collections (cond->> (vals collections) ;; ;; --- Content
(= type :own) (filter #(= :own (:type %))) ;;
(= type :builtin) (filter #(= :builtin (:type %))) ;; (def opts-iref
true (sort-by :created-at)) ;; (-> (l/key :dashboard-icons)
;; (l/derive st/state)))
collection (cond ;;
(uuid? id) (seek #(= id (:id %)) collections) ;; (mf/defc content
:else (first collections)) ;; [{:keys [id type collection] :as props}]
;; (let [{:keys [selected] :as opts} (mf/deref opts-iref)]
id (:id collection)] ;; [:section.dashboard-grid.library
;; (when collection
(mf/use-effect #(st/emit! di/fetch-collections)) ;; [:& grid-header {:collection collection}])
(mf/use-effect ;; (if collection
{:fn #(when id (st/emit! (di/initialize id))) ;; [:& grid {:id id :type type :collection collection :opts opts}]
:deps (mf/deps id)}) ;; [:span "EMPTY STATE TODO"])
;; (when-not (empty? selected)
[:section.dashboard-content ;; #_[:& grid-options {:id id :type type :selected (:selected opts)}])]))
[:& nav {:type type :id id :collections collections}] ;;
[:& content {:type type :id id :collection collection}]])) ;; ;; --- Icons Page
;;
;; (def collections-iref
;; (-> (l/key :icons-collections)
;; (l/derive st/state)))
;;
;; (mf/defc icons-page
;; [{:keys [id type] :as props}]
;; (let [type (or type :own)
;; 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) (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}]]))

View file

@ -12,125 +12,196 @@
(:require (:require
[lentes.core :as l] [lentes.core :as l]
[rumext.alpha :as mf] [rumext.alpha :as mf]
[cuerdas.core :as str]
[uxbox.util.router :as rt]
[uxbox.util.i18n :as i18n :refer [t tr]]
[uxbox.util.color :as uc]
[uxbox.main.data.icons :as dico]
[uxbox.main.data.images :as dimg]
[uxbox.main.data.colors :as dcol]
[uxbox.builtins.icons :as i] [uxbox.builtins.icons :as i]
[uxbox.main.store :as st] [uxbox.main.store :as st]
[uxbox.main.refs :as refs] [uxbox.main.refs :as refs]
[uxbox.util.i18n :as i18n :refer [t tr]]
[uxbox.main.ui.dashboard.components.context-menu :refer [context-menu]])) [uxbox.main.ui.dashboard.components.context-menu :refer [context-menu]]))
(mf/defc library-header (mf/defc library-header
[{:keys [profile] :as props}] [{:keys [section team-id] :as props}]
(let [locale (i18n/use-locale)] (let [icons? (= section :icons)
images? (= section :images)
palettes? (= section :palettes)
locale (i18n/use-locale)]
[:header#main-bar.main-bar [:header#main-bar.main-bar
[:h1.dashboard-title "Libraries"] [:h1.dashboard-title "Libraries"]
[:nav.library-header-navigation [:nav.library-header-navigation
[:a.library-header-navigation-item "Icons"] [:a.library-header-navigation-item
[:a.library-header-navigation-item "Images"] {:class-name (when icons? "current")
[:a.library-header-navigation-item "Colors"]]])) :on-click #(st/emit! (rt/nav :dashboard-library-icons-index {:team-id team-id}))}
(t locale "dashboard.library.menu.icons")]
[:a.library-header-navigation-item
{:class-name (when images? "current")
:on-click #(st/emit! (rt/nav :dashboard-library-images-index {:team-id team-id}))}
(t locale "dashboard.library.menu.images")]
[:a.library-header-navigation-item
{:class-name (when palettes? "current")
:on-click #(st/emit! (rt/nav :dashboard-library-palettes-index {:team-id team-id}))}
(t locale "dashboard.library.menu.palettes")]]]))
(mf/defc library-sidebar (mf/defc library-sidebar
[] [{:keys [section items team-id library-id]}]
(let [locale (i18n/use-locale)]
[:aside.library-sidebar [:aside.library-sidebar
[:button.library-sidebar-add-item [:button.library-sidebar-add-item
{:type "button"} {:type "button"}
"+ New icon library"] (t locale (str "dashboard.library.add-library." (name section)))]
[:ul.library-sidebar-list [:ul.library-sidebar-list
[:li.library-sidebar-list-element [:a "Ecometer"]] (for [item items]
[:li.library-sidebar-list-element [:a "Tipi"]] [:li.library-sidebar-list-element
[:li.library-sidebar-list-element [:a "Taiga (inspirational)"]] {:key (:id item)
[:li.library-sidebar-list-element [:a "DKT photo assets"]]]]) :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)))}
[:a (:name item)]])]]))
(mf/defc library-top-menu (mf/defc library-top-menu
[] [{:keys [selected section]}]
(let [state (mf/use-state {:is-open false})] (let [state (mf/use-state {:is-open false})
locale (i18n/use-locale)]
[:header.library-top-menu [:header.library-top-menu
[:div.library-top-menu-current-element [:div.library-top-menu-current-element
[:h2.library-top-menu-current-element-name "UXBOX"] [:h2.library-top-menu-current-element-name (:name selected)]
[:a.library-top-menu-current-action [:a.library-top-menu-current-action
{ :on-click #(swap! state update :is-open not)} { :on-click #(swap! state update :is-open not)}
[:span i/arrow-down]] [:span i/arrow-down]]
[:& context-menu {:is-open (:is-open @state) [:& context-menu {:is-open (:is-open @state)
:options [["Rename" #(println "Rename")] :options [[(t locale "ds.button.rename") #(println "Rename")]
["Delete" #(println "Delete")]]}]] [(t locale "ds.button.delete") #(println "Delete")]]}]]
[:div.library-top-menu-actions [:div.library-top-menu-actions
[:a i/trash] [:a i/trash]
[:a.btn-dashboard "+ New icon"]]])) [:a.btn-dashboard (t locale (str "dashboard.library.add-item." (name section)))]]]))
(mf/defc library-icon-card [] (mf/defc library-icon-card
(let [state (mf/use-state {:is-open false})] [{:keys [id name url content metadata]}]
(let [locale (i18n/use-locale)
state (mf/use-state {:is-open false})]
[:div.library-card.library-icon [:div.library-card.library-icon
[:div.input-checkbox.check-primary [:div.input-checkbox.check-primary
[:input {:type "checkbox" [:input {:type "checkbox"
:id "card" :id (str "icon-" id)
:on-change #(println "toggle-selection") :on-change #(println "toggle-selection")
#_(:checked false)}] #_(:checked false)}]
[:label {:for "card"}]] [:label {:for (str "icon-" id)}]]
[:div.library-card-image i/trash] [:div.library-card-image
#_[:object { :data url :type "image/svg+xml" }]
[:svg {:view-box (->> metadata :view-box (str/join " "))
:width (:width metadata)
:height (:height metadata)
:dangerouslySetInnerHTML {:__html content}}]]
[:div.library-card-footer [:div.library-card-footer
[:div.library-card-footer-name "my-dear-icon.svg"] [:div.library-card-footer-name name]
[:div.library-card-footer-timestamp "Less than 5 seconds ago"] [:div.library-card-footer-timestamp "Less than 5 seconds ago"]
[:div.library-card-footer-menu [:div.library-card-footer-menu
{ :on-click #(swap! state update :is-open not) } { :on-click #(swap! state update :is-open not) }
i/actions] i/actions]
[:& context-menu {:is-open (:is-open @state) [:& context-menu {:is-open (:is-open @state)
:options [["Delete" #(println "Delete")]]}]]])) :options [[(t locale "ds.button.delete") #(println "Delete")]]}]]]))
(mf/defc library-image-card [] (mf/defc library-image-card
(let [state (mf/use-state {:is-open false})] [{:keys [id name url]}]
(let [locale (i18n/use-locale)
state (mf/use-state {:is-open false})]
[:div.library-card.library-image [:div.library-card.library-image
[:div.input-checkbox.check-primary [:div.input-checkbox.check-primary
[:input {:type "checkbox" [:input {:type "checkbox"
:id "card" :id (str "image-" id)
:on-change #(println "toggle-selection") :on-change #(println "toggle-selection")
#_(:checked false)}] #_(:checked false)}]
[:label {:for "card"}]] [:label {:for (str "image-" id)}]]
[:div.library-card-image [:div.library-card-image
[:img {:src "https://www.placecage.com/200/200"}]] [:img {:src url}]]
[:div.library-card-footer [:div.library-card-footer
[:div.library-card-footer-name "my-dear-icon.svg"] [:div.library-card-footer-name name]
[:div.library-card-footer-timestamp "Less than 5 seconds ago"] [:div.library-card-footer-timestamp "Less than 5 seconds ago"]
[:div.library-card-footer-menu [:div.library-card-footer-menu
{ :on-click #(swap! state update :is-open not) } { :on-click #(swap! state update :is-open not) }
i/actions] i/actions]
[:& context-menu {:is-open (:is-open @state) [:& context-menu {:is-open (:is-open @state)
:options [["Delete" #(println "Delete")]]}]]])) :options [[(t locale "ds.button.delete") #(println "Delete")]]}]]]))
(mf/defc library-color-card [] (mf/defc library-color-card
(let [state (mf/use-state {:is-open false})] [{ :keys [ id content ] }]
(let [locale (i18n/use-locale)
state (mf/use-state {:is-open false})]
[:div.library-card.library-color [:div.library-card.library-color
[:div.input-checkbox.check-primary [:div.input-checkbox.check-primary
[:input {:type "checkbox" [:input {:type "checkbox"
:id "card" :id (str "color-" id)
:on-change #(println "toggle-selection") :on-change #(println "toggle-selection")
#_(:checked false)}] #_(:checked false)}]
[:label {:for "card"}]] [:label {:for (str "color-" id)}]]
[:div.library-card-image [:div.library-card-image
{ :style { :background-color "#9B78FF" }}] { :style { :background-color content }}]
[:div.library-card-footer [:div.library-card-footer
#_[:* [:div.library-card-footer-name content ]
[:div.library-card-footer-name "my-dear-icon.svg"]
[:div.library-card-footer-timestamp "Less than 5 seconds ago"]]
[:*
[:div.library-card-footer-name "#9B78FF"]
[:div.library-card-footer-color [:div.library-card-footer-color
[:span.library-card-footer-color-label "RGB"] [:span.library-card-footer-color-label "RGB"]
[:span.library-card-footer-color-rgb "128, 128, 128"]]] [:span.library-card-footer-color-rgb (str/join " " (uc/hex->rgb content))]]
[:div.library-card-footer-menu [:div.library-card-footer-menu
{ :on-click #(swap! state update :is-open not) } { :on-click #(swap! state update :is-open not) }
i/actions] i/actions]
[:& context-menu {:is-open (:is-open @state) [:& context-menu {:is-open (:is-open @state)
:options [["Delete" #(println "Delete")]]}]]])) :options [[(t locale "ds.button.delete") #(println "Delete")]]}]]]))
(def icon-libraries-ref
(-> (comp (l/key :library) (l/key :icon-libraries))
(l/derive st/state)))
(def image-libraries-ref
(-> (comp (l/key :library) (l/key :image-libraries))
(l/derive st/state)))
(def color-libraries-ref
(-> (comp (l/key :library) (l/key :color-libraries))
(l/derive st/state)))
(def selected-items-ref
(-> (comp (l/key :library) (l/key :selected-items))
(l/derive st/state)))
(mf/defc library-page (mf/defc library-page
[{:keys [team-id]}] [{:keys [team-id library-id section]}]
(mf/use-effect {:fn #(case section
:icons (st/emit! (dico/fetch-icon-libraries team-id))
:images (st/emit! (dimg/fetch-image-libraries team-id))
:palettes (st/emit! (dcol/fetch-color-libraries team-id)))
:deps (mf/deps section team-id)})
(mf/use-effect {:fn #(when library-id
(case section
:icons (st/emit! (dico/fetch-icon-library library-id))
:images (st/emit! (dimg/fetch-image-library library-id))
:palettes (st/emit! (dcol/fetch-color-library library-id))))
:deps (mf/deps library-id)})
(let [libraries (case section
:icons (mf/deref icon-libraries-ref)
:images (mf/deref image-libraries-ref)
:palettes (mf/deref color-libraries-ref))
items (mf/deref selected-items-ref)
selected-library (first (filter #(= (:id %) library-id) libraries))]
[:div.library-page [:div.library-page
[:& library-header] [:& library-header {:section section :team-id team-id}]
[:& library-sidebar] [:& library-sidebar {:items libraries :team-id team-id :library-id library-id :section section}]
(when library-id
[:section.library-content [:section.library-content
[:& library-top-menu] [:& library-top-menu {:selected selected-library :section section}]
[:div.library-page-cards-container [:div.library-page-cards-container
(for [_ (range 0 10)] (for [item items]
#_[:& library-icon-card] (let [item (assoc item :key (:id item))]
#_[:& library-image-card] (case section
[:& library-color-card])]]]) :icons [:& library-icon-card item]
:images [:& library-image-card { :name "Nicolas Cage" :url "https://www.placecage.com/200/200" }]
:palettes [:& library-color-card item ])))]])]))

View file

@ -95,7 +95,7 @@
drafts? (and (= selected-section :dashboard-project) drafts? (and (= selected-section :dashboard-project)
(= selected-team-id (:default-team-id profile)) (= selected-team-id (:default-team-id profile))
(= selected-project-id (:default-project-id profile))) (= selected-project-id (:default-project-id profile)))
library? (and (= selected-section :dashboard-library) library? (and (str/starts-with? (name selected-section) "dashboard-library")
(= selected-team-id (:default-team-id profile))) (= selected-team-id (:default-team-id profile)))
locale (i18n/use-locale)] locale (i18n/use-locale)]
[:ul.library-elements [:ul.library-elements
@ -114,7 +114,7 @@
[:li [:li
{:on-click #(st/emit! (rt/nav :dashboard-library {:team-id team-id})) {:on-click #(st/emit! (rt/nav :dashboard-library-icons-index {:team-id team-id}))
:class-name (when library? "current")} :class-name (when library? "current")}
i/icon-set i/icon-set
[:span.element-title (t locale "dashboard.sidebar.libraries")]] [:span.element-title (t locale "dashboard.sidebar.libraries")]]

View file

@ -15,7 +15,7 @@
[uxbox.main.data.workspace :as dw] [uxbox.main.data.workspace :as dw]
[uxbox.main.refs :as refs] [uxbox.main.refs :as refs]
[uxbox.main.store :as st] [uxbox.main.store :as st]
[uxbox.main.ui.dashboard.icons :as icons] #_[uxbox.main.ui.dashboard.icons :as icons]
[uxbox.main.ui.shapes.icon :as icon] [uxbox.main.ui.shapes.icon :as icon]
[uxbox.util.data :refer [read-string]] [uxbox.util.data :refer [read-string]]
[uxbox.util.dom :as dom] [uxbox.util.dom :as dom]
@ -40,7 +40,7 @@
(mf/defc icons-list (mf/defc icons-list
[{:keys [collection-id] :as props}] [{:keys [collection-id] :as props}]
(let [icons (mf/deref icons/icons-iref) (let [icons [] #_(mf/deref icons/icons-iref) ;; TODO: Fix this
on-select on-select
(fn [event data] (fn [event data]
@ -67,7 +67,7 @@
local (mf/deref refs/workspace-local) local (mf/deref refs/workspace-local)
collections (vals (mf/deref icons/collections-iref)) collections (vals [] #_(mf/deref icons/collections-iref)) ;; TODO: FIX THIS
collection (first collections) collection (first collections)
on-close on-close