0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-28 15:41:25 -05:00

Add more adaptations to make app run in a prefixed path.

This commit is contained in:
Andrey Antukh 2021-04-19 18:35:36 +02:00 committed by Andrés Moya
parent 2828ccda7f
commit 55ea84a056
14 changed files with 115 additions and 98 deletions

View file

@ -0,0 +1,34 @@
;; 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.common.uri
(:require
[app.common.data :as d]
[lambdaisland.uri :as u]
[lambdaisland.uri.normalize :as un]))
(d/export u/uri)
(d/export u/join)
(d/export un/percent-encode)
(defn query-string->map
[s]
(u/query-string->map s))
(defn default-encode-value
[v]
(if (keyword? v) (name v) v))
(defn map->query-string
([params] (map->query-string params nil))
([params {:keys [value-fn key-fn]
:or {value-fn default-encode-value
key-fn identity}}]
(->> params
(into {} (comp
(remove #(nil? (second %)))
(map (fn [[k v]] [(key-fn k) (value-fn v)]))))
(u/map->query-string))))

View file

@ -68,23 +68,23 @@ function readManifest() {
const content = JSON.parse(fs.readFileSync(path, {encoding: "utf8"}));
const index = {
"config": "/js/config.js?ts=" + Date.now(),
"config": "js/config.js?ts=" + Date.now(),
"polyfills": "js/polyfills.js?ts=" + Date.now(),
};
for (let item of content) {
index[item.name] = "/js/" + item["output-name"];
index[item.name] = "js/" + item["output-name"];
};
return index;
} catch (e) {
console.error("Error on reading manifest, using default.");
return {
"config": "/js/config.js",
"config": "js/config.js",
"polyfills": "js/polyfills.js",
"main": "/js/main.js",
"shared": "/js/shared.js",
"worker": "/js/worker.js"
"main": "js/main.js",
"shared": "js/shared.js",
"worker": "js/worker.js"
};
}
}

View file

@ -15,10 +15,9 @@
<meta name="twitter:image" content="https://penpot.app/images/workspace-ui.jpg">
<meta name="twitter:site" content="@penpotapp">
<meta name="twitter:creator" content="@penpotapp">
<link id="theme" href="/css/main-{{& th}}.css?ts={{& ts}}"
rel="stylesheet" type="text/css" />
<link id="theme" href="css/main-{{& th}}.css?ts={{& ts}}" rel="stylesheet" type="text/css" />
<link rel="icon" href="/images/favicon.png" />
<link rel="icon" href="images/favicon.png" />
<script>
window.penpotTranslations = JSON.parse({{& translations}});

View file

@ -6,14 +6,15 @@
(ns app.config
(:require
[clojure.spec.alpha :as s]
[app.common.data :as d]
[app.common.uri :as u]
[app.common.spec :as us]
[app.common.version :as v]
[app.util.avatars :as avatars]
[app.util.dom :as dom]
[app.util.globals :refer [global location]]
[app.util.object :as obj]
[app.util.dom :as dom]
[app.util.avatars :as avatars]
[clojure.spec.alpha :as s]
[cuerdas.core :as str]))
;; --- Auxiliar Functions
@ -76,16 +77,24 @@
(def translations (obj/get global "penpotTranslations"))
(def themes (obj/get global "penpotThemes"))
(def public-uri (or (obj/get global "penpotPublicURI") (.-origin ^js location)))
(def version (delay (parse-version global)))
(def target (delay (parse-target global)))
(def browser (delay (parse-browser)))
(def platform (delay (parse-platform)))
(def public-uri
(let [uri (u/uri (or (obj/get global "penpotPublicURI")
(str (.-origin ^js location)
(.-pathname ^js location))))]
;; Ensure that the path always ends with "/"; this ensures that
;; all path join operations works as expected.
(cond-> uri
(not (str/ends-with? (:path uri) "/"))
(update :path #(str % "/")))))
(when (= :browser @target)
(js/console.log
(str/format "Welcome to penpot! Version: '%s'." (:full @version))))
(str/format "Welcome to penpot! version='%s' base-uri='%s'." (:full @version) (str public-uri))))
;; --- Helper Functions
@ -101,18 +110,20 @@
[{:keys [photo-id fullname name] :as profile}]
(if (nil? photo-id)
(avatars/generate {:name (or fullname name)})
(str public-uri "/assets/by-id/" photo-id)))
(str (u/join public-uri "assets/by-id/" photo-id))))
(defn resolve-team-photo-url
[{:keys [photo-id name] :as team}]
(if (nil? photo-id)
(avatars/generate {:name name})
(str public-uri "/assets/by-id/" photo-id)))
(str (u/join public-uri "assets/by-id/" photo-id))))
(defn resolve-file-media
([media]
(resolve-file-media media false))
([{:keys [id] :as media} thumnail?]
(str public-uri "/assets/by-file-media-id/" id (when thumnail? "/thumbnail"))))
(str (cond-> (u/join public-uri "assets/by-file-media-id/")
(true? thumnail?) (u/join (str id "/thumbnail"))
(false? thumnail?) (u/join (str id))))))

