mirror of
https://github.com/penpot/penpot.git
synced 2025-04-05 11:31:35 -05:00
🚧 Move all page related data events into projects ns.
This commit is contained in:
parent
b7d4908e90
commit
d88bb1cfcb
13 changed files with 309 additions and 541 deletions
|
@ -9,7 +9,7 @@
|
|||
[beicon.core :as rx]
|
||||
[cljs.spec.alpha :as s]
|
||||
[potok.core :as ptk]
|
||||
[uxbox.main.data.pages :as udp]
|
||||
[uxbox.main.data.projects :as dp]
|
||||
[uxbox.main.repo :as rp]
|
||||
[uxbox.util.data :refer [replace-by-id index-by]]
|
||||
[uxbox.util.spec :as us]))
|
||||
|
@ -26,7 +26,7 @@
|
|||
(s/def ::user ::us/uuid)
|
||||
|
||||
(s/def ::shapes
|
||||
(s/every ::udp/minimal-shape :kind vector?))
|
||||
(s/every ::dp/minimal-shape :kind vector?))
|
||||
|
||||
(s/def ::data
|
||||
(s/keys :req-un [::shapes]))
|
||||
|
@ -77,7 +77,7 @@
|
|||
(watch [_ state stream]
|
||||
#_(let [stopper (rx/filter #(= % ::stop-page-watcher) stream)]
|
||||
(->> stream
|
||||
(rx/filter udp/page-persisted?)
|
||||
(rx/filter dp/page-persisted?)
|
||||
(rx/debounce 1000)
|
||||
(rx/flat-map #(rx/of (fetch-history id)
|
||||
(fetch-pinned-history id)))
|
||||
|
@ -192,7 +192,7 @@
|
|||
(assoc :history true
|
||||
:data (:data item)))]
|
||||
(-> state
|
||||
(udp/unpack-page page)
|
||||
(dp/unpack-page page)
|
||||
(assoc-in [:workspace pid :history :selected] version))))))
|
||||
|
||||
;; --- Apply Selected History
|
||||
|
@ -209,7 +209,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
#_(let [pid (get-in state [:workspace :current])]
|
||||
(rx/of (udp/persist-page pid))))))
|
||||
(rx/of (dp/persist-page pid))))))
|
||||
|
||||
;; --- Deselect Page History
|
||||
|
||||
|
@ -219,7 +219,7 @@
|
|||
(update [_ state]
|
||||
#_(let [pid (get-in state [:workspace :current])
|
||||
packed (get-in state [:packed-pages pid])]
|
||||
(-> (udp/unpack-page state packed)
|
||||
(-> (dp/unpack-page state packed)
|
||||
(assoc-in [:workspace pid :history :selected] nil))))))
|
||||
|
||||
;; --- Refresh Page History
|
||||
|
|
|
@ -1,325 +0,0 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) 2015-2017 Andrey Antukh <niwi@niwi.nz>
|
||||
|
||||
(ns uxbox.main.data.pages
|
||||
"Page related events (for workspace mainly)."
|
||||
(:require
|
||||
[cljs.spec.alpha :as s]
|
||||
[beicon.core :as rx]
|
||||
[cuerdas.core :as str]
|
||||
[potok.core :as ptk]
|
||||
[uxbox.main.repo.core :as rp]
|
||||
[uxbox.main.data.projects :as dp]
|
||||
[uxbox.util.data :refer [index-by-id concatv]]
|
||||
[uxbox.util.spec :as us]
|
||||
[uxbox.util.timers :as ts]
|
||||
[uxbox.util.uuid :as uuid]))
|
||||
|
||||
;; --- Struct
|
||||
|
||||
(s/def ::id ::us/uuid)
|
||||
(s/def ::name ::us/string)
|
||||
(s/def ::inst ::us/inst)
|
||||
(s/def ::type ::us/keyword)
|
||||
(s/def ::file-id ::us/uuid)
|
||||
(s/def ::created-at ::us/inst)
|
||||
(s/def ::modified-at ::us/inst)
|
||||
(s/def ::version ::us/number)
|
||||
(s/def ::width (s/and ::us/number ::us/positive))
|
||||
(s/def ::height (s/and ::us/number ::us/positive))
|
||||
|
||||
(s/def ::grid-x-axis ::us/number)
|
||||
(s/def ::grid-y-axis ::us/number)
|
||||
(s/def ::grid-color ::us/string)
|
||||
(s/def ::background ::us/string)
|
||||
(s/def ::background-opacity ::us/number)
|
||||
|
||||
(s/def ::ordering ::us/number)
|
||||
(s/def ::user ::us/uuid)
|
||||
|
||||
(s/def ::metadata
|
||||
(s/keys :opt-un [::grid-y-axis
|
||||
::grid-x-axis
|
||||
::grid-color
|
||||
::background
|
||||
::background-opacity]))
|
||||
|
||||
;; TODO: start using uxbox.common.pagedata/data spec ...
|
||||
|
||||
(s/def ::minimal-shape
|
||||
(s/keys :req-un [::type ::name]
|
||||
:opt-un [::id]))
|
||||
|
||||
(s/def ::shapes (s/coll-of ::us/uuid :kind vector?))
|
||||
(s/def ::canvas (s/coll-of ::us/uuid :kind vector?))
|
||||
|
||||
(s/def ::shapes-by-id
|
||||
(s/map-of ::us/uuid ::minimal-shape))
|
||||
|
||||
(s/def ::data
|
||||
(s/keys :req-un [::shapes ::canvas ::shapes-by-id]))
|
||||
|
||||
(s/def ::page
|
||||
(s/keys :req-un [::id
|
||||
::name
|
||||
::file-id
|
||||
::created-at
|
||||
::modified-at
|
||||
::user-id
|
||||
::ordering
|
||||
::metadata
|
||||
::data]))
|
||||
|
||||
(s/def ::pages
|
||||
(s/every ::page :kind vector?))
|
||||
|
||||
;; --- Protocols
|
||||
|
||||
(defprotocol IPageDataUpdate
|
||||
"A marker protocol for mark events that alters the
|
||||
page and is subject to perform a backend synchronization.")
|
||||
|
||||
(defprotocol IPagePersistentOps
|
||||
(-persistent-ops [o] "Get a list of ops for the event."))
|
||||
|
||||
(defn page-update?
|
||||
[o]
|
||||
(or (satisfies? IPageDataUpdate o)
|
||||
(= ::page-data-update o)))
|
||||
|
||||
;; --- Helpers
|
||||
|
||||
;; (defn pack-page
|
||||
;; "Return a packed version of page object ready
|
||||
;; for send to remore storage service."
|
||||
;; [state id]
|
||||
;; (letfn [(pack-shapes [ids]
|
||||
;; (mapv #(get-in state [:shapes %]) ids))]
|
||||
;; (let [page (get-in state [:pages id])
|
||||
;; data {:shapes (pack-shapes (concatv (:canvas page)
|
||||
;; (:shapes page)))}]
|
||||
;; (-> page
|
||||
;; (assoc :data data)
|
||||
;; (dissoc :shapes)))))
|
||||
|
||||
(defn unpack-page
|
||||
[state {:keys [id data metadata] :as page}]
|
||||
(-> state
|
||||
(update :pages assoc id (dissoc page :data))
|
||||
(update :pages-data assoc id data)))
|
||||
|
||||
(defn purge-page
|
||||
"Remove page and all related stuff from the state."
|
||||
[state id]
|
||||
(if-let [file-id (get-in state [:pages id :file-id])]
|
||||
(-> state
|
||||
(update-in [:files file-id :pages] #(filterv (partial not= id) %))
|
||||
(update-in [:workspace-file :pages] #(filterv (partial not= id) %))
|
||||
(update :pages dissoc id)
|
||||
(update :pages-data dissoc id))
|
||||
state))
|
||||
|
||||
;; --- Fetch Pages (by File ID)
|
||||
|
||||
(declare pages-fetched)
|
||||
|
||||
(defn fetch-pages
|
||||
[file-id]
|
||||
(s/assert ::us/uuid file-id)
|
||||
(reify
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(->> (rp/query :project-pages {:file-id file-id})
|
||||
(rx/map pages-fetched)))))
|
||||
|
||||
;; --- Pages Fetched
|
||||
|
||||
(defn pages-fetched
|
||||
[pages]
|
||||
(s/assert ::pages pages)
|
||||
(ptk/reify ::pages-fetched
|
||||
IDeref
|
||||
(-deref [_] pages)
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(reduce unpack-page state pages))))
|
||||
|
||||
;; --- Fetch Page (By ID)
|
||||
|
||||
(declare page-fetched)
|
||||
|
||||
(defn fetch-page
|
||||
"Fetch page by id."
|
||||
[id]
|
||||
(s/assert ::us/uuid id)
|
||||
(reify
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(->> (rp/query :project-page {:id id})
|
||||
(rx/map page-fetched)))))
|
||||
|
||||
;; --- Page Fetched
|
||||
|
||||
(defn page-fetched
|
||||
[data]
|
||||
(s/assert ::page data)
|
||||
(ptk/reify ::page-fetched
|
||||
IDeref
|
||||
(-deref [_] data)
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(unpack-page state data))))
|
||||
|
||||
;; --- Create Page
|
||||
|
||||
(declare page-created)
|
||||
|
||||
(s/def ::create-page
|
||||
(s/keys :req-un [::name ::file-id]))
|
||||
|
||||
(defn create-page
|
||||
[{:keys [file-id name] :as data}]
|
||||
(s/assert ::create-page data)
|
||||
(ptk/reify ::create-page
|
||||
ptk/WatchEvent
|
||||
(watch [this state s]
|
||||
(let [ordering (count (get-in state [:files file-id :pages]))
|
||||
params {:name name
|
||||
:file-id file-id
|
||||
:ordering ordering
|
||||
:data {:shapes []
|
||||
:canvas []
|
||||
:shapes-by-id {}}
|
||||
:metadata {}}]
|
||||
(->> (rp/mutation :create-project-page params)
|
||||
(rx/map page-created))))))
|
||||
|
||||
;; --- Page Created
|
||||
|
||||
(defn page-created
|
||||
[{:keys [id file-id] :as page}]
|
||||
(s/assert ::page page)
|
||||
(ptk/reify ::page-created
|
||||
cljs.core/IDeref
|
||||
(-deref [_] page)
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [data (:data page)
|
||||
page (dissoc page :data)]
|
||||
(-> state
|
||||
(update-in [:workspace-file :pages] (fnil conj []) id)
|
||||
(update :pages assoc id page)
|
||||
(update :pages-data assoc id data))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(rx/of (uxbox.main.data.projects/fetch-file file-id)))))
|
||||
|
||||
;; --- Rename Page
|
||||
|
||||
(s/def ::rename-page
|
||||
(s/keys :req-un [::id ::name]))
|
||||
|
||||
(defn rename-page
|
||||
[{:keys [id name] :as data}]
|
||||
(s/assert ::rename-page data)
|
||||
(ptk/reify ::rename-page
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [pid (get-in state [:workspace-page :id])
|
||||
state (assoc-in state [:pages id :name] name)]
|
||||
(cond-> state
|
||||
(= pid id) (assoc-in [:workspace-page :name] name))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [params {:id id :name name}]
|
||||
(->> (rp/mutation :rename-page params)
|
||||
(rx/map #(ptk/data-event ::page-renamed data)))))))
|
||||
|
||||
;; --- Delete Page (by ID)
|
||||
|
||||
(defn delete-page
|
||||
[id]
|
||||
{:pre [(uuid? id)]}
|
||||
(reify
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(purge-page state id))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(let [page (:workspace-page state)]
|
||||
(rx/merge
|
||||
(->> (rp/mutation :delete-project-page {:id id})
|
||||
(rx/flat-map (fn [_]
|
||||
(if (= id (:id page))
|
||||
(rx/of (dp/go-to (:file-id page)))
|
||||
(rx/empty))))))))))
|
||||
|
||||
;; --- Persist Page
|
||||
|
||||
(declare page-persisted)
|
||||
|
||||
(def persist-current-page
|
||||
(ptk/reify ::persist-page
|
||||
ptk/WatchEvent
|
||||
(watch [this state s]
|
||||
(let [local (:workspace-local state)
|
||||
page (:workspace-page state)
|
||||
data (:workspace-data state)]
|
||||
(if (:history local)
|
||||
(rx/empty)
|
||||
(let [page (assoc page :data data)]
|
||||
(->> (rp/mutation :update-project-page-data page)
|
||||
(rx/map (fn [res] (merge page res)))
|
||||
(rx/map page-persisted)
|
||||
(rx/catch (fn [err] (rx/of ::page-persist-error))))))))))
|
||||
|
||||
;; --- Page Persisted
|
||||
|
||||
(defn page-persisted
|
||||
[{:keys [id] :as page}]
|
||||
(s/assert ::page page)
|
||||
(ptk/reify ::page-persisted
|
||||
cljs.core/IDeref
|
||||
(-deref [_] page)
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [data (:data page)
|
||||
page (dissoc page :data)]
|
||||
(-> state
|
||||
(assoc :workspace-data data)
|
||||
(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))))
|
|
@ -6,24 +6,29 @@
|
|||
|
||||
(ns uxbox.main.data.projects
|
||||
(:require
|
||||
[beicon.core :as rx]
|
||||
[cljs.spec.alpha :as s]
|
||||
[cuerdas.core :as str]
|
||||
[beicon.core :as rx]
|
||||
[potok.core :as ptk]
|
||||
[uxbox.main.repo.core :as rp]
|
||||
[uxbox.util.uuid :as uuid]
|
||||
[uxbox.util.data :refer [index-by-id concatv]]
|
||||
[uxbox.util.router :as rt]
|
||||
[uxbox.util.spec :as us]
|
||||
[uxbox.util.time :as dt]
|
||||
[uxbox.util.router :as rt]))
|
||||
[uxbox.util.timers :as ts]
|
||||
[uxbox.util.uuid :as uuid]))
|
||||
|
||||
;; --- Specs
|
||||
|
||||
(s/def ::id uuid?)
|
||||
(s/def ::name string?)
|
||||
(s/def ::version integer?)
|
||||
(s/def ::user-id uuid?)
|
||||
(s/def ::created-at inst?)
|
||||
(s/def ::modified-at inst?)
|
||||
(s/def ::id ::us/uuid)
|
||||
(s/def ::name ::us/string)
|
||||
(s/def ::user ::us/uuid)
|
||||
(s/def ::type ::us/keyword)
|
||||
(s/def ::file-id ::us/uuid)
|
||||
(s/def ::created-at ::us/inst)
|
||||
(s/def ::modified-at ::us/inst)
|
||||
(s/def ::version ::us/number)
|
||||
(s/def ::ordering ::us/number)
|
||||
|
||||
(s/def ::project-entity
|
||||
(s/keys ::req-un [::id
|
||||
|
@ -33,8 +38,48 @@
|
|||
::created-at
|
||||
::modified-at]))
|
||||
|
||||
(declare fetch-projects)
|
||||
(declare projects-fetched?)
|
||||
(s/def ::grid-x-axis ::us/number)
|
||||
(s/def ::grid-y-axis ::us/number)
|
||||
(s/def ::grid-color ::us/string)
|
||||
(s/def ::background ::us/string)
|
||||
(s/def ::background-opacity ::us/number)
|
||||
|
||||
(s/def ::metadata
|
||||
(s/keys :opt-un [::grid-y-axis
|
||||
::grid-x-axis
|
||||
::grid-color
|
||||
::background
|
||||
::background-opacity]))
|
||||
|
||||
;; TODO: start using uxbox.common.pagedata/data spec ...
|
||||
|
||||
(s/def ::minimal-shape
|
||||
(s/keys :req-un [::type ::name]
|
||||
:opt-un [::id]))
|
||||
|
||||
(s/def ::shapes (s/coll-of ::us/uuid :kind vector?))
|
||||
(s/def ::canvas (s/coll-of ::us/uuid :kind vector?))
|
||||
|
||||
(s/def ::shapes-by-id
|
||||
(s/map-of ::us/uuid ::minimal-shape))
|
||||
|
||||
(s/def ::data
|
||||
(s/keys :req-un [::shapes ::canvas ::shapes-by-id]))
|
||||
|
||||
(s/def ::page
|
||||
(s/keys :req-un [::id
|
||||
::name
|
||||
::file-id
|
||||
::created-at
|
||||
::modified-at
|
||||
::user-id
|
||||
::ordering
|
||||
::metadata
|
||||
::data]))
|
||||
|
||||
(s/def ::pages
|
||||
(s/every ::page :kind vector?))
|
||||
|
||||
|
||||
;; --- Helpers
|
||||
|
||||
|
@ -49,11 +94,33 @@
|
|||
[state id]
|
||||
(update state :projects dissoc id))
|
||||
|
||||
;; --- Initialize
|
||||
(defn unpack-page
|
||||
[state {:keys [id data metadata] :as page}]
|
||||
(-> state
|
||||
(update :pages assoc id (dissoc page :data))
|
||||
(update :pages-data assoc id data)))
|
||||
|
||||
(defn purge-page
|
||||
"Remove page and all related stuff from the state."
|
||||
[state id]
|
||||
(if-let [file-id (get-in state [:pages id :file-id])]
|
||||
(-> state
|
||||
(update-in [:files file-id :pages] #(filterv (partial not= id) %))
|
||||
(update-in [:workspace-file :pages] #(filterv (partial not= id) %))
|
||||
(update :pages dissoc id)
|
||||
(update :pages-data dissoc id))
|
||||
state))
|
||||
|
||||
;; --- Initialize Dashboard
|
||||
|
||||
(declare fetch-projects)
|
||||
(declare projects-fetched?)
|
||||
|
||||
(declare fetch-files)
|
||||
(declare initialized)
|
||||
|
||||
;; TODO: rename to initialize dashboard
|
||||
|
||||
(defn initialize
|
||||
[id]
|
||||
(ptk/reify ::initialize
|
||||
|
@ -262,3 +329,206 @@
|
|||
(if (nil? id)
|
||||
(rx/of (rt/nav :dashboard-projects {} {}))
|
||||
(rx/of (rt/nav :dashboard-projects {} {:project-id (str id)}))))))
|
||||
|
||||
|
||||
;; --- Fetch Pages (by File ID)
|
||||
|
||||
(declare pages-fetched)
|
||||
|
||||
(defn fetch-pages
|
||||
[file-id]
|
||||
(s/assert ::us/uuid file-id)
|
||||
(reify
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(->> (rp/query :project-pages {:file-id file-id})
|
||||
(rx/map pages-fetched)))))
|
||||
|
||||
;; --- Pages Fetched
|
||||
|
||||
(defn pages-fetched
|
||||
[pages]
|
||||
(s/assert ::pages pages)
|
||||
(ptk/reify ::pages-fetched
|
||||
IDeref
|
||||
(-deref [_] pages)
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(reduce unpack-page state pages))))
|
||||
|
||||
;; --- Fetch Page (By ID)
|
||||
|
||||
(declare page-fetched)
|
||||
|
||||
(defn fetch-page
|
||||
"Fetch page by id."
|
||||
[id]
|
||||
(s/assert ::us/uuid id)
|
||||
(reify
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(->> (rp/query :project-page {:id id})
|
||||
(rx/map page-fetched)))))
|
||||
|
||||
;; --- Page Fetched
|
||||
|
||||
(defn page-fetched
|
||||
[data]
|
||||
(s/assert ::page data)
|
||||
(ptk/reify ::page-fetched
|
||||
IDeref
|
||||
(-deref [_] data)
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(unpack-page state data))))
|
||||
|
||||
;; --- Create Page
|
||||
|
||||
(declare page-created)
|
||||
|
||||
(s/def ::create-page
|
||||
(s/keys :req-un [::name ::file-id]))
|
||||
|
||||
(defn create-page
|
||||
[{:keys [file-id name] :as data}]
|
||||
(s/assert ::create-page data)
|
||||
(ptk/reify ::create-page
|
||||
ptk/WatchEvent
|
||||
(watch [this state s]
|
||||
(let [ordering (count (get-in state [:files file-id :pages]))
|
||||
params {:name name
|
||||
:file-id file-id
|
||||
:ordering ordering
|
||||
:data {:shapes []
|
||||
:canvas []
|
||||
:shapes-by-id {}}
|
||||
:metadata {}}]
|
||||
(->> (rp/mutation :create-project-page params)
|
||||
(rx/map page-created))))))
|
||||
|
||||
;; --- Page Created
|
||||
|
||||
(defn page-created
|
||||
[{:keys [id file-id] :as page}]
|
||||
(s/assert ::page page)
|
||||
(ptk/reify ::page-created
|
||||
cljs.core/IDeref
|
||||
(-deref [_] page)
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [data (:data page)
|
||||
page (dissoc page :data)]
|
||||
(-> state
|
||||
(update-in [:workspace-file :pages] (fnil conj []) id)
|
||||
(update :pages assoc id page)
|
||||
(update :pages-data assoc id data))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(rx/of (uxbox.main.data.projects/fetch-file file-id)))))
|
||||
|
||||
;; --- Rename Page
|
||||
|
||||
(s/def ::rename-page
|
||||
(s/keys :req-un [::id ::name]))
|
||||
|
||||
(defn rename-page
|
||||
[{:keys [id name] :as data}]
|
||||
(s/assert ::rename-page data)
|
||||
(ptk/reify ::rename-page
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [pid (get-in state [:workspace-page :id])
|
||||
state (assoc-in state [:pages id :name] name)]
|
||||
(cond-> state
|
||||
(= pid id) (assoc-in [:workspace-page :name] name))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [params {:id id :name name}]
|
||||
(->> (rp/mutation :rename-page params)
|
||||
(rx/map #(ptk/data-event ::page-renamed data)))))))
|
||||
|
||||
;; --- Delete Page (by ID)
|
||||
|
||||
(defn delete-page
|
||||
[id]
|
||||
{:pre [(uuid? id)]}
|
||||
(reify
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(purge-page state id))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(let [page (:workspace-page state)]
|
||||
(rx/merge
|
||||
(->> (rp/mutation :delete-project-page {:id id})
|
||||
(rx/flat-map (fn [_]
|
||||
(if (= id (:id page))
|
||||
(rx/of (go-to (:file-id page)))
|
||||
(rx/empty))))))))))
|
||||
|
||||
;; --- Persist Page
|
||||
|
||||
(declare page-persisted)
|
||||
|
||||
(def persist-current-page
|
||||
(ptk/reify ::persist-page
|
||||
ptk/WatchEvent
|
||||
(watch [this state s]
|
||||
(let [local (:workspace-local state)
|
||||
page (:workspace-page state)
|
||||
data (:workspace-data state)]
|
||||
(if (:history local)
|
||||
(rx/empty)
|
||||
(let [page (assoc page :data data)]
|
||||
(->> (rp/mutation :update-project-page-data page)
|
||||
(rx/map (fn [res] (merge page res)))
|
||||
(rx/map page-persisted)
|
||||
(rx/catch (fn [err] (rx/of ::page-persist-error))))))))))
|
||||
|
||||
;; --- Page Persisted
|
||||
|
||||
(defn page-persisted
|
||||
[{:keys [id] :as page}]
|
||||
(s/assert ::page page)
|
||||
(ptk/reify ::page-persisted
|
||||
cljs.core/IDeref
|
||||
(-deref [_] page)
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [data (:data page)
|
||||
page (dissoc page :data)]
|
||||
(-> state
|
||||
(assoc :workspace-data data)
|
||||
(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))))
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
[beicon.core :as rx]
|
||||
[cljs.spec.alpha :as s]
|
||||
[potok.core :as ptk]
|
||||
[uxbox.main.data.pages :as udp]
|
||||
[uxbox.main.data.projects :as dp]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.util.spec :as us]))
|
||||
|
||||
|
@ -28,9 +28,9 @@
|
|||
(ptk/reify ::watch-page-changes
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
#_(let [stopper (rx/filter #(= % ::udp/stop-page-watcher) stream)]
|
||||
#_(let [stopper (rx/filter #(= % ::dp/stop-page-watcher) stream)]
|
||||
(->> stream
|
||||
(rx/filter udp/page-update?)
|
||||
(rx/filter dp/page-update?)
|
||||
(rx/filter #(not (undo? %)))
|
||||
(rx/filter #(not (redo? %)))
|
||||
(rx/map #(save-undo-entry id))
|
||||
|
@ -49,7 +49,7 @@
|
|||
(ptk/reify ::save-undo-entry
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
#_(let [page (udp/pack-page state id)
|
||||
#_(let [page (dp/pack-page state id)
|
||||
undo {:data (:data page)
|
||||
:metadata (:metadata page)}]
|
||||
(-> state
|
||||
|
@ -82,7 +82,7 @@
|
|||
;; (pp/pprint packed)
|
||||
|
||||
(-> state
|
||||
(udp/unpack-page packed)
|
||||
(dp/unpack-page packed)
|
||||
(assoc-in [:undo pid :selected] pointer))))))))
|
||||
|
||||
(defn undo?
|
||||
|
@ -113,7 +113,7 @@
|
|||
;; (pp/pprint packed)
|
||||
|
||||
(-> state
|
||||
(udp/unpack-page packed)
|
||||
(dp/unpack-page packed)
|
||||
(assoc-in [:undo pid :selected] pointer))))))))
|
||||
|
||||
(defn redo?
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
[uxbox.main.websockets :as ws]
|
||||
[uxbox.main.constants :as c]
|
||||
[uxbox.main.data.icons :as udi]
|
||||
[uxbox.main.data.pages :as udp]
|
||||
[uxbox.main.data.projects :as dp]
|
||||
[uxbox.main.geom :as geom]
|
||||
[uxbox.main.refs :as refs]
|
||||
|
@ -37,8 +36,6 @@
|
|||
(def clear-ruler nil)
|
||||
(def start-ruler nil)
|
||||
|
||||
(declare shapes-overlaps?)
|
||||
|
||||
;; --- Specs
|
||||
|
||||
(s/def ::id ::us/uuid)
|
||||
|
@ -135,7 +132,6 @@
|
|||
:tooltip nil})
|
||||
|
||||
(declare initialized)
|
||||
(declare watch-page-changes)
|
||||
;; (declare watch-events)
|
||||
|
||||
(defn initialize
|
||||
|
@ -165,12 +161,12 @@
|
|||
;; Stop possible previous watchers and re-fetch the main page
|
||||
;; and all project related pages.
|
||||
(rx/of ::stop-watcher
|
||||
(udp/fetch-page page-id)
|
||||
(dp/fetch-page page-id)
|
||||
(dp/fetch-file file-id)
|
||||
(udp/fetch-pages file-id))
|
||||
(dp/fetch-pages file-id))
|
||||
|
||||
;; When main page is fetched, schedule the main initialization.
|
||||
(->> (rx/zip (rx/filter (ptk/type? ::udp/page-fetched) stream)
|
||||
(->> (rx/zip (rx/filter (ptk/type? ::dp/page-fetched) stream)
|
||||
(rx/filter (ptk/type? ::dp/files-fetched) stream))
|
||||
(rx/take 1)
|
||||
(rx/do #(reset! st/loader false))
|
||||
|
@ -180,7 +176,7 @@
|
|||
;; When workspace is initialized, run the event watchers.
|
||||
(->> (rx/filter (ptk/type? ::initialized) stream)
|
||||
(rx/take 1)
|
||||
(rx/mapcat #(rx/of watch-page-changes)))))
|
||||
(rx/ignore))))
|
||||
|
||||
ptk/EffectEvent
|
||||
(effect [_ state stream]
|
||||
|
@ -203,35 +199,6 @@
|
|||
:workspace-data data
|
||||
:workspace-page page)))))
|
||||
|
||||
;; --- Initialize WebSocket
|
||||
|
||||
(defn initialize-websocket
|
||||
[file-id]
|
||||
(ptk/reify ::initialize-websocket
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(prn "initialize-websocket$update" file-id)
|
||||
(let [uri (str "ws://localhost:6060/sub/" file-id)]
|
||||
(assoc-in state [::ws file-id] (ws/open uri))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(prn "initialize-websocket$watch" file-id)
|
||||
(->> (ws/-stream (get-in state [::ws file-id]))
|
||||
(rx/filter #(= :message (:type %)))
|
||||
(rx/map :payload)
|
||||
(rx/map t/decode)
|
||||
(rx/tap #(js/console.log "ws-message" file-id %))
|
||||
(rx/ignore)))))
|
||||
|
||||
(defn finalize-websocket
|
||||
[file-id]
|
||||
(ptk/reify ::finalize-websocket
|
||||
ptk/EffectEvent
|
||||
(effect [_ state stream]
|
||||
(prn "finalize-websocket" file-id)
|
||||
(ws/-close (get-in state [::ws file-id])))))
|
||||
|
||||
;; --- Toggle layout flag
|
||||
|
||||
(defn toggle-layout-flag
|
||||
|
@ -619,11 +586,6 @@
|
|||
(let [attrs' (->> (apply hash-map attrs)
|
||||
(s/conform ::attributes))]
|
||||
(ptk/reify ::update-shape
|
||||
udp/IPagePersistentOps
|
||||
(-persistent-ops [_]
|
||||
(->> (partition-all 2 attrs)
|
||||
(mapv (fn [[key val]] [:mod-shape id key val]))))
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(cond-> state
|
||||
|
@ -758,7 +720,6 @@
|
|||
[loc]
|
||||
(s/assert ::direction loc)
|
||||
(ptk/reify ::move-selected-layer
|
||||
udp/IPageDataUpdate
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [id (first (get-in state [:workspace-local :selected]))
|
||||
|
@ -910,17 +871,8 @@
|
|||
params {:id (:id page)
|
||||
:version (:version page)
|
||||
:operations operations}]
|
||||
(prn "commit-shapes-changes" params)
|
||||
(->> (rp/mutation :update-project-page params)
|
||||
;; (rx/tap #(prn "foobar" %))
|
||||
(rx/map shapes-changes-commited))))
|
||||
|
||||
;; ptk/EffectEvent
|
||||
;; (effect [_ state stream]
|
||||
;; (let [data {:shapes []
|
||||
;; :shapes-by-id {}}]
|
||||
;; (prn "commit-shapes-changes$effect" (cp/process-ops data operations))))
|
||||
))
|
||||
(rx/map shapes-changes-commited))))))
|
||||
|
||||
(s/def ::shapes-changes-commited
|
||||
(s/keys :req-un [::id ::version ::cp/operations]))
|
||||
|
@ -1173,46 +1125,6 @@
|
|||
{:pre [(uuid? id)]}
|
||||
(UnlockShape. id))
|
||||
|
||||
;; --- Recalculate Shapes relations (Shapes <-> Canvas)
|
||||
|
||||
(def rehash-shapes-relationships
|
||||
(letfn [(overlaps? [canvas shape]
|
||||
(let [shape1 (geom/shape->rect-shape canvas)
|
||||
shape2 (geom/shape->rect-shape shape)]
|
||||
(geom/overlaps? shape1 shape2)))]
|
||||
(ptk/reify ::rehash-shapes-relationships
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [data (:workspace-data state)
|
||||
canvas (map #(get-in data [:shapes-by-id %]) (:canvas data))
|
||||
shapes (map #(get-in data [:shapes-by-id %]) (:shapes data))]
|
||||
(reduce (fn [state {:keys [id] :as shape}]
|
||||
(let [canvas (first (filter #(overlaps? % shape) canvas))]
|
||||
(update-in state [:workspace-data :shapes-by-id id] assoc :canvas (:id canvas))))
|
||||
state
|
||||
shapes))))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Selection Rect IMPL
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; TODO: move to shapes impl maybe...
|
||||
|
||||
(defn selection->rect
|
||||
[data]
|
||||
(let [start (:start data)
|
||||
stop (:stop data)
|
||||
start-x (min (:x start) (:x stop))
|
||||
start-y (min (:y start) (:y stop))
|
||||
end-x (max (:x start) (:x stop))
|
||||
end-y (max (:y start) (:y stop))]
|
||||
(assoc data
|
||||
:x1 start-x
|
||||
:y1 start-y
|
||||
:x2 end-x
|
||||
:y2 end-y
|
||||
:type :rect)))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Canvas Interactions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -1225,24 +1137,6 @@
|
|||
(update [_ state]
|
||||
(update state :workspace-local assoc :selected-canvas id))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Server Interactions DEPRECATED
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; --- Update Metadata
|
||||
|
||||
;; Is a workspace aware wrapper over uxbox.data.pages/UpdateMetadata event.
|
||||
|
||||
(defn update-metadata
|
||||
[id metadata]
|
||||
(s/assert ::us/uuid id)
|
||||
(s/assert ::udp/metadata metadata)
|
||||
(ptk/reify ::update-metadata
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
#_(rx/of (udp/update-metadata id metadata)
|
||||
(initialize-alignment id)))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Navigation
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -1286,66 +1180,3 @@
|
|||
pages (vec (concat before [id] after))]
|
||||
(assoc-in state [:projects (:project-id page) :pages] pages)))))
|
||||
|
||||
;; -- Page Changes Watcher
|
||||
|
||||
(def watch-page-changes
|
||||
(ptk/reify ::watch-page-changes
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [stopper (rx/filter #(= % ::stop-watcher) stream)]
|
||||
(->> stream
|
||||
(rx/filter udp/page-update?)
|
||||
(rx/debounce 500)
|
||||
(rx/mapcat #(rx/of rehash-shapes-relationships
|
||||
udp/persist-current-page))
|
||||
(rx/take-until stopper))))))
|
||||
|
||||
;; (def watch-shapes-changes
|
||||
;; (letfn [(look-for-changes [[old new]]
|
||||
;; (reduce-kv (fn [acc k v]
|
||||
;; (if (identical? v (get old k))
|
||||
;; acc
|
||||
;; (conj acc k)))
|
||||
;; #{}
|
||||
;; new))
|
||||
;; (select-shapes [state]
|
||||
;; (get-in state [:workspace-data :shapes-by-id]))
|
||||
;; ]
|
||||
;; (ptk/reify ::watch-page-changes
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state stream]
|
||||
;; (let [stopper (rx/filter #(= % ::stop-page-watcher) stream)]
|
||||
;; (->> stream
|
||||
;; (rx/filter udp/page-update?)
|
||||
;; (rx/debounce 1000)
|
||||
;; (rx/mapcat #(rx/merge (rx/of persist-page
|
||||
;; (->> (rx/filter page-persisted? stream)
|
||||
;; (rx/timeout 1000 (rx/empty))
|
||||
;; (rx/take 1)
|
||||
;; (rx/ignore)))))
|
||||
;; (rx/take-until stopper))))))
|
||||
|
||||
|
||||
|
||||
;; (let [stoper (rx/filter #(= % ::stop-shapes-watcher) stream)
|
||||
;; into' (fn [dst srcs] (reduce #(into %1 %2) dst srcs))]
|
||||
;; (->> (rx/merge st/store (rx/of state))
|
||||
;; (rx/map #(get-in % [:workspace-data :shapes-by-id]))
|
||||
;; (rx/buffer 2 1)
|
||||
;; (rx/map look-for-changes)
|
||||
;; (rx/buffer-time 300)
|
||||
;; (rx/map #(into' #{} %))
|
||||
;; (rx/filter (complement empty?))
|
||||
;; ;; (rx/tap #(prn "changed" %))
|
||||
;; ;; (rx/mapcat (fn [items] (rx/from-coll
|
||||
;; ;; (map rehash-shape-relationship items))))
|
||||
;; (rx/ignore)
|
||||
;; (rx/take-until stoper)))))))
|
||||
|
||||
(defn shapes-overlaps?
|
||||
[canvas shape]
|
||||
(let [shape1 (geom/shape->rect-shape canvas)
|
||||
shape2 (geom/shape->rect-shape shape)]
|
||||
(geom/overlaps? shape1 shape2)))
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
[rumext.alpha :as mf]
|
||||
[uxbox.main.constants :as c]
|
||||
[uxbox.main.data.history :as udh]
|
||||
[uxbox.main.data.pages :as udp]
|
||||
[uxbox.main.data.undo :as udu]
|
||||
[uxbox.main.data.workspace :as udw]
|
||||
[uxbox.main.refs :as refs]
|
||||
|
|
|
@ -7,12 +7,10 @@
|
|||
|
||||
(ns uxbox.main.ui.workspace.header
|
||||
(:require
|
||||
[rumext.core :as mx]
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.config :as cfg]
|
||||
[uxbox.main.data.history :as udh]
|
||||
[uxbox.main.data.pages :as udp]
|
||||
[uxbox.main.data.undo :as udu]
|
||||
[uxbox.main.data.workspace :as dw]
|
||||
[uxbox.main.ui.workspace.images :refer [import-image-modal]]
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
[rumext.alpha :as mf]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.data.history :as udh]
|
||||
[uxbox.main.data.pages :as udp]
|
||||
[uxbox.main.data.workspace :as dw]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.store :as st]
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
[lentes.core :as l]
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.data.pages :as udp]
|
||||
[uxbox.main.data.workspace :as dw]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.store :as st]
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
[rumext.alpha :as mf]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.constants :as c]
|
||||
[uxbox.main.data.pages :as udp]
|
||||
[uxbox.main.data.workspace :as udw]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.store :as st]
|
||||
|
@ -28,13 +27,13 @@
|
|||
(let [metadata (:metadata page)
|
||||
metadata (merge c/page-metadata metadata)]
|
||||
(letfn [(on-size-change [event attr]
|
||||
(let [value (-> (dom/event->value event)
|
||||
#_(let [value (-> (dom/event->value event)
|
||||
(parse-int nil))]
|
||||
(st/emit! (->> (assoc metadata attr value)
|
||||
(udp/update-metadata (:id page))))))
|
||||
|
||||
(change-color [color]
|
||||
(st/emit! (->> (assoc metadata :background color)
|
||||
#_(st/emit! (->> (assoc metadata :background color)
|
||||
(udp/update-metadata (:id page)))))
|
||||
|
||||
(on-color-change [event]
|
||||
|
@ -42,7 +41,7 @@
|
|||
(change-color value)))
|
||||
|
||||
(on-name-change [event]
|
||||
(let [value (-> (dom/event->value event)
|
||||
#_(let [value (-> (dom/event->value event)
|
||||
(str/trim))]
|
||||
(st/emit! (-> (assoc page :name value)
|
||||
(udp/update-page-attrs)))))
|
||||
|
@ -99,18 +98,18 @@
|
|||
(let [metadata (:metadata page)
|
||||
metadata (merge c/page-metadata metadata)]
|
||||
(letfn [(on-x-change [event]
|
||||
(let [value (-> (dom/event->value 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)
|
||||
#_(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)
|
||||
#_(st/emit! (->> (assoc metadata :grid-color color)
|
||||
(udp/update-metadata (:id page)))))
|
||||
(on-color-change [event]
|
||||
(let [value (dom/event->value event)]
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
[lentes.core :as l]
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.data.pages :as udp]
|
||||
[uxbox.main.data.projects :as dp]
|
||||
[uxbox.main.data.workspace :as dw]
|
||||
[uxbox.main.store :as st]
|
||||
|
@ -30,7 +29,7 @@
|
|||
(mf/defc page-item
|
||||
[{:keys [page index deletable? selected?] :as props}]
|
||||
(let [on-edit #(modal/show! page-form-dialog {:page page})
|
||||
delete-fn #(st/emit! (udp/delete-page (:id page)))
|
||||
delete-fn #(st/emit! (dp/delete-page (:id page)))
|
||||
on-delete #(do
|
||||
(dom/prevent-default %)
|
||||
(dom/stop-propagation %)
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
[cljs.spec.alpha :as s]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.constants :as c]
|
||||
[uxbox.main.data.pages :as udp]
|
||||
[uxbox.main.data.projects :as dp]
|
||||
[uxbox.main.data.workspace :as udw]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.ui.modal :as modal]
|
||||
|
@ -34,8 +34,8 @@
|
|||
(modal/hide!)
|
||||
(let [data (:clean-data form)]
|
||||
(if (nil? (:id data))
|
||||
(st/emit! (udp/create-page data))
|
||||
(st/emit! (udp/rename-page data)))))
|
||||
(st/emit! (dp/create-page data))
|
||||
(st/emit! (dp/rename-page data)))))
|
||||
|
||||
(defn- initial-data
|
||||
[page]
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
[uxbox.util.router :as rt]
|
||||
[uxbox.util.data :refer (parse-int)]
|
||||
[uxbox.main.repo :as rp]
|
||||
[uxbox.main.data.pages :as udpg]
|
||||
[uxbox.main.data.projects :as udpj]))
|
||||
|
||||
;; --- Initialize
|
||||
|
|
Loading…
Add table
Reference in a new issue