mirror of
https://github.com/penpot/penpot.git
synced 2025-03-11 23:31:21 -05:00
♻️ Refactor page deletion.
This commit is contained in:
parent
b7c6204b6c
commit
d987e08461
4 changed files with 137 additions and 148 deletions
|
@ -106,16 +106,16 @@
|
||||||
(defn purge-page
|
(defn purge-page
|
||||||
"Remove page and all related stuff from the state."
|
"Remove page and all related stuff from the state."
|
||||||
[state id]
|
[state id]
|
||||||
(let [shapes (get state :shapes)]
|
(let [pid (get-in state [:pages id :project])]
|
||||||
(-> state
|
(-> state
|
||||||
|
(update-in [:projects pid :pages] #(filterv (partial not= id) %))
|
||||||
(update :pages dissoc id)
|
(update :pages dissoc id)
|
||||||
(update :packed-pages dissoc id)
|
(update :packed-pages dissoc id)
|
||||||
(assoc :shapes (reduce-kv (fn [acc k v]
|
(update :shapes (fn [shapes] (->> shapes
|
||||||
(if (= (:page v) id)
|
(map second)
|
||||||
(dissoc acc k)
|
(filter #(= (:page %) id))
|
||||||
acc))
|
(map :id)
|
||||||
shapes
|
(apply dissoc shapes)))))))
|
||||||
shapes)))))
|
|
||||||
|
|
||||||
(defn assoc-packed-page
|
(defn assoc-packed-page
|
||||||
[state {:keys [id] :as page}]
|
[state {:keys [id] :as page}]
|
||||||
|
@ -125,6 +125,8 @@
|
||||||
[state id]
|
[state id]
|
||||||
(update state :packed-pages dissoc id))
|
(update state :packed-pages dissoc id))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;; --- Pages Fetched
|
;; --- Pages Fetched
|
||||||
|
|
||||||
(deftype PagesFetched [id pages]
|
(deftype PagesFetched [id pages]
|
||||||
|
@ -138,8 +140,6 @@
|
||||||
page-ids (into [] (map :id) pages)]
|
page-ids (into [] (map :id) pages)]
|
||||||
(as-> state $
|
(as-> state $
|
||||||
(assoc-in $ [:projects id :pages] page-ids)
|
(assoc-in $ [:projects id :pages] page-ids)
|
||||||
;; TODO: this is a workaround
|
|
||||||
(assoc-in $ [:projects id :page-id] (first page-ids))
|
|
||||||
(reduce unpack-page $ pages)
|
(reduce unpack-page $ pages)
|
||||||
(reduce assoc-packed-page $ pages)))))
|
(reduce assoc-packed-page $ pages)))))
|
||||||
|
|
||||||
|
@ -168,18 +168,19 @@
|
||||||
|
|
||||||
;; --- Page Created
|
;; --- Page Created
|
||||||
|
|
||||||
(declare reorder-pages)
|
(declare rehash-pages)
|
||||||
|
|
||||||
(deftype PageCreated [data]
|
(deftype PageCreated [data]
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(-> state
|
(let [project-id (:project data)]
|
||||||
(unpack-page data)
|
(-> (update-in state [:projects project-id :pages] conj (:id data))
|
||||||
(assoc-packed-page data)))
|
(unpack-page data)
|
||||||
|
(assoc-packed-page data))))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(rx/of (reorder-pages (:project data)))))
|
(rx/of (rehash-pages (:project data)))))
|
||||||
|
|
||||||
(s/def ::page-created
|
(s/def ::page-created
|
||||||
(s/keys :req-un [::id
|
(s/keys :req-un [::id
|
||||||
|
@ -192,57 +193,66 @@
|
||||||
{:pre [(us/valid? ::page-created data)]}
|
{:pre [(us/valid? ::page-created data)]}
|
||||||
(PageCreated. data))
|
(PageCreated. data))
|
||||||
|
|
||||||
|
(defn page-created?
|
||||||
|
[o]
|
||||||
|
(instance? PageCreated o))
|
||||||
|
|
||||||
;; --- Create Page
|
;; --- Create Page
|
||||||
|
|
||||||
(deftype CreatePage [name project width height layout]
|
(s/def ::create-page-params
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [this state s]
|
|
||||||
(let [params {:name name
|
|
||||||
:project project
|
|
||||||
:data {}
|
|
||||||
:metadata {:width width
|
|
||||||
:height height
|
|
||||||
:layout layout
|
|
||||||
:order -100}}]
|
|
||||||
(->> (rp/req :create/page params)
|
|
||||||
(rx/map :payload)
|
|
||||||
(rx/map page-created)))))
|
|
||||||
|
|
||||||
(s/def ::create-page
|
|
||||||
(s/keys :req-un [::name
|
(s/keys :req-un [::name
|
||||||
::project
|
::project
|
||||||
::width
|
::width
|
||||||
::height
|
::height]))
|
||||||
::layout]))
|
|
||||||
|
|
||||||
(defn create-page
|
(defn create-page
|
||||||
[{:keys [name project width height layout] :as data}]
|
[{:keys [name project width height layout] :as data}]
|
||||||
{:pre [(us/valid? ::create-page data)]}
|
{:pre [(us/valid? ::create-page-params data)]}
|
||||||
(CreatePage. name project width height layout))
|
(reify
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [this state s]
|
||||||
|
(let [canvas {:id (uuid/random)
|
||||||
|
:name "Canvas 1"
|
||||||
|
:type :canvas
|
||||||
|
:x1 200
|
||||||
|
:y1 200
|
||||||
|
:x2 (+ 200 width)
|
||||||
|
:y2 (+ 200 height)}
|
||||||
|
metadata {:width width
|
||||||
|
:height height
|
||||||
|
:order -100}
|
||||||
|
params {:name name
|
||||||
|
:project project
|
||||||
|
:data {:shapes [canvas]}
|
||||||
|
:metadata metadata}]
|
||||||
|
(->> (rp/req :create/page params)
|
||||||
|
(rx/map :payload)
|
||||||
|
(rx/map page-created))))))
|
||||||
|
|
||||||
;; --- Page Persisted
|
;; --- Page Persisted
|
||||||
|
|
||||||
(deftype PagePersisted [data]
|
|
||||||
IDeref
|
|
||||||
(-deref [_] data)
|
|
||||||
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(let [{:keys [id version]} data]
|
|
||||||
(-> state
|
|
||||||
(assoc-in [:pages id :version] version)
|
|
||||||
(assoc-packed-page data)))))
|
|
||||||
|
|
||||||
(defn- page-persisted?
|
|
||||||
[event]
|
|
||||||
(instance? PagePersisted event))
|
|
||||||
|
|
||||||
;; TODO: add page spec
|
;; TODO: add page spec
|
||||||
|
|
||||||
(defn page-persisted
|
(defn page-persisted
|
||||||
[data]
|
[data]
|
||||||
{:pre [(map? data)]}
|
{:pre [(map? data)]}
|
||||||
(PagePersisted. data))
|
(reify
|
||||||
|
cljs.core/IDeref
|
||||||
|
(-deref [_] data)
|
||||||
|
|
||||||
|
ptk/EventType
|
||||||
|
(type [_] ::page-persisted)
|
||||||
|
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(let [{:keys [id version]} data]
|
||||||
|
(-> state
|
||||||
|
(assoc-in [:pages id :version] version)
|
||||||
|
(assoc-packed-page data))))))
|
||||||
|
|
||||||
|
(defn- page-persisted?
|
||||||
|
[event]
|
||||||
|
(= (ptk/type event) ::page-persisted))
|
||||||
|
|
||||||
;; --- Persist Page
|
;; --- Persist Page
|
||||||
|
|
||||||
|
@ -333,28 +343,27 @@
|
||||||
{:pre [(uuid? id) (us/valid? ::metadata metadata)]}
|
{:pre [(uuid? id) (us/valid? ::metadata metadata)]}
|
||||||
(UpdateMetadata. id metadata))
|
(UpdateMetadata. id metadata))
|
||||||
|
|
||||||
;; --- Reorder Pages
|
;; --- Rehash Pages
|
||||||
;;
|
;;
|
||||||
;; A post processing event that normalizes the
|
;; A post processing event that normalizes the
|
||||||
;; page order numbers after a user sorting
|
;; page order numbers after a user sorting
|
||||||
;; operation for a concrete project.
|
;; operation for a concrete project.
|
||||||
|
|
||||||
(defn reorder-pages
|
(defn rehash-pages
|
||||||
[project-id]
|
[id]
|
||||||
{:pre [(uuid? project-id)]}
|
{:pre [(uuid? id)]}
|
||||||
(reify
|
(reify
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [this state]
|
(update [this state]
|
||||||
(let [page-ids (get-in state [:projects project-id :pages])]
|
(let [page-ids (get-in state [:projects id :pages])]
|
||||||
(reduce (fn [state [index id]]
|
(reduce (fn [state [index id]]
|
||||||
(assoc-in state [:pages id :metadata :order] index))
|
(assoc-in state [:pages id :metadata :order] index))
|
||||||
;; TODO: this is workaround
|
state
|
||||||
(assoc-in state [:projects project-id :page-id] (first page-ids))
|
|
||||||
(map-indexed vector page-ids))))
|
(map-indexed vector page-ids))))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(let [page-ids (get-in state [:projects project-id :pages])]
|
(let [page-ids (get-in state [:projects id :pages])]
|
||||||
(->> (rx/from-coll page-ids)
|
(->> (rx/from-coll page-ids)
|
||||||
(rx/map persist-metadata))))))
|
(rx/map persist-metadata))))))
|
||||||
|
|
||||||
|
@ -376,39 +385,36 @@
|
||||||
;; A specialized event for persist data
|
;; A specialized event for persist data
|
||||||
;; from the update page form.
|
;; from the update page form.
|
||||||
|
|
||||||
(deftype PersistPageUpdateForm [id name width height layout]
|
(s/def ::persist-page-update-form-params
|
||||||
ptk/WatchEvent
|
(s/keys :req-un [::id ::name ::width ::height]))
|
||||||
(watch [_ state stream]
|
|
||||||
(let [page (-> (get-in state [:pages id])
|
|
||||||
(assoc-in [:name] name)
|
|
||||||
(assoc-in [:metadata :width] width)
|
|
||||||
(assoc-in [:metadata :height] height)
|
|
||||||
(assoc-in [:metadata :layout] layout))]
|
|
||||||
(rx/of (update-page id page)))))
|
|
||||||
|
|
||||||
(s/def ::persist-page-update-form
|
|
||||||
(s/keys :req-un [::name ::width ::height ::layout]))
|
|
||||||
|
|
||||||
(defn persist-page-update-form
|
(defn persist-page-update-form
|
||||||
[id {:keys [name width height layout] :as data}]
|
[{:keys [id name width height] :as data}]
|
||||||
{:pre [(uuid? id) (us/valid? ::persist-page-update-form data)]}
|
{:pre [(us/valid? ::persist-page-update-form-params data)]}
|
||||||
(PersistPageUpdateForm. id name width height layout))
|
(reify
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state stream]
|
||||||
|
(let [page (-> (get-in state [:pages id])
|
||||||
|
(assoc-in [:name] name)
|
||||||
|
(assoc-in [:metadata :width] width)
|
||||||
|
(assoc-in [:metadata :height] height))]
|
||||||
|
(rx/of (update-page id page))))))
|
||||||
|
|
||||||
|
|
||||||
;; --- Delete Page (by id)
|
;; --- Delete Page (by id)
|
||||||
|
|
||||||
(deftype DeletePage [id callback]
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state s]
|
|
||||||
(letfn [(on-success [_]
|
|
||||||
#(purge-page % id))]
|
|
||||||
(->> (rp/req :delete/page id)
|
|
||||||
(rx/map on-success)
|
|
||||||
(rx/tap callback)
|
|
||||||
(rx/filter identity)))))
|
|
||||||
|
|
||||||
(defn delete-page
|
(defn delete-page
|
||||||
([id] (DeletePage. id (constantly nil)))
|
[id]
|
||||||
([id callback] (DeletePage. id callback)))
|
{:pre [(uuid? id)]}
|
||||||
|
(reify
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(purge-page state id))
|
||||||
|
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state s]
|
||||||
|
(->> (rp/req :delete/page id)
|
||||||
|
(rx/map (constantly ::delete-completed))))))
|
||||||
|
|
||||||
;; --- Watch Page Changes
|
;; --- Watch Page Changes
|
||||||
|
|
||||||
|
|
|
@ -160,74 +160,38 @@
|
||||||
|
|
||||||
;; --- Create Project
|
;; --- Create Project
|
||||||
|
|
||||||
(defrecord CreateProject [name width height layout]
|
(s/def ::create-project-params
|
||||||
ptk/WatchEvent
|
(s/keys :req-un [::name ::udp/width ::udp/height]))
|
||||||
(watch [this state s]
|
|
||||||
(let [project-data {:name name}
|
|
||||||
page-data {:name "Page 0"
|
|
||||||
:data {}
|
|
||||||
:metadata {:width width
|
|
||||||
:height height
|
|
||||||
:layout layout
|
|
||||||
:order 0}}]
|
|
||||||
(->> (rp/req :create/project {:name name})
|
|
||||||
(rx/map :payload)
|
|
||||||
(rx/mapcat (fn [{:keys [id] :as project}]
|
|
||||||
(rp/req :create/page (assoc page-data :project id))))
|
|
||||||
(rx/map #(fetch-projects))))))
|
|
||||||
|
|
||||||
(s/def ::create-project-event
|
|
||||||
(s/keys :req-un [::name
|
|
||||||
::udp/width
|
|
||||||
::udp/height
|
|
||||||
::udp/layout]))
|
|
||||||
|
|
||||||
(defn create-project
|
(defn create-project
|
||||||
[data]
|
[{:keys [name] :as params}]
|
||||||
{:pre [(us/valid? ::create-project-event data)]}
|
{:pre [(us/valid? ::create-project-params params)]}
|
||||||
(map->CreateProject data))
|
(reify
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [this state stream]
|
||||||
|
(rx/merge
|
||||||
|
(->> (rp/req :create/project {:name name})
|
||||||
|
(rx/map :payload)
|
||||||
|
(rx/map (fn [{:keys [id] :as project}]
|
||||||
|
(udp/create-page (assoc params :project id)))))
|
||||||
|
(->> stream
|
||||||
|
(rx/filter udp/page-created?)
|
||||||
|
(rx/take 1)
|
||||||
|
(rx/map #(fetch-projects)))))))
|
||||||
|
|
||||||
;; --- Go To & Go To Page
|
;; --- Go To Project
|
||||||
|
|
||||||
(deftype GoToFirstPage [pages]
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state stream]
|
|
||||||
(let [[page & rest] (sort-by #(get-in % [:metadata :order]) pages)
|
|
||||||
params {:project (:project page)
|
|
||||||
:page (:id page)}]
|
|
||||||
(rx/of (rt/navigate :workspace/page params)))))
|
|
||||||
|
|
||||||
(defn go-to-first-page
|
|
||||||
[pages]
|
|
||||||
(GoToFirstPage. pages))
|
|
||||||
|
|
||||||
(defrecord GoTo [project-id]
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state stream]
|
|
||||||
(let [page-id (get-in state [:projects project-id :page-id])]
|
|
||||||
(if-not page-id
|
|
||||||
(rx/empty)
|
|
||||||
(let [params {:project project-id
|
|
||||||
:page page-id}]
|
|
||||||
(rx/of (rt/navigate :workspace/page params)))))))
|
|
||||||
|
|
||||||
(defrecord GoToPage [project-id page-id]
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state s]
|
|
||||||
(let [params {:project project-id
|
|
||||||
:page page-id}]
|
|
||||||
(rx/of (rt/navigate :workspace/page params)))))
|
|
||||||
|
|
||||||
(defn go-to
|
(defn go-to
|
||||||
"A shortcut event that redirects the user to the
|
[id]
|
||||||
first page of the project."
|
{:pre [(uuid? id)]}
|
||||||
([project-id]
|
(reify
|
||||||
{:pre [(uuid? project-id)]}
|
ptk/WatchEvent
|
||||||
(GoTo. project-id))
|
(watch [_ state stream]
|
||||||
([project-id page-id]
|
(let [[page & rest-pages] (get-in state [:projects id :pages])]
|
||||||
{:pre [(uuid? project-id)
|
(when page
|
||||||
(uuid? page-id)]}
|
(let [params {:project id :page page}]
|
||||||
(GoToPage. project-id page-id)))
|
(rx/of (rt/nav :workspace/page params))))))))
|
||||||
|
|
||||||
|
|
||||||
;; --- Update Opts (Filtering & Ordering)
|
;; --- Update Opts (Filtering & Ordering)
|
||||||
|
|
||||||
|
|
|
@ -899,6 +899,25 @@
|
||||||
{:pre [(uuid? id)]}
|
{:pre [(uuid? id)]}
|
||||||
(UnlockShape. id))
|
(UnlockShape. id))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Pages
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defn delete-page
|
||||||
|
[id]
|
||||||
|
{:pre [(uuid? id)]}
|
||||||
|
(reify
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state stream]
|
||||||
|
(let [pid (get-in state [:pages id :project])]
|
||||||
|
(rx/merge
|
||||||
|
(rx/of (udp/delete-page id))
|
||||||
|
(->> stream
|
||||||
|
(rx/filter #(= % ::udp/delete-completed))
|
||||||
|
(rx/map #(dp/go-to pid))
|
||||||
|
(rx/take 1)))))))
|
||||||
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Selection Rect IMPL
|
;; Selection Rect IMPL
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
|
@ -158,7 +158,7 @@
|
||||||
(def figwheel-options
|
(def figwheel-options
|
||||||
{:open-url false
|
{:open-url false
|
||||||
:pprint-config false
|
:pprint-config false
|
||||||
:load-warninged-code true
|
:load-warninged-code false
|
||||||
:auto-testing false
|
:auto-testing false
|
||||||
:css-dirs ["resources/public/css"]
|
:css-dirs ["resources/public/css"]
|
||||||
:ring-server-options {:port 3449 :host "0.0.0.0"}
|
:ring-server-options {:port 3449 :host "0.0.0.0"}
|
||||||
|
|
Loading…
Add table
Reference in a new issue