mirror of
https://github.com/penpot/penpot.git
synced 2025-07-05 03:47:16 +02:00
🐸 integration with backend data
This commit is contained in:
parent
4102dca55c
commit
57d633b1d2
17 changed files with 301 additions and 116 deletions
|
@ -14,30 +14,33 @@
|
|||
[uxbox.util.router :as r]
|
||||
[uxbox.util.uuid :as uuid]))
|
||||
|
||||
(defn initialize-workspace-libraries []
|
||||
())
|
||||
|
||||
;; Retrieve libraries
|
||||
|
||||
(declare retrieve-libraries-result)
|
||||
|
||||
(defn retrieve-libraries
|
||||
[type team-id]
|
||||
(s/assert ::us/uuid team-id)
|
||||
(let [method (case type
|
||||
:icons :icon-libraries
|
||||
:images :image-libraries
|
||||
:palettes :color-libraries)]
|
||||
(ptk/reify ::retrieve-libraries
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(->> (rp/query! method {:team-id team-id})
|
||||
(rx/map (partial retrieve-libraries-result type)))))))
|
||||
([type] (retrieve-libraries type uuid/zero))
|
||||
([type team-id]
|
||||
(s/assert ::us/uuid team-id)
|
||||
(let [method (case type
|
||||
:icons :icon-libraries
|
||||
:images :image-libraries
|
||||
:palettes :color-libraries)]
|
||||
(ptk/reify ::retrieve-libraries
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(->> (rp/query! method {:team-id team-id})
|
||||
(rx/map (partial retrieve-libraries-result type team-id))))))))
|
||||
|
||||
(defn retrieve-libraries-result [type result]
|
||||
(defn retrieve-libraries-result [type team-id result]
|
||||
(ptk/reify ::retrieve-libraries-result
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(assoc-in [:library type] result)))))
|
||||
(assoc-in [:library type team-id] result)))))
|
||||
|
||||
;; Retrieve library data
|
||||
|
||||
|
@ -78,23 +81,23 @@
|
|||
:images :create-image-library
|
||||
:palettes :create-color-library)]
|
||||
(->> (rp/mutation! method {:team-id team-id
|
||||
:name name})
|
||||
(rx/map (partial create-library-result type)))))))
|
||||
:name name})
|
||||
(rx/map (partial create-library-result type team-id)))))))
|
||||
|
||||
(defn create-library-result
|
||||
[type result]
|
||||
[type team-id result]
|
||||
(ptk/reify ::create-library-result
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(update-in [:library type] #(into [result] %))))))
|
||||
(update-in [:library type team-id] #(into [result] %))))))
|
||||
|
||||
;; Rename library
|
||||
|
||||
(declare rename-library-result)
|
||||
|
||||
(defn rename-library
|
||||
[type library-id name]
|
||||
[type team-id library-id name]
|
||||
(ptk/reify ::rename-library
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
|
@ -104,10 +107,10 @@
|
|||
:palettes :rename-color-library)]
|
||||
(->> (rp/mutation! method {:id library-id
|
||||
:name name})
|
||||
(rx/map #(rename-library-result type library-id name)))))))
|
||||
(rx/map #(rename-library-result type team-id library-id name)))))))
|
||||
|
||||
(defn rename-library-result
|
||||
[type library-id name]
|
||||
[type team-id library-id name]
|
||||
(ptk/reify ::rename-library-result
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
|
@ -118,14 +121,14 @@
|
|||
(update-fn [libraries] (map change-name libraries))]
|
||||
|
||||
(-> state
|
||||
(update-in [:library type] update-fn))))))
|
||||
(update-in [:library type team-id] update-fn))))))
|
||||
|
||||
;; Delete library
|
||||
|
||||
(declare delete-library-result)
|
||||
|
||||
(defn delete-library
|
||||
[type library-id]
|
||||
[type team-id library-id]
|
||||
(ptk/reify ::delete-library
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
|
@ -139,17 +142,17 @@
|
|||
:images :delete-image-library
|
||||
:palettes :delete-color-library)]
|
||||
(->> (rp/mutation! method {:id library-id})
|
||||
(rx/map #(delete-library-result type library-id)))))))
|
||||
(rx/map #(delete-library-result type team-id library-id)))))))
|
||||
|
||||
(defn delete-library-result
|
||||
[type library-id]
|
||||
[type team-id library-id]
|
||||
(ptk/reify ::create-library-result
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [update-fn (fn [libraries]
|
||||
(filterv #(not= library-id (:id %)) libraries))]
|
||||
(-> state
|
||||
(update-in [:library type] update-fn))))))
|
||||
(update-in [:library type team-id] update-fn))))))
|
||||
|
||||
;; Delete library item
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
|
||||
(declare fetch-users)
|
||||
(declare fetch-images)
|
||||
(declare fetch-project)
|
||||
(declare handle-who)
|
||||
(declare handle-pointer-update)
|
||||
(declare handle-pointer-send)
|
||||
|
@ -270,7 +271,7 @@
|
|||
(declare initialize-alignment)
|
||||
|
||||
#_(def default-layout #{:sitemap :layers :element-options :rules})
|
||||
(def default-layout #{:libraries :rules})
|
||||
(def default-layout #{:libraries :rules :colorpalette})
|
||||
|
||||
|
||||
(def workspace-default
|
||||
|
@ -296,7 +297,8 @@
|
|||
|
||||
(defn initialize
|
||||
"Initialize the workspace state."
|
||||
[file-id page-id]
|
||||
[project-id file-id page-id]
|
||||
(us/verify ::us/uuid project-id)
|
||||
(us/verify ::us/uuid file-id)
|
||||
(us/verify ::us/uuid page-id)
|
||||
(ptk/reify ::initialize
|
||||
|
@ -307,9 +309,11 @@
|
|||
(rx/merge
|
||||
(rx/of (fetch-file-with-users file-id)
|
||||
(fetch-pages file-id)
|
||||
(fetch-images file-id))
|
||||
(fetch-images file-id)
|
||||
(fetch-project project-id))
|
||||
(->> (rx/zip (rx/filter (ptk/type? ::pages-fetched) stream)
|
||||
(rx/filter (ptk/type? ::file-fetched) stream))
|
||||
(rx/filter (ptk/type? ::file-fetched) stream)
|
||||
(rx/filter (ptk/type? ::project-fetched) stream))
|
||||
(rx/take 1)
|
||||
(rx/do (fn [_]
|
||||
(uxbox.util.timers/schedule 500 #(reset! st/loader false))))
|
||||
|
@ -357,7 +361,8 @@
|
|||
(rx/of (initialize-page-persistence page-id)))))
|
||||
|
||||
(defn finalize
|
||||
[file-id page-id]
|
||||
[project-id file-id page-id]
|
||||
(us/verify ::us/uuid project-id)
|
||||
(us/verify ::us/uuid file-id)
|
||||
(us/verify ::us/uuid page-id)
|
||||
(ptk/reify ::finalize
|
||||
|
@ -495,6 +500,7 @@
|
|||
(s/def ::data ::cp/data)
|
||||
|
||||
(s/def ::file ::dd/file)
|
||||
(s/def ::project ::dd/project)
|
||||
(s/def ::page
|
||||
(s/keys :req-un [::id
|
||||
::name
|
||||
|
@ -548,6 +554,25 @@
|
|||
state
|
||||
users))))
|
||||
|
||||
;; --- Fetch Project data
|
||||
(declare project-fetched)
|
||||
|
||||
(defn fetch-project
|
||||
[id]
|
||||
(us/verify ::us/uuid id)
|
||||
(ptk/reify ::fetch-project
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(->> (rp/query :project-by-id {:project-id id})
|
||||
(rx/map project-fetched)))))
|
||||
|
||||
(defn project-fetched
|
||||
[project]
|
||||
(us/verify ::project project)
|
||||
(ptk/reify ::project-fetched
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc state :workspace-project project))))
|
||||
|
||||
;; --- Fetch Pages
|
||||
|
||||
|
@ -1931,7 +1956,8 @@
|
|||
(ptk/reify ::go-to-page
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [file-id (get-in state [:workspace-page :file-id])
|
||||
(let [project-id (get-in state [:workspace-project :id])
|
||||
file-id (get-in state [:workspace-page :file-id])
|
||||
path-params {:file-id file-id}
|
||||
query-params {:page-id page-id}]
|
||||
(rx/of (rt/nav :workspace path-params query-params))))))
|
||||
|
@ -1942,8 +1968,9 @@
|
|||
(ptk/reify ::go-to-file
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [page-ids (get-in state [:files file-id :pages])
|
||||
path-params {:file-id file-id}
|
||||
(let [project-id (get-in state [:workspace-project :id])
|
||||
page-ids (get-in state [:files file-id :pages])
|
||||
path-params {:project-id project-id :file-id file-id}
|
||||
query-params {:page-id (first page-ids)}]
|
||||
(rx/of (rt/nav :workspace path-params query-params))))))
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
|
||||
]]]
|
||||
|
||||
["/workspace/:file-id" :workspace]])
|
||||
["/workspace/:project-id/:file-id" :workspace]])
|
||||
|
||||
(mf/defc app-error
|
||||
[{:keys [error] :as props}]
|
||||
|
@ -119,9 +119,11 @@
|
|||
(mf/element dashboard #js {:route route})
|
||||
|
||||
:workspace
|
||||
(let [file-id (uuid (get-in route [:params :path :file-id]))
|
||||
(let [project-id (uuid (get-in route [:params :path :project-id]))
|
||||
file-id (uuid (get-in route [:params :path :file-id]))
|
||||
page-id (uuid (get-in route [:params :query :page-id]))]
|
||||
[:& workspace/workspace {:file-id file-id
|
||||
[:& workspace/workspace {:project-id project-id
|
||||
:file-id file-id
|
||||
:page-id page-id
|
||||
:key file-id}])
|
||||
nil)))
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
handle-select (fn [tab]
|
||||
(let [id (-> tab .-props .-id)]
|
||||
(swap! state assoc :selected id)
|
||||
(on-change-tab id)))]
|
||||
(when on-change-tab (on-change-tab id))))]
|
||||
[:div.tab-container
|
||||
[:div.tab-container-tabs
|
||||
(for [tab children]
|
||||
|
|
|
@ -41,8 +41,9 @@
|
|||
:edition false})
|
||||
locale (i18n/use-locale)
|
||||
on-navigate #(st/emit! (rt/nav :workspace
|
||||
{:file-id (:id file)}
|
||||
{:page-id (first (:pages file))}))
|
||||
{:project-id (:project-id file)
|
||||
:file-id (:id file)}
|
||||
{:page-id (first (:pages file))}))
|
||||
delete-fn #(st/emit! nil (dsh/delete-file (:id file)))
|
||||
on-delete #(do
|
||||
(dom/stop-propagation %)
|
||||
|
@ -75,7 +76,7 @@
|
|||
[:h3 (:name file)])
|
||||
[:& grid-item-metadata {:modified-at (:modified-at file)}]]
|
||||
[:div.project-th-actions {:class (classnames
|
||||
:force-display (:menu-open @local))}
|
||||
:force-display (:menu-open @local))}
|
||||
;; [:div.project-th-icon.pages
|
||||
;; i/page
|
||||
;; #_[:span (:total-pages project)]]
|
||||
|
|
|
@ -122,7 +122,7 @@
|
|||
(dlib/retrieve-libraries :icons (:id item))
|
||||
(st/emit! (rt/nav path {:team-id team-id :library-id (:id item)}))))}
|
||||
[:& editable-label {:value (:name item)
|
||||
:on-change #(st/emit! (dlib/rename-library section library-id %))}]
|
||||
:on-change #(st/emit! (dlib/rename-library section team-id library-id %))}]
|
||||
])]]))
|
||||
|
||||
(mf/defc library-top-menu
|
||||
|
@ -136,7 +136,7 @@
|
|||
[:& editable-label {:edit (:editing-name @state)
|
||||
:on-change #(do
|
||||
(stop-editing)
|
||||
(st/emit! (dlib/rename-library section library-id %)))
|
||||
(st/emit! (dlib/rename-library section team-id library-id %)))
|
||||
:on-cancel #(swap! state assoc :editing-name false)
|
||||
:class-name "library-top-menu-current-element-name"
|
||||
:value (:name selected)}]
|
||||
|
@ -155,7 +155,7 @@
|
|||
(modal/show!
|
||||
confirm-dialog
|
||||
{:on-accept #(do
|
||||
(st/emit! (dlib/delete-library section library-id))
|
||||
(st/emit! (dlib/delete-library section team-id library-id))
|
||||
(st/emit! (rt/nav path {:team-id team-id})))
|
||||
:message "Are you sure you want to delete this library?"
|
||||
:accept-text "Delete"})))]]}]]
|
||||
|
@ -301,8 +301,8 @@
|
|||
:message "Are you sure you want to delete this color?"
|
||||
:accept-text "Delete"}))]]}]]])))
|
||||
|
||||
(defn libraries-ref [section]
|
||||
(-> (comp (l/key :library) (l/key section))
|
||||
(defn libraries-ref [section team-id]
|
||||
(-> (comp (l/key :library) (l/key section) (l/key team-id))
|
||||
(l/derive st/state)))
|
||||
|
||||
(defn selected-items-ref [library-id]
|
||||
|
@ -316,7 +316,7 @@
|
|||
(mf/defc library-page
|
||||
[{:keys [team-id library-id section]}]
|
||||
(let [state (mf/use-state {:selected #{}})
|
||||
libraries (mf/deref (libraries-ref section))
|
||||
libraries (mf/deref (libraries-ref section team-id))
|
||||
items (mf/deref (selected-items-ref library-id))
|
||||
last-deleted-library (mf/deref last-deleted-library-ref)
|
||||
selected-library (first (filter #(= (:id %) library-id) libraries))]
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
:no-tool-bar-left (not left-sidebar?))]
|
||||
[:*
|
||||
(when (:colorpalette layout)
|
||||
[:& colorpalette])
|
||||
[:& colorpalette {:left-sidebar? left-sidebar?}])
|
||||
|
||||
[:main.main-content
|
||||
[:& context-menu {}]
|
||||
|
@ -99,13 +99,13 @@
|
|||
|
||||
|
||||
(mf/defc workspace
|
||||
[{:keys [file-id page-id] :as props}]
|
||||
[{:keys [project-id file-id page-id] :as props}]
|
||||
|
||||
(-> (mf/deps file-id page-id)
|
||||
(mf/use-effect
|
||||
(fn []
|
||||
(st/emit! (dw/initialize file-id page-id))
|
||||
#(st/emit! (dw/finalize file-id page-id)))))
|
||||
(st/emit! (dw/initialize project-id file-id page-id))
|
||||
#(st/emit! (dw/finalize project-id file-id page-id)))))
|
||||
|
||||
(-> (mf/deps file-id)
|
||||
(mf/use-effect
|
||||
|
|
|
@ -42,10 +42,10 @@
|
|||
:on-click select-color}
|
||||
[:span.color {:style {:background color}}]
|
||||
[:span.color-text color]
|
||||
[:span.color-text rgb-color]]))
|
||||
#_[:span.color-text rgb-color]]))
|
||||
|
||||
(mf/defc palette
|
||||
[{:keys [colls] :as props}]
|
||||
[{:keys [colls left-sidebar?] :as props}]
|
||||
(let [local (mf/use-state {})
|
||||
colls (->> colls
|
||||
(filter :id)
|
||||
|
@ -97,9 +97,10 @@
|
|||
|
||||
(mf/use-effect nil after-render)
|
||||
|
||||
[:div.color-palette
|
||||
[:div.color-palette {:class (when left-sidebar? "left-sidebar-open")}
|
||||
[:div.color-palette-actions
|
||||
[:select.input-select {:on-change select-coll
|
||||
[:div.color-palette-actions-button i/actions]
|
||||
#_[:select.input-select {:on-change select-coll
|
||||
:default-value (pr-str (:id coll))}
|
||||
(for [item colls]
|
||||
[:option {:key (:id item) :value (pr-str (:id item))}
|
||||
|
@ -116,14 +117,17 @@
|
|||
:style {:position "relative"
|
||||
:width (str (* 86 (count (:colors coll))) "px")
|
||||
:right (str (* 86 offset) "px")}}
|
||||
(for [color (:colors coll)]
|
||||
[:& palette-item {:color color :key color}])]]
|
||||
#_(for [color (:colors coll)]
|
||||
[:& palette-item {:color color :key color}])
|
||||
(for [color (range 0 20)]
|
||||
[:& palette-item {:color "#FFFF00" :key color}])]]
|
||||
|
||||
[:span.right-arrow {:on-click on-right-arrow-click} i/arrow-slide]
|
||||
[:span.close-palette {:on-click close} i/close]]))
|
||||
#_[:span.close-palette {:on-click close} i/close]]))
|
||||
|
||||
(mf/defc colorpalette
|
||||
[props]
|
||||
[{:keys [left-sidebar?]}]
|
||||
(let [colls (mf/deref collections-iref)]
|
||||
#_(mf/use-effect #(st/emit! (udc/fetch-collections)))
|
||||
[:& palette {:colls (vals colls)}]))
|
||||
[:& palette {:left-sidebar? left-sidebar?
|
||||
:colls (vals colls)}]))
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
(ns uxbox.main.ui.workspace.sidebar.libraries
|
||||
(:require
|
||||
[lentes.core :as l]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.common.data :as d]
|
||||
[uxbox.builtins.icons :as i]
|
||||
|
@ -22,40 +23,98 @@
|
|||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.uuid :as uuid]
|
||||
[uxbox.util.i18n :as i18n :refer [t]]
|
||||
[uxbox.main.ui.components.tab-container :refer [tab-container tab-element]]))
|
||||
[uxbox.main.ui.components.tab-container :refer [tab-container tab-element]]
|
||||
[uxbox.main.data.library :as dlib]))
|
||||
|
||||
(mf/defc library-tab []
|
||||
[:div.library-tab.icons-tab
|
||||
[:select.library-tab-libraries
|
||||
[:option.library-tab-libraries-item "Material design"]
|
||||
[:option.library-tab-libraries-item "Icon library 1"]
|
||||
[:option.library-tab-libraries-item "Icon library 2"]]
|
||||
[:div.library-tab-content
|
||||
(for [_ (range 0 200)]
|
||||
[:div.library-tab-element
|
||||
i/trash
|
||||
[:span.library-tab-element-name "my-icon.svg"]])]])
|
||||
(def project-ref
|
||||
(-> (l/key :workspace-project)
|
||||
(l/derive st/state)))
|
||||
|
||||
(mf/defc images-tab []
|
||||
[:div.library-tab.images-tab
|
||||
[:select.library-tab-libraries
|
||||
[:option.library-tab-libraries-item "Material design"]
|
||||
[:option.library-tab-libraries-item "Icon library 1"]
|
||||
[:option.library-tab-libraries-item "Icon library 2"]]
|
||||
[:div.library-tab-content
|
||||
(for [_ (range 0 200)]
|
||||
[:div.library-tab-element
|
||||
[:img {:src "https://www.placecage.com/c/200/300"}]
|
||||
[:span.library-tab-element-name "my-icon.svg"]])]])
|
||||
(defn libraries-ref [section]
|
||||
(-> (comp (l/key :library) (l/key section))
|
||||
(l/derive st/state)))
|
||||
|
||||
(defn selected-items-ref [library-id]
|
||||
(-> (comp (l/key :library) (l/key :selected-items) (l/key library-id))
|
||||
(l/derive st/state)))
|
||||
|
||||
(mf/defc icons-tab [{:keys [libraries]}]
|
||||
(when (and libraries (-> libraries count (> 0)))
|
||||
(let [state (mf/use-state {:selected-library (-> libraries first :id)})]
|
||||
(mf/use-effect {:fn (fn []
|
||||
(st/emit! (dlib/retrieve-library-data :icons (:selected-library @state))))
|
||||
:deps (mf/deps (:selected-library @state))})
|
||||
|
||||
[:div.library-tab.icons-tab
|
||||
[:select.input-select.library-tab-libraries
|
||||
{:on-change #(swap! state assoc :selected-library (-> % dom/get-target dom/get-value))}
|
||||
(for [library libraries]
|
||||
[:option.library-tab-libraries-item
|
||||
{:key (:id library)
|
||||
:value (:id library)}
|
||||
(:name library)])]
|
||||
[:div.library-tab-content
|
||||
(let [items (mf/deref (selected-items-ref (:selected-library @state)))]
|
||||
(for [item items]
|
||||
[:div.library-tab-element
|
||||
{:key (:id item)}
|
||||
[:svg {:view-box (->> item :metadata :view-box (str/join " "))
|
||||
:width (-> item :metadata :width)
|
||||
:height (-> item :metadat :height)
|
||||
:dangerouslySetInnerHTML {:__html (:content item)}}]
|
||||
[:span.library-tab-element-name (:name item)]]))]])))
|
||||
|
||||
(mf/defc images-tab [{:keys [libraries]}]
|
||||
(when (and libraries (-> libraries count (> 0)))
|
||||
(let [state (mf/use-state {:selected-library (-> libraries first :id)})]
|
||||
(mf/use-effect {:fn (fn []
|
||||
(st/emit! (dlib/retrieve-library-data :images (:selected-library @state))))
|
||||
:deps (mf/deps (:selected-library @state))})
|
||||
|
||||
[:div.library-tab.images-tab
|
||||
[:select.input-select.library-tab-libraries
|
||||
{:on-change #(swap! state assoc :selected-library (-> % dom/get-target dom/get-value))}
|
||||
(for [library libraries]
|
||||
[:option.library-tab-libraries-item
|
||||
{:key (:id library)
|
||||
:value (:id library)}
|
||||
(:name library)])]
|
||||
[:div.library-tab-content
|
||||
(let [items (mf/deref (selected-items-ref (:selected-library @state)))]
|
||||
(for [item items]
|
||||
[:div.library-tab-element
|
||||
{:key (:id item)}
|
||||
[:img {:src (:thumb-uri item)}]
|
||||
[:span.library-tab-element-name (:name item)]]))]])))
|
||||
|
||||
(mf/defc libraries-toolbox
|
||||
[]
|
||||
(let [locale (i18n/use-locale)]
|
||||
[{:keys [key]}]
|
||||
(let [team-id (-> project-ref mf/deref :team-id)
|
||||
locale (i18n/use-locale)]
|
||||
(mf/use-effect {:fn (fn []
|
||||
(st/emit! (dlib/retrieve-libraries :icons))
|
||||
(st/emit! (dlib/retrieve-libraries :images)))
|
||||
:deps (mf/deps key)})
|
||||
(mf/use-effect {:fn (fn []
|
||||
(when team-id
|
||||
(do
|
||||
(st/emit! (dlib/retrieve-libraries :icons team-id))
|
||||
(st/emit! (dlib/retrieve-libraries :images team-id)))))
|
||||
:deps (mf/deps team-id)})
|
||||
[:div#libraries.tool-window
|
||||
[:div.tool-window-bar
|
||||
[:div "Libraries"]
|
||||
[:div "All libraries"]]
|
||||
[:div.libraries-window-bar
|
||||
[:div.libraries-window-bar-title "Libraries"]
|
||||
[:div.libraries-window-bar-options
|
||||
"All libraries"
|
||||
[:button {:type "button"}
|
||||
i/arrow-slide]]]
|
||||
[:div.tool-window-content
|
||||
[:& tab-container {}
|
||||
[:& tab-element {:id :icons :title "Icons"} [:& library-tab]]
|
||||
[:& tab-element {:id :images :title "Images"} [:& images-tab]]]]]))
|
||||
[:& tab-element
|
||||
{:id :icons :title "Icons"}
|
||||
[:& icons-tab {:libraries (-> (libraries-ref :icons) mf/deref vals flatten) }]]
|
||||
|
||||
[:& tab-element
|
||||
{:id :images :title "Images"}
|
||||
[:& images-tab {:libraries (-> (libraries-ref :images) mf/deref vals flatten)}]]]]]))
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue