mirror of
https://github.com/penpot/penpot.git
synced 2025-05-24 10:56:10 +02:00
♻️ Refactor routes
This commit is contained in:
parent
21cdf8b0ae
commit
f08894629d
9 changed files with 153 additions and 138 deletions
|
@ -7,7 +7,6 @@
|
||||||
(ns app.main
|
(ns app.main
|
||||||
(:require
|
(:require
|
||||||
[app.common.logging :as log]
|
[app.common.logging :as log]
|
||||||
[app.common.spec :as us]
|
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
[app.main.data.events :as ev]
|
[app.main.data.events :as ev]
|
||||||
|
@ -18,14 +17,12 @@
|
||||||
[app.main.ui :as ui]
|
[app.main.ui :as ui]
|
||||||
[app.main.ui.confirm]
|
[app.main.ui.confirm]
|
||||||
[app.main.ui.modal :refer [modal]]
|
[app.main.ui.modal :refer [modal]]
|
||||||
|
[app.main.ui.routes :as rt]
|
||||||
[app.main.worker]
|
[app.main.worker]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n]
|
[app.util.i18n :as i18n]
|
||||||
[app.util.router :as rt]
|
|
||||||
[app.util.storage :refer [storage]]
|
|
||||||
[app.util.theme :as theme]
|
[app.util.theme :as theme]
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
[cljs.spec.alpha :as s]
|
|
||||||
[potok.core :as ptk]
|
[potok.core :as ptk]
|
||||||
[rumext.alpha :as mf]))
|
[rumext.alpha :as mf]))
|
||||||
|
|
||||||
|
@ -33,79 +30,32 @@
|
||||||
(log/set-level! :root :warn)
|
(log/set-level! :root :warn)
|
||||||
(log/set-level! :app :info)
|
(log/set-level! :app :info)
|
||||||
|
|
||||||
|
|
||||||
(when (= :browser @cf/target)
|
(when (= :browser @cf/target)
|
||||||
(log/info :message "wecome to penpot" :version (:full @cf/version) :public-uri (str cf/public-uri)))
|
(log/info :message "Welcome to penpot" :version (:full @cf/version) :public-uri (str cf/public-uri)))
|
||||||
|
|
||||||
|
|
||||||
(declare reinit)
|
(declare reinit)
|
||||||
|
|
||||||
(s/def ::any any?)
|
|
||||||
|
|
||||||
(defn match-path
|
|
||||||
[router path]
|
|
||||||
(when-let [match (rt/match router path)]
|
|
||||||
(if-let [conform (get-in match [:data :conform])]
|
|
||||||
(let [spath (get conform :path-params ::any)
|
|
||||||
squery (get conform :query-params ::any)]
|
|
||||||
(try
|
|
||||||
(-> (dissoc match :params)
|
|
||||||
(assoc :path-params (us/conform spath (get match :path-params))
|
|
||||||
:query-params (us/conform squery (get match :query-params))))
|
|
||||||
(catch :default _
|
|
||||||
nil)))
|
|
||||||
match)))
|
|
||||||
|
|
||||||
(defn on-navigate
|
|
||||||
[router path]
|
|
||||||
(let [match (match-path router path)
|
|
||||||
profile (:profile @storage)
|
|
||||||
nopath? (or (= path "") (= path "/"))
|
|
||||||
authed? (and (not (nil? profile))
|
|
||||||
(not= (:id profile) uuid/zero))]
|
|
||||||
|
|
||||||
(cond
|
|
||||||
(and nopath? authed? (nil? match))
|
|
||||||
(if (not= uuid/zero profile)
|
|
||||||
(st/emit! (rt/nav :dashboard-projects {:team-id (du/get-current-team-id profile)}))
|
|
||||||
(st/emit! (rt/nav :auth-login)))
|
|
||||||
|
|
||||||
(and (not authed?) (nil? match))
|
|
||||||
(st/emit! (rt/nav :auth-login))
|
|
||||||
|
|
||||||
(nil? match)
|
|
||||||
(st/emit! (rt/assign-exception {:type :not-found}))
|
|
||||||
|
|
||||||
:else
|
|
||||||
(st/emit! (rt/navigated match)))))
|
|
||||||
|
|
||||||
(defn init-ui
|
(defn init-ui
|
||||||
[]
|
[]
|
||||||
(mf/mount (mf/element ui/app) (dom/get-element "app"))
|
(mf/mount (mf/element ui/app) (dom/get-element "app"))
|
||||||
(mf/mount (mf/element modal) (dom/get-element "modal")))
|
(mf/mount (mf/element modal) (dom/get-element "modal")))
|
||||||
|
|
||||||
|
|
||||||
(defn initialize
|
(defn initialize
|
||||||
[]
|
[]
|
||||||
(letfn [(on-profile [_profile]
|
(ptk/reify ::initialize
|
||||||
(rx/of (rt/initialize-router ui/routes)
|
ptk/UpdateEvent
|
||||||
(rt/initialize-history on-navigate)))]
|
(update [_ state]
|
||||||
(ptk/reify ::initialize
|
(assoc state :session-id (uuid/next)))
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(assoc state :session-id (uuid/next)))
|
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ stream]
|
(watch [_ _ stream]
|
||||||
(rx/merge
|
(rx/merge
|
||||||
(rx/of
|
(rx/of (ptk/event ::ev/initialize)
|
||||||
(ptk/event ::ev/initialize)
|
(du/initialize-profile))
|
||||||
(du/initialize-profile))
|
(->> stream
|
||||||
(->> stream
|
(rx/filter du/profile-fetched?)
|
||||||
(rx/filter (ptk/type? ::du/profile-fetched))
|
(rx/take 1)
|
||||||
(rx/take 1)
|
(rx/map #(rt/init-routes)))))))
|
||||||
(rx/map deref)
|
|
||||||
(rx/mapcat on-profile)))))))
|
|
||||||
|
|
||||||
(defn ^:export init
|
(defn ^:export init
|
||||||
[]
|
[]
|
||||||
|
@ -121,11 +71,14 @@
|
||||||
(mf/unmount (dom/get-element "modal"))
|
(mf/unmount (dom/get-element "modal"))
|
||||||
(init-ui))
|
(init-ui))
|
||||||
|
|
||||||
(add-watch i18n/locale "locale" (fn [_ _ o v]
|
|
||||||
(when (not= o v)
|
|
||||||
(reinit))))
|
|
||||||
|
|
||||||
(defn ^:dev/after-load after-load
|
(defn ^:dev/after-load after-load
|
||||||
[]
|
[]
|
||||||
(reinit))
|
(reinit))
|
||||||
|
|
||||||
|
;; Reload the UI when the language changes
|
||||||
|
(add-watch
|
||||||
|
i18n/locale "locale"
|
||||||
|
(fn [_ _ old-value current-value]
|
||||||
|
(when (not= old-value current-value)
|
||||||
|
(reinit))))
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,9 @@
|
||||||
|
|
||||||
;; --- EVENT: fetch-profile
|
;; --- EVENT: fetch-profile
|
||||||
|
|
||||||
|
(def profile-fetched?
|
||||||
|
(ptk/type? ::profile-fetched))
|
||||||
|
|
||||||
(defn profile-fetched
|
(defn profile-fetched
|
||||||
[{:keys [id] :as profile}]
|
[{:keys [id] :as profile}]
|
||||||
(us/verify ::profile profile)
|
(us/verify ::profile profile)
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
;; 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
|
;; 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/.
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
|
|
||||||
(ns app.main.ui
|
(ns app.main.ui
|
||||||
(:require
|
(:require
|
||||||
[app.common.spec :as us]
|
|
||||||
[app.config :as cf]
|
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.auth :refer [auth]]
|
[app.main.ui.auth :refer [auth]]
|
||||||
|
@ -25,68 +23,8 @@
|
||||||
[app.main.ui.viewer :as viewer]
|
[app.main.ui.viewer :as viewer]
|
||||||
[app.main.ui.workspace :as workspace]
|
[app.main.ui.workspace :as workspace]
|
||||||
[app.util.router :as rt]
|
[app.util.router :as rt]
|
||||||
[cljs.spec.alpha :as s]
|
|
||||||
[rumext.alpha :as mf]))
|
[rumext.alpha :as mf]))
|
||||||
|
|
||||||
;; --- Routes
|
|
||||||
|
|
||||||
(s/def ::page-id ::us/uuid)
|
|
||||||
(s/def ::file-id ::us/uuid)
|
|
||||||
(s/def ::section ::us/keyword)
|
|
||||||
(s/def ::index ::us/integer)
|
|
||||||
(s/def ::token (s/nilable ::us/not-empty-string))
|
|
||||||
(s/def ::share-id ::us/uuid)
|
|
||||||
|
|
||||||
(s/def ::viewer-path-params
|
|
||||||
(s/keys :req-un [::file-id]))
|
|
||||||
|
|
||||||
(s/def ::viewer-query-params
|
|
||||||
(s/keys :opt-un [::index ::share-id ::section ::page-id]))
|
|
||||||
|
|
||||||
(def routes
|
|
||||||
[["/auth"
|
|
||||||
["/login" :auth-login]
|
|
||||||
(when (contains? @cf/flags :registration)
|
|
||||||
["/register" :auth-register])
|
|
||||||
(when (contains? @cf/flags :registration)
|
|
||||||
["/register/validate" :auth-register-validate])
|
|
||||||
(when (contains? @cf/flags :registration)
|
|
||||||
["/register/success" :auth-register-success])
|
|
||||||
["/recovery/request" :auth-recovery-request]
|
|
||||||
["/recovery" :auth-recovery]
|
|
||||||
["/verify-token" :auth-verify-token]]
|
|
||||||
|
|
||||||
["/settings"
|
|
||||||
["/profile" :settings-profile]
|
|
||||||
["/password" :settings-password]
|
|
||||||
["/feedback" :settings-feedback]
|
|
||||||
["/options" :settings-options]]
|
|
||||||
|
|
||||||
["/view/:file-id"
|
|
||||||
{:name :viewer
|
|
||||||
:conform
|
|
||||||
{:path-params ::viewer-path-params
|
|
||||||
:query-params ::viewer-query-params}}]
|
|
||||||
|
|
||||||
(when *assert*
|
|
||||||
["/debug/icons-preview" :debug-icons-preview])
|
|
||||||
|
|
||||||
;; Used for export
|
|
||||||
["/render-object/:file-id/:page-id/:object-id" :render-object]
|
|
||||||
["/render-sprite/:file-id" :render-sprite]
|
|
||||||
|
|
||||||
["/dashboard/team/:team-id"
|
|
||||||
["/members" :dashboard-team-members]
|
|
||||||
["/settings" :dashboard-team-settings]
|
|
||||||
["/projects" :dashboard-projects]
|
|
||||||
["/search" :dashboard-search]
|
|
||||||
["/fonts" :dashboard-fonts]
|
|
||||||
["/fonts/providers" :dashboard-font-providers]
|
|
||||||
["/libraries" :dashboard-libraries]
|
|
||||||
["/projects/:project-id" :dashboard-files]]
|
|
||||||
|
|
||||||
["/workspace/:project-id/:file-id" :workspace]])
|
|
||||||
|
|
||||||
(mf/defc on-main-error
|
(mf/defc on-main-error
|
||||||
[{:keys [error] :as props}]
|
[{:keys [error] :as props}]
|
||||||
(mf/use-effect (st/emitf (rt/assign-exception error)))
|
(mf/use-effect (st/emitf (rt/assign-exception error)))
|
||||||
|
|
122
frontend/src/app/main/ui/routes.cljs
Normal file
122
frontend/src/app/main/ui/routes.cljs
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
;; 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) UXBOX Labs SL
|
||||||
|
|
||||||
|
(ns app.main.ui.routes
|
||||||
|
(:require
|
||||||
|
[app.common.spec :as us]
|
||||||
|
[app.common.uuid :as uuid]
|
||||||
|
[app.config :as cf]
|
||||||
|
[app.main.data.users :as du]
|
||||||
|
[app.main.store :as st]
|
||||||
|
[app.util.router :as rt]
|
||||||
|
[app.util.storage :refer [storage]]
|
||||||
|
[beicon.core :as rx]
|
||||||
|
[cljs.spec.alpha :as s]
|
||||||
|
[potok.core :as ptk]))
|
||||||
|
|
||||||
|
(s/def ::page-id ::us/uuid)
|
||||||
|
(s/def ::file-id ::us/uuid)
|
||||||
|
(s/def ::section ::us/keyword)
|
||||||
|
(s/def ::index ::us/integer)
|
||||||
|
(s/def ::token (s/nilable ::us/not-empty-string))
|
||||||
|
(s/def ::share-id ::us/uuid)
|
||||||
|
|
||||||
|
(s/def ::viewer-path-params
|
||||||
|
(s/keys :req-un [::file-id]))
|
||||||
|
|
||||||
|
(s/def ::viewer-query-params
|
||||||
|
(s/keys :opt-un [::index ::share-id ::section ::page-id]))
|
||||||
|
|
||||||
|
(s/def ::any any?)
|
||||||
|
|
||||||
|
(def routes
|
||||||
|
[["/auth"
|
||||||
|
["/login" :auth-login]
|
||||||
|
(when (contains? @cf/flags :registration)
|
||||||
|
["/register" :auth-register])
|
||||||
|
(when (contains? @cf/flags :registration)
|
||||||
|
["/register/validate" :auth-register-validate])
|
||||||
|
(when (contains? @cf/flags :registration)
|
||||||
|
["/register/success" :auth-register-success])
|
||||||
|
["/recovery/request" :auth-recovery-request]
|
||||||
|
["/recovery" :auth-recovery]
|
||||||
|
["/verify-token" :auth-verify-token]]
|
||||||
|
|
||||||
|
["/settings"
|
||||||
|
["/profile" :settings-profile]
|
||||||
|
["/password" :settings-password]
|
||||||
|
["/feedback" :settings-feedback]
|
||||||
|
["/options" :settings-options]]
|
||||||
|
|
||||||
|
["/view/:file-id"
|
||||||
|
{:name :viewer
|
||||||
|
:conform
|
||||||
|
{:path-params ::viewer-path-params
|
||||||
|
:query-params ::viewer-query-params}}]
|
||||||
|
|
||||||
|
(when *assert*
|
||||||
|
["/debug/icons-preview" :debug-icons-preview])
|
||||||
|
|
||||||
|
;; Used for export
|
||||||
|
["/render-object/:file-id/:page-id/:object-id" :render-object]
|
||||||
|
["/render-sprite/:file-id" :render-sprite]
|
||||||
|
|
||||||
|
["/dashboard/team/:team-id"
|
||||||
|
["/members" :dashboard-team-members]
|
||||||
|
["/settings" :dashboard-team-settings]
|
||||||
|
["/projects" :dashboard-projects]
|
||||||
|
["/search" :dashboard-search]
|
||||||
|
["/fonts" :dashboard-fonts]
|
||||||
|
["/fonts/providers" :dashboard-font-providers]
|
||||||
|
["/libraries" :dashboard-libraries]
|
||||||
|
["/projects/:project-id" :dashboard-files]]
|
||||||
|
|
||||||
|
["/workspace/:project-id/:file-id" :workspace]])
|
||||||
|
|
||||||
|
(defn- match-path
|
||||||
|
[router path]
|
||||||
|
(when-let [match (rt/match router path)]
|
||||||
|
(if-let [conform (get-in match [:data :conform])]
|
||||||
|
(let [spath (get conform :path-params ::any)
|
||||||
|
squery (get conform :query-params ::any)]
|
||||||
|
(try
|
||||||
|
(-> (dissoc match :params)
|
||||||
|
(assoc :path-params (us/conform spath (get match :path-params))
|
||||||
|
:query-params (us/conform squery (get match :query-params))))
|
||||||
|
(catch :default _
|
||||||
|
nil)))
|
||||||
|
match)))
|
||||||
|
|
||||||
|
(defn on-navigate
|
||||||
|
[router path]
|
||||||
|
(let [match (match-path router path)
|
||||||
|
profile (:profile @storage)
|
||||||
|
nopath? (or (= path "") (= path "/"))
|
||||||
|
authed? (and (not (nil? profile))
|
||||||
|
(not= (:id profile) uuid/zero))]
|
||||||
|
|
||||||
|
(cond
|
||||||
|
(and nopath? authed? (nil? match))
|
||||||
|
(if (not= uuid/zero profile)
|
||||||
|
(st/emit! (rt/nav :dashboard-projects {:team-id (du/get-current-team-id profile)}))
|
||||||
|
(st/emit! (rt/nav :auth-login)))
|
||||||
|
|
||||||
|
(and (not authed?) (nil? match))
|
||||||
|
(st/emit! (rt/nav :auth-login))
|
||||||
|
|
||||||
|
(nil? match)
|
||||||
|
(st/emit! (rt/assign-exception {:type :not-found}))
|
||||||
|
|
||||||
|
:else
|
||||||
|
(st/emit! (rt/navigated match)))))
|
||||||
|
|
||||||
|
(defn init-routes
|
||||||
|
[]
|
||||||
|
(ptk/reify ::init-routes
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ _ _]
|
||||||
|
(rx/of (rt/initialize-router routes)
|
||||||
|
(rt/initialize-history on-navigate)))))
|
|
@ -36,9 +36,6 @@
|
||||||
(def picked-color-select
|
(def picked-color-select
|
||||||
(l/derived :picked-color-select refs/workspace-local))
|
(l/derived :picked-color-select refs/workspace-local))
|
||||||
|
|
||||||
(def picked-shift?
|
|
||||||
(l/derived :picked-shift? refs/workspace-local))
|
|
||||||
|
|
||||||
(def viewport
|
(def viewport
|
||||||
(l/derived (l/in [:workspace-local :vport]) st/state))
|
(l/derived (l/in [:workspace-local :vport]) st/state))
|
||||||
|
|
||||||
|
|
|
@ -115,7 +115,8 @@
|
||||||
:on-mouse-down #(reset! dragging? true)
|
:on-mouse-down #(reset! dragging? true)
|
||||||
:on-mouse-up #(reset! dragging? false)
|
:on-mouse-up #(reset! dragging? false)
|
||||||
:on-pointer-down (partial dom/capture-pointer)
|
:on-pointer-down (partial dom/capture-pointer)
|
||||||
:on-pointer-up (partial dom/release-pointer)
|
:on-lost-pointer-capture #(do (dom/release-pointer %)
|
||||||
|
(reset! dragging? false))
|
||||||
:on-click calculate-pos
|
:on-click calculate-pos
|
||||||
:on-mouse-move #(when @dragging? (calculate-pos %))}]
|
:on-mouse-move #(when @dragging? (calculate-pos %))}]
|
||||||
[:div.handler {:style {:pointer-events "none"
|
[:div.handler {:style {:pointer-events "none"
|
||||||
|
|
|
@ -26,7 +26,8 @@
|
||||||
{:on-mouse-down #(reset! dragging? true)
|
{:on-mouse-down #(reset! dragging? true)
|
||||||
:on-mouse-up #(reset! dragging? false)
|
:on-mouse-up #(reset! dragging? false)
|
||||||
:on-pointer-down (partial dom/capture-pointer)
|
:on-pointer-down (partial dom/capture-pointer)
|
||||||
:on-pointer-up (partial dom/release-pointer)
|
:on-lost-pointer-capture #(do (dom/release-pointer %)
|
||||||
|
(reset! dragging? false))
|
||||||
:on-click calculate-pos
|
:on-click calculate-pos
|
||||||
:on-mouse-move #(when @dragging? (calculate-pos %))}
|
:on-mouse-move #(when @dragging? (calculate-pos %))}
|
||||||
[:div.handler {:style {:pointer-events "none"
|
[:div.handler {:style {:pointer-events "none"
|
||||||
|
|
|
@ -35,7 +35,8 @@
|
||||||
:on-mouse-down #(reset! dragging? true)
|
:on-mouse-down #(reset! dragging? true)
|
||||||
:on-mouse-up #(reset! dragging? false)
|
:on-mouse-up #(reset! dragging? false)
|
||||||
:on-pointer-down (partial dom/capture-pointer)
|
:on-pointer-down (partial dom/capture-pointer)
|
||||||
:on-pointer-up (partial dom/release-pointer)
|
:on-lost-pointer-capture #(do (dom/release-pointer %)
|
||||||
|
(reset! dragging? false))
|
||||||
:on-click calculate-pos
|
:on-click calculate-pos
|
||||||
:on-mouse-move #(when @dragging? (calculate-pos %))}
|
:on-mouse-move #(when @dragging? (calculate-pos %))}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue