mirror of
https://github.com/penpot/penpot.git
synced 2025-02-13 18:48:37 -05:00
✨ Migrate pages in the backend
This commit is contained in:
parent
e06d8e754f
commit
593d1cdd39
15 changed files with 95 additions and 62 deletions
2
backend/resources/migrations/0007.remove_version.sql
Normal file
2
backend/resources/migrations/0007.remove_version.sql
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE page
|
||||||
|
DROP COLUMN version;
|
|
@ -116,7 +116,6 @@
|
||||||
{:id id
|
{:id id
|
||||||
:file-id file-id
|
:file-id file-id
|
||||||
:name name
|
:name name
|
||||||
:version version
|
|
||||||
:ordering ordering
|
:ordering ordering
|
||||||
:data data})))
|
:data data})))
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,10 @@
|
||||||
:fn (mg/resource "migrations/0005.libraries.sql")}
|
:fn (mg/resource "migrations/0005.libraries.sql")}
|
||||||
{:desc "Initial presence tables"
|
{:desc "Initial presence tables"
|
||||||
:name "0006-presence"
|
:name "0006-presence"
|
||||||
:fn (mg/resource "migrations/0006.presence.sql")}]})
|
:fn (mg/resource "migrations/0006.presence.sql")}
|
||||||
|
{:desc "Remove version"
|
||||||
|
:name "0007.remove_version"
|
||||||
|
:fn (mg/resource "migrations/0007.remove_version.sql")}]})
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Entry point
|
;; Entry point
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
[uxbox.common.data :as d]
|
[uxbox.common.data :as d]
|
||||||
[uxbox.common.exceptions :as ex]
|
[uxbox.common.exceptions :as ex]
|
||||||
[uxbox.common.pages :as cp]
|
[uxbox.common.pages :as cp]
|
||||||
|
[uxbox.common.migrations :as mg]
|
||||||
[uxbox.common.spec :as us]
|
[uxbox.common.spec :as us]
|
||||||
[uxbox.common.uuid :as uuid]
|
[uxbox.common.uuid :as uuid]
|
||||||
[uxbox.config :as cfg]
|
[uxbox.config :as cfg]
|
||||||
|
@ -178,15 +179,14 @@
|
||||||
(let [sid (:session-id params)
|
(let [sid (:session-id params)
|
||||||
changes (->> (:changes params)
|
changes (->> (:changes params)
|
||||||
(mapv #(assoc % :session-id sid)))
|
(mapv #(assoc % :session-id sid)))
|
||||||
data (-> (:data page)
|
|
||||||
(blob/decode)
|
|
||||||
(cp/process-changes changes)
|
|
||||||
(blob/encode))
|
|
||||||
|
|
||||||
page (assoc page
|
page (-> page
|
||||||
:data data
|
(update :data blob/decode)
|
||||||
:revn (inc (:revn page))
|
(update :data mg/migrate-data)
|
||||||
:changes (blob/encode changes))
|
(update :data cp/process-changes changes)
|
||||||
|
(update :data blob/encode)
|
||||||
|
(update :revn inc)
|
||||||
|
(assoc :changes (blob/encode changes)))
|
||||||
|
|
||||||
chng (insert-page-change! conn page)
|
chng (insert-page-change! conn page)
|
||||||
msg {:type :page-change
|
msg {:type :page-change
|
||||||
|
@ -201,7 +201,7 @@
|
||||||
|
|
||||||
(db/update! conn :page
|
(db/update! conn :page
|
||||||
{:revn (:revn page)
|
{:revn (:revn page)
|
||||||
:data data}
|
:data (:data page)}
|
||||||
{:id (:id page)})
|
{:id (:id page)})
|
||||||
|
|
||||||
(retrieve-lagged-changes conn chng params)))
|
(retrieve-lagged-changes conn chng params)))
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
[promesa.core :as p]
|
[promesa.core :as p]
|
||||||
[uxbox.common.spec :as us]
|
[uxbox.common.spec :as us]
|
||||||
[uxbox.common.exceptions :as ex]
|
[uxbox.common.exceptions :as ex]
|
||||||
|
[uxbox.common.migrations :as mg]
|
||||||
[uxbox.db :as db]
|
[uxbox.db :as db]
|
||||||
[uxbox.services.queries :as sq]
|
[uxbox.services.queries :as sq]
|
||||||
[uxbox.services.queries.files :as files]
|
[uxbox.services.queries.files :as files]
|
||||||
|
@ -38,7 +39,8 @@
|
||||||
[{:keys [profile-id file-id] :as params}]
|
[{:keys [profile-id file-id] :as params}]
|
||||||
(db/with-atomic [conn db/pool]
|
(db/with-atomic [conn db/pool]
|
||||||
(files/check-edition-permissions! conn profile-id file-id)
|
(files/check-edition-permissions! conn profile-id file-id)
|
||||||
(retrieve-pages conn params)))
|
(->> (retrieve-pages conn params)
|
||||||
|
(mapv #(update % :data mg/migrate-data)))))
|
||||||
|
|
||||||
(def ^:private sql:pages
|
(def ^:private sql:pages
|
||||||
"select p.*
|
"select p.*
|
||||||
|
@ -64,7 +66,8 @@
|
||||||
(with-open [conn (db/open)]
|
(with-open [conn (db/open)]
|
||||||
(let [page (retrieve-page conn id)]
|
(let [page (retrieve-page conn id)]
|
||||||
(files/check-edition-permissions! conn profile-id (:file-id page))
|
(files/check-edition-permissions! conn profile-id (:file-id page))
|
||||||
page)))
|
(-> page
|
||||||
|
(update :data mg/migrate-data)))))
|
||||||
|
|
||||||
(def ^:private sql:page
|
(def ^:private sql:page
|
||||||
"select p.* from page as p where id=?")
|
"select p.* from page as p where id=?")
|
||||||
|
|
|
@ -9,11 +9,15 @@
|
||||||
[cognitect.transit :as t]
|
[cognitect.transit :as t]
|
||||||
[clojure.java.io :as io]
|
[clojure.java.io :as io]
|
||||||
[uxbox.util.time :as dt]
|
[uxbox.util.time :as dt]
|
||||||
[uxbox.util.data :as data])
|
[uxbox.util.data :as data]
|
||||||
|
[uxbox.common.geom.point :as gpt]
|
||||||
|
[uxbox.common.geom.matrix :as gmt])
|
||||||
(:import
|
(:import
|
||||||
java.io.ByteArrayInputStream
|
java.io.ByteArrayInputStream
|
||||||
java.io.ByteArrayOutputStream
|
java.io.ByteArrayOutputStream
|
||||||
java.io.File))
|
java.io.File
|
||||||
|
uxbox.common.geom.point.Point
|
||||||
|
uxbox.common.geom.matrix.Matrix))
|
||||||
|
|
||||||
;; --- Handlers
|
;; --- Handlers
|
||||||
|
|
||||||
|
@ -22,10 +26,36 @@
|
||||||
(constantly "file")
|
(constantly "file")
|
||||||
(fn [v] (str v))))
|
(fn [v] (str v))))
|
||||||
|
|
||||||
(def +read-handlers+ dt/+read-handlers+)
|
(def point-write-handler
|
||||||
|
(t/write-handler
|
||||||
|
(constantly "point")
|
||||||
|
(fn [v] (into {} v))))
|
||||||
|
|
||||||
|
(def point-read-handler
|
||||||
|
(t/read-handler
|
||||||
|
(fn [value]
|
||||||
|
(gpt/map->Point value))))
|
||||||
|
|
||||||
|
(def matrix-write-handler
|
||||||
|
(t/write-handler
|
||||||
|
(constantly "matrix")
|
||||||
|
(fn [v] (into {} v))))
|
||||||
|
|
||||||
|
(def matrix-read-handler
|
||||||
|
(t/read-handler
|
||||||
|
(fn [value]
|
||||||
|
(gmt/map->Matrix value))))
|
||||||
|
|
||||||
|
(def +read-handlers+
|
||||||
|
(assoc dt/+read-handlers+
|
||||||
|
"matrix" matrix-read-handler
|
||||||
|
"point" point-read-handler))
|
||||||
|
|
||||||
(def +write-handlers+
|
(def +write-handlers+
|
||||||
(assoc dt/+write-handlers+
|
(assoc dt/+write-handlers+
|
||||||
File file-write-handler))
|
File file-write-handler
|
||||||
|
Matrix matrix-write-handler
|
||||||
|
Point point-write-handler))
|
||||||
|
|
||||||
;; --- Low-Level Api
|
;; --- Low-Level Api
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@
|
||||||
(t/is (= (:name data) (:name result)))
|
(t/is (= (:name data) (:name result)))
|
||||||
(t/is (= (:data data) (:data result)))
|
(t/is (= (:data data) (:data result)))
|
||||||
(t/is (nil? (:share-token result)))
|
(t/is (nil? (:share-token result)))
|
||||||
(t/is (= 0 (:version result)))
|
|
||||||
(t/is (= 0 (:revn result))))))
|
(t/is (= 0 (:revn result))))))
|
||||||
|
|
||||||
(t/testing "generate share token"
|
(t/testing "generate share token"
|
||||||
|
|
|
@ -241,10 +241,10 @@
|
||||||
(defn shapes->rect-shape
|
(defn shapes->rect-shape
|
||||||
[shapes]
|
[shapes]
|
||||||
(let [shapes (mapv shape->rect-shape shapes)
|
(let [shapes (mapv shape->rect-shape shapes)
|
||||||
minx (transduce (map :x1) min shapes)
|
minx (transduce (map :x1) min ##Inf shapes)
|
||||||
miny (transduce (map :y1) min shapes)
|
miny (transduce (map :y1) min ##Inf shapes)
|
||||||
maxx (transduce (map :x2) max shapes)
|
maxx (transduce (map :x2) max ##-Inf shapes)
|
||||||
maxy (transduce (map :y2) max shapes)]
|
maxy (transduce (map :y2) max ##-Inf shapes)]
|
||||||
{:x1 minx
|
{:x1 minx
|
||||||
:y1 miny
|
:y1 miny
|
||||||
:x2 maxx
|
:x2 maxx
|
||||||
|
@ -270,10 +270,10 @@
|
||||||
(mapv #(transform-shape-point % shape (:transform shape (gmt/matrix))) points)))
|
(mapv #(transform-shape-point % shape (:transform shape (gmt/matrix))) points)))
|
||||||
|
|
||||||
(defn points->selrect [points]
|
(defn points->selrect [points]
|
||||||
(let [minx (transduce (map :x) min points)
|
(let [minx (transduce (map :x) min ##Inf points)
|
||||||
miny (transduce (map :y) min points)
|
miny (transduce (map :y) min ##Inf points)
|
||||||
maxx (transduce (map :x) max points)
|
maxx (transduce (map :x) max ##-Inf points)
|
||||||
maxy (transduce (map :y) max points)]
|
maxy (transduce (map :y) max ##-Inf points)]
|
||||||
{:x1 minx
|
{:x1 minx
|
||||||
:y1 miny
|
:y1 miny
|
||||||
:x2 maxx
|
:x2 maxx
|
||||||
|
@ -396,10 +396,10 @@
|
||||||
[shapes]
|
[shapes]
|
||||||
(let [xf-resolve-shape (map :selrect)
|
(let [xf-resolve-shape (map :selrect)
|
||||||
shapes (into [] xf-resolve-shape shapes)
|
shapes (into [] xf-resolve-shape shapes)
|
||||||
minx (transduce (map :x1) min shapes)
|
minx (transduce (map :x1) min ##Inf shapes)
|
||||||
miny (transduce (map :y1) min shapes)
|
miny (transduce (map :y1) min ##Inf shapes)
|
||||||
maxx (transduce (map :x2) max shapes)
|
maxx (transduce (map :x2) max ##-Inf shapes)
|
||||||
maxy (transduce (map :y2) max shapes)]
|
maxy (transduce (map :y2) max ##-Inf shapes)]
|
||||||
{:x1 minx
|
{:x1 minx
|
||||||
:y1 miny
|
:y1 miny
|
||||||
:x2 maxx
|
:x2 maxx
|
||||||
|
|
|
@ -9,24 +9,28 @@
|
||||||
|
|
||||||
(defmulti migrate :version)
|
(defmulti migrate :version)
|
||||||
|
|
||||||
(defn migrate-page
|
(defn migrate-data
|
||||||
([page from-version to-version]
|
([data from-version to-version]
|
||||||
(-> page
|
(-> data
|
||||||
(assoc :version to-version)
|
(assoc :version to-version)
|
||||||
(migrate)))
|
(migrate)))
|
||||||
|
|
||||||
([{:keys [version] :as page}]
|
([data]
|
||||||
(reduce #(migrate-page % (:version %1) %2)
|
(try
|
||||||
page
|
(reduce #(migrate-data %1 %2 (inc %2))
|
||||||
(range version (inc p/page-version)))))
|
data
|
||||||
|
(range (:version data 0) p/page-version))
|
||||||
|
|
||||||
|
;; If an error is thrown, we log the error and return the data without migrations
|
||||||
|
#?(:clj (catch Exception e (.printStackTrace e) data)
|
||||||
|
:cljs (catch :default e (.error js/console e) data)))))
|
||||||
|
|
||||||
;; Default handler, noop
|
;; Default handler, noop
|
||||||
(defmethod migrate :default [page] page)
|
(defmethod migrate :default [data] data)
|
||||||
|
|
||||||
;; -- MIGRATIONS --
|
;; -- MIGRATIONS --
|
||||||
|
|
||||||
(defmethod migrate 4 [page]
|
(defmethod migrate 4 [data]
|
||||||
(prn "Migrate " (:id page))
|
|
||||||
;; We changed the internal model of the shapes so they have their selection rect
|
;; We changed the internal model of the shapes so they have their selection rect
|
||||||
;; and the vertices
|
;; and the vertices
|
||||||
|
|
||||||
|
@ -48,16 +52,13 @@
|
||||||
(if (= (:id shape) uuid/zero)
|
(if (= (:id shape) uuid/zero)
|
||||||
shape
|
shape
|
||||||
(assoc shape :selrect (gsh/points->selrect (:points shape))))))))]
|
(assoc shape :selrect (gsh/points->selrect (:points shape))))))))]
|
||||||
(-> page
|
(-> data
|
||||||
|
|
||||||
;; We only store the version in the page data
|
|
||||||
(update :data dissoc :version )
|
|
||||||
|
|
||||||
;; Adds vertices to shapes
|
;; Adds vertices to shapes
|
||||||
(update-in [:data :objects] calculate-shape-points)
|
(update :objects calculate-shape-points)
|
||||||
|
|
||||||
;; Creates selection rects for shapes
|
;; Creates selection rects for shapes
|
||||||
(update-in [:data :objects] calculate-shape-selrects))))
|
(update :objects calculate-shape-selrects))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -248,8 +248,8 @@
|
||||||
(s/map-of uuid? ::shape))
|
(s/map-of uuid? ::shape))
|
||||||
|
|
||||||
(s/def ::data
|
(s/def ::data
|
||||||
(s/keys :req-un [::options
|
(s/keys :req-un [::version
|
||||||
::version
|
::options
|
||||||
::objects]))
|
::objects]))
|
||||||
|
|
||||||
(s/def ::attr keyword?)
|
(s/def ::attr keyword?)
|
||||||
|
@ -302,7 +302,8 @@
|
||||||
|
|
||||||
(def default-page-data
|
(def default-page-data
|
||||||
"A reference value of the empty page data."
|
"A reference value of the empty page data."
|
||||||
{:options {}
|
{:version page-version
|
||||||
|
:options {}
|
||||||
:objects
|
:objects
|
||||||
{root
|
{root
|
||||||
{:id root
|
{:id root
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
[uxbox.common.data :as d]
|
[uxbox.common.data :as d]
|
||||||
[uxbox.common.exceptions :as ex]
|
[uxbox.common.exceptions :as ex]
|
||||||
[uxbox.common.pages :as cp]
|
[uxbox.common.pages :as cp]
|
||||||
[uxbox.common.migrations :as mg]
|
|
||||||
[uxbox.common.spec :as us]
|
[uxbox.common.spec :as us]
|
||||||
[uxbox.common.uuid :as uuid]
|
[uxbox.common.uuid :as uuid]
|
||||||
[uxbox.config :as cfg]
|
[uxbox.config :as cfg]
|
||||||
|
@ -151,7 +150,6 @@
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(let [page (get-in state [:workspace-pages page-id])
|
(let [page (get-in state [:workspace-pages page-id])
|
||||||
page (mg/migrate-page page)
|
|
||||||
local (get-in state [:workspace-cache page-id] workspace-default)]
|
local (get-in state [:workspace-cache page-id] workspace-default)]
|
||||||
(-> state
|
(-> state
|
||||||
(assoc :current-page-id page-id ; mainly used by events
|
(assoc :current-page-id page-id ; mainly used by events
|
||||||
|
|
|
@ -210,8 +210,7 @@
|
||||||
params {:name name
|
params {:name name
|
||||||
:file-id file-id
|
:file-id file-id
|
||||||
:ordering ordering
|
:ordering ordering
|
||||||
:data cp/default-page-data
|
:data cp/default-page-data}]
|
||||||
:version cp/page-version}]
|
|
||||||
(->> (rp/mutation :create-page params)
|
(->> (rp/mutation :create-page params)
|
||||||
(rx/map page-created))))))
|
(rx/map page-created))))))
|
||||||
|
|
||||||
|
|
|
@ -131,15 +131,13 @@
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(let [;;shape (gsh/shape->rect-shape shape)
|
(let [initial @ms/mouse-position
|
||||||
initial @ms/mouse-position
|
|
||||||
stoper (rx/filter ms/mouse-up? stream)
|
stoper (rx/filter ms/mouse-up? stream)
|
||||||
page-id (get state :current-page-id)
|
page-id (get state :current-page-id)
|
||||||
resizing-shapes (map #(get-in state [:workspace-data page-id :objects %]) ids)
|
resizing-shapes (map #(get-in state [:workspace-data page-id :objects %]) ids)
|
||||||
layout (get state :workspace-layout)]
|
layout (get state :workspace-layout)]
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(->> ms/mouse-position
|
(->> ms/mouse-position
|
||||||
;; (rx/mapcat apply-grid-alignment)
|
|
||||||
(rx/with-latest vector ms/mouse-position-ctrl)
|
(rx/with-latest vector ms/mouse-position-ctrl)
|
||||||
(rx/map normalize-proportion-lock)
|
(rx/map normalize-proportion-lock)
|
||||||
(rx/switch-map (fn [[point :as current]]
|
(rx/switch-map (fn [[point :as current]]
|
||||||
|
|
|
@ -21,16 +21,16 @@
|
||||||
(when num (.toFixed num 2)))
|
(when num (.toFixed num 2)))
|
||||||
|
|
||||||
(mf/defc cross-point [{:keys [point zoom color]}]
|
(mf/defc cross-point [{:keys [point zoom color]}]
|
||||||
(let [width (/ 10 zoom)]
|
(let [width (/ 5 zoom)]
|
||||||
[:g.point
|
[:g.point
|
||||||
[:line {:x1 (- (:x point) 10) :y1 (- (:y point) 10)
|
[:line {:x1 (- (:x point) width) :y1 (- (:y point) width)
|
||||||
:x2 (+ (:x point) 10) :y2 (+ (:y point) 10)
|
:x2 (+ (:x point) width) :y2 (+ (:y point) width)
|
||||||
:stroke color
|
:stroke color
|
||||||
:stroke-width "1px"
|
:stroke-width "1px"
|
||||||
:stroke-opacity 0.5}]
|
:stroke-opacity 0.5}]
|
||||||
|
|
||||||
[:line {:x1 (+ (:x point) 10) :y1 (- (:y point) 10)
|
[:line {:x1 (+ (:x point) width) :y1 (- (:y point) width)
|
||||||
:x2 (- (:x point) 10) :y2 (+ (:y point) 10)
|
:x2 (- (:x point) width) :y2 (+ (:y point) width)
|
||||||
:stroke color
|
:stroke color
|
||||||
:stroke-width "1px"
|
:stroke-width "1px"
|
||||||
:stroke-opacity 0.5}]]))
|
:stroke-opacity 0.5}]]))
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
(def debug-options #{:bounding-boxes :group :events :rotation-handler :resize-handler :selection-center #_:simple-selection })
|
(def debug-options #{:bounding-boxes :group :events :rotation-handler :resize-handler :selection-center #_:simple-selection })
|
||||||
|
|
||||||
(defonce ^:dynamic *debug* (atom #{:bounding-boxes}))
|
(defonce ^:dynamic *debug* (atom #{}))
|
||||||
|
|
||||||
(defn debug-all! [] (reset! *debug* debug-options))
|
(defn debug-all! [] (reset! *debug* debug-options))
|
||||||
(defn debug-none! [] (reset! *debug* #{}))
|
(defn debug-none! [] (reset! *debug* #{}))
|
||||||
|
|
Loading…
Add table
Reference in a new issue