View file

@ -7,21 +7,22 @@
(ns app.main.data.workspace.notifications
(:require
[app.common.data :as d]
[app.common.uri :as u]
[app.common.geom.point :as gpt]
[app.common.pages :as cp]
[app.common.spec :as us]
[app.config :as cfg]
[app.config :as cf]
[app.main.data.workspace.common :as dwc]
[app.main.data.workspace.persistence :as dwp]
[app.main.data.workspace.libraries :as dwl]
[app.main.data.workspace.persistence :as dwp]
[app.main.repo :as rp]
[app.main.store :as st]
[app.main.streams :as ms]
[app.util.avatars :as avatars]
[app.util.i18n :as i18n :refer [tr]]
[app.util.time :as dt]
[app.util.transit :as t]
[app.util.websockets :as ws]
[app.util.i18n :as i18n :refer [tr]]
[beicon.core :as rx]
[cljs.spec.alpha :as s]
[clojure.set :as set]
@ -39,14 +40,24 @@
(s/def ::message
(s/keys :req-un [::type]))
(defn prepare-uri
[params]
(let [base (-> (u/join cf/public-uri "ws/notifications")
(assoc :query (u/map->query-string params)))]
(cond-> base
(= "https" (:scheme base))
(assoc :scheme "wss")
(= "http" (:scheme base))
(assoc :scheme "ws"))))
(defn initialize
[file-id]
(ptk/reify ::initialize
ptk/UpdateEvent
(update [_ state]
(let [sid (:session-id state)
uri (ws/uri "/ws/notifications" {:file-id file-id
:session-id sid})]
uri (prepare-uri {:file-id file-id :session-id sid})]
(assoc-in state [:ws file-id] (ws/open uri))))
ptk/WatchEvent

View file

@ -7,13 +7,13 @@
(ns app.main.repo
(:require
[app.common.data :as d]
[app.common.uri :as u]
[app.config :as cfg]
[app.util.http :as http]
[app.util.time :as dt]
[app.util.transit :as t]
[beicon.core :as rx]
[cuerdas.core :as str]
[lambdaisland.uri :as u]))
[cuerdas.core :as str]))
(defn- handle-response
[{:keys [status body] :as response}]
@ -43,7 +43,7 @@
:status status
:data body})))
(def ^:private base-uri (u/uri cfg/public-uri))
(def ^:private base-uri cfg/public-uri)
(defn- send-query!
"A simple helper for send and receive transit data on the penpot
@ -125,7 +125,7 @@
(defmethod mutation ::multipart-upload
[id params]
(->> (http/send! {:method :post
:uri (u/join base-uri "/api/rpc/mutation/" (name id))
:uri (u/join base-uri "api/rpc/mutation/" (name id))
:body (http/form-data params)})
(rx/map http/conditional-decode-transit)
(rx/mapcat handle-response)))

View file

@ -8,7 +8,7 @@
(:require
[clojure.java.io :as io]
[cuerdas.core :as str]
[lambdaisland.uri.normalize :as uri]))
[app.common.uri :as u]))
(def cursor-folder "images/cursors")
@ -53,7 +53,7 @@
[id rotation x y height]
(let [svg-path (str cursor-folder "/" (name id) ".svg")
data (-> svg-path io/resource slurp parse-svg)
data (uri/percent-encode data)
data (u/percent-encode data)
data (if rotation
(str/fmt "%3Cg transform='rotate(%s 8,8)'%3E%s%3C/g%3E" rotation data)

View file

@ -28,7 +28,6 @@
[app.util.timers :as ts]
[beicon.core :as rx]
[cuerdas.core :as str]
[lambdaisland.uri :as uri]
[rumext.alpha :as mf]))
;; --- Grid Item Thumbnail

View file

@ -67,11 +67,11 @@
:viewer
(:path-params route)
{:token token :index "0"})
link (str cfg/public-uri "/#" link)
link (assoc cfg/public-uri :fragment link)
copy-link
(fn [event]
(wapi/write-to-clipboard link)
(wapi/write-to-clipboard (str link))
(st/emit! (dm/show {:type :info
:content "Link copied successfuly!"
:timeout 3000})))]
@ -89,7 +89,7 @@
[:div.share-link-input
(if (string? token)
[:*
[:span.link link]
[:span.link (str link)]
[:span.link-button {:on-click copy-link}
(t locale "viewer.header.share.copy-link")]]
[:span.link-placeholder (t locale "viewer.header.share.placeholder")])]

View file

