mirror of
https://github.com/penpot/penpot.git
synced 2025-05-05 14:15:54 +02:00
feat(frontend): refactor router
This commit is contained in:
parent
076c29e004
commit
26cdebece4
23 changed files with 418 additions and 293 deletions
|
@ -1,7 +1,7 @@
|
||||||
{:deps {org.clojure/clojurescript {:mvn/version "1.10.516"}
|
{:deps {org.clojure/clojurescript {:mvn/version "1.10.520"}
|
||||||
org.clojure/clojure {:mvn/version "1.10.1"}
|
org.clojure/clojure {:mvn/version "1.10.1"}
|
||||||
funcool/promesa {:mvn/version "2.0.0"}
|
funcool/promesa {:mvn/version "2.0.1"}
|
||||||
com.cognitect/transit-cljs {:mvn/version "0.8.239"}
|
com.cognitect/transit-cljs {:mvn/version "0.8.256"}
|
||||||
|
|
||||||
funcool/rumext {:git/url "https://github.com/funcool/rumext.git",
|
funcool/rumext {:git/url "https://github.com/funcool/rumext.git",
|
||||||
:sha "3d598e749ba429eae6544e532fc9f81369b307f5"}
|
:sha "3d598e749ba429eae6544e532fc9f81369b307f5"}
|
||||||
|
@ -12,20 +12,25 @@
|
||||||
|
|
||||||
environ/environ {:mvn/version "1.1.0"}
|
environ/environ {:mvn/version "1.1.0"}
|
||||||
|
|
||||||
funcool/beicon {:mvn/version "3.2.0"}
|
metosin/reitit-core {:mvn/version "0.3.9"}
|
||||||
funcool/bide {:mvn/version "1.6.0"}
|
metosin/reitit-frontend {:mvn/version "0.3.9"}
|
||||||
|
|
||||||
|
funcool/beicon {:mvn/version "5.0.0"}
|
||||||
|
funcool/bide {:mvn/version "1.6.1-SNAPSHOT"}
|
||||||
funcool/cuerdas {:mvn/version "2.2.0"}
|
funcool/cuerdas {:mvn/version "2.2.0"}
|
||||||
funcool/lentes {:mvn/version "1.2.0"}
|
funcool/lentes {:mvn/version "1.2.0"}
|
||||||
funcool/potok {:mvn/version "2.1.0"}
|
funcool/potok {:mvn/version "2.3.0"}
|
||||||
}
|
}
|
||||||
:paths ["src" "vendor"]
|
:paths ["src" "vendor" "resources"]
|
||||||
:aliases
|
:aliases
|
||||||
{:dev {:extra-deps {com.bhauman/rebel-readline-cljs {:mvn/version "0.1.4"}
|
{:dev {:extra-deps {com.bhauman/rebel-readline-cljs {:mvn/version "0.1.4"}
|
||||||
com.bhauman/rebel-readline {:mvn/version "0.1.4"}
|
com.bhauman/rebel-readline {:mvn/version "0.1.4"}
|
||||||
com.bhauman/figwheel-main {:mvn/version "0.2.1-SNAPSHOT"}
|
com.bhauman/figwheel-main {:mvn/version "0.2.1-SNAPSHOT"}
|
||||||
org.clojure/tools.namespace {:mvn/version "0.2.11"}}
|
org.clojure/tools.namespace {:mvn/version "0.3.0"}}
|
||||||
:extra-paths ["test"]}
|
:extra-paths ["test"]}
|
||||||
|
|
||||||
:repl {:main-opts ["-m" "rebel-readline.main"]}
|
:repl {:main-opts ["-m" "rebel-readline.main"]}
|
||||||
|
:ancient {:main-opts ["-m" "deps-ancient.deps-ancient"]
|
||||||
|
:extra-deps {deps-ancient {:mvn/version "RELEASE"}}}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,28 @@
|
||||||
;; 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/.
|
||||||
;;
|
;;
|
||||||
;; Copyright (c) 2015-2016 Andrey Antukh <niwi@niwi.nz>
|
;; Copyright (c) 2015-2019 Andrey Antukh <niwi@niwi.nz>
|
||||||
|
|
||||||
(ns uxbox.main
|
(ns ^:figwheel-hooks uxbox.main
|
||||||
(:require [uxbox.main.store :as st]
|
(:require
|
||||||
[uxbox.main.ui :as ui]
|
[rumext.core :as mx :include-macros true]
|
||||||
|
[uxbox.main.data.auth :refer [logout]]
|
||||||
[uxbox.main.locales.en :as en]
|
[uxbox.main.locales.en :as en]
|
||||||
[uxbox.main.locales.fr :as fr]
|
[uxbox.main.locales.fr :as fr]
|
||||||
[uxbox.util.i18n :as i18n]))
|
[uxbox.main.store :as st]
|
||||||
|
[uxbox.main.ui :refer [app]]
|
||||||
|
[uxbox.main.ui.lightbox :refer [lightbox]]
|
||||||
|
[uxbox.main.ui.loader :refer [loader]]
|
||||||
|
[uxbox.util.dom :as dom]
|
||||||
|
[uxbox.util.html-history :as html-history]
|
||||||
|
[uxbox.util.i18n :as i18n :refer [tr]]
|
||||||
|
[uxbox.util.messages :as uum]
|
||||||
|
[uxbox.util.router :as rt]
|
||||||
|
[uxbox.util.timers :as ts]))
|
||||||
|
|
||||||
|
;; --- i18n
|
||||||
|
|
||||||
|
(declare reinit)
|
||||||
|
|
||||||
(i18n/update-locales! (fn [locales]
|
(i18n/update-locales! (fn [locales]
|
||||||
(-> locales
|
(-> locales
|
||||||
|
@ -19,10 +33,101 @@
|
||||||
(i18n/on-locale-change!
|
(i18n/on-locale-change!
|
||||||
(fn [new old]
|
(fn [new old]
|
||||||
(println "Locale changed from" old " to " new)
|
(println "Locale changed from" old " to " new)
|
||||||
(ui/reinit)))
|
(reinit)))
|
||||||
|
|
||||||
|
;; --- Error Handling
|
||||||
|
|
||||||
|
(defn- on-error
|
||||||
|
"A default error handler."
|
||||||
|
[{:keys [status] :as error}]
|
||||||
|
(js/console.error "on-error:" (pr-str error))
|
||||||
|
(js/console.error (.-stack error))
|
||||||
|
(reset! st/loader false)
|
||||||
|
(cond
|
||||||
|
;; Unauthorized or Auth timeout
|
||||||
|
(and (:status error)
|
||||||
|
(or (= (:status error) 403)
|
||||||
|
(= (:status error) 419)))
|
||||||
|
(ts/schedule 100 #(st/emit! (logout)))
|
||||||
|
|
||||||
|
;; Conflict
|
||||||
|
(= status 412)
|
||||||
|
(ts/schedule 100 #(st/emit! (uum/error (tr "errors.conflict"))))
|
||||||
|
|
||||||
|
;; Network error
|
||||||
|
(= (:status error) 0)
|
||||||
|
(ts/schedule 100 #(st/emit! (uum/error (tr "errors.network"))))
|
||||||
|
|
||||||
|
;; Something else
|
||||||
|
:else
|
||||||
|
(ts/schedule 100 #(st/emit! (uum/error (tr "errors.generic"))))))
|
||||||
|
|
||||||
|
(set! st/*on-error* on-error)
|
||||||
|
|
||||||
|
(def routes
|
||||||
|
[["/auth"
|
||||||
|
["/login" :auth/login]
|
||||||
|
["/register" :auth/register]
|
||||||
|
["/recovery/request" :auth/recovery-request]
|
||||||
|
["/recovery/token/:token" :auth/recovery]]
|
||||||
|
["/settings"
|
||||||
|
["/profile" :settings/profile]
|
||||||
|
["/password" :settings/password]
|
||||||
|
["/notifications" :settings/notifications]]
|
||||||
|
["/dashboard"
|
||||||
|
["/projects" :dashboard/projects]
|
||||||
|
["/elements" :dashboard/elements]
|
||||||
|
["/icons" :dashboard/icons]
|
||||||
|
["/images" :dashboard/images]
|
||||||
|
["/colors" :dashboard/colors]]
|
||||||
|
["/workspace/:project/:page" :workspace/page]])
|
||||||
|
|
||||||
|
(defn- on-navigate
|
||||||
|
[router path]
|
||||||
|
(let [match (rt/match router path)]
|
||||||
|
(prn "on-navigate" path match)
|
||||||
|
(cond
|
||||||
|
(and (= path "") (nil? match))
|
||||||
|
(html-history/set-path! "/dashboard/projects")
|
||||||
|
|
||||||
|
(nil? match)
|
||||||
|
(prn "TODO 404")
|
||||||
|
|
||||||
|
:else
|
||||||
|
(st/emit! #(assoc % :route match)))))
|
||||||
|
|
||||||
|
(defn init-ui
|
||||||
|
[]
|
||||||
|
(let [router (rt/init routes)
|
||||||
|
cpath (deref html-history/path)]
|
||||||
|
|
||||||
|
(st/emit! #(assoc % :router router))
|
||||||
|
(add-watch html-history/path ::main #(on-navigate router %4))
|
||||||
|
|
||||||
|
(mx/mount (app) (dom/get-element "app"))
|
||||||
|
(mx/mount (lightbox) (dom/get-element "lightbox"))
|
||||||
|
(mx/mount (loader) (dom/get-element "loader"))
|
||||||
|
|
||||||
|
(on-navigate router cpath)))
|
||||||
|
|
||||||
(defn ^:export init
|
(defn ^:export init
|
||||||
[]
|
[]
|
||||||
(st/init)
|
(st/init)
|
||||||
(ui/init-routes)
|
(init-ui))
|
||||||
(ui/init))
|
|
||||||
|
(defn reinit
|
||||||
|
[]
|
||||||
|
(remove-watch html-history/path ::main)
|
||||||
|
(.unmountComponentAtNode js/ReactDOM (dom/get-element "app"))
|
||||||
|
(.unmountComponentAtNode js/ReactDOM (dom/get-element "lightbox"))
|
||||||
|
(.unmountComponentAtNode js/ReactDOM (dom/get-element "loader"))
|
||||||
|
(init-ui))
|
||||||
|
|
||||||
|
(defn ^:after-load after-load
|
||||||
|
[]
|
||||||
|
(reinit))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
(defrecord Login [username password]
|
(defrecord Login [username password]
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(merge state (dissoc (initial-state) :route)))
|
(merge state (dissoc initial-state :route :router)))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [this state s]
|
(watch [this state s]
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
:password password
|
:password password
|
||||||
:scope "webapp"}
|
:scope "webapp"}
|
||||||
on-error #(rx/of (uum/error (tr "errors.auth.unauthorized")))]
|
on-error #(rx/of (uum/error (tr "errors.auth.unauthorized")))]
|
||||||
(->> (rp/req :fetch/token params)
|
(->> (rp/req :auth/login params)
|
||||||
(rx/map :payload)
|
(rx/map :payload)
|
||||||
(rx/map logged-in)
|
(rx/map logged-in)
|
||||||
(rx/catch rp/client-error? on-error)))))
|
(rx/catch rp/client-error? on-error)))))
|
||||||
|
@ -78,11 +78,12 @@
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(swap! storage dissoc :auth)
|
(swap! storage dissoc :auth)
|
||||||
(merge state (dissoc (initial-state) :route)))
|
(merge state (dissoc initial-state :route :router)))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state s]
|
(watch [_ state s]
|
||||||
(rx/of (rt/navigate :auth/login))))
|
(->> (rp/req :auth/logout)
|
||||||
|
(rx/map (constantly (rt/nav :auth/login))))))
|
||||||
|
|
||||||
(defn logout
|
(defn logout
|
||||||
[]
|
[]
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
[uxbox.main.store :as st]
|
[uxbox.main.store :as st]
|
||||||
[uxbox.main.repo :as rp]
|
[uxbox.main.repo :as rp]
|
||||||
[uxbox.util.i18n :refer [tr]]
|
[uxbox.util.i18n :refer [tr]]
|
||||||
|
[uxbox.util.router :as rt]
|
||||||
[uxbox.util.data :refer (jscoll->vec)]
|
[uxbox.util.data :refer (jscoll->vec)]
|
||||||
[uxbox.util.uuid :as uuid]
|
[uxbox.util.uuid :as uuid]
|
||||||
[uxbox.util.time :as ts]
|
[uxbox.util.time :as ts]
|
||||||
|
@ -80,21 +81,6 @@
|
||||||
[type id]
|
[type id]
|
||||||
(Initialize. type id))
|
(Initialize. type id))
|
||||||
|
|
||||||
;; --- Select a Collection
|
|
||||||
|
|
||||||
(defrecord SelectCollection [type id]
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state stream]
|
|
||||||
(rx/of (r/navigate :dashboard/images
|
|
||||||
{:type type :id id}))))
|
|
||||||
|
|
||||||
(defn select-collection
|
|
||||||
([type]
|
|
||||||
(select-collection type nil))
|
|
||||||
([type id]
|
|
||||||
{:pre [(keyword? type)]}
|
|
||||||
(SelectCollection. type id)))
|
|
||||||
|
|
||||||
;; --- Color Collections Fetched
|
;; --- Color Collections Fetched
|
||||||
|
|
||||||
(defrecord CollectionsFetched [items]
|
(defrecord CollectionsFetched [items]
|
||||||
|
@ -135,7 +121,7 @@
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(rx/of (select-collection :own (:id item)))))
|
(rx/of (rt/nav :dashboard/images nil {:type :own :id (:id item)}))))
|
||||||
|
|
||||||
(defn collection-created
|
(defn collection-created
|
||||||
[item]
|
[item]
|
||||||
|
@ -213,7 +199,7 @@
|
||||||
(watch [_ state s]
|
(watch [_ state s]
|
||||||
(let [type (get-in state [:dashboard :images :type])]
|
(let [type (get-in state [:dashboard :images :type])]
|
||||||
(->> (rp/req :delete/image-collection id)
|
(->> (rp/req :delete/image-collection id)
|
||||||
(rx/map #(select-collection type))))))
|
(rx/map #(rt/nav :dashboard/images nil {:type type}))))))
|
||||||
|
|
||||||
(defn delete-collection
|
(defn delete-collection
|
||||||
[id]
|
[id]
|
||||||
|
|
|
@ -70,4 +70,5 @@
|
||||||
(when (:shapes page)
|
(when (:shapes page)
|
||||||
(dom/render-to-html (page-svg page))))
|
(dom/render-to-html (page-svg page))))
|
||||||
(catch :default e
|
(catch :default e
|
||||||
|
(js/console.log e)
|
||||||
nil)))
|
nil)))
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
(let [url (str url "/profile/me")]
|
(let [url (str url "/profile/me")]
|
||||||
(send! {:method :get :url url})))
|
(send! {:method :get :url url})))
|
||||||
|
|
||||||
(defmethod request :fetch/token
|
(defmethod request :auth/login
|
||||||
[type data]
|
[type data]
|
||||||
(let [url (str url "/auth/login")]
|
(let [url (str url "/auth/login")]
|
||||||
(send! {:url url
|
(send! {:url url
|
||||||
|
@ -23,6 +23,12 @@
|
||||||
:auth false
|
:auth false
|
||||||
:body data})))
|
:body data})))
|
||||||
|
|
||||||
|
|
||||||
|
(defmethod request :auth/logout
|
||||||
|
[type data]
|
||||||
|
(let [url (str url "/auth/logout")]
|
||||||
|
(send! {:url url :method :post :auth false})))
|
||||||
|
|
||||||
(defmethod request :update/profile
|
(defmethod request :update/profile
|
||||||
[type data]
|
[type data]
|
||||||
(let [params {:url (str url "/profile/me")
|
(let [params {:url (str url "/profile/me")
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
(defmethod request :fetch/project-by-token
|
(defmethod request :fetch/project-by-token
|
||||||
[_ token]
|
[_ token]
|
||||||
(send! {:url (str url "/projects-by-token/" token)
|
(send! {:url (str url "/projects/by-token/" token)
|
||||||
:method :get}))
|
:method :get}))
|
||||||
|
|
||||||
(defmethod request :create/project
|
(defmethod request :create/project
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
[potok.core :as ptk]
|
[potok.core :as ptk]
|
||||||
[uxbox.builtins.colors :as colors]
|
[uxbox.builtins.colors :as colors]
|
||||||
[uxbox.util.storage :refer [storage]]))
|
[uxbox.util.storage :refer [storage]]))
|
||||||
|
|
||||||
(enable-console-print!)
|
(enable-console-print!)
|
||||||
|
|
||||||
(def ^:dynamic *on-error* identity)
|
(def ^:dynamic *on-error* identity)
|
||||||
|
@ -30,13 +29,13 @@
|
||||||
([event & events]
|
([event & events]
|
||||||
(apply ptk/emit! store (cons event events))))
|
(apply ptk/emit! store (cons event events))))
|
||||||
|
|
||||||
(defn initial-state
|
(def initial-state
|
||||||
[]
|
|
||||||
{:dashboard {:project-order :name
|
{:dashboard {:project-order :name
|
||||||
:project-filter ""
|
:project-filter ""
|
||||||
:images-order :name
|
:images-order :name
|
||||||
:images-filter ""}
|
:images-filter ""}
|
||||||
:route nil
|
:route nil
|
||||||
|
:router nil
|
||||||
:auth (:auth storage nil)
|
:auth (:auth storage nil)
|
||||||
:clipboard #queue []
|
:clipboard #queue []
|
||||||
:undo {}
|
:undo {}
|
||||||
|
@ -53,6 +52,7 @@
|
||||||
|
|
||||||
(defn init
|
(defn init
|
||||||
"Initialize the state materialization."
|
"Initialize the state materialization."
|
||||||
[]
|
([] (init {}))
|
||||||
(emit! initial-state)
|
([props]
|
||||||
(rx/to-atom store state))
|
(emit! #(merge % initial-state props))
|
||||||
|
(rx/to-atom store state)))
|
||||||
|
|
|
@ -5,11 +5,10 @@
|
||||||
;; Copyright (c) 2015-2017 Andrey Antukh <niwi@niwi.nz>
|
;; Copyright (c) 2015-2017 Andrey Antukh <niwi@niwi.nz>
|
||||||
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||||
|
|
||||||
(ns ^:figwheel-hooks uxbox.main.ui
|
(ns uxbox.main.ui
|
||||||
(:require [beicon.core :as rx]
|
(:require [beicon.core :as rx]
|
||||||
[lentes.core :as l]
|
[lentes.core :as l]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[bide.core :as bc]
|
|
||||||
[potok.core :as ptk]
|
[potok.core :as ptk]
|
||||||
[uxbox.builtins.icons :as i]
|
[uxbox.builtins.icons :as i]
|
||||||
[uxbox.main.store :as st]
|
[uxbox.main.store :as st]
|
||||||
|
@ -24,6 +23,7 @@
|
||||||
[uxbox.main.ui.workspace :refer [workspace]]
|
[uxbox.main.ui.workspace :refer [workspace]]
|
||||||
[uxbox.main.ui.shapes]
|
[uxbox.main.ui.shapes]
|
||||||
[uxbox.util.messages :as uum]
|
[uxbox.util.messages :as uum]
|
||||||
|
[uxbox.util.html-history :as html-history]
|
||||||
[uxbox.util.router :as rt]
|
[uxbox.util.router :as rt]
|
||||||
[uxbox.util.timers :as ts]
|
[uxbox.util.timers :as ts]
|
||||||
[uxbox.util.i18n :refer [tr]]
|
[uxbox.util.i18n :refer [tr]]
|
||||||
|
@ -33,48 +33,10 @@
|
||||||
|
|
||||||
;; --- Constants
|
;; --- Constants
|
||||||
|
|
||||||
(def +unrestricted+
|
|
||||||
#{:auth/login
|
|
||||||
:auth/register
|
|
||||||
:auth/recovery-request
|
|
||||||
:auth/recovery})
|
|
||||||
|
|
||||||
(def restricted?
|
|
||||||
(complement +unrestricted+))
|
|
||||||
|
|
||||||
(def route-ref
|
(def route-ref
|
||||||
(-> (l/key :route)
|
(-> (l/key :route)
|
||||||
(l/derive st/state)))
|
(l/derive st/state)))
|
||||||
|
|
||||||
;; --- Error Handling
|
|
||||||
|
|
||||||
(defn- on-error
|
|
||||||
"A default error handler."
|
|
||||||
[{:keys [status] :as error}]
|
|
||||||
(js/console.error "on-error:" (pr-str error))
|
|
||||||
(js/console.error (.-stack error))
|
|
||||||
(reset! st/loader false)
|
|
||||||
(cond
|
|
||||||
;; Unauthorized or Auth timeout
|
|
||||||
(and (:status error)
|
|
||||||
(or (= (:status error) 403)
|
|
||||||
(= (:status error) 419)))
|
|
||||||
(ts/schedule 100 #(st/emit! (logout)))
|
|
||||||
|
|
||||||
;; Conflict
|
|
||||||
(= status 412)
|
|
||||||
(ts/schedule 100 #(st/emit! (uum/error (tr "errors.conflict"))))
|
|
||||||
|
|
||||||
;; Network error
|
|
||||||
(= (:status error) 0)
|
|
||||||
(ts/schedule 100 #(st/emit! (uum/error (tr "errors.network"))))
|
|
||||||
|
|
||||||
;; Something else
|
|
||||||
:else
|
|
||||||
(ts/schedule 100 #(st/emit! (uum/error (tr "errors.generic"))))))
|
|
||||||
|
|
||||||
(set! st/*on-error* on-error)
|
|
||||||
|
|
||||||
;; --- Main App (Component)
|
;; --- Main App (Component)
|
||||||
|
|
||||||
(defn app-will-mount
|
(defn app-will-mount
|
||||||
|
@ -88,35 +50,34 @@
|
||||||
:mixins [mx/reactive]}
|
:mixins [mx/reactive]}
|
||||||
[]
|
[]
|
||||||
(let [route (mx/react route-ref)
|
(let [route (mx/react route-ref)
|
||||||
auth (mx/react st/auth-ref)
|
auth (mx/react st/auth-ref)]
|
||||||
location (:id route)
|
(prn "main$app" route)
|
||||||
params (:params route)]
|
(case (get-in route [:data :name])
|
||||||
(if (and (restricted? location) (not auth))
|
|
||||||
(do (ts/schedule 0 #(st/emit! (rt/navigate :auth/login))) nil)
|
|
||||||
(case location
|
|
||||||
:auth/login (auth/login-page)
|
:auth/login (auth/login-page)
|
||||||
:auth/register (auth/register-page)
|
:auth/register (auth/register-page)
|
||||||
:auth/recovery-request (auth/recovery-request-page)
|
:auth/recovery-request (auth/recovery-request-page)
|
||||||
:auth/recovery (auth/recovery-page (:token params))
|
:auth/recovery (let [token (get-in route [:params :path :token])]
|
||||||
|
(auth/recovery-page token))
|
||||||
:dashboard/projects (dashboard/projects-page)
|
:dashboard/projects (dashboard/projects-page)
|
||||||
;; :dashboard/elements (dashboard/elements-page)
|
;; ;; :dashboard/elements (dashboard/elements-page)
|
||||||
:dashboard/icons (let [{:keys [id type]} params
|
|
||||||
type (when (str/alpha? type) (keyword type))
|
:dashboard/icons (let [{:keys [id type]} (get-in route [:params :query])
|
||||||
id (cond
|
id (cond
|
||||||
(str/digits? id) (parse-int id)
|
(str/digits? id) (parse-int id)
|
||||||
(uuid-str? id) (uuid id)
|
(uuid-str? id) (uuid id)
|
||||||
:else nil)]
|
:else nil)
|
||||||
|
type (when (str/alpha? type) (keyword type))]
|
||||||
(dashboard/icons-page type id))
|
(dashboard/icons-page type id))
|
||||||
|
|
||||||
:dashboard/images (let [{:keys [id type]} params
|
:dashboard/images (let [{:keys [id type]} (get-in route [:params :query])
|
||||||
type (when (str/alpha? type) (keyword type))
|
|
||||||
id (cond
|
id (cond
|
||||||
(str/digits? id) (parse-int id)
|
(str/digits? id) (parse-int id)
|
||||||
(uuid-str? id) (uuid id)
|
(uuid-str? id) (uuid id)
|
||||||
:else nil)]
|
:else nil)
|
||||||
|
type (when (str/alpha? type) (keyword type))]
|
||||||
(dashboard/images-page type id))
|
(dashboard/images-page type id))
|
||||||
|
|
||||||
:dashboard/colors (let [{:keys [id type]} params
|
:dashboard/colors (let [{:keys [id type]} (get-in route [:params :query])
|
||||||
type (when (str/alpha? type) (keyword type))
|
type (when (str/alpha? type) (keyword type))
|
||||||
id (cond
|
id (cond
|
||||||
(str/digits? id) (parse-int id)
|
(str/digits? id) (parse-int id)
|
||||||
|
@ -126,57 +87,8 @@
|
||||||
:settings/profile (settings/profile-page)
|
:settings/profile (settings/profile-page)
|
||||||
:settings/password (settings/password-page)
|
:settings/password (settings/password-page)
|
||||||
:settings/notifications (settings/notifications-page)
|
:settings/notifications (settings/notifications-page)
|
||||||
:workspace/page (let [projectid (uuid (:project params))
|
:workspace/page (let [projectid (uuid (get-in route [:params :path :project]))
|
||||||
pageid (uuid (:page params))]
|
pageid (uuid (get-in route [:params :path :page]))]
|
||||||
(workspace projectid pageid))
|
(workspace projectid pageid))
|
||||||
nil
|
nil
|
||||||
))))
|
)))
|
||||||
|
|
||||||
;; --- Routes
|
|
||||||
|
|
||||||
(def routes
|
|
||||||
[["/auth/login" :auth/login]
|
|
||||||
["/auth/register" :auth/register]
|
|
||||||
["/auth/recovery/request" :auth/recovery-request]
|
|
||||||
["/auth/recovery/token/:token" :auth/recovery]
|
|
||||||
["/settings/profile" :settings/profile]
|
|
||||||
["/settings/password" :settings/password]
|
|
||||||
["/settings/notifications" :settings/notifications]
|
|
||||||
["/dashboard/projects" :dashboard/projects]
|
|
||||||
["/dashboard/elements" :dashboard/elements]
|
|
||||||
|
|
||||||
["/dashboard/icons" :dashboard/icons]
|
|
||||||
["/dashboard/icons/:type/:id" :dashboard/icons]
|
|
||||||
["/dashboard/icons/:type" :dashboard/icons]
|
|
||||||
|
|
||||||
["/dashboard/images" :dashboard/images]
|
|
||||||
["/dashboard/images/:type/:id" :dashboard/images]
|
|
||||||
["/dashboard/images/:type" :dashboard/images]
|
|
||||||
|
|
||||||
["/dashboard/colors" :dashboard/colors]
|
|
||||||
["/dashboard/colors/:type/:id" :dashboard/colors]
|
|
||||||
["/dashboard/colors/:type" :dashboard/colors]
|
|
||||||
|
|
||||||
["/workspace/:project/:page" :workspace/page]])
|
|
||||||
|
|
||||||
;; --- Main Entry Point
|
|
||||||
|
|
||||||
(defn init-routes
|
|
||||||
[]
|
|
||||||
(rt/init st/store routes {:default :auth/login}))
|
|
||||||
|
|
||||||
(defn ^:export init
|
|
||||||
[]
|
|
||||||
(mx/mount (app) (dom/get-element "app"))
|
|
||||||
(mx/mount (lightbox) (dom/get-element "lightbox"))
|
|
||||||
(mx/mount (loader) (dom/get-element "loader")))
|
|
||||||
|
|
||||||
(defn reinit
|
|
||||||
[]
|
|
||||||
(.unmountComponentAtNode js/ReactDOM (dom/get-element "app"))
|
|
||||||
(.unmountComponentAtNode js/ReactDOM (dom/get-element "lightbox"))
|
|
||||||
(.unmountComponentAtNode js/ReactDOM (dom/get-element "loader"))
|
|
||||||
(init))
|
|
||||||
|
|
||||||
(defn ^:after-load my-after-reload-callback []
|
|
||||||
(reinit))
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
[uxbox.builtins.icons :as i]
|
[uxbox.builtins.icons :as i]
|
||||||
[uxbox.main.ui.users :as ui.u]
|
[uxbox.main.ui.users :as ui.u]
|
||||||
[uxbox.util.i18n :refer (tr)]
|
[uxbox.util.i18n :refer (tr)]
|
||||||
[uxbox.util.router :as r]
|
[uxbox.util.router :as rt]
|
||||||
[rumext.core :as mx :include-macros true]))
|
[rumext.core :as mx :include-macros true]))
|
||||||
|
|
||||||
(def header-ref
|
(def header-ref
|
||||||
|
@ -22,8 +22,8 @@
|
||||||
|
|
||||||
(mx/defc header-link
|
(mx/defc header-link
|
||||||
[section content]
|
[section content]
|
||||||
(let [link (r/route-for section)]
|
(let [on-click #(st/emit! (rt/navigate section))]
|
||||||
[:a {:href (str "/#" link)} content]))
|
[:a {:on-click on-click} content]))
|
||||||
|
|
||||||
(mx/defc header
|
(mx/defc header
|
||||||
{:mixins [mx/static mx/reactive]}
|
{:mixins [mx/static mx/reactive]}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
[uxbox.main.ui.lightbox :as lbx]
|
[uxbox.main.ui.lightbox :as lbx]
|
||||||
[uxbox.main.ui.dashboard.header :refer (header)]
|
[uxbox.main.ui.dashboard.header :refer (header)]
|
||||||
[uxbox.main.ui.keyboard :as kbd]
|
[uxbox.main.ui.keyboard :as kbd]
|
||||||
|
[uxbox.util.router :as rt]
|
||||||
[uxbox.util.i18n :as t :refer (tr)]
|
[uxbox.util.i18n :as t :refer (tr)]
|
||||||
[uxbox.util.data :refer (read-string)]
|
[uxbox.util.data :refer (read-string)]
|
||||||
[rumext.core :as mx :include-macros true]
|
[rumext.core :as mx :include-macros true]
|
||||||
|
@ -135,7 +136,7 @@
|
||||||
local (:rum/local own)]
|
local (:rum/local own)]
|
||||||
(letfn [(on-click [event]
|
(letfn [(on-click [event]
|
||||||
(let [type (or type :own)]
|
(let [type (or type :own)]
|
||||||
(st/emit! (di/select-collection type id))))
|
(st/emit! (rt/navigate :dashboard/icons {} {:type type :id id}))))
|
||||||
(on-input-change [event]
|
(on-input-change [event]
|
||||||
(let [value (dom/get-target event)
|
(let [value (dom/get-target event)
|
||||||
value (dom/get-value value)]
|
value (dom/get-value value)]
|
||||||
|
@ -199,8 +200,8 @@
|
||||||
(let [colls (->> (map second colls)
|
(let [colls (->> (map second colls)
|
||||||
(filter #(= :builtin (:type %)))
|
(filter #(= :builtin (:type %)))
|
||||||
(sort-by :name))]
|
(sort-by :name))]
|
||||||
(st/emit! (di/select-collection type (:id (first colls)))))
|
(st/emit! (rt/navigate :dashboard/icons {} {:type type :id (first colls)})))
|
||||||
(st/emit! (di/select-collection type))))]
|
(st/emit! (rt/navigate :dashboard/icons {} {:type type}))))]
|
||||||
[:div.library-bar {}
|
[:div.library-bar {}
|
||||||
[:div.library-bar-inside {}
|
[:div.library-bar-inside {}
|
||||||
[:ul.library-tabs {}
|
[:ul.library-tabs {}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
[uxbox.main.ui.lightbox :as lbx]
|
[uxbox.main.ui.lightbox :as lbx]
|
||||||
[uxbox.main.ui.keyboard :as kbd]
|
[uxbox.main.ui.keyboard :as kbd]
|
||||||
[uxbox.main.ui.dashboard.header :refer [header]]
|
[uxbox.main.ui.dashboard.header :refer [header]]
|
||||||
|
[uxbox.util.router :as rt]
|
||||||
[uxbox.util.time :as dt]
|
[uxbox.util.time :as dt]
|
||||||
[uxbox.util.data :refer [read-string jscoll->vec]]
|
[uxbox.util.data :refer [read-string jscoll->vec]]
|
||||||
[uxbox.util.dom :as dom]))
|
[uxbox.util.dom :as dom]))
|
||||||
|
@ -130,7 +131,7 @@
|
||||||
[{:keys [rum/local] :as own} {:keys [id type name num-images] :as coll} selected?]
|
[{:keys [rum/local] :as own} {:keys [id type name num-images] :as coll} selected?]
|
||||||
(letfn [(on-click [event]
|
(letfn [(on-click [event]
|
||||||
(let [type (or type :own)]
|
(let [type (or type :own)]
|
||||||
(st/emit! (di/select-collection type id))))
|
(st/emit! (rt/nav :dashboard/images {} {:type type :id id}))))
|
||||||
(on-input-change [event]
|
(on-input-change [event]
|
||||||
(let [value (dom/get-target event)
|
(let [value (dom/get-target event)
|
||||||
value (dom/get-value value)]
|
value (dom/get-value value)]
|
||||||
|
@ -192,14 +193,14 @@
|
||||||
builtin? (= type :builtin)]
|
builtin? (= type :builtin)]
|
||||||
(letfn [(select-tab [type]
|
(letfn [(select-tab [type]
|
||||||
(if own?
|
(if own?
|
||||||
(st/emit! (di/select-collection type))
|
(st/emit! (rt/nav :dashboard/images nil {:type type}))
|
||||||
(let [coll (->> (map second colls)
|
(let [coll (->> (map second colls)
|
||||||
(filter #(= type (:type %)))
|
(filter #(= type (:type %)))
|
||||||
(sort-by :name)
|
(sort-by :name)
|
||||||
(first))]
|
(first))]
|
||||||
(if coll
|
(if coll
|
||||||
(st/emit! (di/select-collection type (:id coll)))
|
(st/emit! (rt/nav :dashboard/images nil {:type type :id (:id coll)}))
|
||||||
(st/emit! (di/select-collection type))))))]
|
(st/emit! (rt/nav :dashboard/images nil {:type type}))))))]
|
||||||
[:div.library-bar {}
|
[:div.library-bar {}
|
||||||
[:div.library-bar-inside {}
|
[:div.library-bar-inside {}
|
||||||
[:ul.library-tabs {}
|
[:ul.library-tabs {}
|
||||||
|
|
|
@ -123,7 +123,7 @@
|
||||||
[:p.info {} "Download a single page of your project in SVG."]
|
[:p.info {} "Download a single page of your project in SVG."]
|
||||||
[:select.input-select {:ref "page" :default-value (pr-str current)}
|
[:select.input-select {:ref "page" :default-value (pr-str current)}
|
||||||
(for [{:keys [id name]} pages]
|
(for [{:keys [id name]} pages]
|
||||||
[:option {:value (pr-str id)} name])]
|
[:option {:value (pr-str id) :key (pr-str id)} name])]
|
||||||
[:a.btn-primary {:href "#" :on-click download-page} "Download page"]]
|
[:a.btn-primary {:href "#" :on-click download-page} "Download page"]]
|
||||||
[:div.content-col {}
|
[:div.content-col {}
|
||||||
[:span.icon {} i/folder-zip]
|
[:span.icon {} i/folder-zip]
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
pages (deref refs/selected-project-pages)
|
pages (deref refs/selected-project-pages)
|
||||||
index (index-of pages page)
|
index (index-of pages page)
|
||||||
rval (rand-int 1000000)
|
rval (rand-int 1000000)
|
||||||
url (str cfg/viewurl "?v=" rval "#/" token "/" index)]
|
url (str cfg/viewurl "?v=" rval "#/preview/" token "/" index)]
|
||||||
(st/emit! (udp/persist-page (:id page) #(js/open url "new tab" "")))))
|
(st/emit! (udp/persist-page (:id page) #(js/open url "new tab" "")))))
|
||||||
|
|
||||||
(mx/defc header
|
(mx/defc header
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
(defn render-to-html
|
(defn render-to-html
|
||||||
[component]
|
[component]
|
||||||
(.renderToStatciMarkup js/ReactDOMServer component))
|
(.renderToStaticMarkup js/ReactDOMServer component))
|
||||||
|
|
||||||
(defn get-element-by-class
|
(defn get-element-by-class
|
||||||
([classname]
|
([classname]
|
||||||
|
|
29
frontend/src/uxbox/util/html_history.cljs
Normal file
29
frontend/src/uxbox/util/html_history.cljs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
;; 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.util.html-history
|
||||||
|
"A singleton abstraction for the html5 fragment based history."
|
||||||
|
(:require [goog.events :as e])
|
||||||
|
(:import bide.impl.TokenTransformer
|
||||||
|
goog.history.Html5History
|
||||||
|
goog.history.EventType))
|
||||||
|
|
||||||
|
(defonce +instance+
|
||||||
|
(doto (Html5History. nil (TokenTransformer.))
|
||||||
|
(.setUseFragment true)
|
||||||
|
(.setEnabled true)))
|
||||||
|
|
||||||
|
(defonce path (atom (.getToken +instance+)))
|
||||||
|
|
||||||
|
(e/listen +instance+ EventType.NAVIGATE #(reset! path (.-token %)))
|
||||||
|
|
||||||
|
(defn set-path!
|
||||||
|
[path]
|
||||||
|
(.setToken +instance+ path))
|
||||||
|
|
||||||
|
(defn replace-path!
|
||||||
|
[path]
|
||||||
|
(.replaceToken +instance+ path))
|
|
@ -2,65 +2,104 @@
|
||||||
;; 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/.
|
||||||
;;
|
;;
|
||||||
;; Copyright (c) 2015-2017 Andrey Antukh <niwi@niwi.nz>
|
;; Copyright (c) 2015-2019 Andrey Antukh <niwi@niwi.nz>
|
||||||
|
|
||||||
(ns uxbox.util.router
|
(ns uxbox.util.router
|
||||||
(:require [bide.core :as r]
|
(:require [reitit.core :as r]
|
||||||
[beicon.core :as rx]
|
[cuerdas.core :as str]
|
||||||
[potok.core :as ptk]))
|
[potok.core :as ptk]
|
||||||
|
[uxbox.util.html-history :as html-history])
|
||||||
|
(:import goog.Uri
|
||||||
|
goog.Uri.QueryData))
|
||||||
|
|
||||||
(defonce +router+ nil)
|
(defonce +router+ nil)
|
||||||
|
|
||||||
;; --- Update Location (Event)
|
;; --- API
|
||||||
|
|
||||||
(deftype UpdateLocation [id params]
|
(defn- parse-query-data
|
||||||
ptk/UpdateEvent
|
[^QueryData qdata]
|
||||||
(update [_ state]
|
(persistent!
|
||||||
(let [route (merge {:id id}
|
(reduce (fn [acc key]
|
||||||
(when params
|
(let [values (.getValues qdata key)
|
||||||
{:params params}))]
|
rkey (str/keyword key)]
|
||||||
(assoc state :route route))))
|
(cond
|
||||||
|
(> (alength values) 1)
|
||||||
|
(assoc! acc rkey (into [] values))
|
||||||
|
|
||||||
(defn update-location?
|
(= (alength values) 1)
|
||||||
[v]
|
(assoc! acc rkey (aget values 0))
|
||||||
(instance? UpdateLocation v))
|
|
||||||
|
|
||||||
(defn update-location
|
:else
|
||||||
[name params]
|
acc)))
|
||||||
(UpdateLocation. name params))
|
(transient {})
|
||||||
|
(.getKeys qdata))))
|
||||||
|
|
||||||
;; --- Navigate (Event)
|
(defn- resolve-url
|
||||||
|
([router id] (resolve-url router id {} {}))
|
||||||
(deftype Navigate [id params]
|
([router id params] (resolve-url router id params {}))
|
||||||
ptk/EffectEvent
|
([router id params qparams]
|
||||||
(effect [_ state stream]
|
(when-let [match (r/match-by-name router id params)]
|
||||||
(r/navigate! +router+ id params)))
|
(if (empty? qparams)
|
||||||
|
(r/match->path match)
|
||||||
(defn navigate
|
(let [uri (.parse goog.Uri (r/match->path match))
|
||||||
([id] (navigate id nil))
|
qdt (.createFromMap QueryData (clj->js qparams))]
|
||||||
([id params]
|
(.setQueryData uri qdt)
|
||||||
{:pre [(keyword? id)]}
|
(.toString uri))))))
|
||||||
(Navigate. id params)))
|
|
||||||
|
|
||||||
;; --- Public Api
|
|
||||||
|
|
||||||
(defn init
|
(defn init
|
||||||
[store routes {:keys [default] :or {default :auth/login}}]
|
[routes]
|
||||||
(let [opts {:on-navigate #(ptk/emit! store (update-location %1 %2))
|
(r/router routes))
|
||||||
:default default}
|
|
||||||
router (-> (r/router routes)
|
(defn query-params
|
||||||
(r/start! opts))]
|
"Given goog.Uri, read query parameters into Clojure map."
|
||||||
(set! +router+ router)
|
[^goog.Uri uri]
|
||||||
router))
|
(let [q (.getQueryData uri)]
|
||||||
|
(->> q
|
||||||
|
(.getKeys)
|
||||||
|
(map (juxt keyword #(.get q %)))
|
||||||
|
(into {}))))
|
||||||
|
|
||||||
|
(defn navigate!
|
||||||
|
([router id] (navigate! router id {} {}))
|
||||||
|
([router id params] (navigate! router id params {}))
|
||||||
|
([router id params qparams]
|
||||||
|
(-> (resolve-url router id params qparams)
|
||||||
|
(html-history/set-path!))))
|
||||||
|
|
||||||
|
(defn match
|
||||||
|
"Given routing tree and current path, return match with possibly
|
||||||
|
coerced parameters. Return nil if no match found."
|
||||||
|
[router path]
|
||||||
|
(let [uri (.parse Uri path)]
|
||||||
|
(when-let [match (r/match-by-path router (.getPath uri))]
|
||||||
|
(let [qparams (parse-query-data (.getQueryData uri))
|
||||||
|
params {:path (:path-params match) :query qparams}]
|
||||||
|
(assoc match
|
||||||
|
:params params
|
||||||
|
:query-params qparams)))))
|
||||||
|
|
||||||
(defn route-for
|
(defn route-for
|
||||||
"Given a location handler and optional parameter map, return the URI
|
"Given a location handler and optional parameter map, return the URI
|
||||||
for such handler and parameters."
|
for such handler and parameters."
|
||||||
([id]
|
([id] (route-for id {}))
|
||||||
(if +router+
|
|
||||||
(r/resolve +router+ id)
|
|
||||||
""))
|
|
||||||
([id params]
|
([id params]
|
||||||
(if +router+
|
(str (some-> +router+ (resolve-url id params)))))
|
||||||
(r/resolve +router+ id params)
|
|
||||||
"")))
|
;; --- Navigate (Event)
|
||||||
|
|
||||||
|
(deftype Navigate [id params qparams]
|
||||||
|
ptk/EffectEvent
|
||||||
|
(effect [_ state stream]
|
||||||
|
(let [router (:router state)]
|
||||||
|
(prn "Navigate:" id params qparams "| Match:" (resolve-url router id params qparams))
|
||||||
|
(navigate! router id params qparams))))
|
||||||
|
|
||||||
|
(defn nav
|
||||||
|
([id] (navigate id nil nil))
|
||||||
|
([id params] (navigate id params nil))
|
||||||
|
([id params qparams]
|
||||||
|
{:pre [(keyword? id)]}
|
||||||
|
(Navigate. id params qparams)))
|
||||||
|
|
||||||
|
(def navigate nav)
|
||||||
|
|
||||||
|
|
|
@ -4,26 +4,101 @@
|
||||||
;;
|
;;
|
||||||
;; Copyright (c) 2016-2017 Andrey Antukh <niwi@niwi.nz>
|
;; Copyright (c) 2016-2017 Andrey Antukh <niwi@niwi.nz>
|
||||||
|
|
||||||
(ns uxbox.view
|
(ns ^:figwheel-hooks uxbox.view
|
||||||
(:require [uxbox.config]
|
(:require
|
||||||
|
[rumext.core :as mx :include-macros true]
|
||||||
|
[uxbox.config]
|
||||||
|
[uxbox.util.dom :as dom]
|
||||||
|
[uxbox.util.html-history :as html-history]
|
||||||
|
[uxbox.util.i18n :as i18n :refer [tr]]
|
||||||
|
[uxbox.util.messages :as uum]
|
||||||
|
[uxbox.util.router :as rt]
|
||||||
|
[uxbox.view.locales.en :as en]
|
||||||
|
[uxbox.view.locales.fr :as fr]
|
||||||
[uxbox.view.store :as st]
|
[uxbox.view.store :as st]
|
||||||
[uxbox.view.ui :as ui]
|
[uxbox.view.ui :refer [app]]
|
||||||
[uxbox.main.locales.en :as en]
|
[uxbox.view.ui.lightbox :refer [lightbox]]
|
||||||
[uxbox.main.locales.fr :as fr]
|
[uxbox.view.ui.loader :refer [loader]]))
|
||||||
[uxbox.util.i18n :as i18n]))
|
|
||||||
|
|
||||||
(i18n/update-locales! (fn [locales]
|
(i18n/update-locales! (fn [locales]
|
||||||
(-> locales
|
(-> locales
|
||||||
(assoc :en en/locales)
|
(assoc :en en/locales)
|
||||||
(assoc :fr fr/locales))))
|
(assoc :fr fr/locales))))
|
||||||
|
|
||||||
|
(declare reinit)
|
||||||
|
|
||||||
(i18n/on-locale-change!
|
(i18n/on-locale-change!
|
||||||
(fn [new old]
|
(fn [new old]
|
||||||
(println "Locale changed from" old " to " new)
|
(println "Locale changed from" old " to " new)
|
||||||
(ui/init)))
|
(reinit)))
|
||||||
|
|
||||||
|
(defn- on-error
|
||||||
|
"A default error handler."
|
||||||
|
[error]
|
||||||
|
(cond
|
||||||
|
;; Network error
|
||||||
|
(= (:status error) 0)
|
||||||
|
(do
|
||||||
|
(st/emit! (uum/error (tr "errors.network")))
|
||||||
|
(js/console.error "Stack:" (.-stack error)))
|
||||||
|
|
||||||
|
;; Something else
|
||||||
|
:else
|
||||||
|
(do
|
||||||
|
(st/emit! (uum/error (tr "errors.generic")))
|
||||||
|
(js/console.error "Stack:" (.-stack error)))))
|
||||||
|
|
||||||
|
(set! st/*on-error* on-error)
|
||||||
|
|
||||||
|
;; --- Routes
|
||||||
|
|
||||||
|
(def routes
|
||||||
|
[["/preview/:token/:index" :view/viewer]
|
||||||
|
["/not-found" :view/notfound]])
|
||||||
|
|
||||||
|
(defn- on-navigate
|
||||||
|
[router path]
|
||||||
|
(let [match (rt/match router path)]
|
||||||
|
(prn "on-navigate" path match)
|
||||||
|
(cond
|
||||||
|
(and (= path "") (nil? match))
|
||||||
|
(html-history/set-path! "/not-found")
|
||||||
|
|
||||||
|
(nil? match)
|
||||||
|
(prn "TODO 404")
|
||||||
|
|
||||||
|
:else
|
||||||
|
(st/emit! #(assoc % :route match)))))
|
||||||
|
|
||||||
|
(defn init-ui
|
||||||
|
[]
|
||||||
|
(let [router (rt/init routes)
|
||||||
|
cpath (deref html-history/path)]
|
||||||
|
|
||||||
|
(st/emit! #(assoc % :router router))
|
||||||
|
(add-watch html-history/path ::view #(on-navigate router %4))
|
||||||
|
|
||||||
|
(mx/mount (app) (dom/get-element "app"))
|
||||||
|
(mx/mount (lightbox) (dom/get-element "lightbox"))
|
||||||
|
(mx/mount (loader) (dom/get-element "loader"))
|
||||||
|
|
||||||
|
(on-navigate router cpath)))
|
||||||
|
|
||||||
(defn ^:export init
|
(defn ^:export init
|
||||||
[]
|
[]
|
||||||
(st/init)
|
(st/init)
|
||||||
(ui/init-routes)
|
(init-ui))
|
||||||
(ui/init))
|
|
||||||
|
(defn reinit
|
||||||
|
[]
|
||||||
|
(remove-watch html-history/path ::view)
|
||||||
|
(.unmountComponentAtNode js/ReactDOM (dom/get-element "app"))
|
||||||
|
(.unmountComponentAtNode js/ReactDOM (dom/get-element "lightbox"))
|
||||||
|
(.unmountComponentAtNode js/ReactDOM (dom/get-element "loader"))
|
||||||
|
(init-ui))
|
||||||
|
|
||||||
|
(defn ^:after-load after-load
|
||||||
|
[]
|
||||||
|
(reinit))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -76,8 +76,8 @@
|
||||||
(defrecord SelectPage [index]
|
(defrecord SelectPage [index]
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(let [token (get-in state [:route :params :token])]
|
(let [token (get-in state [:route :params :path :token])]
|
||||||
(rx/of (rt/navigate :view/viewer {:token token :index index :id nil})))))
|
(rx/of (rt/nav :view/viewer {:token token :index index})))))
|
||||||
|
|
||||||
(defn select-page
|
(defn select-page
|
||||||
[index]
|
[index]
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
;; Copyright (c) 2015-2016 Andrey Antukh <niwi@niwi.nz>
|
;; Copyright (c) 2015-2016 Andrey Antukh <niwi@niwi.nz>
|
||||||
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||||
|
|
||||||
(ns uxbox.view.locales.en)
|
(ns uxbox.view.locales.fr)
|
||||||
|
|
||||||
(defonce locales
|
(defonce locales
|
||||||
{"viewer.sitemap" "plan du site"
|
{"viewer.sitemap" "plan du site"
|
||||||
|
|
|
@ -26,8 +26,7 @@
|
||||||
([event & events]
|
([event & events]
|
||||||
(apply ptk/emit! store (cons event events))))
|
(apply ptk/emit! store (cons event events))))
|
||||||
|
|
||||||
(defn- initial-state
|
(def initial-state
|
||||||
[]
|
|
||||||
{:route nil
|
{:route nil
|
||||||
:project nil
|
:project nil
|
||||||
:pages nil
|
:pages nil
|
||||||
|
|
|
@ -20,56 +20,20 @@
|
||||||
[rumext.core :as mx :include-macros true]
|
[rumext.core :as mx :include-macros true]
|
||||||
[uxbox.util.dom :as dom]))
|
[uxbox.util.dom :as dom]))
|
||||||
|
|
||||||
|
|
||||||
(def route-ref
|
(def route-ref
|
||||||
(-> (l/key :route)
|
(-> (l/key :route)
|
||||||
(l/derive st/state)))
|
(l/derive st/state)))
|
||||||
|
|
||||||
(defn- on-error
|
|
||||||
"A default error handler."
|
|
||||||
[error]
|
|
||||||
(cond
|
|
||||||
;; Network error
|
|
||||||
(= (:status error) 0)
|
|
||||||
(do
|
|
||||||
(st/emit! (uum/error (tr "errors.network")))
|
|
||||||
(js/console.error "Stack:" (.-stack error)))
|
|
||||||
|
|
||||||
;; Something else
|
|
||||||
:else
|
|
||||||
(do
|
|
||||||
(st/emit! (uum/error (tr "errors.generic")))
|
|
||||||
(js/console.error "Stack:" (.-stack error)))))
|
|
||||||
|
|
||||||
(set! st/*on-error* on-error)
|
|
||||||
|
|
||||||
;; --- Main App (Component)
|
;; --- Main App (Component)
|
||||||
|
|
||||||
(mx/defc app
|
(mx/defc app
|
||||||
{:mixins [mx/static mx/reactive]}
|
{:mixins [mx/static mx/reactive]}
|
||||||
[]
|
[]
|
||||||
(let [{loc :id params :params} (mx/react route-ref)]
|
(let [route (mx/react route-ref)]
|
||||||
(case loc
|
(prn "view$app" route)
|
||||||
|
(case (get-in route [:data :name])
|
||||||
:view/notfound (notfound-page)
|
:view/notfound (notfound-page)
|
||||||
:view/viewer (let [{:keys [index token]} params]
|
:view/viewer (let [{:keys [index token]} (get-in route [:params :path])]
|
||||||
(viewer-page token (parse-int index 0)))
|
(viewer-page token (parse-int index 0)))
|
||||||
nil)))
|
nil)))
|
||||||
|
|
||||||
;; --- Routes
|
|
||||||
|
|
||||||
(def routes
|
|
||||||
[["/:token/:index" :view/viewer]
|
|
||||||
["/:token" :view/viewer]
|
|
||||||
["/not-found" :view/notfound]])
|
|
||||||
|
|
||||||
;; --- Main Entry Point
|
|
||||||
|
|
||||||
(defn init-routes
|
|
||||||
[]
|
|
||||||
(rt/init st/store routes {:default :view/notfound}))
|
|
||||||
|
|
||||||
(defn init
|
|
||||||
[]
|
|
||||||
(mx/mount (app) (dom/get-element "app"))
|
|
||||||
(mx/mount (lightbox) (dom/get-element "lightbox"))
|
|
||||||
(mx/mount (loader) (dom/get-element "loader")))
|
|
||||||
|
|
|
@ -16,15 +16,15 @@
|
||||||
(def demo? (boolean (:uxbox-demo env nil)))
|
(def demo? (boolean (:uxbox-demo env nil)))
|
||||||
|
|
||||||
(def closure-defines
|
(def closure-defines
|
||||||
{"uxbox.config.url" (:uxbox-api-url env "http://127.0.0.1:6060/api")
|
{"uxbox.config.url" (:uxbox-api-url env "http://localhost:6060/api")
|
||||||
"uxbox.config.viewurl" (:uxbox-view-url env "/view/")
|
"uxbox.config.viewurl" (:uxbox-view-url env "/view/index.html")
|
||||||
"uxbox.config.isdemo" demo?})
|
"uxbox.config.isdemo" demo?})
|
||||||
|
|
||||||
(def default-build-options
|
(def default-build-options
|
||||||
{:cache-analysis true
|
{:cache-analysis true
|
||||||
:parallel-build true
|
:parallel-build true
|
||||||
:language-in :ecmascript6
|
:language-in :ecmascript6
|
||||||
:language-out :ecmascript5
|
:language-out :ecmascript6
|
||||||
:closure-defines closure-defines
|
:closure-defines closure-defines
|
||||||
:optimizations :none
|
:optimizations :none
|
||||||
:verbose false
|
:verbose false
|
||||||
|
@ -76,6 +76,7 @@
|
||||||
[args]
|
[args]
|
||||||
(figwheel/start
|
(figwheel/start
|
||||||
{:open-url false
|
{:open-url false
|
||||||
|
:load-warninged-code true
|
||||||
:auto-testing false
|
:auto-testing false
|
||||||
:css-dirs ["resources/public/css"
|
:css-dirs ["resources/public/css"
|
||||||
"resources/public/view/css"]
|
"resources/public/view/css"]
|
||||||
|
|
Loading…
Add table
Reference in a new issue