From a17b79da77db05c38bbe79e722c64aa00f2266b8 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Sat, 19 Mar 2016 17:47:31 +0200 Subject: [PATCH] Implement page persistence. --- src/uxbox/data/pages.cljs | 10 +-- src/uxbox/state/project.cljs | 25 ++++++ src/uxbox/ui/workspace.cljs | 145 +++++++++++++++++++++-------------- 3 files changed, 116 insertions(+), 64 deletions(-) diff --git a/src/uxbox/data/pages.cljs b/src/uxbox/data/pages.cljs index 7460ecf39..2a42d1a75 100644 --- a/src/uxbox/data/pages.cljs +++ b/src/uxbox/data/pages.cljs @@ -25,7 +25,7 @@ (defrecord PagesFetched [pages] rs/UpdateEvent (-apply-update [_ state] - (reduce stpr/assoc-page state pages))) + (reduce stpr/unpack-page state pages))) (defn pages-fetched? [v] @@ -70,7 +70,6 @@ :layout [sc/required sc/string] :width [sc/required sc/integer] :height [sc/required sc/integer] - :data [sc/required] :project [sc/required sc/uuid]}) (defn create-page @@ -106,7 +105,6 @@ {:name [sc/required sc/string] :width [sc/required sc/integer] :height [sc/required sc/integer] - :data [sc/required] :layout [sc/required sc/string]}) (defn update-page @@ -132,7 +130,6 @@ rs/WatchEvent (-apply-watch [this state s] - (println "UpdatePageMetadata" "-apply-watch") (letfn [(on-success [{page :payload}] (println "on-success") #(assoc-in % [:pages-by-id id :version] (:version page))) @@ -144,12 +141,9 @@ (rx/map on-success) (rx/catch on-failure))))) -(def ^:static +update-page-metadata-schema+ - (dissoc +update-page-schema+ :data)) - (defn update-page-metadata [data] - (sc/validate! +update-page-metadata-schema+ data) + (sc/validate! +update-page-schema+ data) (map->UpdatePageMetadata (dissoc data :data))) diff --git a/src/uxbox/state/project.cljs b/src/uxbox/state/project.cljs index ee9c750e8..605d28428 100644 --- a/src/uxbox/state/project.cljs +++ b/src/uxbox/state/project.cljs @@ -30,6 +30,31 @@ acc)) shapes shapes)))) +(defn pack-page + "Return a packed version of page object ready + for send to remore storage service." + [state id] + (let [page (get-in state [:pages-by-id id]) + xf (filter #(= (:page (second %)) id)) + shapes (into {} xf (:shapes-by-id state))] + (-> page + (assoc-in [:data :shapes] (into [] (:shapes page))) + (assoc-in [:data :shapes-by-id] shapes) + (update-in [:data] dissoc :items) + (dissoc :shapes)))) + +(defn unpack-page + "Unpacks packed page object and assocs it to the + provided state." + [state page] + (let [shapes (get-in page [:data :shapes]) + shapes-by-id (get-in page [:data :shapes-by-id]) + page (-> page + (dissoc page :data) + (assoc :shapes shapes))] + (-> state + (update :shapes-by-id merge shapes-by-id) + (assoc-page page)))) (defn dissoc-page "Remove page and all related stuff from the state." diff --git a/src/uxbox/ui/workspace.cljs b/src/uxbox/ui/workspace.cljs index 558c850bd..405ebeadc 100644 --- a/src/uxbox/ui/workspace.cljs +++ b/src/uxbox/ui/workspace.cljs @@ -1,13 +1,16 @@ (ns uxbox.ui.workspace + (:refer-clojure :exclude [dedupe]) (:require [sablono.core :as html :refer-macros [html]] [rum.core :as rum] [beicon.core :as rx] [lentes.core :as l] [uxbox.rstore :as rs] [uxbox.state :as st] + [uxbox.state.project :as stpr] [uxbox.data.workspace :as dw] [uxbox.data.projects :as dp] [uxbox.data.pages :as udp] + [uxbox.util.lens :as ul] [uxbox.util.geom.point :as gpt] [uxbox.util.data :refer (classnames)] [uxbox.ui.core :as uuc] @@ -25,6 +28,92 @@ ;; Workspace ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(defn focus-page + [id] + (as-> (ul/getter #(stpr/pack-page % id)) $ + (l/focus-atom $ st/state))) + +(defn on-page-change + [page] + (rs/emit! (udp/update-page page))) + +(defn subscribe-to-page-changes + [pageid] + (as-> (focus-page pageid) $ + (rx/from-atom $) + (rx/skip 1 $) + (rx/dedupe #(dissoc % :version) $) + (rx/debounce 1000 $) + (rx/subscribe $ on-page-change #(throw %)))) + +(defn- workspace-will-mount + [own] + (let [[projectid pageid] (:rum/props own)] + (rs/emit! (dw/initialize projectid pageid) + (dp/fetch-projects) + (udp/fetch-pages projectid)) + own)) + +(defn- workspace-did-mount + [own] + (letfn [(handle-scroll-interaction [] + (let [stoper (->> uuc/actions-s + (rx/map :type) + (rx/filter #(not= % :scroll/viewport)) + (rx/take 1)) + local (:rum/local own) + initial @uuwb/mouse-viewport-a] + (swap! local assoc :scrolling true) + (as-> uuwb/mouse-viewport-s $ + (rx/take-until stoper $) + (rx/subscribe $ #(on-scroll % initial) nil on-scroll-end)))) + + (on-scroll-end [] + (let [local (:rum/local own)] + (swap! local assoc :scrolling false))) + + (on-scroll [pt initial] + (let [{:keys [x y]} (gpt/subtract pt initial) + el (mx/get-ref-dom own "workspace-canvas") + cx (.-scrollLeft el) + cy (.-scrollTop el)] + (set! (.-scrollLeft el) (- cx x)) + (set! (.-scrollTop el) (- cy y))))] + (let [[projectid pageid] (:rum/props own) + el (mx/get-ref-dom own "workspace-canvas") + sub1 (as-> uuc/actions-s $ + (rx/map :type $) + (rx/dedupe $) + (rx/filter #(= :scroll/viewport %) $) + (rx/on-value $ handle-scroll-interaction)) + sub2 (subscribe-to-page-changes pageid)] + (set! (.-scrollLeft el) uuwb/canvas-start-scroll-x) + (set! (.-scrollTop el) uuwb/canvas-start-scroll-y) + (assoc own ::sub1 sub1 ::sub2 sub2)))) + +(defn- workspace-will-unmount + [own] + (let [sub1 (::sub1 own) + sub2 (::sub2 own)] + (.close sub1) + (.close sub2) + (dissoc own ::sub1 ::sub2))) + +(defn- workspace-transfer-state + [old-state state] + (let [[projectid pageid] (:rum/props state) + [oldprojectid oldpageid] (:rum/props old-state)] + (if (not= pageid oldpageid) + (do + (rs/emit! (dw/initialize projectid pageid)) + (.close (::sub2 old-state)) + (assoc state + ::sub1 (::sub1 old-state) + ::sub2 (subscribe-to-page-changes pageid))) + (assoc state + ::sub1 (::sub1 old-state) + ::sub2 (::sub2 old-state))))) + (defn- on-scroll [event] (let [target (.-target event) @@ -66,62 +155,6 @@ (right-sidebar)) ]]))) -(defn- workspace-will-mount - [own] - (let [[projectid pageid] (:rum/props own)] - (rs/emit! (dw/initialize projectid pageid) - (dp/fetch-projects) - (udp/fetch-pages projectid)) - own)) - -(defn- workspace-did-mount - [own] - (letfn [(handle-scroll-interaction [] - (let [stoper (->> uuc/actions-s - (rx/map :type) - (rx/filter #(not= % :scroll/viewport)) - (rx/take 1)) - local (:rum/local own) - initial @uuwb/mouse-viewport-a] - (swap! local assoc :scrolling true) - (as-> uuwb/mouse-viewport-s $ - (rx/take-until stoper $) - (rx/subscribe $ #(on-scroll % initial) nil on-scroll-end)))) - - (on-scroll-end [] - (let [local (:rum/local own)] - (swap! local assoc :scrolling false))) - - (on-scroll [pt initial] - (let [{:keys [x y]} (gpt/subtract pt initial) - el (mx/get-ref-dom own "workspace-canvas") - cx (.-scrollLeft el) - cy (.-scrollTop el)] - (set! (.-scrollLeft el) (- cx x)) - (set! (.-scrollTop el) (- cy y))))] - - (let [el (mx/get-ref-dom own "workspace-canvas") - sub (as-> uuc/actions-s $ - (rx/map :type $) - (rx/dedupe $) - (rx/filter #(= :scroll/viewport %) $) - (rx/on-value $ handle-scroll-interaction))] - (set! (.-scrollLeft el) uuwb/canvas-start-scroll-x) - (set! (.-scrollTop el) uuwb/canvas-start-scroll-y) - (assoc own ::sub sub)))) - -(defn- workspace-will-unmount - [own] - (let [unsub (::sub own)] - (unsub) - (dissoc own ::sub))) - -(defn- workspace-transfer-state - [old-state state] - (let [[projectid pageid] (:rum/props state)] - (rs/emit! (dw/initialize projectid pageid)) - (assoc state ::sub (::sub old-state)))) - (def ^:static workspace (mx/component {:render workspace-render