mirror of
https://github.com/penpot/penpot.git
synced 2025-08-07 14:38:33 +02:00
commit
3d7df5b005
16 changed files with 1522 additions and 1208 deletions
File diff suppressed because it is too large
Load diff
|
@ -941,7 +941,7 @@
|
||||||
(update-in [:dashboard-projects project-id :count] inc)))))
|
(update-in [:dashboard-projects project-id :count] inc)))))
|
||||||
|
|
||||||
(defn create-file
|
(defn create-file
|
||||||
[{:keys [project-id] :as params}]
|
[{:keys [project-id name] :as params}]
|
||||||
(dm/assert! (uuid? project-id))
|
(dm/assert! (uuid? project-id))
|
||||||
(ptk/reify ::create-file
|
(ptk/reify ::create-file
|
||||||
ev/Event
|
ev/Event
|
||||||
|
@ -955,7 +955,7 @@
|
||||||
|
|
||||||
files (get state :dashboard-files)
|
files (get state :dashboard-files)
|
||||||
unames (cfh/get-used-names files)
|
unames (cfh/get-used-names files)
|
||||||
name (cfh/generate-unique-name unames (str (tr "dashboard.new-file-prefix") " 1"))
|
name (or name (cfh/generate-unique-name unames (str (tr "dashboard.new-file-prefix") " 1")))
|
||||||
features (-> (features/get-team-enabled-features state)
|
features (-> (features/get-team-enabled-features state)
|
||||||
(set/difference cfeat/frontend-only-features))
|
(set/difference cfeat/frontend-only-features))
|
||||||
params (-> params
|
params (-> params
|
||||||
|
|
43
frontend/src/app/main/data/plugins.cljs
Normal file
43
frontend/src/app/main/data/plugins.cljs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
;; 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) KALEIDOS INC
|
||||||
|
|
||||||
|
(ns app.main.data.plugins
|
||||||
|
(:require
|
||||||
|
[app.plugins.register :as pr]
|
||||||
|
[app.util.globals :as ug]
|
||||||
|
[beicon.v2.core :as rx]
|
||||||
|
[potok.v2.core :as ptk]))
|
||||||
|
|
||||||
|
(defn open-plugin!
|
||||||
|
[{:keys [plugin-id name description host code icon permissions]}]
|
||||||
|
(try
|
||||||
|
(.ɵloadPlugin
|
||||||
|
^js ug/global
|
||||||
|
#js {:pluginId plugin-id
|
||||||
|
:name name
|
||||||
|
:description description
|
||||||
|
:host host
|
||||||
|
:code code
|
||||||
|
:icon icon
|
||||||
|
:permissions (apply array permissions)})
|
||||||
|
(catch :default e
|
||||||
|
(.error js/console "Error" e))))
|
||||||
|
|
||||||
|
(defn delay-open-plugin
|
||||||
|
[plugin]
|
||||||
|
(ptk/reify ::delay-open-plugin
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(assoc state ::open-plugin (:plugin-id plugin)))))
|
||||||
|
|
||||||
|
(defn check-open-plugin
|
||||||
|
[]
|
||||||
|
(ptk/reify ::check-open-plugin
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(when-let [pid (::open-plugin state)]
|
||||||
|
(open-plugin! (pr/get-plugin pid))
|
||||||
|
(rx/of #(dissoc % ::open-plugin))))))
|
|
@ -42,6 +42,7 @@
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
[app.main.data.persistence :as dps]
|
[app.main.data.persistence :as dps]
|
||||||
|
[app.main.data.plugins :as dp]
|
||||||
[app.main.data.users :as du]
|
[app.main.data.users :as du]
|
||||||
[app.main.data.workspace.bool :as dwb]
|
[app.main.data.workspace.bool :as dwb]
|
||||||
[app.main.data.workspace.collapse :as dwco]
|
[app.main.data.workspace.collapse :as dwco]
|
||||||
|
@ -131,6 +132,7 @@
|
||||||
(when (and (not (boolean (-> state :profile :props :v2-info-shown)))
|
(when (and (not (boolean (-> state :profile :props :v2-info-shown)))
|
||||||
(features/active-feature? state "components/v2"))
|
(features/active-feature? state "components/v2"))
|
||||||
(modal/show :v2-info {}))
|
(modal/show :v2-info {}))
|
||||||
|
(dp/check-open-plugin)
|
||||||
(fdf/fix-deleted-fonts)
|
(fdf/fix-deleted-fonts)
|
||||||
(fbs/fix-broken-shapes)))))
|
(fbs/fix-broken-shapes)))))
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,15 @@
|
||||||
(:require-macros [app.main.style :as stl])
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
|
[app.common.data.macros :as dm]
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
[app.main.data.dashboard :as dd]
|
[app.main.data.dashboard :as dd]
|
||||||
[app.main.data.dashboard.shortcuts :as sc]
|
[app.main.data.dashboard.shortcuts :as sc]
|
||||||
|
[app.main.data.events :as ev]
|
||||||
|
[app.main.data.modal :as modal]
|
||||||
|
[app.main.data.notifications :as notif]
|
||||||
|
[app.main.data.plugins :as dp]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.context :as ctx]
|
[app.main.ui.context :as ctx]
|
||||||
|
@ -25,11 +30,17 @@
|
||||||
[app.main.ui.dashboard.team :refer [team-settings-page team-members-page team-invitations-page team-webhooks-page]]
|
[app.main.ui.dashboard.team :refer [team-settings-page team-members-page team-invitations-page team-webhooks-page]]
|
||||||
[app.main.ui.dashboard.templates :refer [templates-section]]
|
[app.main.ui.dashboard.templates :refer [templates-section]]
|
||||||
[app.main.ui.hooks :as hooks]
|
[app.main.ui.hooks :as hooks]
|
||||||
|
[app.main.ui.workspace.plugins]
|
||||||
|
[app.plugins.register :as preg]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
|
[app.util.http :as http]
|
||||||
[app.util.keyboard :as kbd]
|
[app.util.keyboard :as kbd]
|
||||||
[app.util.object :as obj]
|
[app.util.object :as obj]
|
||||||
|
[app.util.router :as rt]
|
||||||
|
[beicon.v2.core :as rx]
|
||||||
[goog.events :as events]
|
[goog.events :as events]
|
||||||
[okulary.core :as l]
|
[okulary.core :as l]
|
||||||
|
[potok.v2.core :as ptk]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(defn ^boolean uuid-str?
|
(defn ^boolean uuid-str?
|
||||||
|
@ -143,6 +154,70 @@
|
||||||
(def dashboard-initialized
|
(def dashboard-initialized
|
||||||
(l/derived :current-team-id st/state))
|
(l/derived :current-team-id st/state))
|
||||||
|
|
||||||
|
(defn use-plugin-register
|
||||||
|
[plugin-url team-id project-id]
|
||||||
|
|
||||||
|
(let [navegate-file!
|
||||||
|
(fn [plugin {:keys [project-id id data]}]
|
||||||
|
(st/emit!
|
||||||
|
(dp/delay-open-plugin plugin)
|
||||||
|
(rt/nav :workspace
|
||||||
|
{:project-id project-id :file-id id}
|
||||||
|
{:page-id (dm/get-in data [:pages 0])})))
|
||||||
|
|
||||||
|
create-file!
|
||||||
|
(fn [plugin]
|
||||||
|
(st/emit!
|
||||||
|
(modal/hide)
|
||||||
|
(let [data
|
||||||
|
(with-meta
|
||||||
|
{:project-id project-id
|
||||||
|
:name (dm/str "Try plugin: " (:name plugin))}
|
||||||
|
{:on-success (partial navegate-file! plugin)})]
|
||||||
|
(-> (dd/create-file data)
|
||||||
|
(with-meta {::ev/origin "plugin-try-out"})))))
|
||||||
|
|
||||||
|
open-try-out-dialog
|
||||||
|
(fn [plugin]
|
||||||
|
(modal/show
|
||||||
|
:plugin-try-out
|
||||||
|
{:plugin plugin
|
||||||
|
:on-accept #(create-file! plugin)
|
||||||
|
:on-close #(modal/hide!)}))
|
||||||
|
|
||||||
|
open-permissions-dialog
|
||||||
|
(fn [plugin]
|
||||||
|
(modal/show!
|
||||||
|
:plugin-permissions
|
||||||
|
{:plugin plugin
|
||||||
|
:on-accept
|
||||||
|
#(do (preg/install-plugin! plugin)
|
||||||
|
(st/emit! (modal/hide)
|
||||||
|
(rt/nav :dashboard-projects {:team-id team-id})
|
||||||
|
(open-try-out-dialog plugin)))
|
||||||
|
:on-close
|
||||||
|
#(st/emit! (modal/hide)
|
||||||
|
(rt/nav :dashboard-projects {:team-id team-id}))}))]
|
||||||
|
|
||||||
|
(mf/with-layout-effect
|
||||||
|
[plugin-url team-id project-id]
|
||||||
|
(when plugin-url
|
||||||
|
(->> (http/send! {:method :get
|
||||||
|
:uri plugin-url
|
||||||
|
:omit-default-headers true
|
||||||
|
:response-type :json})
|
||||||
|
(rx/map :body)
|
||||||
|
(rx/subs!
|
||||||
|
(fn [body]
|
||||||
|
(if-let [plugin (preg/parse-manifest plugin-url body)]
|
||||||
|
(do
|
||||||
|
(st/emit! (ptk/event ::ev/event {::ev/name "install-plugin" :name (:name plugin) :url plugin-url}))
|
||||||
|
(open-permissions-dialog plugin))
|
||||||
|
(st/emit! (notif/error "Cannot parser the plugin manifest"))))
|
||||||
|
|
||||||
|
(fn [_]
|
||||||
|
(st/emit! (notif/error "The plugin URL is incorrect")))))))))
|
||||||
|
|
||||||
(mf/defc dashboard
|
(mf/defc dashboard
|
||||||
{::mf/props :obj}
|
{::mf/props :obj}
|
||||||
[{:keys [route profile]}]
|
[{:keys [route profile]}]
|
||||||
|
@ -150,8 +225,12 @@
|
||||||
params (parse-params route)
|
params (parse-params route)
|
||||||
|
|
||||||
project-id (:project-id params)
|
project-id (:project-id params)
|
||||||
|
|
||||||
team-id (:team-id params)
|
team-id (:team-id params)
|
||||||
search-term (:search-term params)
|
search-term (:search-term params)
|
||||||
|
|
||||||
|
plugin-url (-> route :query-params :plugin)
|
||||||
|
|
||||||
invite-email (-> route :query-params :invite-email)
|
invite-email (-> route :query-params :invite-email)
|
||||||
|
|
||||||
teams (mf/deref refs/teams)
|
teams (mf/deref refs/teams)
|
||||||
|
@ -160,6 +239,8 @@
|
||||||
projects (mf/deref refs/dashboard-projects)
|
projects (mf/deref refs/dashboard-projects)
|
||||||
project (get projects project-id)
|
project (get projects project-id)
|
||||||
|
|
||||||
|
default-project (->> projects vals (d/seek :is-default))
|
||||||
|
|
||||||
initialized? (mf/deref dashboard-initialized)]
|
initialized? (mf/deref dashboard-initialized)]
|
||||||
|
|
||||||
(hooks/use-shortcuts ::dashboard sc/shortcuts)
|
(hooks/use-shortcuts ::dashboard sc/shortcuts)
|
||||||
|
@ -178,6 +259,8 @@
|
||||||
(fn []
|
(fn []
|
||||||
(events/unlistenByKey key))))
|
(events/unlistenByKey key))))
|
||||||
|
|
||||||
|
(use-plugin-register plugin-url team-id (:id default-project))
|
||||||
|
|
||||||
[:& (mf/provider ctx/current-team-id) {:value team-id}
|
[:& (mf/provider ctx/current-team-id) {:value team-id}
|
||||||
[:& (mf/provider ctx/current-project-id) {:value project-id}
|
[:& (mf/provider ctx/current-project-id) {:value project-id}
|
||||||
;; NOTE: dashboard events and other related functions assumes
|
;; NOTE: dashboard events and other related functions assumes
|
||||||
|
@ -206,4 +289,3 @@
|
||||||
:search-term search-term
|
:search-term search-term
|
||||||
:team team
|
:team team
|
||||||
:invite-email invite-email}])])]]))
|
:invite-email invite-email}])])]]))
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
|
[app.common.uri :as u]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
[app.main.data.users :as du]
|
[app.main.data.users :as du]
|
||||||
|
@ -16,6 +17,7 @@
|
||||||
[app.util.router :as rt]
|
[app.util.router :as rt]
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[cljs.spec.alpha :as s]
|
[cljs.spec.alpha :as s]
|
||||||
|
[cuerdas.core :as str]
|
||||||
[potok.v2.core :as ptk]))
|
[potok.v2.core :as ptk]))
|
||||||
|
|
||||||
(s/def ::page-id ::us/uuid)
|
(s/def ::page-id ::us/uuid)
|
||||||
|
@ -94,10 +96,11 @@
|
||||||
(defn on-navigate
|
(defn on-navigate
|
||||||
[router path]
|
[router path]
|
||||||
(let [location (.-location js/document)
|
(let [location (.-location js/document)
|
||||||
|
[base-path qs] (str/split path "?")
|
||||||
location-path (dm/str (.-origin location) (.-pathname location))
|
location-path (dm/str (.-origin location) (.-pathname location))
|
||||||
valid-location? (= location-path (dm/str cf/public-uri))
|
valid-location? (= location-path (dm/str cf/public-uri))
|
||||||
match (match-path router path)
|
match (match-path router path)
|
||||||
empty-path? (or (= path "") (= path "/"))]
|
empty-path? (or (= base-path "") (= base-path "/"))]
|
||||||
(cond
|
(cond
|
||||||
(not valid-location?)
|
(not valid-location?)
|
||||||
(st/emit! (rt/assign-exception {:type :not-found}))
|
(st/emit! (rt/assign-exception {:type :not-found}))
|
||||||
|
@ -116,7 +119,7 @@
|
||||||
(st/emit! (rt/nav :auth-login))
|
(st/emit! (rt/nav :auth-login))
|
||||||
|
|
||||||
empty-path?
|
empty-path?
|
||||||
(st/emit! (rt/nav :dashboard-projects {:team-id (du/get-current-team-id profile)}))
|
(st/emit! (rt/nav :dashboard-projects {:team-id (du/get-current-team-id profile)} (u/query-string->map qs)))
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(st/emit! (rt/assign-exception {:type :not-found})))))))))
|
(st/emit! (rt/assign-exception {:type :not-found})))))))))
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
[app.main.data.events :as ev]
|
[app.main.data.events :as ev]
|
||||||
[app.main.data.exports :as de]
|
[app.main.data.exports :as de]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
|
[app.main.data.plugins :as dp]
|
||||||
[app.main.data.shortcuts :as scd]
|
[app.main.data.shortcuts :as scd]
|
||||||
[app.main.data.users :as du]
|
[app.main.data.users :as du]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
|
@ -29,7 +30,6 @@
|
||||||
[app.main.ui.context :as ctx]
|
[app.main.ui.context :as ctx]
|
||||||
[app.main.ui.hooks.resize :as r]
|
[app.main.ui.hooks.resize :as r]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.main.ui.workspace.plugins :as uwp]
|
|
||||||
[app.plugins.register :as preg]
|
[app.plugins.register :as preg]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
|
@ -637,7 +637,7 @@
|
||||||
::ev/origin "workspace:menu"
|
::ev/origin "workspace:menu"
|
||||||
:name name
|
:name name
|
||||||
:host host}))
|
:host host}))
|
||||||
(uwp/open-plugin! manifest))
|
(dp/open-plugin! manifest))
|
||||||
:class (stl/css :submenu-item)
|
:class (stl/css :submenu-item)
|
||||||
:on-key-down (fn [event]
|
:on-key-down (fn [event]
|
||||||
(when (kbd/enter? event)
|
(when (kbd/enter? event)
|
||||||
|
@ -646,7 +646,7 @@
|
||||||
::ev/origin "workspace:menu"
|
::ev/origin "workspace:menu"
|
||||||
:name name
|
:name name
|
||||||
:host host}))
|
:host host}))
|
||||||
(uwp/open-plugin! manifest))))}
|
(dp/open-plugin! manifest))))}
|
||||||
[:span {:class (stl/css :item-name)} name]])])))
|
[:span {:class (stl/css :item-name)} name]])])))
|
||||||
|
|
||||||
(mf/defc menu
|
(mf/defc menu
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
[app.main.data.events :as ev]
|
[app.main.data.events :as ev]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
|
[app.main.data.plugins :as dp]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.search-bar :refer [search-bar]]
|
[app.main.ui.components.search-bar :refer [search-bar]]
|
||||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||||
|
@ -59,22 +60,6 @@
|
||||||
[:button {:class (stl/css :trash-button)
|
[:button {:class (stl/css :trash-button)
|
||||||
:on-click handle-delete-click} i/delete]]))
|
:on-click handle-delete-click} i/delete]]))
|
||||||
|
|
||||||
|
|
||||||
(defn open-plugin!
|
|
||||||
[{:keys [plugin-id name description host code icon permissions]}]
|
|
||||||
(try
|
|
||||||
(.ɵloadPlugin
|
|
||||||
js/window
|
|
||||||
#js {:pluginId plugin-id
|
|
||||||
:name name
|
|
||||||
:description description
|
|
||||||
:host host
|
|
||||||
:code code
|
|
||||||
:icon icon
|
|
||||||
:permissions (apply array permissions)})
|
|
||||||
(catch :default e
|
|
||||||
(.error js/console "Error" e))))
|
|
||||||
|
|
||||||
(mf/defc plugin-management-dialog
|
(mf/defc plugin-management-dialog
|
||||||
{::mf/register modal/components
|
{::mf/register modal/components
|
||||||
::mf/register-as :plugin-management}
|
::mf/register-as :plugin-management}
|
||||||
|
@ -144,7 +129,7 @@
|
||||||
::ev/origin "workspace:plugins"
|
::ev/origin "workspace:plugins"
|
||||||
:name (:name manifest)
|
:name (:name manifest)
|
||||||
:host (:host manifest)}))
|
:host (:host manifest)}))
|
||||||
(open-plugin! manifest)
|
(dp/open-plugin! manifest)
|
||||||
(modal/hide!)))
|
(modal/hide!)))
|
||||||
|
|
||||||
handle-remove-plugin
|
handle-remove-plugin
|
||||||
|
@ -215,7 +200,7 @@
|
||||||
(mf/defc plugins-permissions-dialog
|
(mf/defc plugins-permissions-dialog
|
||||||
{::mf/register modal/components
|
{::mf/register modal/components
|
||||||
::mf/register-as :plugin-permissions}
|
::mf/register-as :plugin-permissions}
|
||||||
[{:keys [plugin on-accept]}]
|
[{:keys [plugin on-accept on-close]}]
|
||||||
|
|
||||||
(let [{:keys [host permissions]} plugin
|
(let [{:keys [host permissions]} plugin
|
||||||
permissions (set permissions)
|
permissions (set permissions)
|
||||||
|
@ -224,25 +209,26 @@
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(st/emit! (modal/hide))
|
(st/emit! (ptk/event ::ev/event {::ev/name "allow-plugin-permissions"
|
||||||
(ptk/event ::ev/event {::ev/name "allow-plugin-permissions"
|
:host host
|
||||||
:host host
|
:permissions (->> permissions (str/join ", "))})
|
||||||
:permissions (->> permissions (str/join ", "))})
|
(modal/hide))
|
||||||
(on-accept)))
|
(when on-accept (on-accept))))
|
||||||
|
|
||||||
handle-close-dialog
|
handle-close-dialog
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(ptk/event ::ev/event {::ev/name "reject-plugin-permissions"
|
(st/emit! (ptk/event ::ev/event {::ev/name "reject-plugin-permissions"
|
||||||
:host host
|
:host host
|
||||||
:permissions (->> permissions (str/join ", "))})
|
:permissions (->> permissions (str/join ", "))})
|
||||||
(st/emit! (modal/hide))))]
|
(modal/hide))
|
||||||
|
(when on-close (on-close))))]
|
||||||
|
|
||||||
[:div {:class (stl/css :modal-overlay)}
|
[:div {:class (stl/css :modal-overlay)}
|
||||||
[:div {:class (stl/css :modal-dialog :plugin-permissions)}
|
[:div {:class (stl/css :modal-dialog :plugin-permissions)}
|
||||||
[:button {:class (stl/css :close-btn) :on-click handle-close-dialog} close-icon]
|
[:button {:class (stl/css :close-btn) :on-click handle-close-dialog} close-icon]
|
||||||
[:div {:class (stl/css :modal-title)} (tr "workspace.plugins.permissions.title")]
|
[:div {:class (stl/css :modal-title)} (tr "workspace.plugins.permissions.title" (str/upper (:name plugin)))]
|
||||||
|
|
||||||
[:div {:class (stl/css :modal-content)}
|
[:div {:class (stl/css :modal-content)}
|
||||||
[:div {:class (stl/css :permissions-list)}
|
[:div {:class (stl/css :permissions-list)}
|
||||||
|
@ -277,7 +263,27 @@
|
||||||
[:div {:class (stl/css :permissions-list-entry)}
|
[:div {:class (stl/css :permissions-list-entry)}
|
||||||
i/oauth-3
|
i/oauth-3
|
||||||
[:p {:class (stl/css :permissions-list-text)}
|
[:p {:class (stl/css :permissions-list-text)}
|
||||||
(tr "workspace.plugins.permissions.library-read")]])]
|
(tr "workspace.plugins.permissions.library-read")]])
|
||||||
|
|
||||||
|
(cond
|
||||||
|
(contains? permissions "comment:write")
|
||||||
|
[:div {:class (stl/css :permissions-list-entry)}
|
||||||
|
i/oauth-1
|
||||||
|
[:p {:class (stl/css :permissions-list-text)}
|
||||||
|
(tr "workspace.plugins.permissions.comment-write")]]
|
||||||
|
|
||||||
|
(contains? permissions "comment:read")
|
||||||
|
[:div {:class (stl/css :permissions-list-entry)}
|
||||||
|
i/oauth-1
|
||||||
|
[:p {:class (stl/css :permissions-list-text)}
|
||||||
|
(tr "workspace.plugins.permissions.comment-read")]])
|
||||||
|
|
||||||
|
(cond
|
||||||
|
(contains? permissions "allow:downloads")
|
||||||
|
[:div {:class (stl/css :permissions-list-entry)}
|
||||||
|
i/oauth-1
|
||||||
|
[:p {:class (stl/css :permissions-list-text)}
|
||||||
|
(tr "workspace.plugins.permissions.allow-download")]])]
|
||||||
|
|
||||||
[:div {:class (stl/css :permissions-disclaimer)}
|
[:div {:class (stl/css :permissions-disclaimer)}
|
||||||
(tr "workspace.plugins.permissions.disclaimer")]]
|
(tr "workspace.plugins.permissions.disclaimer")]]
|
||||||
|
@ -295,3 +301,55 @@
|
||||||
:type "button"
|
:type "button"
|
||||||
:value (tr "ds.confirm-allow")
|
:value (tr "ds.confirm-allow")
|
||||||
:on-click handle-accept-dialog}]]]]]))
|
:on-click handle-accept-dialog}]]]]]))
|
||||||
|
|
||||||
|
|
||||||
|
(mf/defc plugins-try-out-dialog
|
||||||
|
{::mf/register modal/components
|
||||||
|
::mf/register-as :plugin-try-out}
|
||||||
|
[{:keys [plugin on-accept on-close]}]
|
||||||
|
|
||||||
|
(let [{:keys [icon host name]} plugin
|
||||||
|
|
||||||
|
handle-accept-dialog
|
||||||
|
(mf/use-callback
|
||||||
|
(fn [event]
|
||||||
|
(dom/prevent-default event)
|
||||||
|
(st/emit! (ptk/event ::ev/event {::ev/name "try-out-accept"})
|
||||||
|
(modal/hide))
|
||||||
|
(when on-accept (on-accept))))
|
||||||
|
|
||||||
|
handle-close-dialog
|
||||||
|
(mf/use-callback
|
||||||
|
(fn [event]
|
||||||
|
(dom/prevent-default event)
|
||||||
|
(st/emit! (ptk/event ::ev/event {::ev/name "try-out-cancel"})
|
||||||
|
(modal/hide))
|
||||||
|
(when on-close (on-close))))]
|
||||||
|
|
||||||
|
[:div {:class (stl/css :modal-overlay)}
|
||||||
|
[:div {:class (stl/css :modal-dialog :plugin-try-out)}
|
||||||
|
[:button {:class (stl/css :close-btn) :on-click handle-close-dialog} close-icon]
|
||||||
|
[:div {:class (stl/css :modal-title)}
|
||||||
|
[:div {:class (stl/css :plugin-icon)}
|
||||||
|
[:img {:src (if (some? icon)
|
||||||
|
(dm/str host icon)
|
||||||
|
(avatars/generate {:name name}))}]]
|
||||||
|
(tr "workspace.plugins.try-out.title" (str/upper (:name plugin)))]
|
||||||
|
|
||||||
|
[:div {:class (stl/css :modal-content)}
|
||||||
|
[:div {:class (stl/css :modal-message)}
|
||||||
|
(tr "workspace.plugins.try-out.message")]]
|
||||||
|
|
||||||
|
[:div {:class (stl/css :modal-footer)}
|
||||||
|
[:div {:class (stl/css :action-buttons)}
|
||||||
|
[:input
|
||||||
|
{:class (stl/css :cancel-button :button-expand)
|
||||||
|
:type "button"
|
||||||
|
:value (tr "workspace.plugins.try-out.cancel")
|
||||||
|
:on-click handle-close-dialog}]
|
||||||
|
|
||||||
|
[:input
|
||||||
|
{:class (stl/css :primary-button :button-expand)
|
||||||
|
:type "button"
|
||||||
|
:value (tr "workspace.plugins.try-out.try")
|
||||||
|
:on-click handle-accept-dialog}]]]]]))
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
@extend .modal-container-base;
|
@extend .modal-container-base;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-rows: auto 1fr auto;
|
grid-template-rows: auto 1fr auto;
|
||||||
|
max-height: initial;
|
||||||
|
|
||||||
&.plugin-permissions {
|
&.plugin-permissions {
|
||||||
width: $s-412;
|
width: $s-412;
|
||||||
|
@ -25,6 +26,11 @@
|
||||||
max-width: $s-472;
|
max-width: $s-472;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.plugin-try-out {
|
||||||
|
width: $s-452;
|
||||||
|
max-width: $s-452;
|
||||||
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border-color: var(--color-background-tertiary);
|
border-color: var(--color-background-tertiary);
|
||||||
}
|
}
|
||||||
|
@ -47,6 +53,8 @@
|
||||||
@include headlineMediumTypography;
|
@include headlineMediumTypography;
|
||||||
margin-block-end: $s-32;
|
margin-block-end: $s-32;
|
||||||
color: var(--modal-title-foreground-color);
|
color: var(--modal-title-foreground-color);
|
||||||
|
display: flex;
|
||||||
|
gap: $s-12;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-content {
|
.modal-content {
|
||||||
|
@ -63,6 +71,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-message {
|
||||||
|
font-size: $fs-14;
|
||||||
|
color: var(--color-foreground-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
.primary-button {
|
.primary-button {
|
||||||
@extend .button-primary;
|
@extend .button-primary;
|
||||||
@include headlineSmallTypography;
|
@include headlineSmallTypography;
|
||||||
|
@ -253,8 +266,8 @@ div.input-error {
|
||||||
.permissions-disclaimer {
|
.permissions-disclaimer {
|
||||||
@include bodySmallTypography;
|
@include bodySmallTypography;
|
||||||
padding: $s-16;
|
padding: $s-16;
|
||||||
background: var(--color-background-tertiary);
|
background: var(--color-background-quaternary);
|
||||||
color: var(--color-foreground-secondary);
|
color: var(--color-foreground-quaternary);
|
||||||
border-radius: $br-4;
|
border-radius: $br-4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,18 +76,15 @@
|
||||||
|
|
||||||
(getFile
|
(getFile
|
||||||
[_]
|
[_]
|
||||||
(file/file-proxy $plugin (:current-file-id @st/state)))
|
(when (some? (:current-file-id @st/state))
|
||||||
|
(file/file-proxy $plugin (:current-file-id @st/state))))
|
||||||
|
|
||||||
(getPage
|
(getPage
|
||||||
[_]
|
[_]
|
||||||
(let [file-id (:current-file-id @st/state)
|
(let [file-id (:current-file-id @st/state)
|
||||||
page-id (:current-page-id @st/state)]
|
page-id (:current-page-id @st/state)]
|
||||||
(page/page-proxy $plugin file-id page-id)))
|
(when (and (some? file-id) (some? page-id))
|
||||||
|
(page/page-proxy $plugin file-id page-id))))
|
||||||
(getSelected
|
|
||||||
[_]
|
|
||||||
(let [selection (get-in @st/state [:workspace-local :selected])]
|
|
||||||
(apply array (map str selection))))
|
|
||||||
|
|
||||||
(getSelectedShapes
|
(getSelectedShapes
|
||||||
[_]
|
[_]
|
||||||
|
@ -143,7 +140,9 @@
|
||||||
|
|
||||||
(getRoot
|
(getRoot
|
||||||
[_]
|
[_]
|
||||||
(shape/shape-proxy $plugin uuid/zero))
|
(when (and (some? (:current-file-id @st/state))
|
||||||
|
(some? (:current-page-id @st/state)))
|
||||||
|
(shape/shape-proxy $plugin uuid/zero)))
|
||||||
|
|
||||||
(getTheme
|
(getTheme
|
||||||
[_]
|
[_]
|
||||||
|
@ -444,6 +443,7 @@
|
||||||
{:name "root" :get #(.getRoot ^js %)}
|
{:name "root" :get #(.getRoot ^js %)}
|
||||||
{:name "currentFile" :get #(.getFile ^js %)}
|
{:name "currentFile" :get #(.getFile ^js %)}
|
||||||
{:name "currentPage" :get #(.getPage ^js %)}
|
{:name "currentPage" :get #(.getPage ^js %)}
|
||||||
|
{:name "theme" :get #(.getTheme ^js %)}
|
||||||
|
|
||||||
{:name "selection"
|
{:name "selection"
|
||||||
:get #(.getSelectedShapes ^js %)
|
:get #(.getSelectedShapes ^js %)
|
||||||
|
|
|
@ -27,9 +27,16 @@
|
||||||
(remove [_]
|
(remove [_]
|
||||||
(p/create
|
(p/create
|
||||||
(fn [resolve reject]
|
(fn [resolve reject]
|
||||||
(->> (rp/cmd! :delete-comment {:id $id})
|
(cond
|
||||||
(rx/tap #(st/emit! (dc/retrieve-comment-threads $file)))
|
(not (r/check-permission $plugin "comment:write"))
|
||||||
(rx/subs! #(resolve) reject))))))
|
(do
|
||||||
|
(u/display-not-valid :remove "Plugin doesn't have 'comment:write' permission")
|
||||||
|
(reject "Plugin doesn't have 'comment:write' permission"))
|
||||||
|
|
||||||
|
:else
|
||||||
|
(->> (rp/cmd! :delete-comment {:id $id})
|
||||||
|
(rx/tap #(st/emit! (dc/retrieve-comment-threads $file)))
|
||||||
|
(rx/subs! #(resolve) reject)))))))
|
||||||
|
|
||||||
(defn comment-proxy? [p]
|
(defn comment-proxy? [p]
|
||||||
(instance? CommentProxy p))
|
(instance? CommentProxy p))
|
||||||
|
@ -60,8 +67,8 @@
|
||||||
(not= (:id profile) (:owner-id data))
|
(not= (:id profile) (:owner-id data))
|
||||||
(u/display-not-valid :content "Cannot change content from another user's comments")
|
(u/display-not-valid :content "Cannot change content from another user's comments")
|
||||||
|
|
||||||
(not (r/check-permission plugin-id "content:write"))
|
(not (r/check-permission plugin-id "comment:write"))
|
||||||
(u/display-not-valid :content "Plugin doesn't have 'content:write' permission")
|
(u/display-not-valid :content "Plugin doesn't have 'comment:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(->> (rp/cmd! :update-comment {:id (:id data) :content content})
|
(->> (rp/cmd! :update-comment {:id (:id data) :content content})
|
||||||
|
@ -74,22 +81,29 @@
|
||||||
[_]
|
[_]
|
||||||
(p/create
|
(p/create
|
||||||
(fn [resolve reject]
|
(fn [resolve reject]
|
||||||
(->> (rp/cmd! :get-comments {:thread-id $id})
|
(cond
|
||||||
(rx/subs!
|
(not (r/check-permission $plugin "comment:read"))
|
||||||
(fn [comments]
|
(do
|
||||||
(resolve
|
(u/display-not-valid :findComments "Plugin doesn't have 'comment:read' permission")
|
||||||
(format/format-array
|
(reject "Plugin doesn't have 'comment:read' permission"))
|
||||||
#(comment-proxy $plugin $file $page $id $users %) comments)))
|
|
||||||
reject)))))
|
:else
|
||||||
|
(->> (rp/cmd! :get-comments {:thread-id $id})
|
||||||
|
(rx/subs!
|
||||||
|
(fn [comments]
|
||||||
|
(resolve
|
||||||
|
(format/format-array
|
||||||
|
#(comment-proxy $plugin $file $page $id $users %) comments)))
|
||||||
|
reject))))))
|
||||||
|
|
||||||
(reply
|
(reply
|
||||||
[_ content]
|
[_ content]
|
||||||
(cond
|
(cond
|
||||||
(not (r/check-permission $plugin "content:write"))
|
(not (r/check-permission $plugin "comment:write"))
|
||||||
(u/display-not-valid :content "Plugin doesn't have 'content:write' permission")
|
(u/display-not-valid :reply "Plugin doesn't have 'comment:write' permission")
|
||||||
|
|
||||||
(or (not (string? content)) (empty? content))
|
(or (not (string? content)) (empty? content))
|
||||||
(u/display-not-valid :content "Not valid")
|
(u/display-not-valid :reply "Not valid")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(p/create
|
(p/create
|
||||||
|
@ -100,11 +114,11 @@
|
||||||
(remove [_]
|
(remove [_]
|
||||||
(let [profile (:profile @st/state)]
|
(let [profile (:profile @st/state)]
|
||||||
(cond
|
(cond
|
||||||
(not (r/check-permission $plugin "content:write"))
|
(not (r/check-permission $plugin "comment:write"))
|
||||||
(u/display-not-valid :removeCommentThread "Plugin doesn't have 'content:write' permission")
|
(u/display-not-valid :remove "Plugin doesn't have 'comment:write' permission")
|
||||||
|
|
||||||
(not= (:id profile) owner)
|
(not= (:id profile) owner)
|
||||||
(u/display-not-valid :content "Cannot change content from another user's comments")
|
(u/display-not-valid :remove "Cannot change content from another user's comments")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(p/create
|
(p/create
|
||||||
|
@ -140,8 +154,8 @@
|
||||||
(or (not (us/safe-number? (:x position))) (not (us/safe-number? (:y position))))
|
(or (not (us/safe-number? (:x position))) (not (us/safe-number? (:y position))))
|
||||||
(u/display-not-valid :position "Not valid point")
|
(u/display-not-valid :position "Not valid point")
|
||||||
|
|
||||||
(not (r/check-permission plugin-id "content:write"))
|
(not (r/check-permission plugin-id "comment:write"))
|
||||||
(u/display-not-valid :content "Plugin doesn't have 'content:write' permission")
|
(u/display-not-valid :position "Plugin doesn't have 'comment:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(do (st/emit! (dwc/update-comment-thread-position @data* [(:x position) (:y position)]))
|
(do (st/emit! (dwc/update-comment-thread-position @data* [(:x position) (:y position)]))
|
||||||
|
@ -155,8 +169,8 @@
|
||||||
(not (boolean? is-resolved))
|
(not (boolean? is-resolved))
|
||||||
(u/display-not-valid :resolved "Not a boolean type")
|
(u/display-not-valid :resolved "Not a boolean type")
|
||||||
|
|
||||||
(not (r/check-permission plugin-id "content:write"))
|
(not (r/check-permission plugin-id "comment:write"))
|
||||||
(u/display-not-valid :resolved "Plugin doesn't have 'content:write' permission")
|
(u/display-not-valid :resolved "Plugin doesn't have 'comment:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(do (st/emit! (dc/update-comment-thread (assoc @data* :is-resolved is-resolved)))
|
(do (st/emit! (dc/update-comment-thread (assoc @data* :is-resolved is-resolved)))
|
||||||
|
|
|
@ -258,7 +258,7 @@
|
||||||
(u/display-not-valid :removeRulerGuide "Guide not provided")
|
(u/display-not-valid :removeRulerGuide "Guide not provided")
|
||||||
|
|
||||||
(not (r/check-permission $plugin "content:write"))
|
(not (r/check-permission $plugin "content:write"))
|
||||||
(u/display-not-valid :removeRulerGuide "Plugin doesn't have 'content:write' permission")
|
(u/display-not-valid :removeRulerGuide "Plugin doesn't have 'comment:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(let [guide (u/proxy->ruler-guide value)]
|
(let [guide (u/proxy->ruler-guide value)]
|
||||||
|
@ -279,8 +279,8 @@
|
||||||
(and (some? board) (or (not (shape/shape-proxy? board)) (not (cfh/frame-shape? shape))))
|
(and (some? board) (or (not (shape/shape-proxy? board)) (not (cfh/frame-shape? shape))))
|
||||||
(u/display-not-valid :addCommentThread "Board not valid")
|
(u/display-not-valid :addCommentThread "Board not valid")
|
||||||
|
|
||||||
(not (r/check-permission $plugin "content:write"))
|
(not (r/check-permission $plugin "comment:write"))
|
||||||
(u/display-not-valid :addCommentThread "Plugin doesn't have 'content:write' permission")
|
(u/display-not-valid :addCommentThread "Plugin doesn't have 'comment:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(let [position
|
(let [position
|
||||||
|
@ -311,7 +311,7 @@
|
||||||
(not (pc/comment-thread-proxy? thread))
|
(not (pc/comment-thread-proxy? thread))
|
||||||
(u/display-not-valid :removeCommentThread "Comment thread not valid")
|
(u/display-not-valid :removeCommentThread "Comment thread not valid")
|
||||||
|
|
||||||
(not (r/check-permission $plugin "content:write"))
|
(not (r/check-permission $plugin "comment:write"))
|
||||||
(u/display-not-valid :removeCommentThread "Plugin doesn't have 'content:write' permission")
|
(u/display-not-valid :removeCommentThread "Plugin doesn't have 'content:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
|
@ -328,23 +328,30 @@
|
||||||
user-id (-> @st/state :profile :id)]
|
user-id (-> @st/state :profile :id)]
|
||||||
(p/create
|
(p/create
|
||||||
(fn [resolve reject]
|
(fn [resolve reject]
|
||||||
(->> (rx/zip (rp/cmd! :get-team-users {:file-id $file})
|
(cond
|
||||||
(rp/cmd! :get-comment-threads {:file-id $file}))
|
(not (r/check-permission $plugin "comment:read"))
|
||||||
(rx/take 1)
|
(do
|
||||||
(rx/subs!
|
(u/display-not-valid :findCommentThreads "Plugin doesn't have 'comment:read' permission")
|
||||||
(fn [[users comments]]
|
(reject "Plugin doesn't have 'comment:read' permission"))
|
||||||
(let [users (d/index-by :id users)
|
|
||||||
comments
|
|
||||||
(cond->> comments
|
|
||||||
(not show-resolved)
|
|
||||||
(filter (comp not :is-resolved))
|
|
||||||
|
|
||||||
only-yours
|
:else
|
||||||
(filter #(contains? (:participants %) user-id)))]
|
(->> (rx/zip (rp/cmd! :get-team-users {:file-id $file})
|
||||||
(resolve
|
(rp/cmd! :get-comment-threads {:file-id $file}))
|
||||||
(format/format-array
|
(rx/take 1)
|
||||||
#(pc/comment-thread-proxy $plugin $file $id users %) comments))))
|
(rx/subs!
|
||||||
reject)))))))
|
(fn [[users comments]]
|
||||||
|
(let [users (d/index-by :id users)
|
||||||
|
comments
|
||||||
|
(cond->> comments
|
||||||
|
(not show-resolved)
|
||||||
|
(filter (comp not :is-resolved))
|
||||||
|
|
||||||
|
only-yours
|
||||||
|
(filter #(contains? (:participants %) user-id)))]
|
||||||
|
(resolve
|
||||||
|
(format/format-array
|
||||||
|
#(pc/comment-thread-proxy $plugin $file $id users %) comments))))
|
||||||
|
reject))))))))
|
||||||
|
|
||||||
(crc/define-properties!
|
(crc/define-properties!
|
||||||
PageProxy
|
PageProxy
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
;; Copyright (c) KALEIDOS INC
|
;; Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
(ns app.plugins.register
|
(ns app.plugins.register
|
||||||
"RPC for plugins runtime."
|
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
|
@ -26,6 +25,10 @@
|
||||||
(->> (:ids @registry)
|
(->> (:ids @registry)
|
||||||
(mapv #(dm/get-in @registry [:data %]))))
|
(mapv #(dm/get-in @registry [:data %]))))
|
||||||
|
|
||||||
|
(defn get-plugin
|
||||||
|
[id]
|
||||||
|
(dm/get-in @registry [:data id]))
|
||||||
|
|
||||||
(defn parse-manifest
|
(defn parse-manifest
|
||||||
"Read the manifest.json defined by the plugins definition and transforms it into an
|
"Read the manifest.json defined by the plugins definition and transforms it into an
|
||||||
object that will be stored in the register."
|
object that will be stored in the register."
|
||||||
|
@ -42,7 +45,10 @@
|
||||||
(conj "content:read")
|
(conj "content:read")
|
||||||
|
|
||||||
(contains? permissions "library:write")
|
(contains? permissions "library:write")
|
||||||
(conj "content:write"))
|
(conj "content:write")
|
||||||
|
|
||||||
|
(contains? permissions "comment:write")
|
||||||
|
(conj "comment:read"))
|
||||||
|
|
||||||
origin (obj/get (js/URL. plugin-url) "origin")
|
origin (obj/get (js/URL. plugin-url) "origin")
|
||||||
|
|
||||||
|
|
|
@ -987,7 +987,7 @@
|
||||||
:get (fn [self]
|
:get (fn [self]
|
||||||
(let [shape (u/proxy->shape self)
|
(let [shape (u/proxy->shape self)
|
||||||
parent-id (:parent-id shape)]
|
parent-id (:parent-id shape)]
|
||||||
(shape-proxy (obj/get self "$file") (obj/get self "$page") parent-id)))}
|
(shape-proxy plugin-id (obj/get self "$file") (obj/get self "$page") parent-id)))}
|
||||||
{:name "parentX"
|
{:name "parentX"
|
||||||
:get (fn [self]
|
:get (fn [self]
|
||||||
(let [shape (u/proxy->shape self)
|
(let [shape (u/proxy->shape self)
|
||||||
|
|
|
@ -5580,7 +5580,7 @@ msgstr "Read and modify the content of files that users have access to."
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/plugins.cljs:274
|
#: src/app/main/ui/workspace/plugins.cljs:274
|
||||||
msgid "workspace.plugins.permissions.disclaimer"
|
msgid "workspace.plugins.permissions.disclaimer"
|
||||||
msgstr "Note that this plugin has been created by an external party."
|
msgstr "Please note that this plugin is created by an external party, so ensure you trust it before granting access. Your data privacy and security are important to us. If you have any concerns, please contact support."
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/plugins.cljs:271
|
#: src/app/main/ui/workspace/plugins.cljs:271
|
||||||
msgid "workspace.plugins.permissions.library-read"
|
msgid "workspace.plugins.permissions.library-read"
|
||||||
|
@ -5590,14 +5590,35 @@ msgstr "Read your libraries and assets."
|
||||||
msgid "workspace.plugins.permissions.library-write"
|
msgid "workspace.plugins.permissions.library-write"
|
||||||
msgstr "Read and modify your libraries and assets."
|
msgstr "Read and modify your libraries and assets."
|
||||||
|
|
||||||
|
msgid "workspace.plugins.permissions.comment-read"
|
||||||
|
msgstr "Read your comments and replies."
|
||||||
|
|
||||||
|
msgid "workspace.plugins.permissions.comment-write"
|
||||||
|
msgstr "Read and modify your comments and reply in your name."
|
||||||
|
|
||||||
|
msgid "workspace.plugins.permissions.allow-download"
|
||||||
|
msgstr "Start file downloads."
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/plugins.cljs:236
|
#: src/app/main/ui/workspace/plugins.cljs:236
|
||||||
msgid "workspace.plugins.permissions.title"
|
msgid "workspace.plugins.permissions.title"
|
||||||
msgstr "THIS PLUGIN WANTS ACCESS TO:"
|
msgstr "'%s' PLUGIN WANTS ACCESS TO:"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/plugins.cljs:258
|
#: src/app/main/ui/workspace/plugins.cljs:258
|
||||||
msgid "workspace.plugins.permissions.user-read"
|
msgid "workspace.plugins.permissions.user-read"
|
||||||
msgstr "Read the profile information of the current user."
|
msgstr "Read the profile information of the current user."
|
||||||
|
|
||||||
|
msgid "workspace.plugins.try-out.title"
|
||||||
|
msgstr "'%s' PLUGIN IS INSTALLED FOR YOUR USER!"
|
||||||
|
|
||||||
|
msgid "workspace.plugins.try-out.message"
|
||||||
|
msgstr "Want to take a look? It will open in a new draft for your current team. (If not, you can always find it in the installed plugins of any file.)"
|
||||||
|
|
||||||
|
msgid "workspace.plugins.try-out.cancel"
|
||||||
|
msgstr "NOT NOW"
|
||||||
|
|
||||||
|
msgid "workspace.plugins.try-out.try"
|
||||||
|
msgstr "TRY PLUGIN"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/plugins.cljs:192
|
#: src/app/main/ui/workspace/plugins.cljs:192
|
||||||
msgid "workspace.plugins.plugin-list-link"
|
msgid "workspace.plugins.plugin-list-link"
|
||||||
msgstr "Plugins List"
|
msgstr "Plugins List"
|
||||||
|
|
|
@ -5567,7 +5567,7 @@ msgstr "Leer y modificar el contenido de sus archivos."
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/plugins.cljs:274
|
#: src/app/main/ui/workspace/plugins.cljs:274
|
||||||
msgid "workspace.plugins.permissions.disclaimer"
|
msgid "workspace.plugins.permissions.disclaimer"
|
||||||
msgstr "Tenga en cuenta que esta extensión ha sido desarrollada por terceros."
|
msgstr "Ten en cuenta que las extensiones están desarrolladas por terceros, aseguraté que confías antes de conceder el permiso. Tu privacidad y seguridad es importante para nosotros. Si tienes cualquier duda, contacta con soporte."
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/plugins.cljs:271
|
#: src/app/main/ui/workspace/plugins.cljs:271
|
||||||
msgid "workspace.plugins.permissions.library-read"
|
msgid "workspace.plugins.permissions.library-read"
|
||||||
|
@ -5577,14 +5577,35 @@ msgstr "Leer la información de sus bibliotecas y recursos."
|
||||||
msgid "workspace.plugins.permissions.library-write"
|
msgid "workspace.plugins.permissions.library-write"
|
||||||
msgstr "Leer y modificar la información de sus bibliotecas y recursos."
|
msgstr "Leer y modificar la información de sus bibliotecas y recursos."
|
||||||
|
|
||||||
|
msgid "workspace.plugins.permissions.comment-read"
|
||||||
|
msgstr "Leer tus comentarios y respuestas."
|
||||||
|
|
||||||
|
msgid "workspace.plugins.permissions.comment-write"
|
||||||
|
msgstr "Leer y modificar tus comentarios y responder en tu nombre."
|
||||||
|
|
||||||
|
msgid "workspace.plugins.permissions.allow-download"
|
||||||
|
msgstr "Comenzar descargas de ficheros."
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/plugins.cljs:236
|
#: src/app/main/ui/workspace/plugins.cljs:236
|
||||||
msgid "workspace.plugins.permissions.title"
|
msgid "workspace.plugins.permissions.title"
|
||||||
msgstr "LA EXTENSIÓN SOLICITA PERMISO PARA ACCEDER:"
|
msgstr "LA EXTENSIÓN '%s' SOLICITA PERMISO PARA ACCEDER:"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/plugins.cljs:258
|
#: src/app/main/ui/workspace/plugins.cljs:258
|
||||||
msgid "workspace.plugins.permissions.user-read"
|
msgid "workspace.plugins.permissions.user-read"
|
||||||
msgstr "Leer la información del usuario actual."
|
msgstr "Leer la información del usuario actual."
|
||||||
|
|
||||||
|
msgid "workspace.plugins.try-out.title"
|
||||||
|
msgstr "¡LA EXTENSIÓN '%s' HA SIDO INSTALADA PARA TU USUARIO!"
|
||||||
|
|
||||||
|
msgid "workspace.plugins.try-out.message"
|
||||||
|
msgstr "¿Quieres echar un vistazo?. Crearemos un nuevo borrador en tu equipo actual. (Si no, puedes encontrar los plugins instalados en cualquier fichero.)"
|
||||||
|
|
||||||
|
msgid "workspace.plugins.try-out.cancel"
|
||||||
|
msgstr "AHORA NO"
|
||||||
|
|
||||||
|
msgid "workspace.plugins.try-out.try"
|
||||||
|
msgstr "PROBAR PLUGIN"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/plugins.cljs:192
|
#: src/app/main/ui/workspace/plugins.cljs:192
|
||||||
msgid "workspace.plugins.plugin-list-link"
|
msgid "workspace.plugins.plugin-list-link"
|
||||||
msgstr "Lista de extensiones"
|
msgstr "Lista de extensiones"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue