mirror of
https://github.com/penpot/penpot.git
synced 2025-08-04 19:58:23 +02:00
♻️ Refactor page options data structure
This commit is contained in:
parent
2dea0b52ed
commit
4ad4057878
41 changed files with 659 additions and 525 deletions
|
@ -741,46 +741,36 @@
|
|||
|
||||
(defn add-guide
|
||||
[file guide]
|
||||
|
||||
(let [guide (cond-> guide
|
||||
(nil? (:id guide))
|
||||
(assoc :id (uuid/next)))
|
||||
page-id (:current-page-id file)
|
||||
old-guides (or (dm/get-in file [:data :pages-index page-id :options :guides]) {})
|
||||
new-guides (assoc old-guides (:id guide) guide)]
|
||||
page-id (:current-page-id file)]
|
||||
(-> file
|
||||
(commit-change
|
||||
{:type :set-option
|
||||
{:type :set-guide
|
||||
:page-id page-id
|
||||
:option :guides
|
||||
:value new-guides})
|
||||
:id (:id guide)
|
||||
:params guide})
|
||||
(assoc :last-id (:id guide)))))
|
||||
|
||||
(defn delete-guide
|
||||
[file id]
|
||||
|
||||
(let [page-id (:current-page-id file)
|
||||
old-guides (or (dm/get-in file [:data :pages-index page-id :options :guides]) {})
|
||||
new-guides (dissoc old-guides id)]
|
||||
(-> file
|
||||
(commit-change
|
||||
{:type :set-option
|
||||
:page-id page-id
|
||||
:option :guides
|
||||
:value new-guides}))))
|
||||
(let [page-id (:current-page-id file)]
|
||||
(commit-change file
|
||||
{:type :set-guide
|
||||
:page-id page-id
|
||||
:id id
|
||||
:params nil})))
|
||||
|
||||
(defn update-guide
|
||||
[file guide]
|
||||
|
||||
(let [page-id (:current-page-id file)
|
||||
old-guides (or (dm/get-in file [:data :pages-index page-id :options :guides]) {})
|
||||
new-guides (assoc old-guides (:id guide) guide)]
|
||||
(-> file
|
||||
(commit-change
|
||||
{:type :set-option
|
||||
:page-id page-id
|
||||
:option :guides
|
||||
:value new-guides}))))
|
||||
(let [page-id (:current-page-id file)]
|
||||
(commit-change file
|
||||
{:type :set-guide
|
||||
:page-id page-id
|
||||
:id (:id guide)
|
||||
:params guide})))
|
||||
|
||||
(defn strip-image-extension [filename]
|
||||
(let [image-extensions-re #"(\.png)|(\.jpg)|(\.jpeg)|(\.webp)|(\.gif)|(\.svg)$"]
|
||||
|
|
|
@ -10,21 +10,25 @@
|
|||
[app.common.data.macros :as dm]
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.files.helpers :as cfh]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.schema.desc-native :as smd]
|
||||
[app.common.schema.generators :as sg]
|
||||
[app.common.types.color :as ctc]
|
||||
[app.common.types.colors-list :as ctcl]
|
||||
[app.common.types.component :as ctk]
|
||||
[app.common.types.components-list :as ctkl]
|
||||
[app.common.types.container :as ctn]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.common.types.grid :as ctg]
|
||||
[app.common.types.page :as ctp]
|
||||
[app.common.types.pages-list :as ctpl]
|
||||
[app.common.types.shape :as cts]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.types.typographies-list :as ctyl]
|
||||
[app.common.types.typography :as ctt]
|
||||
[app.common.uuid :as uuid]
|
||||
[clojure.set :as set]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -60,6 +64,44 @@
|
|||
[:type [:= :set-remote-synced]]
|
||||
[:remote-synced {:optional true} [:maybe :boolean]]]]])
|
||||
|
||||
(defn- set-default-grid-change-generator
|
||||
[]
|
||||
(->> (sg/elements #{:square :column :row})
|
||||
(sg/mcat (fn [type]
|
||||
(sg/fmap (fn [params]
|
||||
{:page-id (uuid/next)
|
||||
:type :mod-grid
|
||||
:grid-type type
|
||||
:params params})
|
||||
|
||||
(case type
|
||||
:square (sg/generator ctg/schema:square-params)
|
||||
:column (sg/generator ctg/schema:column-params)
|
||||
:row (sg/generator ctg/schema:column-params)))))))
|
||||
|
||||
(def schema:set-default-grid-change
|
||||
[:multi {:decode/json #(update % :grid-type keyword)
|
||||
:gen/gen (set-default-grid-change-generator)
|
||||
:dispatch :grid-type
|
||||
::smd/simplified true}
|
||||
[:square
|
||||
[:map
|
||||
[:page-id ::sm/uuid]
|
||||
[:grid-type [:and :keyword [:= :square]]]
|
||||
[:params [:maybe ctg/schema:square-params]]]]
|
||||
|
||||
[:column
|
||||
[:map
|
||||
[:page-id ::sm/uuid]
|
||||
[:grid-type [:and :keyword [:= :column]]]
|
||||
[:params [:maybe ctg/schema:column-params]]]]
|
||||
|
||||
[:row
|
||||
[:map
|
||||
[:page-id ::sm/uuid]
|
||||
[:grid-type [:and :keyword [:= :row]]]
|
||||
[:params [:maybe ctg/schema:column-params]]]]])
|
||||
|
||||
(def schema:change
|
||||
[:schema
|
||||
[:multi {:dispatch :type
|
||||
|
@ -67,13 +109,18 @@
|
|||
:decode/json #(update % :type keyword)
|
||||
::smd/simplified true}
|
||||
[:set-option
|
||||
[:map {:title "SetOptionChange"}
|
||||
[:type [:= :set-option]]
|
||||
|
||||
;; DEPRECATED: remove before 2.3 release
|
||||
;;
|
||||
;; Is still there for not cause error when event is received
|
||||
[:map {:title "SetOptionChange"}]]
|
||||
|
||||
[:set-comment-thread-position
|
||||
[:map
|
||||
[:comment-thread-id ::sm/uuid]
|
||||
[:page-id ::sm/uuid]
|
||||
[:option [:union
|
||||
[:keyword]
|
||||
[:vector {:gen/max 10} :keyword]]]
|
||||
[:value :any]]]
|
||||
[:frame-id [:maybe ::sm/uuid]]
|
||||
[:position [:maybe ::gpt/point]]]]
|
||||
|
||||
[:add-obj
|
||||
[:map {:title "AddObjChange"}
|
||||
|
@ -103,6 +150,22 @@
|
|||
[:component-id {:optional true} ::sm/uuid]
|
||||
[:ignore-touched {:optional true} :boolean]]]
|
||||
|
||||
[:set-guide
|
||||
[:map {:title "SetGuideChange"}
|
||||
[:page-id ::sm/uuid]
|
||||
[:id ::sm/uuid]
|
||||
[:params [:maybe ::ctp/guide]]]]
|
||||
|
||||
[:set-flow
|
||||
[:map {:title "SetFlowChange"}
|
||||
[:page-id ::sm/uuid]
|
||||
[:id ::sm/uuid]
|
||||
[:params [:maybe ::ctp/flow]]]]
|
||||
|
||||
;; Change used for all crud operation on persisted grid options on
|
||||
;; the page.
|
||||
[:set-default-grid schema:set-default-grid-change]
|
||||
|
||||
[:fix-obj
|
||||
[:map {:title "FixObjChange"}
|
||||
[:type [:= :fix-obj]]
|
||||
|
@ -143,7 +206,10 @@
|
|||
[:map {:title "ModPageChange"}
|
||||
[:type [:= :mod-page]]
|
||||
[:id ::sm/uuid]
|
||||
[:name :string]]]
|
||||
;; All props are optional, background can be nil because is the
|
||||
;; way to remove already set background
|
||||
[:background {:optional true} [:maybe ::ctc/rgb-color]]
|
||||
[:name {:optional true} :string]]]
|
||||
|
||||
[:mod-plugin-data
|
||||
[:map {:title "ModPagePluginData"}
|
||||
|
@ -356,14 +422,49 @@
|
|||
#?(:clj (validate-shapes! data result items))
|
||||
result))))
|
||||
|
||||
;; DEPRECATED: remove before 2.3 release
|
||||
(defmethod process-change :set-option
|
||||
[data {:keys [page-id option value]}]
|
||||
[data _]
|
||||
data)
|
||||
|
||||
;; --- Comment Threads
|
||||
|
||||
(defmethod process-change :set-comment-thread-position
|
||||
[data {:keys [page-id comment-thread-id position frame-id]}]
|
||||
(d/update-in-when data [:pages-index page-id]
|
||||
(fn [data]
|
||||
(let [path (if (seqable? option) option [option])]
|
||||
(if value
|
||||
(assoc-in data (into [:options] path) value)
|
||||
(assoc data :options (d/dissoc-in (:options data) path)))))))
|
||||
(fn [page]
|
||||
(if (and position frame-id)
|
||||
(update page :comment-thread-positions assoc
|
||||
comment-thread-id {:frame-id frame-id
|
||||
:position position})
|
||||
(update page :comment-thread-positions dissoc
|
||||
comment-thread-id)))))
|
||||
|
||||
;; --- Guides
|
||||
|
||||
(defmethod process-change :set-guide
|
||||
[data {:keys [page-id id params]}]
|
||||
(if (nil? params)
|
||||
(d/update-in-when data [:pages-index page-id] update :guides dissoc id)
|
||||
(d/update-in-when data [:pages-index page-id] update :guides assoc id params)))
|
||||
|
||||
;; --- Flows
|
||||
|
||||
(defmethod process-change :set-flow
|
||||
[data {:keys [page-id id params]}]
|
||||
(if (nil? params)
|
||||
(d/update-in-when data [:pages-index page-id] update :flows dissoc id)
|
||||
(d/update-in-when data [:pages-index page-id] update :flows assoc id params)))
|
||||
|
||||
;; --- Grids
|
||||
|
||||
(defmethod process-change :set-default-grid
|
||||
[data {:keys [page-id grid-type params]}]
|
||||
(if (nil? params)
|
||||
(d/update-in-when data [:pages-index page-id] update :default-grids dissoc grid-type)
|
||||
(d/update-in-when data [:pages-index page-id] update :default-grids assoc grid-type params)))
|
||||
|
||||
;; --- Shape / Obj
|
||||
|
||||
(defmethod process-change :add-obj
|
||||
[data {:keys [id obj page-id component-id frame-id parent-id index ignore-touched]}]
|
||||
|
@ -603,8 +704,20 @@
|
|||
(ctpl/add-page data page)))
|
||||
|
||||
(defmethod process-change :mod-page
|
||||
[data {:keys [id name]}]
|
||||
(d/update-in-when data [:pages-index id] assoc :name name))
|
||||
[data {:keys [id] :as params}]
|
||||
(d/update-in-when data [:pages-index id]
|
||||
(fn [page]
|
||||
(let [name (get params :name)
|
||||
bg (get params :background :not-found)]
|
||||
(cond-> page
|
||||
(string? name)
|
||||
(assoc :name name)
|
||||
|
||||
(string? bg)
|
||||
(assoc :background bg)
|
||||
|
||||
(nil? bg)
|
||||
(dissoc :background))))))
|
||||
|
||||
(defmethod process-change :mod-plugin-data
|
||||
[data {:keys [object-type object-id page-id namespace key value]}]
|
||||
|
@ -660,6 +773,7 @@
|
|||
[data _]
|
||||
data)
|
||||
|
||||
|
||||
;; -- Media
|
||||
|
||||
(defmethod process-change :add-media
|
||||
|
|
|
@ -135,12 +135,6 @@
|
|||
(or (contains? (meta changes) ::page-id)
|
||||
(contains? (meta changes) ::component-id))))
|
||||
|
||||
(defn- assert-page!
|
||||
[changes]
|
||||
(dm/assert!
|
||||
"Call (with-page) before using this function"
|
||||
(contains? (meta changes) ::page)))
|
||||
|
||||
(defn- assert-objects!
|
||||
[changes]
|
||||
(dm/assert!
|
||||
|
@ -195,11 +189,30 @@
|
|||
(apply-changes-local)))
|
||||
|
||||
(defn mod-page
|
||||
[changes page new-name]
|
||||
(-> changes
|
||||
(update :redo-changes conj {:type :mod-page :id (:id page) :name new-name})
|
||||
(update :undo-changes conj {:type :mod-page :id (:id page) :name (:name page)})
|
||||
(apply-changes-local)))
|
||||
([changes options]
|
||||
(let [page (::page (meta changes))]
|
||||
(mod-page changes page options)))
|
||||
|
||||
([changes page {:keys [name background]}]
|
||||
(let [change {:type :mod-page :id (:id page)}
|
||||
redo (cond-> change
|
||||
(some? name)
|
||||
(assoc :name name)
|
||||
|
||||
(some? background)
|
||||
(assoc :background background))
|
||||
|
||||
undo (cond-> change
|
||||
(some? name)
|
||||
(assoc :name (:name page))
|
||||
|
||||
(some? background)
|
||||
(assoc :background (:background page)))]
|
||||
|
||||
(-> changes
|
||||
(update :redo-changes conj redo)
|
||||
(update :undo-changes conj undo)
|
||||
(apply-changes-local)))))
|
||||
|
||||
(defn mod-plugin-data
|
||||
([changes namespace key value]
|
||||
|
@ -246,42 +259,77 @@
|
|||
(update :undo-changes conj {:type :mov-page :id page-id :index prev-index})
|
||||
(apply-changes-local)))
|
||||
|
||||
(defn set-page-option
|
||||
[changes option-key option-val]
|
||||
(assert-page! changes)
|
||||
|
||||
(defn set-guide
|
||||
[changes id guide]
|
||||
(let [page-id (::page-id (meta changes))
|
||||
page (::page (meta changes))
|
||||
old-val (get-in page [:options option-key])]
|
||||
page (::page (meta changes))
|
||||
old-val (dm/get-in page [:guides id])]
|
||||
|
||||
(-> changes
|
||||
(update :redo-changes conj {:type :set-option
|
||||
(update :redo-changes conj {:type :set-guide
|
||||
:page-id page-id
|
||||
:option option-key
|
||||
:value option-val})
|
||||
(update :undo-changes conj {:type :set-option
|
||||
:id id
|
||||
:params guide})
|
||||
(update :undo-changes conj {:type :set-guide
|
||||
:page-id page-id
|
||||
:option option-key
|
||||
:value old-val})
|
||||
(apply-changes-local))))
|
||||
|
||||
(defn update-page-option
|
||||
[changes option-key update-fn & args]
|
||||
(assert-page! changes)
|
||||
:id id
|
||||
:params old-val}))))
|
||||
(defn set-flow
|
||||
[changes id flow]
|
||||
(let [page-id (::page-id (meta changes))
|
||||
page (::page (meta changes))
|
||||
old-val (get-in page [:options option-key])
|
||||
new-val (apply update-fn old-val args)]
|
||||
page (::page (meta changes))
|
||||
old-val (dm/get-in page [:flows id])
|
||||
|
||||
(-> changes
|
||||
(update :redo-changes conj {:type :set-option
|
||||
:page-id page-id
|
||||
:option option-key
|
||||
:value new-val})
|
||||
(update :undo-changes conj {:type :set-option
|
||||
:page-id page-id
|
||||
:option option-key
|
||||
:value old-val})
|
||||
(apply-changes-local))))
|
||||
changes (-> changes
|
||||
(update :redo-changes conj {:type :set-flow
|
||||
:page-id page-id
|
||||
:id id
|
||||
:params flow})
|
||||
(update :undo-changes conj {:type :set-flow
|
||||
:page-id page-id
|
||||
:id id
|
||||
:params old-val}))]
|
||||
;; FIXME: not sure if we need this
|
||||
(apply-changes-local changes)))
|
||||
|
||||
(defn set-comment-thread-position
|
||||
[changes {:keys [id frame-id position] :as thread}]
|
||||
(let [page-id (::page-id (meta changes))
|
||||
page (::page (meta changes))
|
||||
|
||||
old-val (dm/get-in page [:comment-thread-positions id])
|
||||
|
||||
changes (-> changes
|
||||
(update :redo-changes conj {:type :set-comment-thread-position
|
||||
:comment-thread-id id
|
||||
:page-id page-id
|
||||
:frame-id frame-id
|
||||
:position position})
|
||||
(update :undo-changes conj {:type :set-comment-thread-position
|
||||
:page-id page-id
|
||||
:comment-thread-id id
|
||||
:frame-id (:frame-id old-val)
|
||||
:position (:position old-val)}))]
|
||||
;; FIXME: not sure if we need this
|
||||
(apply-changes-local changes)))
|
||||
|
||||
(defn set-default-grid
|
||||
[changes type params]
|
||||
(let [page-id (::page-id (meta changes))
|
||||
page (::page (meta changes))
|
||||
old-val (dm/get-in page [:grids type])
|
||||
|
||||
changes (update changes :redo-changes conj {:type :set-default-grid
|
||||
:page-id page-id
|
||||
:grid-type type
|
||||
:params params})
|
||||
changes (update changes :undo-changes conj {:type :set-default-grid
|
||||
:page-id page-id
|
||||
:grid-type type
|
||||
:params old-val})]
|
||||
;; FIXME: not sure if we need this
|
||||
(apply-changes-local changes)))
|
||||
|
||||
;; Shape tree changes
|
||||
|
||||
|
|
|
@ -6,4 +6,4 @@
|
|||
|
||||
(ns app.common.files.defaults)
|
||||
|
||||
(def version 51)
|
||||
(def version 52)
|
||||
|
|
|
@ -1017,6 +1017,30 @@
|
|||
(into {} (filter #(-> % val valid-color?) colors)))]
|
||||
(update data :colors update-colors)))
|
||||
|
||||
(defn migrate-up-52
|
||||
"This migration moves page options to the page level"
|
||||
[data]
|
||||
(let [update-page
|
||||
(fn [{:keys [options] :as page}]
|
||||
(cond-> page
|
||||
(and (some? (:saved-grids options))
|
||||
(not (contains? page :default-grids)))
|
||||
(assoc :default-grids (:saved-grids options))
|
||||
|
||||
(and (some? (:flows options))
|
||||
(not (contains? page :flows)))
|
||||
(assoc :flows (:flows options))
|
||||
|
||||
(and (some? (:guides options))
|
||||
(not (contains? page :guides)))
|
||||
(assoc :guides (:guides options))
|
||||
|
||||
(and (some? (:comment-threads-position options))
|
||||
(not (contains? page :comment-thread-positions)))
|
||||
(assoc :comment-thread-positions (:comment-threads-position options))))]
|
||||
|
||||
(update data :pages-index d/update-vals update-page)))
|
||||
|
||||
(def migrations
|
||||
"A vector of all applicable migrations"
|
||||
[{:id 2 :migrate-up migrate-up-2}
|
||||
|
@ -1059,4 +1083,5 @@
|
|||
{:id 48 :migrate-up migrate-up-48}
|
||||
{:id 49 :migrate-up migrate-up-49}
|
||||
{:id 50 :migrate-up migrate-up-50}
|
||||
{:id 51 :migrate-up migrate-up-51}])
|
||||
{:id 51 :migrate-up migrate-up-51}
|
||||
{:id 52 :migrate-up migrate-up-52}])
|
||||
|
|
|
@ -15,10 +15,10 @@
|
|||
[old-page page check-attrs]
|
||||
|
||||
(let [old-objects (get old-page :objects)
|
||||
old-guides (or (get-in old-page [:options :guides]) [])
|
||||
old-guides (or (get old-page :guides) [])
|
||||
|
||||
new-objects (get page :objects)
|
||||
new-guides (or (get-in page [:options :guides]) [])
|
||||
new-guides (or (get page :guides) [])
|
||||
|
||||
changed-object?
|
||||
(fn [id]
|
||||
|
|
|
@ -1947,54 +1947,54 @@
|
|||
|
||||
(defn generate-duplicate-flows
|
||||
[changes shapes page ids-map]
|
||||
(let [flows (-> page :options :flows)
|
||||
unames (volatile! (into #{} (map :name flows)))
|
||||
frames-with-flow (->> shapes
|
||||
(filter #(= (:type %) :frame))
|
||||
(filter #(some? (ctp/get-frame-flow flows (:id %)))))]
|
||||
(if-not (empty? frames-with-flow)
|
||||
(let [update-flows (fn [flows]
|
||||
(reduce
|
||||
(fn [flows frame]
|
||||
(let [name (cfh/generate-unique-name @unames "Flow 1")
|
||||
_ (vswap! unames conj name)
|
||||
new-flow {:id (uuid/next)
|
||||
:name name
|
||||
:starting-frame (get ids-map (:id frame))}]
|
||||
(ctp/add-flow flows new-flow)))
|
||||
flows
|
||||
frames-with-flow))]
|
||||
(pcb/update-page-option changes :flows update-flows))
|
||||
changes)))
|
||||
(let [flows (get page :flows)
|
||||
unames (volatile! (cfh/get-used-names (vals flows)))
|
||||
has-flow? (partial ctp/get-frame-flow flows)]
|
||||
|
||||
(reduce (fn [changes frame-id]
|
||||
(let [name (cfh/generate-unique-name @unames "Flow 1")
|
||||
frame-id (get ids-map frame-id)
|
||||
flow-id (uuid/next)
|
||||
new-flow {:id flow-id
|
||||
:name name
|
||||
:starting-frame frame-id}]
|
||||
|
||||
(vswap! unames conj name)
|
||||
(pcb/set-flow changes flow-id new-flow)))
|
||||
|
||||
changes
|
||||
(->> shapes
|
||||
(filter cfh/frame-shape?)
|
||||
(map :id)
|
||||
(filter has-flow?)))))
|
||||
|
||||
(defn generate-duplicate-guides
|
||||
[changes shapes page ids-map delta]
|
||||
(let [guides (get-in page [:options :guides])
|
||||
frames (->> shapes (filter cfh/frame-shape?))
|
||||
(let [guides (get page :guides)
|
||||
frames (filter cfh/frame-shape? shapes)]
|
||||
|
||||
new-guides
|
||||
(reduce
|
||||
(fn [g frame]
|
||||
(let [new-id (ids-map (:id frame))
|
||||
new-frame (-> frame (gsh/move delta))
|
||||
;; FIXME: this can be implemented efficiently just indexing guides
|
||||
;; by frame-id instead of iterate over all guides all the time
|
||||
|
||||
new-guides
|
||||
(->> guides
|
||||
(vals)
|
||||
(filter #(= (:frame-id %) (:id frame)))
|
||||
(map #(-> %
|
||||
(assoc :id (uuid/next))
|
||||
(assoc :frame-id new-id)
|
||||
(assoc :position (if (= (:axis %) :x)
|
||||
(+ (:position %) (- (:x new-frame) (:x frame)))
|
||||
(+ (:position %) (- (:y new-frame) (:y frame))))))))]
|
||||
(cond-> g
|
||||
(not-empty new-guides)
|
||||
(conj (into {} (map (juxt :id identity) new-guides))))))
|
||||
guides
|
||||
frames)]
|
||||
(-> (pcb/with-page changes page)
|
||||
(pcb/set-page-option :guides new-guides))))
|
||||
(reduce (fn [changes frame]
|
||||
(let [new-id (get ids-map (:id frame))
|
||||
new-frame (gsh/move frame delta)]
|
||||
|
||||
(reduce-kv (fn [changes _ guide]
|
||||
(if (= (:id frame) (:frame-id guide))
|
||||
(let [guide-id (uuid/next)
|
||||
position (if (= (:axis guide) :x)
|
||||
(+ (:position guide) (- (:x new-frame) (:x frame)))
|
||||
(+ (:position guide) (- (:y new-frame) (:y frame))))
|
||||
guide {:id guide-id
|
||||
:frame-id new-id
|
||||
:position position}]
|
||||
(pcb/set-guide changes guide-id guide))
|
||||
changes))
|
||||
changes
|
||||
guides)))
|
||||
(pcb/with-page changes page)
|
||||
frames)))
|
||||
|
||||
(defn generate-duplicate-component-change
|
||||
[changes objects page component-root parent-id frame-id delta libraries library-data]
|
||||
|
|
|
@ -7,13 +7,11 @@
|
|||
(ns app.common.logic.shapes
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.files.changes-builder :as pcb]
|
||||
[app.common.files.helpers :as cfh]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.types.component :as ctk]
|
||||
[app.common.types.container :as ctn]
|
||||
[app.common.types.page :as ctp]
|
||||
[app.common.types.shape.interactions :as ctsi]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.uuid :as uuid]))
|
||||
|
@ -85,7 +83,9 @@
|
|||
(pcb/with-page page)
|
||||
(pcb/with-objects objects)
|
||||
(pcb/with-library-data file))
|
||||
|
||||
lookup (d/getf objects)
|
||||
|
||||
groups-to-unmask
|
||||
(reduce (fn [group-ids id]
|
||||
;; When the shape to delete is the mask of a masked group,
|
||||
|
@ -110,23 +110,14 @@
|
|||
interactions)))
|
||||
(vals objects))
|
||||
|
||||
ids-set (set ids-to-delete)
|
||||
guides-to-remove
|
||||
(->> (dm/get-in page [:options :guides])
|
||||
(vals)
|
||||
(filter #(contains? ids-set (:frame-id %)))
|
||||
(map :id))
|
||||
changes
|
||||
(reduce (fn [changes {:keys [id] :as flow}]
|
||||
(if (contains? ids-to-delete (:starting-frame flow))
|
||||
(pcb/set-flow changes id nil)
|
||||
changes))
|
||||
changes
|
||||
(:flows page))
|
||||
|
||||
guides
|
||||
(->> guides-to-remove
|
||||
(reduce dissoc (dm/get-in page [:options :guides])))
|
||||
|
||||
starting-flows
|
||||
(filter (fn [flow]
|
||||
;; If any of the deleted is a frame that starts a flow,
|
||||
;; this must be deleted, too.
|
||||
(contains? ids-to-delete (:starting-frame flow)))
|
||||
(-> page :options :flows))
|
||||
|
||||
all-parents
|
||||
(reduce (fn [res id]
|
||||
|
@ -172,8 +163,18 @@
|
|||
(into ids-to-delete all-children))
|
||||
[])
|
||||
|
||||
changes (-> changes
|
||||
(pcb/set-page-option :guides guides))
|
||||
ids-set (set ids-to-delete)
|
||||
|
||||
guides-to-delete
|
||||
(->> (:guides page)
|
||||
(vals)
|
||||
(filter #(contains? ids-set (:frame-id %)))
|
||||
(map :id))
|
||||
|
||||
changes (reduce (fn [changes guide-id]
|
||||
(pcb/set-flow changes guide-id nil))
|
||||
changes
|
||||
guides-to-delete)
|
||||
|
||||
changes (reduce (fn [changes component-id]
|
||||
;; It's important to delete the component before the main instance, because we
|
||||
|
@ -181,6 +182,7 @@
|
|||
(pcb/delete-component changes component-id (:id page)))
|
||||
changes
|
||||
components-to-delete)
|
||||
|
||||
changes (-> changes
|
||||
(generate-update-shape-flags ids-to-hide objects {:hidden true})
|
||||
(pcb/remove-objects all-children {:ignore-touched true})
|
||||
|
@ -197,11 +199,7 @@
|
|||
(into []
|
||||
(remove #(and (ctsi/has-destination %)
|
||||
(contains? ids-to-delete (:destination %))))
|
||||
interactions)))))
|
||||
(cond-> (seq starting-flows)
|
||||
(pcb/update-page-option :flows (fn [flows]
|
||||
(->> (map :id starting-flows)
|
||||
(reduce ctp/remove-flow flows))))))]
|
||||
interactions))))))]
|
||||
[all-parents changes]))
|
||||
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
(ns app.common.types.grid
|
||||
(:require
|
||||
[app.common.colors :as clr]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.types.color :as ctc]))
|
||||
|
||||
|
@ -54,7 +55,7 @@
|
|||
[:display :boolean]
|
||||
[:params schema:square-params]]]])
|
||||
|
||||
(def schema:saved-grids
|
||||
(def schema:default-grids
|
||||
[:map {:title "PageGrid"}
|
||||
[:square {:optional true} ::square-params]
|
||||
[:row {:optional true} ::column-params]
|
||||
|
@ -63,4 +64,24 @@
|
|||
(sm/register! ::square-params schema:square-params)
|
||||
(sm/register! ::column-params schema:column-params)
|
||||
(sm/register! ::grid schema:grid)
|
||||
(sm/register! ::saved-grids schema:saved-grids)
|
||||
(sm/register! ::default-grids schema:default-grids)
|
||||
|
||||
(def ^:private default-square-params
|
||||
{:size 16
|
||||
:color {:color clr/info
|
||||
:opacity 0.4}})
|
||||
|
||||
(def ^:private default-layout-params
|
||||
{:size 12
|
||||
:type :stretch
|
||||
:item-length nil
|
||||
:gutter 8
|
||||
:margin 0
|
||||
:color {:color clr/default-layout
|
||||
:opacity 0.1}})
|
||||
|
||||
(def default-grid-params
|
||||
{:square default-square-params
|
||||
:column default-layout-params
|
||||
:row default-layout-params})
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
(ns app.common.types.page
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.point :as-alias gpt]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.types.color :as-alias ctc]
|
||||
[app.common.types.grid :as ctg]
|
||||
|
@ -24,38 +25,56 @@
|
|||
[:name :string]
|
||||
[:starting-frame ::sm/uuid]])
|
||||
|
||||
(def schema:flows
|
||||
[:map-of {:gen/max 2} ::sm/uuid schema:flow])
|
||||
|
||||
(def schema:guide
|
||||
[:map {:title "Guide"}
|
||||
[:id ::sm/uuid]
|
||||
[:axis [::sm/one-of #{:x :y}]]
|
||||
[:position ::sm/safe-number]
|
||||
;; FIXME: remove maybe?
|
||||
[:frame-id {:optional true} [:maybe ::sm/uuid]]])
|
||||
|
||||
(def schema:guides
|
||||
[:map-of {:gen/max 2} ::sm/uuid schema:guide])
|
||||
|
||||
(def schema:objects
|
||||
[:map-of {:gen/max 5} ::sm/uuid ::cts/shape])
|
||||
|
||||
(def schema:comment-thread-position
|
||||
[:map {:title "CommentThreadPosition"}
|
||||
[:frame-id ::sm/uuid]
|
||||
[:position ::gpt/point]])
|
||||
|
||||
(def schema:page
|
||||
[:map {:title "FilePage"}
|
||||
[:id ::sm/uuid]
|
||||
[:name :string]
|
||||
[:objects
|
||||
[:map-of {:gen/max 5} ::sm/uuid ::cts/shape]]
|
||||
[:objects schema:objects]
|
||||
[:default-grids {:optional true} ::ctg/default-grids]
|
||||
[:flows {:optional true} schema:flows]
|
||||
[:guides {:optional true} schema:guides]
|
||||
[:plugin-data {:optional true} ::ctpg/plugin-data]
|
||||
[:background {:optional true} ::ctc/rgb-color]
|
||||
|
||||
[:comment-thread-positions {:optional true}
|
||||
[:map-of ::sm/uuid schema:comment-thread-position]]
|
||||
|
||||
[:options
|
||||
[:map {:title "PageOptions"}
|
||||
[:background {:optional true} ::ctc/rgb-color]
|
||||
[:saved-grids {:optional true} ::ctg/saved-grids]
|
||||
[:flows {:optional true}
|
||||
[:vector {:gen/max 2} schema:flow]]
|
||||
[:guides {:optional true}
|
||||
[:map-of {:gen/max 2} ::sm/uuid schema:guide]]
|
||||
[:plugin-data {:optional true} ::ctpg/plugin-data]]]])
|
||||
;; DEPERECATED: remove after 2.3 release
|
||||
[:map {:title "PageOptions"}]]])
|
||||
|
||||
(sm/register! ::page schema:page)
|
||||
(sm/register! ::guide schema:guide)
|
||||
(sm/register! ::flow schema:flow)
|
||||
|
||||
(def check-page-guide!
|
||||
(sm/check-fn ::guide))
|
||||
(def valid-guide?
|
||||
(sm/lazy-validator schema:guide))
|
||||
|
||||
;; FIXME: convert to validator
|
||||
(def check-page!
|
||||
(sm/check-fn ::page))
|
||||
(sm/check-fn schema:page))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; INIT & HELPERS
|
||||
|
@ -80,25 +99,6 @@
|
|||
(assoc :id (or id (uuid/next)))
|
||||
(assoc :name (or name "Page 1"))))
|
||||
|
||||
;; --- Helpers for flow
|
||||
|
||||
(defn rename-flow
|
||||
[flow name]
|
||||
(assoc flow :name name))
|
||||
|
||||
(defn add-flow
|
||||
[flows flow]
|
||||
(conj (or flows []) flow))
|
||||
|
||||
(defn remove-flow
|
||||
[flows flow-id]
|
||||
(d/removev #(= (:id %) flow-id) flows))
|
||||
|
||||
(defn update-flow
|
||||
[flows flow-id update-fn]
|
||||
(let [index (d/index-of-pred flows #(= (:id %) flow-id))]
|
||||
(update flows index update-fn)))
|
||||
|
||||
(defn get-frame-flow
|
||||
[flows frame-id]
|
||||
(d/seek #(= (:starting-frame %) frame-id) flows))
|
||||
(d/seek #(= (:starting-frame %) frame-id) (vals flows)))
|
||||
|
|
|
@ -19,71 +19,6 @@
|
|||
(binding [ffeat/*current* #{"components/v2"}]
|
||||
(ctf/make-file-data file-id page-id)))
|
||||
|
||||
(t/deftest process-change-set-option
|
||||
(let [file-id (uuid/custom 2 2)
|
||||
page-id (uuid/custom 1 1)
|
||||
data (make-file-data file-id page-id)]
|
||||
(t/testing "Sets option single"
|
||||
(let [chg {:type :set-option
|
||||
:page-id page-id
|
||||
:option :test
|
||||
:value "test"}
|
||||
res (ch/process-changes data [chg])]
|
||||
(t/is (= "test" (get-in res [:pages-index page-id :options :test])))))
|
||||
|
||||
(t/testing "Sets option nested"
|
||||
(let [chgs [{:type :set-option
|
||||
:page-id page-id
|
||||
:option [:values :test :a]
|
||||
:value "a"}
|
||||
{:type :set-option
|
||||
:page-id page-id
|
||||
:option [:values :test :b]
|
||||
:value "b"}]
|
||||
res (ch/process-changes data chgs)]
|
||||
(t/is (= {:a "a" :b "b"}
|
||||
(get-in res [:pages-index page-id :options :values :test])))))
|
||||
|
||||
(t/testing "Remove option single"
|
||||
(let [chg {:type :set-option
|
||||
:page-id page-id
|
||||
:option :test
|
||||
:value nil}
|
||||
res (ch/process-changes data [chg])]
|
||||
(t/is (empty? (keys (get-in res [:pages-index page-id :options]))))))
|
||||
|
||||
(t/testing "Remove option nested 1"
|
||||
(let [chgs [{:type :set-option
|
||||
:page-id page-id
|
||||
:option [:values :test :a]
|
||||
:value "a"}
|
||||
{:type :set-option
|
||||
:page-id page-id
|
||||
:option [:values :test :b]
|
||||
:value "b"}
|
||||
{:type :set-option
|
||||
:page-id page-id
|
||||
:option [:values :test]
|
||||
:value nil}]
|
||||
res (ch/process-changes data chgs)]
|
||||
(t/is (empty? (keys (get-in res [:pages-index page-id :options]))))))
|
||||
|
||||
(t/testing "Remove option nested 2"
|
||||
(let [chgs [{:type :set-option
|
||||
:option [:values :test1 :a]
|
||||
:page-id page-id
|
||||
:value "a"}
|
||||
{:type :set-option
|
||||
:option [:values :test2 :b]
|
||||
:page-id page-id
|
||||
:value "b"}
|
||||
{:type :set-option
|
||||
:page-id page-id
|
||||
:option [:values :test2]
|
||||
:value nil}]
|
||||
res (ch/process-changes data chgs)]
|
||||
(t/is (= [:test1] (keys (get-in res [:pages-index page-id :options :values]))))))))
|
||||
|
||||
(t/deftest process-change-add-obj
|
||||
(let [file-id (uuid/custom 2 2)
|
||||
page-id (uuid/custom 1 1)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue