mirror of
https://github.com/penpot/penpot.git
synced 2025-03-27 23:21:47 -05:00
🎉 Allow import a template from a link
This commit is contained in:
parent
0d70ceb264
commit
2f5f31814a
6 changed files with 103 additions and 20 deletions
|
@ -111,6 +111,7 @@
|
|||
(def grid-help-uri (obj/get global "penpotGridHelpURI" "https://help.penpot.app/user-guide/flexible-layouts/"))
|
||||
(def plugins-list-uri (obj/get global "penpotPluginsListUri" "https://penpot.app/penpothub/plugins"))
|
||||
(def plugins-whitelist (into #{} (obj/get global "penpotPluginsWhitelist" [])))
|
||||
(def templates-uri (obj/get global "penpotTemplatesUri" "https://penpot.github.io/penpot-files/"))
|
||||
|
||||
(defn- normalize-uri
|
||||
[uri-str]
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
(mf/defc dashboard-legacy-redirect*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [section team-id project-id search-term plugin-url]}]
|
||||
[{:keys [section team-id project-id search-term plugin-url template-url]}]
|
||||
(let [section (case section
|
||||
:dashboard-legacy-search
|
||||
:dashboard-search
|
||||
|
@ -97,7 +97,8 @@
|
|||
(let [params {:team-id team-id
|
||||
:project-id project-id
|
||||
:search-term search-term
|
||||
:plugin plugin-url}]
|
||||
:plugin plugin-url
|
||||
:template-url template-url}]
|
||||
(st/emit! (rt/nav section (d/without-nils params)))))
|
||||
|
||||
[:> loader*
|
||||
|
@ -211,11 +212,12 @@
|
|||
:dashboard-invitations
|
||||
:dashboard-webhooks
|
||||
:dashboard-settings)
|
||||
(let [params (get params :query)
|
||||
team-id (some-> params :team-id uuid)
|
||||
project-id (some-> params :project-id uuid)
|
||||
search-term (some-> params :search-term)
|
||||
plugin-url (some-> params :plugin)]
|
||||
(let [params (get params :query)
|
||||
team-id (some-> params :team-id uuid)
|
||||
project-id (some-> params :project-id uuid)
|
||||
search-term (some-> params :search-term)
|
||||
plugin-url (some-> params :plugin)
|
||||
template-url (some-> params :template)]
|
||||
[:?
|
||||
#_[:& app.main.ui.releases/release-notes-modal {:version "2.4"}]
|
||||
#_[:& app.main.ui.onboarding/onboarding-templates-modal]
|
||||
|
@ -241,7 +243,8 @@
|
|||
:team-id team-id
|
||||
:search-term search-term
|
||||
:plugin-url plugin-url
|
||||
:project-id project-id}]]])
|
||||
:project-id project-id
|
||||
:template-url template-url}]]])
|
||||
|
||||
:workspace
|
||||
(let [params (get params :query)
|
||||
|
@ -322,13 +325,15 @@
|
|||
(let [team-id (some-> params :path :team-id uuid)
|
||||
project-id (some-> params :path :project-id uuid)
|
||||
search-term (some-> params :query :search-term)
|
||||
plugin-url (some-> params :query :plugin)]
|
||||
plugin-url (some-> params :query :plugin)
|
||||
template-url (some-> params :template)]
|
||||
[:> dashboard-legacy-redirect*
|
||||
{:team-id team-id
|
||||
:section section
|
||||
:project-id project-id
|
||||
:search-term search-term
|
||||
:plugin-url plugin-url}])
|
||||
:plugin-url plugin-url
|
||||
:template-url template-url}])
|
||||
|
||||
:viewer-legacy
|
||||
(let [{:keys [query-params path-params]} route
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
[app.main.data.modal :as modal]
|
||||
[app.main.data.notifications :as notif]
|
||||
[app.main.data.plugins :as dp]
|
||||
[app.main.data.project :as dpj]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.router :as rt]
|
||||
[app.main.store :as st]
|
||||
|
@ -33,9 +34,14 @@
|
|||
[app.main.ui.workspace.plugins]
|
||||
[app.plugins.register :as preg]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.http :as http]
|
||||
[app.util.i18n :refer [tr]]
|
||||
[app.util.keyboard :as kbd]
|
||||
[app.util.object :as obj]
|
||||
[app.util.storage :as storage]
|
||||
[app.util.webapi :as wapi]
|
||||
[beicon.v2.core :as rx]
|
||||
[cuerdas.core :as str]
|
||||
[goog.events :as events]
|
||||
[okulary.core :as l]
|
||||
[potok.v2.core :as ptk]
|
||||
|
@ -205,9 +211,47 @@
|
|||
(fn [_]
|
||||
(st/emit! (notif/error "The plugin URL is incorrect")))))))))
|
||||
|
||||
(defn use-templates-import
|
||||
[can-edit? template-url default-project-id]
|
||||
(mf/with-layout-effect
|
||||
[can-edit? template-url default-project-id]
|
||||
(when (and (some? template-url) (some? default-project-id))
|
||||
(if can-edit?
|
||||
(let [valid-url? (and (str/ends-with? template-url ".penpot")
|
||||
(str/starts-with? template-url cf/templates-uri))
|
||||
template-name (when valid-url? (subs template-url (count cf/templates-uri)))
|
||||
on-import #(st/emit! (dpj/fetch-files default-project-id)
|
||||
(dd/fetch-recent-files)
|
||||
(dd/fetch-projects)
|
||||
(dd/clear-selected-files)
|
||||
(ptk/event ::ev/event {::ev/name "install-template-from-link-finished"
|
||||
:name template-name
|
||||
:url template-url}))]
|
||||
(if valid-url?
|
||||
(do
|
||||
(st/emit! (ptk/event ::ev/event {::ev/name "install-template-from-link" :name template-name :url template-url}))
|
||||
(->> (http/send! {:method :get
|
||||
:uri template-url
|
||||
:response-type :blob
|
||||
:omit-default-headers true})
|
||||
(rx/subs!
|
||||
(fn [result]
|
||||
(if (or (< (:status result) 200) (>= (:status result) 300))
|
||||
(st/emit! (notif/error (tr "dashboard.import.error")))
|
||||
(st/emit! (modal/show
|
||||
{:type :import
|
||||
:project-id default-project-id
|
||||
:entries [{:name template-name :uri (wapi/create-uri (:body result))}]
|
||||
:on-finish-import on-import})))))))
|
||||
(st/emit! (notif/error (tr "dashboard.import.bad-url")))))
|
||||
(st/emit! (notif/error (tr "dashboard.import.no-perms"))))
|
||||
|
||||
(binding [storage/*sync* true]
|
||||
(swap! storage/session dissoc :template-url)))))
|
||||
|
||||
(mf/defc dashboard*
|
||||
{::mf/props :obj}
|
||||
[{:keys [profile project-id team-id search-term plugin-url section]}]
|
||||
[{:keys [profile project-id team-id search-term plugin-url template-url section]}]
|
||||
(let [team (mf/deref refs/team)
|
||||
projects (mf/deref refs/projects)
|
||||
|
||||
|
@ -216,6 +260,9 @@
|
|||
(->> (vals projects)
|
||||
(filterv #(= team-id (:team-id %)))))
|
||||
|
||||
can-edit? (dm/get-in team [:permissions :can-edit])
|
||||
template-url (or template-url (:template-url storage/session))
|
||||
|
||||
default-project
|
||||
(mf/with-memo [projects]
|
||||
(->> projects
|
||||
|
@ -239,6 +286,7 @@
|
|||
(events/unlistenByKey key))))
|
||||
|
||||
(use-plugin-register plugin-url team-id (:id default-project))
|
||||
(use-templates-import can-edit? template-url (:id default-project))
|
||||
|
||||
[:& (mf/provider ctx/current-project-id) {:value project-id}
|
||||
[:> modal-container*]
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
[app.main.repo :as rp]
|
||||
[app.main.router :as rt]
|
||||
[app.main.store :as st]
|
||||
[app.util.storage :as storage]
|
||||
[beicon.v2.core :as rx]
|
||||
[cuerdas.core :as str]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
@ -75,14 +76,23 @@
|
|||
["/workspace" :workspace]
|
||||
["/workspace/:project-id/:file-id" :workspace-legacy]])
|
||||
|
||||
|
||||
(defn- store-session-params
|
||||
[{:keys [template]}]
|
||||
(binding [storage/*sync* true]
|
||||
(when (some? template)
|
||||
(swap! storage/session assoc
|
||||
:template-url template))))
|
||||
|
||||
(defn on-navigate
|
||||
[router path]
|
||||
(let [location (.-location js/document)
|
||||
[base-path qs] (str/split path "?")
|
||||
location-path (dm/str (.-origin location) (.-pathname location))
|
||||
(let [location (.-location js/document)
|
||||
[base-path qs] (str/split path "?")
|
||||
location-path (dm/str (.-origin location) (.-pathname location))
|
||||
valid-location? (= location-path (dm/str cf/public-uri))
|
||||
match (rt/match router path)
|
||||
empty-path? (or (= base-path "") (= base-path "/"))]
|
||||
match (rt/match router path)
|
||||
empty-path? (or (= base-path "") (= base-path "/"))
|
||||
query-params (u/query-string->map qs)]
|
||||
|
||||
(cond
|
||||
(not valid-location?)
|
||||
|
@ -99,14 +109,15 @@
|
|||
(rx/subs! (fn [{:keys [id] :as profile}]
|
||||
(cond
|
||||
(= id uuid/zero)
|
||||
(st/emit! (rt/nav :auth-login))
|
||||
(do
|
||||
(store-session-params query-params)
|
||||
(st/emit! (rt/nav :auth-login)))
|
||||
|
||||
empty-path?
|
||||
(let [team-id (or (dtm/get-last-team-id)
|
||||
(:default-team-id profile))]
|
||||
(st/emit! (rt/nav :dashboard-recent
|
||||
(-> (u/query-string->map qs)
|
||||
(assoc :team-id team-id)))))
|
||||
(assoc query-params :team-id team-id))))
|
||||
|
||||
:else
|
||||
(st/emit! (rt/assign-exception {:type :not-found})))))))))
|
||||
|
|
|
@ -6966,6 +6966,15 @@ msgstr "None"
|
|||
msgid "dashboard.settings.notifications.submit"
|
||||
msgstr "Update settings"
|
||||
|
||||
msgid "dashboard.import.error"
|
||||
msgstr "Import failed. Please try again"
|
||||
|
||||
msgid "dashboard.import.bad-url"
|
||||
msgstr "Import failed. The template URL is incorrect"
|
||||
|
||||
msgid "dashboard.import.no-perms"
|
||||
msgstr "You don’t have permission to import to this team"
|
||||
|
||||
msgid "labels.notifications"
|
||||
msgstr "Notifications"
|
||||
|
||||
|
|
|
@ -6687,7 +6687,7 @@ msgstr "Nombre"
|
|||
|
||||
#: src/app/main/ui/workspace/tokens/form.cljs
|
||||
msgid "workspace.token.enter-token-name"
|
||||
msgstr "Introduce un nombre para el token %s"
|
||||
msgstr "Introduce un nombre para el token %s"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/form.cljs
|
||||
msgid "workspace.token.token-value"
|
||||
|
@ -6923,6 +6923,15 @@ msgstr "Ninguna"
|
|||
msgid "dashboard.settings.notifications.submit"
|
||||
msgstr "Actualizar configuración"
|
||||
|
||||
msgid "dashboard.import.error"
|
||||
msgstr "La importación ha fallado. Intentalo de nuevo, por favor"
|
||||
|
||||
msgid "dashboard.import.bad-url"
|
||||
msgstr "La importación ha fallado. La URL de la plantilla es incorrecta"
|
||||
|
||||
msgid "dashboard.import.no-perms"
|
||||
msgstr "No tienes permisos para importar en este equipo"
|
||||
|
||||
msgid "labels.notifications"
|
||||
msgstr "Notificaciones"
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue