From b2474fc3fbfa7ebc4c9cc69ef14c6e7630903359 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 16 Mar 2020 15:52:02 +0100 Subject: [PATCH] :neckbeard: retrieve data from backend --- backend/src/uxbox/config.clj | 2 + backend/src/uxbox/fixtures.clj | 15 +- backend/src/uxbox/services/queries/icons.clj | 1 + backend/src/uxbox/services/queries/images.clj | 1 + frontend/resources/locales.json | 102 ++- .../styles/main/layouts/library-page.scss | 24 +- frontend/src/uxbox/main/data/colors.cljs | 46 ++ frontend/src/uxbox/main/data/icons.cljs | 509 +++++++------ frontend/src/uxbox/main/data/images.cljs | 43 ++ frontend/src/uxbox/main/ui.cljs | 22 +- frontend/src/uxbox/main/ui/dashboard.cljs | 33 +- .../src/uxbox/main/ui/dashboard/icons.cljs | 708 +++++++++--------- .../src/uxbox/main/ui/dashboard/library.cljs | 193 +++-- .../src/uxbox/main/ui/dashboard/sidebar.cljs | 4 +- .../main/ui/workspace/sidebar/icons.cljs | 6 +- 15 files changed, 1022 insertions(+), 687 deletions(-) diff --git a/backend/src/uxbox/config.clj b/backend/src/uxbox/config.clj index 7c5199dbb..665959869 100644 --- a/backend/src/uxbox/config.clj +++ b/backend/src/uxbox/config.clj @@ -23,6 +23,8 @@ {:http-server-port 6060 :http-server-cors "http://localhost:3449" :database-uri "postgresql://127.0.0.1/uxbox" + :database-username "uxbox" + :database-password "uxbox" :media-directory "resources/public/media" :assets-directory "resources/public/static" :media-uri "http://localhost:6060/media/" diff --git a/backend/src/uxbox/fixtures.clj b/backend/src/uxbox/fixtures.clj index ae9f82a66..d3c65dacc 100644 --- a/backend/src/uxbox/fixtures.clj +++ b/backend/src/uxbox/fixtures.clj @@ -66,9 +66,20 @@ values ($1, $2, $3, $4, $5, $6) 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 - {:num-teams 50 - :num-profiles 50 + {:num-teams 5 + :num-profiles 5 :num-profiles-per-team 5 :num-projects-per-team 5 :num-files-per-project 5 diff --git a/backend/src/uxbox/services/queries/icons.clj b/backend/src/uxbox/services/queries/icons.clj index 08688a14c..b1922f37f 100644 --- a/backend/src/uxbox/services/queries/icons.clj +++ b/backend/src/uxbox/services/queries/icons.clj @@ -31,6 +31,7 @@ (s/def ::name ::us/string) (s/def ::profile-id ::us/uuid) (s/def ::library-id ::us/uuid) +(s/def ::team-id ::us/uuid) (defn decode-row [{:keys [metadata] :as row}] diff --git a/backend/src/uxbox/services/queries/images.clj b/backend/src/uxbox/services/queries/images.clj index 1243bf8d0..a690a5cc1 100644 --- a/backend/src/uxbox/services/queries/images.clj +++ b/backend/src/uxbox/services/queries/images.clj @@ -21,6 +21,7 @@ (s/def ::id ::us/uuid) (s/def ::name ::us/string) (s/def ::profile-id ::us/uuid) +(s/def ::team-id ::us/uuid) (s/def ::library-id ::us/uuid) ;; --- Query: Image Librarys diff --git a/frontend/resources/locales.json b/frontend/resources/locales.json index 1ae0c5323..b1247c605 100644 --- a/frontend/resources/locales.json +++ b/frontend/resources/locales.json @@ -78,14 +78,68 @@ "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" : { - "used-in" : [ "src/uxbox/main/ui/dashboard/sidebar.cljs:113" ], + "used-in" : [ "src/uxbox/main/ui/dashboard/sidebar.cljs:112" ], "translations" : { "en" : "Drafts" } }, "dashboard.sidebar.libraries" : { - "used-in" : [ "src/uxbox/main/ui/dashboard/sidebar.cljs:118" ], + "used-in" : [ "src/uxbox/main/ui/dashboard/sidebar.cljs:117" ], "translations" : { "en" : "Libraries" } @@ -97,7 +151,7 @@ "unused" : true }, "dashboard.sidebar.recent" : { - "used-in" : [ "src/uxbox/main/ui/dashboard/sidebar.cljs:106" ], + "used-in" : [ "src/uxbox/main/ui/dashboard/sidebar.cljs:105" ], "translations" : { "en" : "Recent" } @@ -109,6 +163,24 @@ "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" : { "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/history.cljs:114" ], "translations" : { @@ -166,7 +238,7 @@ } }, "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" : { "en" : "Unnamed Collection (%s)", "fr" : "Collection sans nom (%s)" @@ -244,7 +316,7 @@ } }, "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" : { "en" : "Delete", "fr" : "Supprimer" @@ -300,7 +372,7 @@ "unused" : true }, "ds.search.placeholder" : { - "used-in" : [ "src/uxbox/main/ui/dashboard/sidebar.cljs:168" ], + "used-in" : [ "src/uxbox/main/ui/dashboard/sidebar.cljs:140" ], "translations" : { "en" : "Search...", "fr" : "Rechercher..." @@ -356,7 +428,7 @@ } }, "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" : { "en" : "Uploaded at %s", "fr" : "Mise en ligne : %s" @@ -426,14 +498,14 @@ } }, "errors.generic" : { - "used-in" : [ "src/uxbox/main/ui.cljs:135" ], + "used-in" : [ "src/uxbox/main/ui.cljs:131" ], "translations" : { "en" : "Something wrong has happened.", "fr" : "Quelque chose c'est mal passé." } }, "errors.network" : { - "used-in" : [ "src/uxbox/main/ui.cljs:129" ], + "used-in" : [ "src/uxbox/main/ui.cljs:125" ], "translations" : { "en" : "Unable to connect to backend server.", "fr" : "Impossible de se connecter au serveur principal." @@ -538,7 +610,7 @@ } }, "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" : { "en" : "Go back!", "fr" : "Retour!" @@ -895,7 +967,7 @@ } }, "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" : { "en" : "Color", "fr" : "Couleur" @@ -937,7 +1009,7 @@ } }, "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" : { "en" : "Size, position & rotation", "fr" : "Taille, position et rotation" @@ -951,21 +1023,21 @@ } }, "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" : { "en" : "Position", "fr" : "Position" } }, "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" : { "en" : "Rotation & Radius", "fr" : "TODO" } }, "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" : { "en" : "Size", "fr" : "Taille" diff --git a/frontend/resources/styles/main/layouts/library-page.scss b/frontend/resources/styles/main/layouts/library-page.scss index 2b169471b..2bc0746f6 100644 --- a/frontend/resources/styles/main/layouts/library-page.scss +++ b/frontend/resources/styles/main/layouts/library-page.scss @@ -47,6 +47,8 @@ .library-sidebar { background-color: $color-white; padding: $size-2; + height: 100%; + overflow: hidden; } .library-sidebar-add-item { @@ -66,11 +68,17 @@ .library-sidebar-list { margin-top: $size-4; + overflow: scroll; + height: 100%; + padding-bottom: 4rem; } .library-sidebar-list-element { padding: $size-4 $size-2; cursor: pointer; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; & a { color: $color-black; @@ -138,17 +146,19 @@ } .library-page-cards-container { - padding: $size-2; + align-content: flex-start; display: flex; flex-wrap: wrap; - overflow: scroll; height: 100%; - align-content: flex-start; + overflow: scroll; + padding: $size-2; + padding-bottom: 4rem; } .library-card { margin: $size-2; background: $color-white; + border: 2px solid transparent; &.library-icon, &.library-color { width: 200px; @@ -167,7 +177,11 @@ visibility: hidden; opacity: 0; } - + + &:hover { + border: 2px solid $color-primary; + } + &:hover .library-card-footer-menu { visibility: visible; opacity: 1; @@ -204,7 +218,7 @@ text-align: center; display: flex; - & svg, & img { + & object, & svg, & img { margin: auto; width: auto; height: auto; diff --git a/frontend/src/uxbox/main/data/colors.cljs b/frontend/src/uxbox/main/data/colors.cljs index 69a011577..cdfed29bd 100644 --- a/frontend/src/uxbox/main/data/colors.cljs +++ b/frontend/src/uxbox/main/data/colors.cljs @@ -6,9 +6,11 @@ (ns uxbox.main.data.colors (:require + [cljs.spec.alpha :as s] [beicon.core :as rx] [clojure.set :as set] [potok.core :as ptk] + [uxbox.common.spec :as us] [uxbox.main.repo :as rp] [uxbox.main.store :as st] [uxbox.util.color :as color] @@ -241,3 +243,47 @@ (defn delete-colors [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))))) diff --git a/frontend/src/uxbox/main/data/icons.cljs b/frontend/src/uxbox/main/data/icons.cljs index 6c3ccc60d..a7ac82f15 100644 --- a/frontend/src/uxbox/main/data/icons.cljs +++ b/frontend/src/uxbox/main/data/icons.cljs @@ -35,20 +35,61 @@ ::user-id])) -(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] #{})) +(declare fetch-icon-libraries-result) +(defn fetch-icon-libraries + [team-id] + (s/assert ::us/uuid team-id) + (ptk/reify ::fetch-icon-libraries ptk/WatchEvent (watch [_ state stream] - (rx/of (fetch-icons collection-id))))) + (->> (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 + (update [_ state] + (-> 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 + (watch [_ state stream] + (->> (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 (declare collections-fetched) @@ -79,156 +120,156 @@ items)))) -;; --- Create Collection - -(declare collection-created) - -(def create-collection - (ptk/reify ::create-collection - ptk/WatchEvent - (watch [_ state s] - (let [name (tr "ds.default-library-title" (gensym "c")) - data {:name name}] - (->> (rp/mutation! :create-icons-collection data) - (rx/map collection-created)))))) - - -;; --- Collection Created - -(defn collection-created - [item] - (s/assert ::collection item) - (ptk/reify ::collection-created - ptk/UpdateEvent - (update [_ state] - (let [{:keys [id] :as item} (assoc item :type :own)] - (update state :icons-collections assoc id item))))) - -;; --- Rename Collection - -(defn rename-collection - [id name] - (ptk/reify ::rename-collection - ptk/UpdateEvent - (update [_ state] - (assoc-in state [:icons-collections id :name] name)) - - ptk/WatchEvent - (watch [_ state s] - (let [params {:id id :name name}] - (->> (rp/mutation! :rename-icons-collection params) - (rx/ignore)))))) - -;; --- Delete Collection - -(defn delete-collection - [id on-success] - (ptk/reify ::delete-collection - ptk/UpdateEvent - (update [_ state] - (update state :icons-collections dissoc id)) - - ptk/WatchEvent - (watch [_ state s] - (->> (rp/mutation! :delete-icons-collection {:id id}) - (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 Persisted - -(defrecord IconPersisted [id data] - ptk/UpdateEvent - (update [_ state] - (assoc-in state [:icons id] data))) - -(defn icon-persisted - [{:keys [id] :as data}] - {:pre [(map? data)]} - (IconPersisted. id data)) - -;; --- Persist Icon - -(defn persist-icon - [id] - (s/assert ::us/uuid id) - (ptk/reify ::persist-icon - ptk/WatchEvent - (watch [_ state stream] - (let [data (get-in state [:icons id])] - (->> (rp/mutation! :update-icon data) - (rx/ignore)))))) - +;; ;; --- Create Collection +;; +;; (declare collection-created) +;; +;; (def create-collection +;; (ptk/reify ::create-collection +;; ptk/WatchEvent +;; (watch [_ state s] +;; (let [name (tr "ds.default-library-title" (gensym "c")) +;; data {:name name}] +;; (->> (rp/mutation! :create-icons-collection data) +;; (rx/map collection-created)))))) +;; +;; +;; ;; --- Collection Created +;; +;; (defn collection-created +;; [item] +;; (s/assert ::collection item) +;; (ptk/reify ::collection-created +;; ptk/UpdateEvent +;; (update [_ state] +;; (let [{:keys [id] :as item} (assoc item :type :own)] +;; (update state :icons-collections assoc id item))))) +;; +;; ;; --- Rename Collection +;; +;; (defn rename-collection +;; [id name] +;; (ptk/reify ::rename-collection +;; ptk/UpdateEvent +;; (update [_ state] +;; (assoc-in state [:icons-collections id :name] name)) +;; +;; ptk/WatchEvent +;; (watch [_ state s] +;; (let [params {:id id :name name}] +;; (->> (rp/mutation! :rename-icons-collection params) +;; (rx/ignore)))))) +;; +;; ;; --- Delete Collection +;; +;; (defn delete-collection +;; [id on-success] +;; (ptk/reify ::delete-collection +;; ptk/UpdateEvent +;; (update [_ state] +;; (update state :icons-collections dissoc id)) +;; +;; ptk/WatchEvent +;; (watch [_ state s] +;; (->> (rp/mutation! :delete-icons-collection {:id id}) +;; (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 Persisted +;; +;; (defrecord IconPersisted [id data] +;; ptk/UpdateEvent +;; (update [_ state] +;; (assoc-in state [:icons id] data))) +;; +;; (defn icon-persisted +;; [{:keys [id] :as data}] +;; {:pre [(map? data)]} +;; (IconPersisted. id data)) +;; +;; ;; --- Persist Icon +;; +;; (defn persist-icon +;; [id] +;; (s/assert ::us/uuid id) +;; (ptk/reify ::persist-icon +;; ptk/WatchEvent +;; (watch [_ state stream] +;; (let [data (get-in state [:icons id])] +;; (->> (rp/mutation! :update-icon data) +;; (rx/ignore)))))) +;; ;; --- Load Icons (declare icons-fetched) @@ -253,80 +294,80 @@ (let [icons (d/index-by :id items)] (assoc state :icons icons))))) -;; --- Rename Icon - -(defn rename-icon - [id name] - (s/assert ::us/uuid id) - (s/assert ::us/string name) - (ptk/reify ::rename-icon - ptk/UpdateEvent - (update [_ state] - (assoc-in state [:icons id :name] name)) - - ptk/WatchEvent - (watch [_ state stream] - (rx/of (persist-icon id))))) - -;; --- Icon Selection - -(defn select-icon - [id] - (ptk/reify ::select-icon - ptk/UpdateEvent - (update [_ state] - (update-in state [:dashboard-icons :selected] (fnil conj #{}) id)))) - -(defn deselect-icon - [id] - (ptk/reify ::deselect-icon - ptk/UpdateEvent - (update [_ state] - (update-in state [:dashboard-icons :selected] (fnil disj #{}) id)))) - -(def deselect-all-icons - (ptk/reify ::deselect-all-icons - ptk/UpdateEvent - (update [_ state] - (assoc-in state [:dashboard-icons :selected] #{})))) - -;; --- Delete Icons - -(defn delete-icon - [id] - (ptk/reify ::delete-icon - ptk/UpdateEvent - (update [_ state] - (update state :icons dissoc id)) - - ptk/WatchEvent - (watch [_ state s] - (rx/merge - (rx/of deselect-all-icons) - (->> (rp/mutation! :delete-icon {:id id}) - (rx/ignore)))))) - -;; --- Delete Selected - -(def delete-selected - (ptk/reify ::delete-selected - ptk/WatchEvent - (watch [_ state stream] - (let [selected (get-in state [:dashboard-icons :selected])] - (->> (rx/from selected) - (rx/map delete-icon)))))) -;; --- 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-icons merge - {:edition edition} - (when order {:order order}) - (when filter {:filter filter}))))) +;; ;; --- Rename Icon +;; +;; (defn rename-icon +;; [id name] +;; (s/assert ::us/uuid id) +;; (s/assert ::us/string name) +;; (ptk/reify ::rename-icon +;; ptk/UpdateEvent +;; (update [_ state] +;; (assoc-in state [:icons id :name] name)) +;; +;; ptk/WatchEvent +;; (watch [_ state stream] +;; (rx/of (persist-icon id))))) +;; +;; ;; --- Icon Selection +;; +;; (defn select-icon +;; [id] +;; (ptk/reify ::select-icon +;; ptk/UpdateEvent +;; (update [_ state] +;; (update-in state [:dashboard-icons :selected] (fnil conj #{}) id)))) +;; +;; (defn deselect-icon +;; [id] +;; (ptk/reify ::deselect-icon +;; ptk/UpdateEvent +;; (update [_ state] +;; (update-in state [:dashboard-icons :selected] (fnil disj #{}) id)))) +;; +;; (def deselect-all-icons +;; (ptk/reify ::deselect-all-icons +;; ptk/UpdateEvent +;; (update [_ state] +;; (assoc-in state [:dashboard-icons :selected] #{})))) +;; +;; ;; --- Delete Icons +;; +;; (defn delete-icon +;; [id] +;; (ptk/reify ::delete-icon +;; ptk/UpdateEvent +;; (update [_ state] +;; (update state :icons dissoc id)) +;; +;; ptk/WatchEvent +;; (watch [_ state s] +;; (rx/merge +;; (rx/of deselect-all-icons) +;; (->> (rp/mutation! :delete-icon {:id id}) +;; (rx/ignore)))))) +;; +;; ;; --- Delete Selected +;; +;; (def delete-selected +;; (ptk/reify ::delete-selected +;; ptk/WatchEvent +;; (watch [_ state stream] +;; (let [selected (get-in state [:dashboard-icons :selected])] +;; (->> (rx/from selected) +;; (rx/map delete-icon)))))) +;; ;; --- 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-icons merge +;; {:edition edition} +;; (when order {:order order}) +;; (when filter {:filter filter}))))) ;; --- Copy Selected Icon diff --git a/frontend/src/uxbox/main/data/images.cljs b/frontend/src/uxbox/main/data/images.cljs index 99f2ac642..bbdbc881d 100644 --- a/frontend/src/uxbox/main/data/images.cljs +++ b/frontend/src/uxbox/main/data/images.cljs @@ -398,3 +398,46 @@ ;; {:pre [(or (uuid? id) (nil? 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))))) diff --git a/frontend/src/uxbox/main/ui.cljs b/frontend/src/uxbox/main/ui.cljs index bdc69b717..0c96fa476 100644 --- a/frontend/src/uxbox/main/ui.cljs +++ b/frontend/src/uxbox/main/ui.cljs @@ -56,7 +56,20 @@ ["/" :dashboard-team] ["/search" :dashboard-search] ["/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]]) @@ -91,7 +104,12 @@ (:dashboard-search :dashboard-team :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}) :workspace diff --git a/frontend/src/uxbox/main/ui/dashboard.cljs b/frontend/src/uxbox/main/ui/dashboard.cljs index 90a3b02b2..a1377ec4d 100644 --- a/frontend/src/uxbox/main/ui/dashboard.cljs +++ b/frontend/src/uxbox/main/ui/dashboard.cljs @@ -32,8 +32,10 @@ (defn- parse-params [route profile] (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]) - 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-> {:search-term search-term} @@ -48,14 +50,21 @@ (and (= "drafts" project-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 [{:keys [route] :as props}] (let [profile (mf/deref refs/profile) - section (get-in route [:data :name]) - {:keys [search-term team-id project-id]} (parse-params route profile)] + page (get-in route [:data :name]) + {:keys [search-term team-id project-id library-id library-section] :as params} + (parse-params route profile)] [:main.dashboard-main [:& messages-widget] [:section.dashboard-layout @@ -63,18 +72,24 @@ [:& profile-section {:profile profile}] [:& sidebar {:team-id team-id :project-id project-id - :search-term search-term - :section section}] + :section page}] [:div.dashboard-content - (case section + (case page :dashboard-search (mf/element search-page #js {:team-id team-id :search-term search-term}) :dashboard-team (mf/element recent-files-page #js {:team-id team-id}) - :dashboard-library - (mf/element library-page #js {:team-id team-id}) + (:dashboard-library-icons + :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 (mf/element project-page #js {:team-id team-id diff --git a/frontend/src/uxbox/main/ui/dashboard/icons.cljs b/frontend/src/uxbox/main/ui/dashboard/icons.cljs index c1df4f714..6381a39fa 100644 --- a/frontend/src/uxbox/main/ui/dashboard/icons.cljs +++ b/frontend/src/uxbox/main/ui/dashboard/icons.cljs @@ -28,357 +28,357 @@ [uxbox.util.router :as rt] [uxbox.util.time :as dt])) -;; --- Helpers & Constants - -(def +ordering-options+ - {:name "ds.ordering.by-name" - :created "ds.ordering.by-creation-date"}) - -(defn- sort-icons-by - [ordering icons] - (case ordering - :name (sort-by :name icons) - :created (reverse (sort-by :created-at icons)) - icons)) - -(defn- contains-term? - [phrase term] - {:pre [(string? phrase) - (string? term)]} - (let [term (name term)] - (str/includes? (str/lower phrase) (str/trim (str/lower term))))) - -(defn- filter-icons-by - [term icons] - (if (str/blank? term) - icons - (filter #(contains-term? (:name %) term) icons))) - -;; --- Component: Grid Header - -(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-icons 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 [collection selected?] :as props}] - (let [local (mf/use-state {}) - {:keys [id type name]} collection - editable? (= type :own) - - on-click - (fn [event] - (let [type (or type :own)] - (st/emit! (rt/nav :dashboard-icons {} {:type type :id id})))) - - - on-input-change - (fn [event] - (-> (dom/get-target event) - (dom/get-value) - (swap! local assoc :name))) - - on-cancel #(swap! local dissoc :name :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))] - (st/emit! (di/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 (or (: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])])) - - -(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-icons nil {:type :own})) - select-buitin-tab #(st/emit! (rt/nav :dashboard-icons 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-icons-title")] - - [:li {:class (when builtin? "current") - :on-click select-buitin-tab} - (t locale "ds.store-icons-title")]] - - - ;; Collections List - [:ul.library-elements - (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 -;; [: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 [locale (i18n/use-locale) - 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-icons id)))] - [:div.grid-item.add-project {:on-click on-click} - (if uploading? - [:div i/loader-pencil] - [:span (t locale "ds.icon-new")]) - [:input.upload-icon-input - {:style {:display "none"} - :multiple true - :ref input - :value "" - :accept "icon/svg+xml" - :type "file" - :on-change on-select}]])) - -;; --- Grid Item - -(mf/defc grid-item - [{:keys [icon selected? edition?] :as props}] - (let [toggle-selection #(st/emit! (if selected? - (di/deselect-icon (:id icon)) - (di/select-icon (:id icon)))) - on-blur - (fn [event] - (let [target (dom/get-target event) - name (dom/get-value target)] - (st/emit! (di/update-opts :edition false) - (di/rename-icon (:id icon) name)))) - - on-key-down - (fn [event] - (when (kbd/enter? event) - (on-blur event))) - - ignore-click - (fn [event] - (dom/stop-propagation event) - (dom/prevent-default event)) - - on-edit - (fn [event] - (dom/stop-propagation event) - (dom/prevent-default event) - (st/emit! (di/update-opts :edition (:id icon))))] - - [:div.grid-item.small-item.project-th - [:div.input-checkbox.check-primary - [:input {:type "checkbox" - :id (:id icon) - :on-change toggle-selection - :checked selected?}] - [:label {:for (:id icon)}]] - [:span.grid-item-icon - [:& icon/icon-svg {:shape icon}]] - [:div.item-info {:on-click ignore-click} - (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 icon)}] - [:h3 {:on-double-click on-edit} - (:name icon)]) - (str (tr "ds.uploaded-at" (dt/format (:created-at icon) "dd/MM/yyyy")))]])) - -;; --- Grid - -(def icons-iref - (-> (comp (l/key :icons) (l/lens vals)) - (l/derive st/state))) - -(mf/defc grid - [{:keys [id type collection opts] :as props}] - (let [editable? (= type :own) - icons (->> (mf/deref icons-iref) - (filter-icons-by (:filter opts "")) - (sort-icons-by (:order opts :name)))] - [:div.dashboard-grid-content - [:div.dashboard-grid-row - (when editable? - [:& grid-form {:id id :type type :uploading? (:uploading opts)}]) - - [:& chunked-list {:items icons - :initial-size 30 - :chunk-size 30 - :key (str type id (count icons))} - (fn [icon] - [:& grid-item {:icon icon - :key (:id icon) - :selected (contains? (:selected opts) (:id icon)) - :edition? (= (:edition opts) (:id icon))}])]]])) - -;; --- Content - -(def opts-iref - (-> (l/key :dashboard-icons) - (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 opts)}])])) - -;; --- 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}]])) +;; ;; --- Helpers & Constants +;; +;; (def +ordering-options+ +;; {:name "ds.ordering.by-name" +;; :created "ds.ordering.by-creation-date"}) +;; +;; (defn- sort-icons-by +;; [ordering icons] +;; (case ordering +;; :name (sort-by :name icons) +;; :created (reverse (sort-by :created-at icons)) +;; icons)) +;; +;; (defn- contains-term? +;; [phrase term] +;; {:pre [(string? phrase) +;; (string? term)]} +;; (let [term (name term)] +;; (str/includes? (str/lower phrase) (str/trim (str/lower term))))) +;; +;; (defn- filter-icons-by +;; [term icons] +;; (if (str/blank? term) +;; icons +;; (filter #(contains-term? (:name %) term) icons))) +;; +;; ;; --- Component: Grid Header +;; +;; (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-icons 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 [collection selected?] :as props}] +;; (let [local (mf/use-state {}) +;; {:keys [id type name]} collection +;; editable? (= type :own) +;; +;; on-click +;; (fn [event] +;; (let [type (or type :own)] +;; (st/emit! (rt/nav :dashboard-icons {} {:type type :id id})))) +;; +;; +;; on-input-change +;; (fn [event] +;; (-> (dom/get-target event) +;; (dom/get-value) +;; (swap! local assoc :name))) +;; +;; on-cancel #(swap! local dissoc :name :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))] +;; (st/emit! (di/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 (or (: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])])) +;; +;; +;; (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-icons nil {:type :own})) +;; select-buitin-tab #(st/emit! (rt/nav :dashboard-icons 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-icons-title")] +;; +;; [:li {:class (when builtin? "current") +;; :on-click select-buitin-tab} +;; (t locale "ds.store-icons-title")]] +;; +;; +;; ;; Collections List +;; [:ul.library-elements +;; (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 +;; ;; [: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 [locale (i18n/use-locale) +;; 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-icons id)))] +;; [:div.grid-item.add-project {:on-click on-click} +;; (if uploading? +;; [:div i/loader-pencil] +;; [:span (t locale "ds.icon-new")]) +;; [:input.upload-icon-input +;; {:style {:display "none"} +;; :multiple true +;; :ref input +;; :value "" +;; :accept "icon/svg+xml" +;; :type "file" +;; :on-change on-select}]])) +;; +;; ;; --- Grid Item +;; +;; (mf/defc grid-item +;; [{:keys [icon selected? edition?] :as props}] +;; (let [toggle-selection #(st/emit! (if selected? +;; (di/deselect-icon (:id icon)) +;; (di/select-icon (:id icon)))) +;; on-blur +;; (fn [event] +;; (let [target (dom/get-target event) +;; name (dom/get-value target)] +;; (st/emit! (di/update-opts :edition false) +;; (di/rename-icon (:id icon) name)))) +;; +;; on-key-down +;; (fn [event] +;; (when (kbd/enter? event) +;; (on-blur event))) +;; +;; ignore-click +;; (fn [event] +;; (dom/stop-propagation event) +;; (dom/prevent-default event)) +;; +;; on-edit +;; (fn [event] +;; (dom/stop-propagation event) +;; (dom/prevent-default event) +;; (st/emit! (di/update-opts :edition (:id icon))))] +;; +;; [:div.grid-item.small-item.project-th +;; [:div.input-checkbox.check-primary +;; [:input {:type "checkbox" +;; :id (:id icon) +;; :on-change toggle-selection +;; :checked selected?}] +;; [:label {:for (:id icon)}]] +;; [:span.grid-item-icon +;; [:& icon/icon-svg {:shape icon}]] +;; [:div.item-info {:on-click ignore-click} +;; (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 icon)}] +;; [:h3 {:on-double-click on-edit} +;; (:name icon)]) +;; (str (tr "ds.uploaded-at" (dt/format (:created-at icon) "dd/MM/yyyy")))]])) +;; +;; ;; --- Grid +;; +;; (def icons-iref +;; (-> (comp (l/key :icons) (l/lens vals)) +;; (l/derive st/state))) +;; +;; (mf/defc grid +;; [{:keys [id type collection opts] :as props}] +;; (let [editable? (= type :own) +;; icons (->> (mf/deref icons-iref) +;; (filter-icons-by (:filter opts "")) +;; (sort-icons-by (:order opts :name)))] +;; [:div.dashboard-grid-content +;; [:div.dashboard-grid-row +;; (when editable? +;; [:& grid-form {:id id :type type :uploading? (:uploading opts)}]) +;; +;; [:& chunked-list {:items icons +;; :initial-size 30 +;; :chunk-size 30 +;; :key (str type id (count icons))} +;; (fn [icon] +;; [:& grid-item {:icon icon +;; :key (:id icon) +;; :selected (contains? (:selected opts) (:id icon)) +;; :edition? (= (:edition opts) (:id icon))}])]]])) +;; +;; ;; --- Content +;; +;; (def opts-iref +;; (-> (l/key :dashboard-icons) +;; (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 opts)}])])) +;; +;; ;; --- 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}]])) diff --git a/frontend/src/uxbox/main/ui/dashboard/library.cljs b/frontend/src/uxbox/main/ui/dashboard/library.cljs index 5cad30fec..da4f9eaf3 100644 --- a/frontend/src/uxbox/main/ui/dashboard/library.cljs +++ b/frontend/src/uxbox/main/ui/dashboard/library.cljs @@ -12,125 +12,196 @@ (:require [lentes.core :as l] [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.main.store :as st] [uxbox.main.refs :as refs] - [uxbox.util.i18n :as i18n :refer [t tr]] [uxbox.main.ui.dashboard.components.context-menu :refer [context-menu]])) (mf/defc library-header - [{:keys [profile] :as props}] - (let [locale (i18n/use-locale)] + [{:keys [section team-id] :as props}] + (let [icons? (= section :icons) + images? (= section :images) + palettes? (= section :palettes) + locale (i18n/use-locale)] [:header#main-bar.main-bar [:h1.dashboard-title "Libraries"] [:nav.library-header-navigation - [:a.library-header-navigation-item "Icons"] - [:a.library-header-navigation-item "Images"] - [:a.library-header-navigation-item "Colors"]]])) + [:a.library-header-navigation-item + {:class-name (when icons? "current") + :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 - [] - [:aside.library-sidebar - [:button.library-sidebar-add-item - {:type "button"} - "+ New icon library"] - [:ul.library-sidebar-list - [:li.library-sidebar-list-element [:a "Ecometer"]] - [:li.library-sidebar-list-element [:a "Tipi"]] - [:li.library-sidebar-list-element [:a "Taiga (inspirational)"]] - [:li.library-sidebar-list-element [:a "DKT photo assets"]]]]) + [{:keys [section items team-id library-id]}] + (let [locale (i18n/use-locale)] + [:aside.library-sidebar + [:button.library-sidebar-add-item + {:type "button"} + (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)))} + [:a (:name item)]])]])) (mf/defc library-top-menu - [] - (let [state (mf/use-state {:is-open false})] + [{:keys [selected section]}] + (let [state (mf/use-state {:is-open false}) + locale (i18n/use-locale)] [:header.library-top-menu [: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 { :on-click #(swap! state update :is-open not)} [:span i/arrow-down]] [:& context-menu {:is-open (:is-open @state) - :options [["Rename" #(println "Rename")] - ["Delete" #(println "Delete")]]}]] + :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 "+ New icon"]]])) + [:a.btn-dashboard (t locale (str "dashboard.library.add-item." (name section)))]]])) -(mf/defc library-icon-card [] - (let [state (mf/use-state {:is-open false})] +(mf/defc library-icon-card + [{:keys [id name url content metadata]}] + (let [locale (i18n/use-locale) + state (mf/use-state {:is-open false})] [:div.library-card.library-icon [:div.input-checkbox.check-primary [:input {:type "checkbox" - :id "card" + :id (str "icon-" id) :on-change #(println "toggle-selection") #_(:checked false)}] - [:label {:for "card"}]] - [:div.library-card-image i/trash] + [:label {:for (str "icon-" id)}]] + [: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-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-menu { :on-click #(swap! state update :is-open not) } i/actions] [:& context-menu {:is-open (:is-open @state) - :options [["Delete" #(println "Delete")]]}]]])) + :options [[(t locale "ds.button.delete") #(println "Delete")]]}]]])) -(mf/defc library-image-card [] - (let [state (mf/use-state {:is-open false})] +(mf/defc library-image-card + [{:keys [id name url]}] + (let [locale (i18n/use-locale) + state (mf/use-state {:is-open false})] [:div.library-card.library-image [:div.input-checkbox.check-primary [:input {:type "checkbox" - :id "card" + :id (str "image-" id) :on-change #(println "toggle-selection") #_(:checked false)}] - [:label {:for "card"}]] + [:label {:for (str "image-" id)}]] [:div.library-card-image - [:img {:src "https://www.placecage.com/200/200"}]] + [:img {:src url}]] [: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-menu { :on-click #(swap! state update :is-open not) } i/actions] [:& context-menu {:is-open (:is-open @state) - :options [["Delete" #(println "Delete")]]}]]])) + :options [[(t locale "ds.button.delete") #(println "Delete")]]}]]])) -(mf/defc library-color-card [] - (let [state (mf/use-state {:is-open false})] +(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 "card" + :id (str "color-" id) :on-change #(println "toggle-selection") #_(:checked false)}] - [:label {:for "card"}]] + [:label {:for (str "color-" id)}]] [:div.library-card-image - { :style { :background-color "#9B78FF" }}] + { :style { :background-color content }}] [:div.library-card-footer - #_[:* - [: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 - [:span.library-card-footer-color-label "RGB"] - [:span.library-card-footer-color-rgb "128, 128, 128"]]] + [: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 [["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 - [{:keys [team-id]}] - [:div.library-page - [:& library-header] - [:& library-sidebar] - [:section.library-content - [:& library-top-menu] - [:div.library-page-cards-container - (for [_ (range 0 10)] - #_[:& library-icon-card] - #_[:& library-image-card] - [:& library-color-card])]]]) + [{: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 + [:& library-header {:section section :team-id team-id}] + [:& library-sidebar {:items libraries :team-id team-id :library-id library-id :section section}] + + (when library-id + [:section.library-content + [:& library-top-menu {:selected selected-library :section section}] + [: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" }] + :palettes [:& library-color-card item ])))]])])) diff --git a/frontend/src/uxbox/main/ui/dashboard/sidebar.cljs b/frontend/src/uxbox/main/ui/dashboard/sidebar.cljs index 5a28e755d..58fbc5870 100644 --- a/frontend/src/uxbox/main/ui/dashboard/sidebar.cljs +++ b/frontend/src/uxbox/main/ui/dashboard/sidebar.cljs @@ -95,7 +95,7 @@ drafts? (and (= selected-section :dashboard-project) (= selected-team-id (:default-team-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))) locale (i18n/use-locale)] [:ul.library-elements @@ -114,7 +114,7 @@ [: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")} i/icon-set [:span.element-title (t locale "dashboard.sidebar.libraries")]] diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/icons.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/icons.cljs index 1b9b474a2..1a843f4ab 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/icons.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/icons.cljs @@ -15,7 +15,7 @@ [uxbox.main.data.workspace :as dw] [uxbox.main.refs :as refs] [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.util.data :refer [read-string]] [uxbox.util.dom :as dom] @@ -40,7 +40,7 @@ (mf/defc icons-list [{:keys [collection-id] :as props}] - (let [icons (mf/deref icons/icons-iref) + (let [icons [] #_(mf/deref icons/icons-iref) ;; TODO: Fix this on-select (fn [event data] @@ -67,7 +67,7 @@ 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) on-close