0
Fork 0
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:
Andrey Antukh 2019-08-26 21:42:12 +02:00
parent b7c6204b6c
commit d987e08461
4 changed files with 137 additions and 148 deletions

View file

@ -106,16 +106,16 @@
(defn purge-page
"Remove page and all related stuff from the state."
[state id]
(let [shapes (get state :shapes)]
(let [pid (get-in state [:pages id :project])]
(-> state
(update-in [:projects pid :pages] #(filterv (partial not= id) %))
(update :pages dissoc id)
(update :packed-pages dissoc id)
(assoc :shapes (reduce-kv (fn [acc k v]
(if (= (:page v) id)
(dissoc acc k)
acc))
shapes
shapes)))))
(update :shapes (fn [shapes] (->> shapes
(map second)
(filter #(= (:page %) id))
(map :id)
(apply dissoc shapes)))))))
(defn assoc-packed-page
[state {:keys [id] :as page}]
@ -125,6 +125,8 @@
[state id]
(update state :packed-pages dissoc id))
;; --- Pages Fetched
(deftype PagesFetched [id pages]
@ -138,8 +140,6 @@
page-ids (into [] (map :id) pages)]
(as-> state $
(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 assoc-packed-page $ pages)))))
@ -168,18 +168,19 @@
;; --- Page Created
(declare reorder-pages)
(declare rehash-pages)
(deftype PageCreated [data]
ptk/UpdateEvent
(update [_ state]
(-> state
(let [project-id (:project data)]
(-> (update-in state [:projects project-id :pages] conj (:id data))
(unpack-page data)
(assoc-packed-page data)))
(assoc-packed-page data))))
ptk/WatchEvent
(watch [_ state stream]
(rx/of (reorder-pages (:project data)))))
(rx/of (rehash-pages (:project data)))))
(s/def ::page-created
(s/keys :req-un [::id
@ -192,57 +193,66 @@
{:pre [(us/valid? ::page-created data)]}
(PageCreated. data))
(defn page-created?
[o]
(instance? PageCreated o))
;; --- Create Page
(deftype CreatePage [name project width height layout]
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/def ::create-page-params
(s/keys :req-un [::name
::project
::width
::height
::layout]))
::height]))
(defn create-page
[{:keys [name project width height layout] :as data}]
{:pre [(us/valid? ::create-page data)]}
(CreatePage. name project width height layout))
{:pre [(us/valid? ::create-page-params data)]}
(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
(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
(defn page-persisted
[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
@ -333,28 +343,27 @@
{:pre [(uuid? id) (us/valid? ::metadata metadata)]}
(UpdateMetadata. id metadata))
;; --- Reorder Pages
;; --- Rehash Pages
;;
;; A post processing event that normalizes the
;; page order numbers after a user sorting
;; operation for a concrete project.
(defn reorder-pages
[project-id]
{:pre [(uuid? project-id)]}
(defn rehash-pages
[id]
{:pre [(uuid? id)]}
(reify
ptk/UpdateEvent
(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]]
(assoc-in state [:pages id :metadata :order] index))
;; TODO: this is workaround
(assoc-in state [:projects project-id :page-id] (first page-ids))
state
(map-indexed vector page-ids))))
ptk/WatchEvent
(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/map persist-metadata))))))
@ -376,39 +385,36 @@
;; A specialized event for persist data
;; from the update page form.
(deftype PersistPageUpdateForm [id name width height layout]
(s/def ::persist-page-update-form-params
(s/keys :req-un [::id ::name ::width ::height]))
(defn persist-page-update-form
[{:keys [id name width height] :as data}]
{:pre [(us/valid? ::persist-page-update-form-params data)]}
(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)
(assoc-in [:metadata :layout] layout))]
(rx/of (update-page id page)))))
(assoc-in [:metadata :height] height))]
(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
[id {:keys [name width height layout] :as data}]
{:pre [(uuid? id) (us/valid? ::persist-page-update-form data)]}
(PersistPageUpdateForm. id name width height layout))
;; --- Delete Page (by id)
(deftype DeletePage [id callback]
(defn delete-page
[id]
{:pre [(uuid? id)]}
(reify
ptk/UpdateEvent
(update [_ state]
(purge-page state id))
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
([id] (DeletePage. id (constantly nil)))
([id callback] (DeletePage. id callback)))
(rx/map (constantly ::delete-completed))))))
;; --- Watch Page Changes

View file

@ -160,74 +160,38 @@
;; --- Create Project
(defrecord CreateProject [name width height layout]
ptk/WatchEvent
(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]))
(s/def ::create-project-params
(s/keys :req-un [::name ::udp/width ::udp/height]))
(defn create-project
[data]
{:pre [(us/valid? ::create-project-event data)]}
(map->CreateProject data))
;; --- Go To & Go To Page
(deftype GoToFirstPage [pages]
[{:keys [name] :as params}]
{:pre [(us/valid? ::create-project-params params)]}
(reify
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)))))
(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)))))))
(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)))))
;; --- Go To Project
(defn go-to
"A shortcut event that redirects the user to the
first page of the project."
([project-id]
{:pre [(uuid? project-id)]}
(GoTo. project-id))
([project-id page-id]
{:pre [(uuid? project-id)
(uuid? page-id)]}
(GoToPage. project-id page-id)))
[id]
{:pre [(uuid? id)]}
(reify
ptk/WatchEvent
(watch [_ state stream]
(let [[page & rest-pages] (get-in state [:projects id :pages])]
(when page
(let [params {:project id :page page}]
(rx/of (rt/nav :workspace/page params))))))))
;; --- Update Opts (Filtering & Ordering)

View file

@ -899,6 +899,25 @@
{:pre [(uuid? 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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View file

@ -158,7 +158,7 @@
(def figwheel-options
{:open-url false
:pprint-config false
:load-warninged-code true
:load-warninged-code false
:auto-testing false
:css-dirs ["resources/public/css"]
:ring-server-options {:port 3449 :host "0.0.0.0"}