diff --git a/frontend/src/uxbox/main/data/colors.cljs b/frontend/src/uxbox/main/data/colors.cljs index cefca0b53..812844ab0 100644 --- a/frontend/src/uxbox/main/data/colors.cljs +++ b/frontend/src/uxbox/main/data/colors.cljs @@ -246,66 +246,6 @@ ;;;; 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))))) - -(declare create-color-library-result) - -(defn create-color-library - [team-id name] - (ptk/reify ::create-color-library - ptk/WatchEvent - (watch [_ state stream] - (->> (rp/mutation! :create-color-library {:team-id team-id - :name name}) - (rx/map create-color-library-result))))) - -(defn create-color-library-result [result] - (ptk/reify ::create-color-library-result - ptk/UpdateEvent - (update [_ state] - (-> state - (update-in [:library :color-libraries] #(into [result] %)))))) - (declare create-color-result) (defn create-color diff --git a/frontend/src/uxbox/main/data/icons.cljs b/frontend/src/uxbox/main/data/icons.cljs index 9866e9246..132f881fb 100644 --- a/frontend/src/uxbox/main/data/icons.cljs +++ b/frontend/src/uxbox/main/data/icons.cljs @@ -34,66 +34,6 @@ ::modified-at ::user-id])) - -(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] - (->> (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 create-icon-library-result) - -(defn create-icon-library - [team-id name] - (ptk/reify ::create-icon-library - ptk/WatchEvent - (watch [_ state stream] - (->> (rp/mutation! :create-icon-library {:team-id team-id - :name name}) - (rx/map create-icon-library-result))))) - -(defn create-icon-library-result [result] - (ptk/reify ::create-icon-library-result - ptk/UpdateEvent - (update [_ state] - (-> state - (update-in [:library :icon-libraries] #(into [result] %)))))) - ;; rename-icon-library ;; delete-icon-library diff --git a/frontend/src/uxbox/main/data/images.cljs b/frontend/src/uxbox/main/data/images.cljs index 2b8b2cb54..d9a5614a4 100644 --- a/frontend/src/uxbox/main/data/images.cljs +++ b/frontend/src/uxbox/main/data/images.cljs @@ -350,67 +350,6 @@ ;;;;;;; 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! :images {: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))))) - -(declare create-image-library-result) - -(defn create-image-library - [team-id name] - (ptk/reify ::create-image-library - ptk/WatchEvent - (watch [_ state stream] - (->> (rp/mutation! :create-image-library {:team-id team-id - :name name}) - (rx/map create-image-library-result))))) - -(defn create-image-library-result [result] - (ptk/reify ::create-image-library-result - ptk/UpdateEvent - (update [_ state] - (-> state - (update-in [:library :image-libraries] #(into [result] %)))))) - - - ;; --- Create Image (declare create-images-result) (def allowed-file-types #{"image/jpeg" "image/png"}) diff --git a/frontend/src/uxbox/main/data/library.cljs b/frontend/src/uxbox/main/data/library.cljs index 34192ed3e..1adb784dd 100644 --- a/frontend/src/uxbox/main/data/library.cljs +++ b/frontend/src/uxbox/main/data/library.cljs @@ -127,6 +127,11 @@ (defn delete-library [type library-id] (ptk/reify ::delete-library + ptk/UpdateEvent + (update [_ state] + (-> state + (assoc-in [:library :last-deleted-library] library-id))) + ptk/WatchEvent (watch [_ state stream] (let [method (case type @@ -172,4 +177,31 @@ (-> state (update-in [:library :selected-items library-id] update-fn)))))) -;; Rename library item +;; Batch delete + +(declare batch-delete-item-result) + +(defn batch-delete-item + [type library-id item-ids] + (ptk/reify ::batch-delete-item + ptk/WatchEvent + (watch [_ state stream] + (let [method (case type + :icons :delete-icon + :images :delete-image + :palettes :delete-color)] + (->> (rx/from item-ids) + (rx/flat-map #(rp/mutation! method {:id %})) + (rx/last) + (rx/map #(batch-delete-item-result type library-id item-ids))))))) + +(defn batch-delete-item-result + [type library-id item-ids] + (ptk/reify ::batch-delete-item-result + ptk/UpdateEvent + (update [_ state] + (let [item-ids-set (set item-ids) + update-fn (fn [items] + (filter #(not (item-ids-set (:id %))) items))] + (-> state + (update-in [:library :selected-items library-id] update-fn)))))) diff --git a/frontend/src/uxbox/main/ui/dashboard.cljs b/frontend/src/uxbox/main/ui/dashboard.cljs index a1377ec4d..ab0549a75 100644 --- a/frontend/src/uxbox/main/ui/dashboard.cljs +++ b/frontend/src/uxbox/main/ui/dashboard.cljs @@ -87,7 +87,8 @@ :dashboard-library-images-index :dashboard-library-palettes :dashboard-library-palettes-index) - (mf/element library-page #js {:team-id team-id + (mf/element library-page #js {:key library-id + :team-id team-id :library-id library-id :section library-section}) diff --git a/frontend/src/uxbox/main/ui/dashboard/library.cljs b/frontend/src/uxbox/main/ui/dashboard/library.cljs index d4f7ac3f2..d6b1a3e36 100644 --- a/frontend/src/uxbox/main/ui/dashboard/library.cljs +++ b/frontend/src/uxbox/main/ui/dashboard/library.cljs @@ -17,6 +17,7 @@ [uxbox.util.i18n :as i18n :refer [t tr]] [uxbox.util.color :as uc] [uxbox.util.dom :as dom] + [uxbox.util.time :as dt] [uxbox.main.data.library :as dlib] [uxbox.main.data.icons :as dico] [uxbox.main.data.images :as dimg] @@ -118,14 +119,14 @@ :on-click (fn [] (let [path (keyword (str "dashboard-library-" (name section)))] - (dico/fetch-icon-library (:id item)) + (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 %))}] ])]])) (mf/defc library-top-menu - [{:keys [selected section library-id team-id]}] + [{:keys [selected section library-id team-id on-delete-selected]}] (let [state (mf/use-state {:is-open false :editing-name false}) locale (i18n/use-locale) @@ -155,7 +156,9 @@ (st/emit! (rt/nav path {:team-id team-id}))))]]}]] [:div.library-top-menu-actions - [:a.library-top-menu-actions-delete i/trash] + [:a.library-top-menu-actions-delete + {:on-click #(when on-delete-selected (on-delete-selected))} + i/trash] (if (= section :palettes) [:button.btn-dashboard @@ -176,18 +179,25 @@ :style {:display "none"}}]])]])) (mf/defc library-icon-card - [{:keys [id name url content metadata library-id]}] - (let [locale (i18n/use-locale) - state (mf/use-state {:is-open false})] + [{:keys [item on-select on-unselect]}] + (let [{:keys [id name url content metadata library-id modified-at]} item + locale (i18n/use-locale) + state (mf/use-state {:is-open false + :selected false}) + time (dt/timeago modified-at {:locale locale}) + handle-change (fn [] + (swap! state update :selected not) + (if (:selected @state) + (when on-unselect (on-unselect id)) + (when on-select (on-select id))))] [:div.library-card.library-icon [:div.input-checkbox.check-primary [:input {:type "checkbox" :id (str "icon-" id) - :on-change #(println "toggle-selection") - #_(:checked false)}] + :on-change handle-change + :checked (:selected @state)}] [: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) @@ -195,7 +205,7 @@ [:div.library-card-footer [:div.library-card-footer-name name] - [:div.library-card-footer-timestamp "Less than 5 seconds ago"] + [:div.library-card-footer-timestamp time] [:div.library-card-footer-menu { :on-click #(swap! state update :is-open not) } i/actions] @@ -206,21 +216,28 @@ #(st/emit! (dlib/delete-item :icons library-id id))]]}]]])) (mf/defc library-image-card - [{:keys [id name thumb-uri library-id]}] - (let [locale (i18n/use-locale) - state (mf/use-state {:is-open false})] + [{:keys [item on-select on-unselect]}] + (let [{:keys [id name thumb-uri library-id modified-at]} item + locale (i18n/use-locale) + state (mf/use-state {:is-open false}) + time (dt/timeago modified-at {:locale locale}) + handle-change (fn [] + (swap! state update :selected not) + (if (:selected @state) + (when on-unselect (on-unselect id)) + (when on-select (on-select id))))] [:div.library-card.library-image [:div.input-checkbox.check-primary [:input {:type "checkbox" :id (str "image-" id) - :on-change #(println "toggle-selection") + :on-change handle-change #_(:checked false)}] [:label {:for (str "image-" id)}]] [:div.library-card-image [:img {:src thumb-uri}]] [:div.library-card-footer [:div.library-card-footer-name name] - [:div.library-card-footer-timestamp "Less than 5 seconds ago"] + [:div.library-card-footer-timestamp time] [:div.library-card-footer-menu { :on-click #(swap! state update :is-open not) } i/actions] @@ -231,32 +248,38 @@ #(st/emit! (dlib/delete-item :images library-id id))]]}]]])) (mf/defc library-color-card - [{ :keys [ id content library-id] }] - (when content - (let [locale (i18n/use-locale) - state (mf/use-state {:is-open false})] - [:div.library-card.library-color - [:div.input-checkbox.check-primary - [:input {:type "checkbox" - :id (str "color-" id) - :on-change #(println "toggle-selection") - #_(:checked false)}] - [:label {:for (str "color-" id)}]] - [:div.library-card-image - { :style { :background-color content }}] - [:div.library-card-footer - [:div.library-card-footer-name content ] - [:div.library-card-footer-color - [:span.library-card-footer-color-label "RGB"] - [:span.library-card-footer-color-rgb (str/join " " (uc/hex->rgb content))]] - [:div.library-card-footer-menu - { :on-click #(swap! state update :is-open not) } - i/actions] - [:& context-menu - {:show (:is-open @state) - :on-close #(swap! state update :is-open not) - :options [[(t locale "ds.button.delete") - #(st/emit! (dlib/delete-item :palettes library-id id))]]}]]]))) + [{:keys [item on-select on-unselect]}] + (let [{:keys [ id content library-id modified-at]} item + locale (i18n/use-locale) + state (mf/use-state {:is-open false}) + handle-change (fn [] + (swap! state update :selected not) + (if (:selected @state) + (when on-unselect (on-unselect id)) + (when on-select (on-select id))))] + (when content + [:div.library-card.library-color + [:div.input-checkbox.check-primary + [:input {:type "checkbox" + :id (str "color-" id) + :on-change handle-change + #_(:checked false)}] + [:label {:for (str "color-" id)}]] + [:div.library-card-image + { :style { :background-color content }}] + [:div.library-card-footer + [:div.library-card-footer-name content ] + [:div.library-card-footer-color + [:span.library-card-footer-color-label "RGB"] + [:span.library-card-footer-color-rgb (str/join " " (uc/hex->rgb content))]] + [:div.library-card-footer-menu + { :on-click #(swap! state update :is-open not) } + i/actions] + [:& context-menu + {:show (:is-open @state) + :on-close #(swap! state update :is-open not) + :options [[(t locale "ds.button.delete") + #(st/emit! (dlib/delete-item :palettes library-id id))]]}]]]))) (defn libraries-ref [section] (-> (comp (l/key :library) (l/key section)) @@ -266,21 +289,34 @@ (-> (comp (l/key :library) (l/key :selected-items) (l/key library-id)) (l/derive st/state))) +(def last-deleted-library-ref + (-> (comp (l/key :library) (l/key :last-deleted-library)) + (l/derive st/state))) + (mf/defc library-page [{:keys [team-id library-id section]}] - (let [libraries (mf/deref (libraries-ref section)) + (let [state (mf/use-state {:selected #{}}) + libraries (mf/deref (libraries-ref section)) 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))] - (mf/use-effect {:fn #(st/emit! (dlib/retrieve-libraries section team-id)) - :deps (mf/deps section team-id)}) - (mf/use-effect {:fn #(when library-id - (st/emit! (dlib/retrieve-library-data section library-id))) - :deps (mf/deps library-id)}) (mf/use-effect {:fn #(if (and (nil? library-id) (> (count libraries) 0)) (let [path (keyword (str "dashboard-library-" (name section)))] (st/emit! (rt/nav path {:team-id team-id :library-id (:id (first libraries))})))) - :deps (mf/deps library-id section team-id)}) + :deps (mf/deps libraries)}) + + (mf/use-effect {:fn #(if (and library-id (not (some (fn [{id :id}] (= library-id id)) libraries))) + (let [path (keyword (str "dashboard-library-" (name section) "-index"))] + (st/emit! (rt/nav path {:team-id team-id})))) + :deps (mf/deps libraries)}) + + (mf/use-effect {:fn #(st/emit! (dlib/retrieve-libraries section team-id)) + :deps (mf/deps section team-id)}) + + (mf/use-effect {:fn #(when (and library-id (not= last-deleted-library library-id)) + (st/emit! (dlib/retrieve-library-data section library-id))) + :deps (mf/deps library-id last-deleted-library)}) [:div.library-page [:& library-header {:section section :team-id team-id}] @@ -288,7 +324,14 @@ (if library-id [:section.library-content - [:& library-top-menu {:selected selected-library :section section :library-id library-id :team-id team-id}] + [:& library-top-menu + {:selected selected-library + :section section + :library-id library-id + :team-id team-id + :on-delete-selected + #(when (-> @state :selected count (> 0)) + (st/emit! (dlib/batch-delete-item section library-id (:selected @state))))}] [:* ;; TODO: Fix the chunked list #_[:& chunked-list {:items items @@ -303,11 +346,15 @@ (if (> (count items) 0) [:div.library-page-cards-container (for [item items] - (let [item (assoc item :key (:id item))] + (let [item (assoc item :key (:id item)) + props {:item item + :key (:id item) + :on-select #(swap! state update :selected conj %) + :on-unselect #(swap! state update :selected disj %)}] (case section - :icons [:& library-icon-card item] - :images [:& library-image-card item] - :palettes [:& library-color-card item ])))] + :icons [:& library-icon-card props] + :images [:& library-image-card props] + :palettes [:& library-color-card props])))] [:div.library-content-empty [:p.library-content-empty-text "You still have no elements in this library"]])]] diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs index 6e8547214..ea4cbfd3f 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs @@ -57,7 +57,6 @@ (st/emit! (dw/rename-shape (:id shape) name)) (swap! local assoc :edition false))) on-key-down (fn [event] - (js/console.log event) (when (kbd/enter? event) (on-blur event))) on-click (fn [event]