@ -8,13 +8,13 @@
"A http client with rx streams interface."
(:require
[app.common.data :as d]
[app.common.uri :as u]
[app.config :as cfg]
[app.util.globals :as globals]
[app.util.object :as obj]
[app.util.transit :as t]
[beicon.core :as rx]
[cuerdas.core :as str]
[lambdaisland.uri :as u]
[promesa.core :as p]))
(defprotocol IBodyData

View file

@ -1,3 +1,9 @@
;; 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.util.logging)
(defn- log-expr [form level keyvals]

View file

@ -9,37 +9,17 @@
(:require
[app.common.data :as d]
[app.config :as cfg]
[app.common.uri :as u]
[app.util.browser-history :as bhistory]
[app.util.timers :as ts]
[beicon.core :as rx]
[cuerdas.core :as str]
[goog.events :as e]
[potok.core :as ptk]
[reitit.core :as r])
(:import
goog.Uri
goog.Uri.QueryData))
[reitit.core :as r]))
;; --- Router API
(defn- parse-query-data
[^QueryData qdata]
(persistent!
(reduce (fn [acc key]
(let [values (.getValues qdata key)
rkey (str/keyword key)]
(cond
(> (alength values) 1)
(assoc! acc rkey (into [] values))
(= (alength values) 1)
(assoc! acc rkey (aget values 0))
:else
acc)))
(transient {})
(.getKeys qdata))))
(defn resolve
([router id] (resolve router id {} {}))
([router id params] (resolve router id params {}))
@ -47,12 +27,10 @@
(when-let [match (r/match-by-name router id params)]
(if (empty? qparams)
(r/match->path match)
(let [uri (.parse goog.Uri (r/match->path match))
qdt (.createFromMap QueryData (-> qparams
(d/without-nils)
(clj->js)))]
(.setQueryData ^js uri qdt)
(.toString ^js uri))))))
(let [query (u/map->query-string qparams)]
(-> (u/uri (r/match->path match))
(assoc :query query)
(str)))))))
(defn create
[routes]
@ -65,26 +43,18 @@
(update [_ state]
(assoc state :router (create routes)))))
(defn query-params
"Given goog.Uri, read query parameters into Clojure map."
[^goog.Uri uri]
(let [^js q (.getQueryData uri)]
(->> q
(.getKeys)
(map (juxt keyword #(.get q %)))
(into {}))))
(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 ^js Uri path)]
(when-let [match (r/match-by-path router (.getPath ^js uri))]
(let [qparams (parse-query-data (.getQueryData ^js uri))
params {:path (:path-params match) :query qparams}]
(assoc match
:params params
:query-params qparams)))))
(let [uri (u/uri path)]
(when-let [match (r/match-by-path router (:path uri))]
(let [qparams (u/query-string->map (:query uri))
params {:path (:path-params match)
:query qparams}]
(-> match
(assoc :params params)
(assoc :query-params qparams))))))
;; --- Navigate (Event)
@ -119,8 +89,9 @@
(effect [_ state stream]
(let [router (:router state)
path (resolve router id params qparams)
uri (str cfg/public-uri "/#" path)]
(js/window.open uri "_blank"))))
uri (-> (u/uri cfg/public-uri)
(assoc :fragment path))]
(js/window.open (str uri) "_blank"))))
(defn nav-new-window
([id] (nav-new-window id nil nil))

View file

@ -7,13 +7,13 @@
(ns app.util.websockets
"A interface to webworkers exposed functionality."
(:require
[app.common.uri :as u]
[app.config :as cfg]
[app.util.transit :as t]
[beicon.core :as rx]
[goog.events :as ev]
[potok.core :as ptk])
(:import
goog.Uri
goog.net.WebSocket
goog.net.WebSocket.EventType))
@ -22,19 +22,6 @@
(-send [_ message] "send a message")
(-close [_] "close websocket"))
(defn uri
([path] (uri path {}))
([path params]
(let [uri (.parse ^js Uri cfg/public-uri)]
(.setPath ^js uri path)
(if (= (.getScheme ^js uri) "http")
(.setScheme ^js uri "ws")
(.setScheme ^js uri "wss"))
(run! (fn [[k v]]
(.setParameterValue ^js uri (name k) (str v)))
params)
(.toString uri))))
(defn open
[uri]
(let [sb (rx/subject)
@ -45,7 +32,7 @@
#(rx/push! sb {:type :error :payload %}))
lk3 (ev/listen ws EventType.OPENED
#(rx/push! sb {:type :opened :payload %}))]
(.open ws uri)
(.open ws (str uri))
(reify
cljs.core/IDeref
(-deref [_] ws)

View file

@ -19,8 +19,7 @@
[app.worker.snaps]
[app.util.object :as obj]
[app.util.transit :as t]
[app.util.worker :as w])
(:import goog.Uri))
[app.util.worker :as w]))
;; --- Messages Handling
@ -119,7 +118,7 @@
(rx/debounce 1)
(rx/subs (fn [[messages dropped last]]
;; Send back the dropped messages replies
;; Send back the dropped messages replies
(doseq [msg dropped]
(drop-message msg))