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 (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

View file

@ -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)

View file

@ -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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View file

@ -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"}