mirror of
https://github.com/penpot/penpot.git
synced 2025-02-23 23:35:58 -05:00
✨ Improve page options handling.
This commit is contained in:
parent
9c68877328
commit
c8298c72ea
8 changed files with 269 additions and 283 deletions
|
@ -81,7 +81,7 @@ CREATE TABLE IF NOT EXISTS project_page_snapshots (
|
|||
label text NOT NULL DEFAULT '',
|
||||
|
||||
data bytea NOT NULL,
|
||||
operations bytea NULL DEFAULT NULL
|
||||
changes bytea NULL DEFAULT NULL
|
||||
);
|
||||
|
||||
-- Indexes
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
(s/def ::data ::cp/data)
|
||||
(s/def ::user ::us/uuid)
|
||||
(s/def ::project-id ::us/uuid)
|
||||
(s/def ::metadata ::cp/metadata)
|
||||
(s/def ::ordering ::us/number)
|
||||
|
||||
;; --- Mutation: Create Page
|
||||
|
@ -36,7 +35,7 @@
|
|||
(declare create-page)
|
||||
|
||||
(s/def ::create-project-page
|
||||
(s/keys :req-un [::user ::file-id ::name ::ordering ::metadata ::data]
|
||||
(s/keys :req-un [::user ::file-id ::name ::ordering ::data]
|
||||
:opt-un [::id]))
|
||||
|
||||
(sm/defmutation ::create-project-page
|
||||
|
@ -46,15 +45,14 @@
|
|||
(create-page conn params)))
|
||||
|
||||
(defn create-page
|
||||
[conn {:keys [id user file-id name ordering data metadata] :as params}]
|
||||
[conn {:keys [id user file-id name ordering data] :as params}]
|
||||
(let [sql "insert into project_pages (id, user_id, file_id, name,
|
||||
ordering, data, metadata, version)
|
||||
values ($1, $2, $3, $4, $5, $6, $7, 0)
|
||||
ordering, data, version)
|
||||
values ($1, $2, $3, $4, $5, $6, 0)
|
||||
returning *"
|
||||
id (or id (uuid/next))
|
||||
data (blob/encode data)
|
||||
mdata (blob/encode metadata)]
|
||||
(-> (db/query-one conn [sql id user file-id name ordering data mdata])
|
||||
data (blob/encode data)]
|
||||
(-> (db/query-one conn [sql id user file-id name ordering data])
|
||||
(p/then' decode-row))))
|
||||
|
||||
;; --- Mutation: Update Page Data
|
||||
|
@ -98,11 +96,11 @@
|
|||
(p/then' su/constantly-nil))))
|
||||
|
||||
(defn- insert-page-snapshot
|
||||
[conn {:keys [user-id id version data operations]}]
|
||||
(let [sql "insert into project_page_snapshots (user_id, page_id, version, data, operations)
|
||||
[conn {:keys [user-id id version data changes]}]
|
||||
(let [sql "insert into project_page_snapshots (user_id, page_id, version, data, changes)
|
||||
values ($1, $2, $3, $4, $5)
|
||||
returning id, page_id, user_id, version, operations"]
|
||||
(db/query-one conn [sql user-id id version data operations])))
|
||||
returning id, page_id, user_id, version, changes"]
|
||||
(db/query-one conn [sql user-id id version data changes])))
|
||||
|
||||
;; --- Mutation: Rename Page
|
||||
|
||||
|
@ -129,16 +127,16 @@
|
|||
|
||||
;; --- Mutation: Update Page
|
||||
|
||||
;; A generic, Ops based (granular) page update method.
|
||||
;; A generic, Changes based (granular) page update method.
|
||||
|
||||
(s/def ::operations
|
||||
(s/def ::changes
|
||||
(s/coll-of vector? :kind vector?))
|
||||
|
||||
(s/def ::update-project-page
|
||||
(s/keys :opt-un [::id ::user ::version ::operations]))
|
||||
(s/keys :opt-un [::id ::user ::version ::changes]))
|
||||
|
||||
(declare update-project-page)
|
||||
(declare retrieve-lagged-operations)
|
||||
(declare retrieve-lagged-changes)
|
||||
|
||||
(sm/defmutation ::update-project-page
|
||||
[{:keys [id user] :as params}]
|
||||
|
@ -156,17 +154,17 @@
|
|||
:hint "The incoming version is greater that stored version."
|
||||
:context {:incoming-version (:version params)
|
||||
:stored-version (:version page)}))
|
||||
(let [ops (:operations params)
|
||||
(let [changes (:changes params)
|
||||
data (-> (:data page)
|
||||
(blob/decode)
|
||||
(cp/process-ops ops)
|
||||
(cp/process-changes changes)
|
||||
(blob/encode))
|
||||
|
||||
page (assoc page
|
||||
:user-id (:user params)
|
||||
:data data
|
||||
:version (inc (:version page))
|
||||
:operations (blob/encode ops))]
|
||||
:changes (blob/encode changes))]
|
||||
|
||||
(-> (update-page-data conn page)
|
||||
(p/then (fn [_] (insert-page-snapshot conn page)))
|
||||
|
@ -176,24 +174,24 @@
|
|||
:user-id (:user-id s)
|
||||
:page-id (:page-id s)
|
||||
:version (:version s)
|
||||
:operations ops})
|
||||
(retrieve-lagged-operations conn s params))))))))
|
||||
:changes changes})
|
||||
(retrieve-lagged-changes conn s params))))))))
|
||||
|
||||
(su/defstr sql:lagged-snapshots
|
||||
"select s.id, s.operations
|
||||
"select s.id, s.changes
|
||||
from project_page_snapshots as s
|
||||
where s.page_id = $1
|
||||
and s.version > $2")
|
||||
|
||||
(defn- retrieve-lagged-operations
|
||||
(defn- retrieve-lagged-changes
|
||||
[conn snapshot params]
|
||||
(let [sql sql:lagged-snapshots]
|
||||
(-> (db/query conn [sql (:id params) (:version params) #_(:id snapshot)])
|
||||
(p/then (fn [rows]
|
||||
{:page-id (:id params)
|
||||
:version (:version snapshot)
|
||||
:operations (into [] (comp (map decode-row)
|
||||
(map :operations)
|
||||
:changes (into [] (comp (map decode-row)
|
||||
(map :changes)
|
||||
(mapcat identity))
|
||||
rows)})))))
|
||||
|
||||
|
|
|
@ -120,9 +120,9 @@
|
|||
;; --- Helpers
|
||||
|
||||
(defn decode-row
|
||||
[{:keys [data metadata operations] :as row}]
|
||||
[{:keys [data metadata changes] :as row}]
|
||||
(when row
|
||||
(cond-> row
|
||||
data (assoc :data (blob/decode data))
|
||||
metadata (assoc :metadata (blob/decode metadata))
|
||||
operations (assoc :operations (blob/decode operations)))))
|
||||
changes (assoc :changes (blob/decode changes)))))
|
||||
|
|
|
@ -10,25 +10,83 @@
|
|||
(s/def ::name string?)
|
||||
(s/def ::type keyword?)
|
||||
|
||||
;; Metadata related
|
||||
(s/def ::grid-x-axis number?)
|
||||
(s/def ::grid-y-axis number?)
|
||||
;; Page Options
|
||||
(s/def ::grid-x number?)
|
||||
(s/def ::grid-y number?)
|
||||
(s/def ::grid-color string?)
|
||||
(s/def ::background string?)
|
||||
(s/def ::background-opacity number?)
|
||||
|
||||
(s/def ::metadata
|
||||
(s/keys :opt-un [::grid-y-axis
|
||||
::grid-x-axis
|
||||
::grid-color
|
||||
::background
|
||||
::background-opacity]))
|
||||
(s/def ::options
|
||||
(s/keys :opt-un [::grid-y
|
||||
::grid-x
|
||||
::grid-color]))
|
||||
|
||||
;; Page Data related
|
||||
(s/def ::shape
|
||||
(s/def ::blocked boolean?)
|
||||
(s/def ::collapsed boolean?)
|
||||
(s/def ::content string?)
|
||||
(s/def ::fill-color string?)
|
||||
(s/def ::fill-opacity number?)
|
||||
(s/def ::font-family string?)
|
||||
(s/def ::font-size number?)
|
||||
(s/def ::font-style string?)
|
||||
(s/def ::font-weight string?)
|
||||
(s/def ::hidden boolean?)
|
||||
(s/def ::letter-spacing number?)
|
||||
(s/def ::line-height number?)
|
||||
(s/def ::locked boolean?)
|
||||
(s/def ::page-id uuid?)
|
||||
(s/def ::proportion number?)
|
||||
(s/def ::proportion-lock boolean?)
|
||||
(s/def ::rx number?)
|
||||
(s/def ::ry number?)
|
||||
(s/def ::stroke-color string?)
|
||||
(s/def ::stroke-opacity number?)
|
||||
(s/def ::stroke-style #{:none :solid :dotted :dashed :mixed})
|
||||
(s/def ::stroke-width number?)
|
||||
(s/def ::text-align #{"left" "right" "center" "justify"})
|
||||
(s/def ::type #{:rect :path :circle :image :text :canvas})
|
||||
(s/def ::x number?)
|
||||
(s/def ::y number?)
|
||||
(s/def ::cx number?)
|
||||
(s/def ::cy number?)
|
||||
(s/def ::width number?)
|
||||
(s/def ::height number?)
|
||||
|
||||
(s/def ::shape-attrs
|
||||
(s/keys :opt-un [::blocked
|
||||
::collapsed
|
||||
::content
|
||||
::fill-color
|
||||
::fill-opacity
|
||||
::font-family
|
||||
::font-size
|
||||
::font-style
|
||||
::font-weight
|
||||
::hidden
|
||||
;; ::page-id ??
|
||||
::letter-spacing
|
||||
::line-height
|
||||
::locked
|
||||
::proportion
|
||||
::proportion-lock
|
||||
::rx ::ry
|
||||
::cx ::cy
|
||||
::x ::y
|
||||
::stroke-color
|
||||
::stroke-opacity
|
||||
::stroke-style
|
||||
::stroke-width
|
||||
::text-align
|
||||
::width ::height]))
|
||||
|
||||
(s/def ::minimal-shape
|
||||
(s/keys :req-un [::type ::name]
|
||||
:opt-un [::id]))
|
||||
|
||||
(s/def ::shape
|
||||
(s/and ::minimal-shape ::shape-attrs
|
||||
(s/keys :opt-un [::id])))
|
||||
|
||||
(s/def ::shapes (s/coll-of uuid? :kind vector?))
|
||||
(s/def ::canvas (s/coll-of uuid? :kind vector?))
|
||||
|
||||
|
@ -36,12 +94,16 @@
|
|||
(s/map-of uuid? ::shape))
|
||||
|
||||
(s/def ::data
|
||||
(s/keys :req-un [::shapes ::canvas ::shapes-by-id]))
|
||||
(s/keys :req-un [::shapes
|
||||
::canvas
|
||||
::options
|
||||
::shapes-by-id]))
|
||||
|
||||
;; Changes related
|
||||
(s/def ::attr-change
|
||||
(s/tuple #{:set} keyword? any?))
|
||||
|
||||
(s/def ::operation
|
||||
(s/def ::change
|
||||
(s/or :mod-shape (s/cat :name #(= % :mod-shape)
|
||||
:id uuid?
|
||||
:changes (s/* ::attr-change))
|
||||
|
@ -64,12 +126,12 @@
|
|||
:del-canvas (s/cat :name #(= % :del-canvas)
|
||||
:id uuid?)))
|
||||
|
||||
(s/def ::operations
|
||||
(s/coll-of ::operation :kind vector?))
|
||||
(s/def ::changes
|
||||
(s/coll-of ::change :kind vector?))
|
||||
|
||||
;; --- Operations Processing Impl
|
||||
;; --- Changes Processing Impl
|
||||
|
||||
(declare process-operation)
|
||||
(declare process-change)
|
||||
(declare process-mod-shape)
|
||||
(declare process-mod-opts)
|
||||
(declare process-mov-shape)
|
||||
|
@ -78,12 +140,12 @@
|
|||
(declare process-del-shape)
|
||||
(declare process-del-canvas)
|
||||
|
||||
(defn process-ops
|
||||
[data operations]
|
||||
(->> (s/assert ::operations operations)
|
||||
(reduce process-operation data)))
|
||||
(defn process-changes
|
||||
[data items]
|
||||
(->> (s/assert ::changes items)
|
||||
(reduce process-change data)))
|
||||
|
||||
(defn- process-operation
|
||||
(defn- process-change
|
||||
[data [op & rest]]
|
||||
(case op
|
||||
:mod-shape (process-mod-shape data rest)
|
||||
|
|
|
@ -471,26 +471,3 @@
|
|||
(assoc :workspace-page page)
|
||||
(update :pages assoc id page)
|
||||
(update :pages-data assoc id data))))))
|
||||
|
||||
;; --- Update Page
|
||||
|
||||
;; TODO: deprecated, need refactor (this is used on page options)
|
||||
(defn update-page-attrs
|
||||
[{:keys [id] :as data}]
|
||||
(s/assert ::page data)
|
||||
(ptk/reify ::update-page-attrs
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :workspace-page merge (dissoc data :id :version)))))
|
||||
|
||||
;; --- Update Page Metadata
|
||||
|
||||
;; TODO: deprecated, need refactor (this is used on page options)
|
||||
(defn update-metadata
|
||||
[id metadata]
|
||||
(s/assert ::id id)
|
||||
(s/assert ::metadata metadata)
|
||||
(reify
|
||||
ptk/UpdateEvent
|
||||
(update [this state]
|
||||
(assoc-in state [:pages id :metadata] metadata))))
|
||||
|
|
|
@ -34,89 +34,24 @@
|
|||
[uxbox.util.uuid :as uuid]
|
||||
[vendor.randomcolor]))
|
||||
|
||||
|
||||
;; TODO: temporal workaround
|
||||
(def clear-ruler nil)
|
||||
(def start-ruler nil)
|
||||
|
||||
;; --- Specs
|
||||
|
||||
(s/def ::id ::us/uuid)
|
||||
(s/def ::blocked boolean?)
|
||||
(s/def ::collapsed boolean?)
|
||||
(s/def ::content string?)
|
||||
(s/def ::fill-color string?)
|
||||
(s/def ::fill-opacity number?)
|
||||
(s/def ::font-family string?)
|
||||
(s/def ::font-size number?)
|
||||
(s/def ::font-style string?)
|
||||
(s/def ::font-weight string?)
|
||||
(s/def ::hidden boolean?)
|
||||
(s/def ::id uuid?)
|
||||
(s/def ::letter-spacing number?)
|
||||
(s/def ::line-height number?)
|
||||
(s/def ::locked boolean?)
|
||||
(s/def ::name string?)
|
||||
(s/def ::page uuid?)
|
||||
(s/def ::proportion number?)
|
||||
(s/def ::proportion-lock boolean?)
|
||||
(s/def ::rx number?)
|
||||
(s/def ::ry number?)
|
||||
(s/def ::stroke-color string?)
|
||||
(s/def ::stroke-opacity number?)
|
||||
(s/def ::stroke-style #{:none :solid :dotted :dashed :mixed})
|
||||
(s/def ::stroke-width number?)
|
||||
(s/def ::text-align #{"left" "right" "center" "justify"})
|
||||
(s/def ::type #{:rect :path :circle :image :text :canvas})
|
||||
(s/def ::x number?)
|
||||
(s/def ::y number?)
|
||||
(s/def ::cx number?)
|
||||
(s/def ::cy number?)
|
||||
(s/def ::width number?)
|
||||
(s/def ::height number?)
|
||||
|
||||
(s/def ::attributes
|
||||
(s/keys :opt-un [::blocked
|
||||
::collapsed
|
||||
::content
|
||||
::fill-color
|
||||
::fill-opacity
|
||||
::font-family
|
||||
::font-size
|
||||
::font-style
|
||||
::font-weight
|
||||
::hidden
|
||||
::letter-spacing
|
||||
::line-height
|
||||
::locked
|
||||
::proportion
|
||||
::proportion-lock
|
||||
::rx ::ry
|
||||
::cx ::cy
|
||||
::x ::y
|
||||
::stroke-color
|
||||
::stroke-opacity
|
||||
::stroke-style
|
||||
::stroke-width
|
||||
::text-align
|
||||
::width ::height]))
|
||||
|
||||
(s/def ::minimal-shape
|
||||
(s/keys :req-un [::id ::page ::type ::name]))
|
||||
|
||||
(s/def ::shape
|
||||
(s/and ::minimal-shape ::attributes))
|
||||
|
||||
(s/def ::rect-like-shape
|
||||
(s/keys :req-un [::x1 ::y1 ::x2 ::y2 ::type]))
|
||||
|
||||
(s/def ::shape-attrs ::cp/shape-attrs)
|
||||
(s/def ::set-of-uuid
|
||||
(s/every ::us/uuid :kind set?))
|
||||
(s/every uuid? :kind set?))
|
||||
|
||||
;; --- Expose inner functions
|
||||
|
||||
(defn interrupt? [e] (= e :interrupt))
|
||||
|
||||
;; --- Protocols
|
||||
|
||||
(defprotocol IAsyncChange)
|
||||
|
||||
;; --- Declarations
|
||||
|
||||
(declare fetch-users)
|
||||
|
@ -125,8 +60,8 @@
|
|||
(declare handle-pointer-send)
|
||||
(declare handle-page-snapshot)
|
||||
(declare shapes-changes-commited)
|
||||
(declare commit-shapes-changes)
|
||||
(declare async-commit-shapes-changes)
|
||||
(declare commit-changes)
|
||||
(declare commit-async-changes)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Websockets Events
|
||||
|
@ -320,19 +255,14 @@
|
|||
(watch [_ state stream]
|
||||
(let [stoper (rx/filter #(or (ptk/type? ::finalize %)
|
||||
(ptk/type? ::initialize-page %))
|
||||
stream)
|
||||
notifier (->> stream
|
||||
(rx/filter (ptk/type? ::async-commit-shapes-changes))
|
||||
(rx/debounce 500))]
|
||||
stream)]
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::async-commit-shapes-changes))
|
||||
(rx/map deref)
|
||||
(rx/mapcat identity)
|
||||
(rx/buffer-until notifier)
|
||||
(rx/map vec)
|
||||
(rx/map commit-shapes-changes)
|
||||
(rx/take-until stoper)
|
||||
(rx/finalize #(prn "FINALIZE" %)))))))
|
||||
(rx/filter #(satisfies? IAsyncChange %))
|
||||
(rx/debounce 500)
|
||||
(rx/map (constantly commit-async-changes))
|
||||
(rx/finalize #(prn "FINALIZE" %))
|
||||
(rx/take-until stoper))))))
|
||||
|
||||
|
||||
;; --- Fetch Workspace Users
|
||||
|
||||
|
@ -612,7 +542,7 @@
|
|||
|
||||
(defn add-shape
|
||||
[data]
|
||||
(s/assert ::attributes data)
|
||||
(s/assert ::shape-attrs data)
|
||||
(let [id (uuid/random)]
|
||||
(ptk/reify ::add-shape
|
||||
ptk/UpdateEvent
|
||||
|
@ -626,7 +556,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [shape (get-in state [:workspace-data :shapes-by-id id])]
|
||||
(rx/of (commit-shapes-changes [[:add-shape id shape]])
|
||||
(rx/of (commit-changes [[:add-shape id shape]])
|
||||
(select-shape id)))))))
|
||||
|
||||
(def canvas-default-attrs
|
||||
|
@ -637,7 +567,7 @@
|
|||
|
||||
(defn add-canvas
|
||||
[data]
|
||||
(s/assert ::attributes data)
|
||||
(s/assert ::shape-attrs data)
|
||||
(let [id (uuid/random)]
|
||||
(ptk/reify ::add-canvas
|
||||
ptk/UpdateEvent
|
||||
|
@ -651,7 +581,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [shape (get-in state [:workspace-data :shapes-by-id id])]
|
||||
(rx/of (commit-shapes-changes [[:add-canvas id shape]])
|
||||
(rx/of (commit-changes [[:add-canvas id shape]])
|
||||
(select-shape id)))))))
|
||||
|
||||
|
||||
|
@ -671,7 +601,7 @@
|
|||
shapes (map duplicate selected)]
|
||||
(rx/merge
|
||||
(rx/from (map (fn [s] #(impl-assoc-shape % s)) shapes))
|
||||
(rx/of (commit-shapes-changes (mapv #(vector :add-shape (:id %) %) shapes))))))))
|
||||
(rx/of (commit-changes (mapv #(vector :add-shape (:id %) %) shapes))))))))
|
||||
|
||||
;; --- Toggle shape's selection status (selected or deselected)
|
||||
|
||||
|
@ -740,8 +670,9 @@
|
|||
(defn update-shape
|
||||
[id attrs]
|
||||
(s/assert ::us/uuid id)
|
||||
(s/assert ::attributes attrs)
|
||||
(s/assert ::shape-attrs attrs)
|
||||
(ptk/reify ::update-shape
|
||||
IAsyncChange
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [shape-old (get-in state [:workspace-data :shapes-by-id id])
|
||||
|
@ -749,13 +680,23 @@
|
|||
diff (d/diff-maps shape-old shape-new)]
|
||||
(-> state
|
||||
(assoc-in [:workspace-data :shapes-by-id id] shape-new)
|
||||
(assoc ::tmp-change (into [:mod-shape id] diff)))))
|
||||
(update ::async-changes (fnil conj []) (into [:mod-shape id] diff)))))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [change (::tmp-change state)]
|
||||
(rx/of (async-commit-shapes-changes [change])
|
||||
#(dissoc state ::tmp-change))))))
|
||||
;; --- Update Page Options
|
||||
|
||||
(defn update-options
|
||||
[opts]
|
||||
(s/assert ::cp/options opts)
|
||||
(ptk/reify ::update-options
|
||||
IAsyncChange
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [opts-old (get-in state [:workspace-data :options])
|
||||
opts-new (merge opts-old opts)
|
||||
diff (d/diff-maps opts-old opts-new)]
|
||||
(-> state
|
||||
(assoc-in [:workspace-data :options] opts-new)
|
||||
(update ::async-changes (fnil conj []) (into [:mod-opts] diff)))))))
|
||||
|
||||
;; --- Update Selected Shapes attrs
|
||||
|
||||
|
@ -844,7 +785,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [selected (get-in state [:workspace-local :selected])]
|
||||
(rx/of (commit-shapes-changes (mapv #(vector :del-shape %) selected)))))))
|
||||
(rx/of (commit-changes (mapv #(vector :del-shape %) selected)))))))
|
||||
|
||||
;; --- Rename Shape
|
||||
|
||||
|
@ -858,7 +799,7 @@
|
|||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(rx/of (commit-shapes-changes [[:mod-shape id [:mod :name name]]])))))
|
||||
(rx/of (commit-changes [[:mod-shape id [:mod :name name]]])))))
|
||||
|
||||
;; --- Shape Vertical Ordering
|
||||
|
||||
|
@ -897,7 +838,6 @@
|
|||
[id index]
|
||||
(s/assert ::us/uuid id)
|
||||
(s/assert number? index)
|
||||
{:pre [(uuid? id) (number? index)]}
|
||||
(ptk/reify ::change-shape-order
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
|
@ -905,18 +845,18 @@
|
|||
shapes (into [] (remove #(= % id)) shapes)
|
||||
[before after] (split-at index shapes)
|
||||
shapes (d/concat [] before [id] after)
|
||||
operation [:mov-shape id :after (last before)]]
|
||||
change [:mov-shape id :after (last before)]]
|
||||
(-> state
|
||||
(assoc-in [:workspace-data :shapes] shapes)
|
||||
(assoc ::tmp-changes [operation]))))))
|
||||
(assoc ::tmp-shape-order-change change))))))
|
||||
|
||||
(def commit-shape-order-change
|
||||
(ptk/reify ::commit-shape-order-change
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [changes (::tmp-changes state)]
|
||||
(rx/of (commit-shapes-changes changes)
|
||||
#(dissoc state ::tmp-changes))))))
|
||||
(let [change (::tmp-shape-order-change state)]
|
||||
(rx/of #(dissoc state ::tmp-changes)
|
||||
(commit-changes [change]))))))
|
||||
|
||||
;; --- Change Canvas Order (D&D Ordering)
|
||||
|
||||
|
@ -1001,50 +941,46 @@
|
|||
diff (d/diff-maps shape-old shape-new)]
|
||||
(-> state
|
||||
(assoc-in [:workspace-data :shapes-by-id id] shape-new)
|
||||
(update ::tmp-changes (fnil conj []) (into [:mod-shape id] diff)))))]
|
||||
(update ::async-changes (fnil conj []) (into [:mod-shape id] diff)))))]
|
||||
|
||||
(ptk/reify ::materialize-temporal-modifier-in-bulk
|
||||
IAsyncChange
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(reduce process-shape state ids))
|
||||
(reduce process-shape state ids)))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [changes (::tmp-changes state)]
|
||||
(rx/of (commit-shapes-changes changes)
|
||||
#(dissoc state ::tmp-changes)))))))
|
||||
|
||||
(defn commit-shapes-changes
|
||||
[operations]
|
||||
(s/assert ::cp/operations operations)
|
||||
(ptk/reify ::commit-shapes-changes
|
||||
(defn commit-changes
|
||||
[changes]
|
||||
(s/assert ::cp/changes changes)
|
||||
(ptk/reify ::commit-changes
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [pid (get-in state [:workspace-local :page-id])
|
||||
data (get-in state [:pages-data pid])]
|
||||
(update-in state [:pages-data pid] cp/process-ops operations)))
|
||||
(update-in state [:pages-data pid] cp/process-changes changes)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [page (:workspace-page state)
|
||||
params {:id (:id page)
|
||||
:version (:version page)
|
||||
:operations operations}]
|
||||
:changes changes}]
|
||||
(->> (rp/mutation :update-project-page params)
|
||||
(rx/map shapes-changes-commited))))))
|
||||
|
||||
(defn async-commit-shapes-changes
|
||||
[operations]
|
||||
(s/assert ::cp/operations operations)
|
||||
(ptk/reify ::async-commit-shapes-changes
|
||||
cljs.core/IDeref
|
||||
(-deref [_] operations)))
|
||||
(def commit-async-changes
|
||||
(ptk/reify ::commit-async-changes
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [changes (::async-changes state)]
|
||||
(rx/of #(dissoc % ::async-changes)
|
||||
(commit-changes changes))))))
|
||||
|
||||
(s/def ::shapes-changes-commited
|
||||
(s/keys :req-un [::page-id ::version ::cp/operations]))
|
||||
(s/keys :req-un [::page-id ::version ::cp/changes]))
|
||||
|
||||
(defn shapes-changes-commited
|
||||
[{:keys [page-id version operations] :as params}]
|
||||
[{:keys [page-id version changes] :as params}]
|
||||
(s/assert ::shapes-changes-commited params)
|
||||
(ptk/reify ::shapes-changes-commited
|
||||
ptk/UpdateEvent
|
||||
|
@ -1052,8 +988,8 @@
|
|||
(-> state
|
||||
(assoc-in [:workspace-page :version] version)
|
||||
(assoc-in [:pages page-id :version] version)
|
||||
(update-in [:pages-data page-id] cp/process-ops operations)
|
||||
(update :workspace-data cp/process-ops operations)))))
|
||||
(update-in [:pages-data page-id] cp/process-changes changes)
|
||||
(update :workspace-data cp/process-changes changes)))))
|
||||
|
||||
;; --- Start shape "edition mode"
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
(:require
|
||||
[cuerdas.core :as str]
|
||||
[rumext.alpha :as mf]
|
||||
[lentes.core :as l]
|
||||
[uxbox.common.data :as d]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.constants :as c]
|
||||
[uxbox.main.data.workspace :as udw]
|
||||
|
@ -22,65 +24,83 @@
|
|||
[uxbox.util.i18n :refer [tr]]
|
||||
[uxbox.util.spec :refer [color?]]))
|
||||
|
||||
(mf/defc metadata-options
|
||||
[{:keys [page] :as props}]
|
||||
(let [metadata (:metadata page)
|
||||
;; (mf/defc metadata-options
|
||||
;; [{:keys [page] :as props}]
|
||||
;; (let [metadata (:metadata page)
|
||||
;; change-color
|
||||
;; (fn [color]
|
||||
;; #_(st/emit! (->> (assoc metadata :background color)
|
||||
;; (udp/update-metadata (:id page)))))
|
||||
;; on-color-change
|
||||
;; (fn [event]
|
||||
;; (let [value (dom/event->value event)]
|
||||
;; (change-color value)))
|
||||
|
||||
;; show-color-picker
|
||||
;; (fn [event]
|
||||
;; (let [x (.-clientX event)
|
||||
;; y (.-clientY event)
|
||||
;; props {:x x :y y
|
||||
;; :default "#ffffff"
|
||||
;; :value (:background metadata)
|
||||
;; :transparent? true
|
||||
;; :on-change change-color}]
|
||||
;; (modal/show! colorpicker-modal props)))]
|
||||
|
||||
;; [:div.element-set
|
||||
;; [:div.element-set-title (tr "workspace.options.page-measures")]
|
||||
;; [:div.element-set-content
|
||||
;; [:span (tr "workspace.options.background-color")]
|
||||
;; [:div.row-flex.color-data
|
||||
;; [:span.color-th
|
||||
;; {:style {:background-color (:background metadata "#ffffff")}
|
||||
;; :on-click show-color-picker}]
|
||||
;; [:div.color-info
|
||||
;; [:input
|
||||
;; {:on-change on-color-change
|
||||
;; :value (:background metadata "#ffffff")}]]]]]))
|
||||
|
||||
(def default-options
|
||||
"Default data for page metadata."
|
||||
{:grid-x 10
|
||||
:grid-y 10
|
||||
:grid-color "#cccccc"})
|
||||
|
||||
(def options-iref
|
||||
(-> (l/key :options)
|
||||
(l/derive refs/workspace-data)))
|
||||
|
||||
(mf/defc grid-options
|
||||
{:wrap [mf/wrap-memo]}
|
||||
[props]
|
||||
(let [options (->> (mf/deref options-iref)
|
||||
(merge default-options))
|
||||
on-x-change
|
||||
(fn [event]
|
||||
(let [value (-> (dom/get-target event)
|
||||
(dom/get-value)
|
||||
(d/parse-integer 0))]
|
||||
(st/emit! (udw/update-options {:grid-x value}))))
|
||||
|
||||
on-y-change
|
||||
(fn [event]
|
||||
(let [value (-> (dom/get-target event)
|
||||
(dom/get-value)
|
||||
(d/parse-integer 0))]
|
||||
(st/emit! (udw/update-options {:grid-y value}))))
|
||||
|
||||
change-color
|
||||
(fn [color]
|
||||
#_(st/emit! (->> (assoc metadata :background color)
|
||||
(udp/update-metadata (:id page)))))
|
||||
(st/emit! (udw/update-options {:grid-color color})))
|
||||
|
||||
on-color-change
|
||||
(fn [event]
|
||||
(let [value (dom/event->value event)]
|
||||
(let [value (-> (dom/get-target event)
|
||||
(dom/get-value))]
|
||||
(change-color value)))
|
||||
|
||||
show-color-picker
|
||||
(fn [event]
|
||||
(let [x (.-clientX event)
|
||||
y (.-clientY event)
|
||||
props {:x x :y y
|
||||
:default "#ffffff"
|
||||
:value (:background metadata)
|
||||
:transparent? true
|
||||
:on-change change-color}]
|
||||
(modal/show! colorpicker-modal props)))]
|
||||
|
||||
[:div.element-set
|
||||
[:div.element-set-title (tr "workspace.options.page-measures")]
|
||||
[:div.element-set-content
|
||||
[:span (tr "workspace.options.background-color")]
|
||||
[:div.row-flex.color-data
|
||||
[:span.color-th
|
||||
{:style {:background-color (:background metadata "#ffffff")}
|
||||
:on-click show-color-picker}]
|
||||
[:div.color-info
|
||||
[:input
|
||||
{:on-change on-color-change
|
||||
:value (:background metadata "#ffffff")}]]]]]))
|
||||
|
||||
(mf/defc grid-options
|
||||
[{:keys [page] :as props}]
|
||||
(let [metadata (:metadata page)
|
||||
metadata (merge c/page-metadata metadata)]
|
||||
(letfn [(on-x-change [event]
|
||||
#_(let [value (-> (dom/event->value event)
|
||||
(parse-int nil))]
|
||||
(st/emit! (->> (assoc metadata :grid-x-axis value)
|
||||
(udp/update-metadata (:id page))))))
|
||||
(on-y-change [event]
|
||||
#_(let [value (-> (dom/event->value event)
|
||||
(parse-int nil))]
|
||||
(st/emit! (->> (assoc metadata :grid-y-axis value)
|
||||
(udp/update-metadata (:id page))))))
|
||||
|
||||
(change-color [color]
|
||||
#_(st/emit! (->> (assoc metadata :grid-color color)
|
||||
(udp/update-metadata (:id page)))))
|
||||
(on-color-change [event]
|
||||
(let [value (dom/event->value event)]
|
||||
(change-color value)))
|
||||
|
||||
(show-color-picker [event]
|
||||
(let [x (.-clientX event)
|
||||
y (.-clientY event)
|
||||
props {:x x :y y
|
||||
|
@ -95,30 +115,23 @@
|
|||
[:span (tr "workspace.options.size")]
|
||||
[:div.row-flex
|
||||
[:div.input-element.pixels
|
||||
[:input.input-text
|
||||
{:type "number"
|
||||
:value (:grid-x-axis metadata)
|
||||
:on-change on-x-change
|
||||
:placeholder "x"}]]
|
||||
[:input.input-text {:type "number"
|
||||
:value (:grid-x options)
|
||||
:on-change on-x-change}]]
|
||||
[:div.input-element.pixels
|
||||
[:input.input-text
|
||||
{:type "number"
|
||||
:value (:grid-y-axis metadata)
|
||||
:on-change on-y-change
|
||||
:placeholder "y"}]]]
|
||||
[:input.input-text {:type "number"
|
||||
:value (:grid-y options)
|
||||
:on-change on-y-change}]]]
|
||||
[:span (tr "workspace.options.color")]
|
||||
[:div.row-flex.color-data
|
||||
[:span.color-th
|
||||
{:style {:background-color (:grid-color metadata)}
|
||||
[:span.color-th {:style {:background-color (:grid-color options)}
|
||||
:on-click show-color-picker}]
|
||||
[:div.color-info
|
||||
[:input
|
||||
{:on-change on-color-change
|
||||
:value (:grid-color metadata "#cccccc")}]]]]])))
|
||||
[:input {:on-change on-color-change
|
||||
:value (:grid-color options)}]]]]]))
|
||||
|
||||
(mf/defc options
|
||||
[{:keys [page] :as props}]
|
||||
[:div
|
||||
#_[:& metadata-options {:page page}]
|
||||
[:& grid-options {:page page}]])
|
||||
|
||||
|
|
|
@ -150,7 +150,7 @@
|
|||
shapes-by-id (:shapes-by-id data)
|
||||
shapes (map #(get shapes-by-id %) (:shapes data []))
|
||||
canvas (map #(get shapes-by-id %) (:canvas data []))]
|
||||
[:*
|
||||
[:g.shapes
|
||||
(for [item canvas]
|
||||
[:& shape-wrapper {:shape item :key (:id item)}])
|
||||
(for [item shapes]
|
||||
|
@ -285,7 +285,7 @@
|
|||
:modifiers (:modifiers local)}])]
|
||||
|
||||
(if (contains? flags :grid)
|
||||
[:& grid {:page page}])]
|
||||
[:& grid])]
|
||||
|
||||
(when (contains? flags :ruler)
|
||||
[:& ruler {:zoom zoom :ruler (:ruler local)}])
|
||||
|
|
Loading…
Add table
Reference in a new issue