mirror of
https://github.com/penpot/penpot.git
synced 2025-07-25 20:27:52 +02:00
Merge pull request #5090 from penpot/alotor-new-apis
Plugins - API's modifications
This commit is contained in:
commit
b50fcee079
21 changed files with 2280 additions and 1603 deletions
|
@ -10,7 +10,7 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.types.plugins :refer [schema:plugin-data]]
|
||||
[app.common.types.plugins :refer [schema:plugin-registry]]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
|
@ -43,7 +43,7 @@
|
|||
|
||||
(def schema:props
|
||||
[:map {:title "ProfileProps"}
|
||||
[:plugins {:optional true} schema:plugin-data]
|
||||
[:plugins {:optional true} schema:plugin-registry]
|
||||
[:newsletter-updates {:optional true} ::sm/boolean]
|
||||
[:newsletter-news {:optional true} ::sm/boolean]
|
||||
[:onboarding-team-id {:optional true} ::sm/uuid]
|
||||
|
|
|
@ -29,3 +29,25 @@
|
|||
schema:string]])
|
||||
|
||||
(sm/register! ::plugin-data schema:plugin-data)
|
||||
|
||||
|
||||
(def ^:private schema:registry-entry
|
||||
[:map
|
||||
[:plugin-id :string]
|
||||
[:name :string]
|
||||
[:description {:optional true} :string]
|
||||
[:host :string]
|
||||
[:code :string]
|
||||
[:icon {:optional true} :string]
|
||||
[:permissions [:set :string]]])
|
||||
|
||||
(def schema:plugin-registry
|
||||
[:map
|
||||
[:ids [:vector :string]]
|
||||
[:data
|
||||
[:map-of {:gen/max 5}
|
||||
:string
|
||||
schema:registry-entry]]])
|
||||
|
||||
(sm/register! ::plugin-registry schema:plugin-registry)
|
||||
(sm/register! ::registry-entry schema:registry-entry)
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -56,27 +56,30 @@
|
|||
(declare refresh-comment-thread)
|
||||
|
||||
(defn created-thread-on-workspace
|
||||
[{:keys [id comment page-id] :as thread}]
|
||||
(ptk/reify ::created-thread-on-workspace
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [position (select-keys thread [:position :frame-id])]
|
||||
(-> state
|
||||
(update :comment-threads assoc id (dissoc thread :comment))
|
||||
(update-in [:workspace-data :pages-index page-id :options :comment-threads-position] assoc id position)
|
||||
(update :comments-local assoc :open id)
|
||||
(update :comments-local assoc :options nil)
|
||||
(update :comments-local dissoc :draft)
|
||||
(update :workspace-drawing dissoc :comment)
|
||||
(update-in [:comments id] assoc (:id comment) comment))))
|
||||
([params]
|
||||
(created-thread-on-workspace params true))
|
||||
([{:keys [id comment page-id] :as thread} open?]
|
||||
(ptk/reify ::created-thread-on-workspace
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [position (select-keys thread [:position :frame-id])]
|
||||
(-> state
|
||||
(update :comment-threads assoc id (dissoc thread :comment))
|
||||
(update-in [:workspace-data :pages-index page-id :options :comment-threads-position] assoc id position)
|
||||
(cond-> open?
|
||||
(update :comments-local assoc :open id))
|
||||
(update :comments-local assoc :options nil)
|
||||
(update :comments-local dissoc :draft)
|
||||
(update :workspace-drawing dissoc :comment)
|
||||
(update-in [:comments id] assoc (:id comment) comment))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(rx/of (ptk/data-event ::ev/event
|
||||
{::ev/name "create-comment-thread"
|
||||
::ev/origin "workspace"
|
||||
:id id
|
||||
:content-size (count (:content comment))})))))
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(rx/of (ptk/data-event ::ev/event
|
||||
{::ev/name "create-comment-thread"
|
||||
::ev/origin "workspace"
|
||||
:id id
|
||||
:content-size (count (:content comment))}))))))
|
||||
|
||||
|
||||
|
||||
|
@ -89,24 +92,27 @@
|
|||
[:content :string]])
|
||||
|
||||
(defn create-thread-on-workspace
|
||||
[params]
|
||||
(dm/assert! (sm/check! schema:create-thread-on-workspace params))
|
||||
([params]
|
||||
(create-thread-on-workspace params identity true))
|
||||
([params on-thread-created open?]
|
||||
(dm/assert! (sm/check! schema:create-thread-on-workspace params))
|
||||
|
||||
(ptk/reify ::create-thread-on-workspace
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
frame-id (ctst/get-frame-id-by-position objects (:position params))
|
||||
params (assoc params :frame-id frame-id)]
|
||||
(->> (rp/cmd! :create-comment-thread params)
|
||||
(rx/mapcat #(rp/cmd! :get-comment-thread {:file-id (:file-id %) :id (:id %)}))
|
||||
(rx/map created-thread-on-workspace)
|
||||
(rx/catch (fn [{:keys [type code] :as cause}]
|
||||
(if (and (= type :restriction)
|
||||
(= code :max-quote-reached))
|
||||
(rx/throw cause)
|
||||
(rx/throw {:type :comment-error})))))))))
|
||||
(ptk/reify ::create-thread-on-workspace
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
frame-id (ctst/get-frame-id-by-position objects (:position params))
|
||||
params (assoc params :frame-id frame-id)]
|
||||
(->> (rp/cmd! :create-comment-thread params)
|
||||
(rx/mapcat #(rp/cmd! :get-comment-thread {:file-id (:file-id %) :id (:id %)}))
|
||||
(rx/tap on-thread-created)
|
||||
(rx/map #(created-thread-on-workspace % open?))
|
||||
(rx/catch (fn [{:keys [type code] :as cause}]
|
||||
(if (and (= type :restriction)
|
||||
(= code :max-quote-reached))
|
||||
(rx/throw cause)
|
||||
(rx/throw {:type :comment-error}))))))))))
|
||||
|
||||
(defn created-thread-on-viewer
|
||||
[{:keys [id comment page-id] :as thread}]
|
||||
|
@ -257,29 +263,31 @@
|
|||
(rx/map #(retrieve-comment-threads file-id)))))))
|
||||
|
||||
(defn delete-comment-thread-on-workspace
|
||||
[{:keys [id] :as thread}]
|
||||
(dm/assert!
|
||||
"expected valid comment thread"
|
||||
(check-comment-thread! thread))
|
||||
(ptk/reify ::delete-comment-thread-on-workspace
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [page-id (:current-page-id state)]
|
||||
(-> state
|
||||
(update-in [:workspace-data :pages-index page-id :options :comment-threads-position] dissoc id)
|
||||
(update :comments dissoc id)
|
||||
(update :comment-threads dissoc id))))
|
||||
([params]
|
||||
(delete-comment-thread-on-workspace params identity))
|
||||
([{:keys [id] :as thread} on-delete]
|
||||
(dm/assert! (uuid? id))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(rx/concat
|
||||
(->> (rp/cmd! :delete-comment-thread {:id id})
|
||||
(rx/catch #(rx/throw {:type :comment-error}))
|
||||
(rx/ignore))
|
||||
(rx/of (ptk/data-event ::ev/event
|
||||
{::ev/name "delete-comment-thread"
|
||||
::ev/origin "workspace"
|
||||
:id id}))))))
|
||||
(ptk/reify ::delete-comment-thread-on-workspace
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [page-id (:current-page-id state)]
|
||||
(-> state
|
||||
(update-in [:workspace-data :pages-index page-id :options :comment-threads-position] dissoc id)
|
||||
(update :comments dissoc id)
|
||||
(update :comment-threads dissoc id))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(rx/concat
|
||||
(->> (rp/cmd! :delete-comment-thread {:id id})
|
||||
(rx/catch #(rx/throw {:type :comment-error}))
|
||||
(rx/tap on-delete)
|
||||
(rx/ignore))
|
||||
(rx/of (ptk/data-event ::ev/event
|
||||
{::ev/name "delete-comment-thread"
|
||||
::ev/origin "workspace"
|
||||
:id id})))))))
|
||||
|
||||
(defn delete-comment-thread-on-viewer
|
||||
[{:keys [id] :as thread}]
|
||||
|
|
|
@ -970,25 +970,27 @@
|
|||
(map #(gal/align-to-rect % rect axis) selected-objs)))
|
||||
|
||||
(defn align-objects
|
||||
[axis]
|
||||
(dm/assert!
|
||||
"expected valid align axis value"
|
||||
(contains? gal/valid-align-axis axis))
|
||||
([axis]
|
||||
(align-objects axis nil))
|
||||
([axis selected]
|
||||
(dm/assert!
|
||||
"expected valid align axis value"
|
||||
(contains? gal/valid-align-axis axis))
|
||||
|
||||
(ptk/reify ::align-objects
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
selected (wsh/lookup-selected state)
|
||||
moved (if (= 1 (count selected))
|
||||
(align-object-to-parent objects (first selected) axis)
|
||||
(align-objects-list objects selected axis))
|
||||
undo-id (js/Symbol)]
|
||||
(when (can-align? selected objects)
|
||||
(rx/of (dwu/start-undo-transaction undo-id)
|
||||
(dwt/position-shapes moved)
|
||||
(ptk/data-event :layout/update {:ids selected})
|
||||
(dwu/commit-undo-transaction undo-id)))))))
|
||||
(ptk/reify ::align-objects
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
selected (or selected (wsh/lookup-selected state))
|
||||
moved (if (= 1 (count selected))
|
||||
(align-object-to-parent objects (first selected) axis)
|
||||
(align-objects-list objects selected axis))
|
||||
undo-id (js/Symbol)]
|
||||
(when (can-align? selected objects)
|
||||
(rx/of (dwu/start-undo-transaction undo-id)
|
||||
(dwt/position-shapes moved)
|
||||
(ptk/data-event :layout/update {:ids selected})
|
||||
(dwu/commit-undo-transaction undo-id))))))))
|
||||
|
||||
(defn can-distribute? [selected]
|
||||
(cond
|
||||
|
@ -997,25 +999,27 @@
|
|||
:else true))
|
||||
|
||||
(defn distribute-objects
|
||||
[axis]
|
||||
(dm/assert!
|
||||
"expected valid distribute axis value"
|
||||
(contains? gal/valid-dist-axis axis))
|
||||
([axis]
|
||||
(distribute-objects axis nil))
|
||||
([axis ids]
|
||||
(dm/assert!
|
||||
"expected valid distribute axis value"
|
||||
(contains? gal/valid-dist-axis axis))
|
||||
|
||||
(ptk/reify ::distribute-objects
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
selected (wsh/lookup-selected state)
|
||||
moved (-> (map #(get objects %) selected)
|
||||
(gal/distribute-space axis))
|
||||
undo-id (js/Symbol)]
|
||||
(when (can-distribute? selected)
|
||||
(rx/of (dwu/start-undo-transaction undo-id)
|
||||
(dwt/position-shapes moved)
|
||||
(ptk/data-event :layout/update {:ids selected})
|
||||
(dwu/commit-undo-transaction undo-id)))))))
|
||||
(ptk/reify ::distribute-objects
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
selected (or ids (wsh/lookup-selected state))
|
||||
moved (-> (map #(get objects %) selected)
|
||||
(gal/distribute-space axis))
|
||||
undo-id (js/Symbol)]
|
||||
(when (can-distribute? selected)
|
||||
(rx/of (dwu/start-undo-transaction undo-id)
|
||||
(dwt/position-shapes moved)
|
||||
(ptk/data-event :layout/update {:ids selected})
|
||||
(dwu/commit-undo-transaction undo-id))))))))
|
||||
|
||||
;; --- Shape Proportions
|
||||
|
||||
|
|
|
@ -15,24 +15,27 @@
|
|||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
(defn convert-selected-to-path []
|
||||
(ptk/reify ::convert-selected-to-path
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state)
|
||||
selected (->> (wsh/lookup-selected state)
|
||||
(remove #(ctn/has-any-copy-parent? objects (get objects %))))
|
||||
(defn convert-selected-to-path
|
||||
([]
|
||||
(convert-selected-to-path nil))
|
||||
([ids]
|
||||
(ptk/reify ::convert-selected-to-path
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state)
|
||||
selected (->> (or ids (wsh/lookup-selected state))
|
||||
(remove #(ctn/has-any-copy-parent? objects (get objects %))))
|
||||
|
||||
children-ids
|
||||
(into #{}
|
||||
(mapcat #(cph/get-children-ids objects %))
|
||||
selected)
|
||||
children-ids
|
||||
(into #{}
|
||||
(mapcat #(cph/get-children-ids objects %))
|
||||
selected)
|
||||
|
||||
changes
|
||||
(-> (pcb/empty-changes it page-id)
|
||||
(pcb/with-objects objects)
|
||||
(pcb/update-shapes selected #(upsp/convert-to-path % objects))
|
||||
(pcb/remove-objects children-ids))]
|
||||
changes
|
||||
(-> (pcb/empty-changes it page-id)
|
||||
(pcb/with-objects objects)
|
||||
(pcb/update-shapes selected #(upsp/convert-to-path % objects))
|
||||
(pcb/remove-objects children-ids))]
|
||||
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
(rx/of (dch/commit-changes changes)))))))
|
||||
|
|
|
@ -91,7 +91,9 @@
|
|||
input-status* (mf/use-state nil) ;; :error-url :error-manifest :success
|
||||
input-status @input-status*
|
||||
|
||||
error? (contains? #{:error-url :error-manifest} input-status)
|
||||
error-url? (= :error-url input-status)
|
||||
error-manifest? (= :error-manifest input-status)
|
||||
error? (or error-url? error-manifest?)
|
||||
|
||||
handle-close-dialog
|
||||
(mf/use-callback
|
||||
|
@ -117,17 +119,20 @@
|
|||
(rx/subs!
|
||||
(fn [body]
|
||||
(reset! fetching-manifest? false)
|
||||
(let [plugin (preg/parse-manifest plugin-url body)]
|
||||
(st/emit! (ptk/event ::ev/event {::ev/name "install-plugin" :name (:name plugin) :url plugin-url}))
|
||||
(modal/show!
|
||||
:plugin-permissions
|
||||
{:plugin plugin
|
||||
:on-accept
|
||||
#(do
|
||||
(preg/install-plugin! plugin)
|
||||
(modal/show! :plugin-management {}))})
|
||||
(reset! input-status* :success)
|
||||
(reset! plugin-url* "")))
|
||||
(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}))
|
||||
(modal/show!
|
||||
:plugin-permissions
|
||||
{:plugin plugin
|
||||
:on-accept
|
||||
#(do
|
||||
(preg/install-plugin! plugin)
|
||||
(modal/show! :plugin-management {}))})
|
||||
(reset! input-status* :success)
|
||||
(reset! plugin-url* ""))
|
||||
;; Cannot get the manifest
|
||||
(reset! input-status* :error-manifest)))
|
||||
(fn [_]
|
||||
(reset! fetching-manifest? false)
|
||||
(reset! input-status* :error-url))))))
|
||||
|
@ -170,10 +175,14 @@
|
|||
:disabled @fetching-manifest?
|
||||
:on-click handle-install-click} (tr "workspace.plugins.install")]]
|
||||
|
||||
(when error?
|
||||
(when error-url?
|
||||
[:div {:class (stl/css-case :info true :error error?)}
|
||||
(tr "workspace.plugins.error.url")])
|
||||
|
||||
(when error-manifest?
|
||||
[:div {:class (stl/css-case :info true :error error?)}
|
||||
(tr "workspace.plugins.error.manifest")])
|
||||
|
||||
[:> i18n/tr-html*
|
||||
{:class (stl/css :discover)
|
||||
:on-click #(st/emit! (ptk/event ::ev/event {::ev/name "open-plugins-list"}))
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
[app.plugins.grid :as grid]
|
||||
[app.plugins.library :as library]
|
||||
[app.plugins.public-utils]
|
||||
[app.plugins.ruler-guides :as rg]
|
||||
[app.plugins.shape :as shape]
|
||||
[app.util.globals :refer [global]]
|
||||
[app.util.object :as obj]
|
||||
|
@ -43,6 +44,8 @@
|
|||
(set! flex/shape-proxy? shape/shape-proxy?)
|
||||
(set! grid/shape-proxy? shape/shape-proxy?)
|
||||
(set! format/shape-proxy shape/shape-proxy)
|
||||
(set! rg/shape-proxy shape/shape-proxy)
|
||||
(set! rg/shape-proxy? shape/shape-proxy?)
|
||||
|
||||
(set! shape/lib-typography-proxy? library/lib-typography-proxy?)
|
||||
(set! shape/lib-component-proxy library/lib-component-proxy)
|
||||
|
|
|
@ -368,7 +368,73 @@
|
|||
(openPage
|
||||
[_ page]
|
||||
(let [id (obj/get page "$id")]
|
||||
(st/emit! (dw/go-to-page id)))))
|
||||
(st/emit! (dw/go-to-page id))))
|
||||
|
||||
(alignHorizontal
|
||||
[_ shapes direction]
|
||||
(let [dir (case direction
|
||||
"left" :hleft
|
||||
"center" :hcenter
|
||||
"right" :hright
|
||||
nil)]
|
||||
(cond
|
||||
(nil? dir)
|
||||
(u/display-not-valid :alignHorizontal-direction "Direction not valid")
|
||||
|
||||
(or (not (array? shapes)) (not (every? shape/shape-proxy? shapes)))
|
||||
(u/display-not-valid :alignHorizontal-shapes "Not valid shapes")
|
||||
|
||||
:else
|
||||
(let [ids (into #{} (map #(obj/get % "$id")) shapes)]
|
||||
(st/emit! (dw/align-objects dir ids))))))
|
||||
|
||||
(alignVertical
|
||||
[_ shapes direction]
|
||||
(let [dir (case direction
|
||||
"top" :vtop
|
||||
"center" :vcenter
|
||||
"bottom" :vbottom
|
||||
nil)]
|
||||
(cond
|
||||
(nil? dir)
|
||||
(u/display-not-valid :alignVertical-direction "Direction not valid")
|
||||
|
||||
(or (not (array? shapes)) (not (every? shape/shape-proxy? shapes)))
|
||||
(u/display-not-valid :alignVertical-shapes "Not valid shapes")
|
||||
|
||||
:else
|
||||
(let [ids (into #{} (map #(obj/get % "$id")) shapes)]
|
||||
(st/emit! (dw/align-objects dir ids))))))
|
||||
|
||||
(distributeHorizontal
|
||||
[_ shapes]
|
||||
(cond
|
||||
(or (not (array? shapes)) (not (every? shape/shape-proxy? shapes)))
|
||||
(u/display-not-valid :distributeHorizontal-shapes "Not valid shapes")
|
||||
|
||||
:else
|
||||
(let [ids (into #{} (map #(obj/get % "$id")) shapes)]
|
||||
(st/emit! (dw/distribute-objects :horizontal ids)))))
|
||||
|
||||
(distributeVertical
|
||||
[_ shapes]
|
||||
(cond
|
||||
(or (not (array? shapes)) (not (every? shape/shape-proxy? shapes)))
|
||||
(u/display-not-valid :distributeVertical-shapes "Not valid shapes")
|
||||
|
||||
:else
|
||||
(let [ids (into #{} (map #(obj/get % "$id")) shapes)]
|
||||
(st/emit! (dw/distribute-objects :vertical ids)))))
|
||||
|
||||
(flatten
|
||||
[_ shapes]
|
||||
(cond
|
||||
(or (not (array? shapes)) (not (every? shape/shape-proxy? shapes)))
|
||||
(u/display-not-valid :flatten-shapes "Not valid shapes")
|
||||
|
||||
:else
|
||||
(let [ids (into #{} (map #(obj/get % "$id")) shapes)]
|
||||
(st/emit! (dw/convert-selected-to-path ids))))))
|
||||
|
||||
(defn create-context
|
||||
[plugin-id]
|
||||
|
|
164
frontend/src/app/plugins/comments.cljs
Normal file
164
frontend/src/app/plugins/comments.cljs
Normal file
|
@ -0,0 +1,164 @@
|
|||
;; 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.plugins.comments
|
||||
(:require
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.record :as crc]
|
||||
[app.common.spec :as us]
|
||||
[app.main.data.comments :as dc]
|
||||
[app.main.data.workspace.comments :as dwc]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.store :as st]
|
||||
[app.plugins.format :as format]
|
||||
[app.plugins.parser :as parser]
|
||||
[app.plugins.register :as r]
|
||||
[app.plugins.shape :as shape]
|
||||
[app.plugins.user :as user]
|
||||
[app.plugins.utils :as u]
|
||||
[beicon.v2.core :as rx]
|
||||
[promesa.core :as p]))
|
||||
|
||||
(deftype CommentProxy [$plugin $file $page $thread $id]
|
||||
Object
|
||||
(remove [_]
|
||||
(p/create
|
||||
(fn [resolve reject]
|
||||
(->> (rp/cmd! :delete-comment {:id $id})
|
||||
(rx/tap #(st/emit! (dc/retrieve-comment-threads $file)))
|
||||
(rx/subs! #(resolve) reject))))))
|
||||
|
||||
(defn comment-proxy? [p]
|
||||
(instance? CommentProxy p))
|
||||
|
||||
(defn comment-proxy
|
||||
[plugin-id file-id page-id thread-id users data]
|
||||
(let [data* (atom data)]
|
||||
(crc/add-properties!
|
||||
(CommentProxy. plugin-id file-id page-id thread-id (:id data))
|
||||
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
|
||||
{:name "$file" :enumerable false :get (constantly file-id)}
|
||||
{:name "$page" :enumerable false :get (constantly page-id)}
|
||||
{:name "$thread" :enumerable false :get (constantly thread-id)}
|
||||
{:name "$id" :enumerable false :get (constantly (:id data))}
|
||||
|
||||
{:name "user" :get (fn [_] (user/user-proxy plugin-id (get users (:owner-id data))))}
|
||||
{:name "date" :get (fn [_] (:created-at data))}
|
||||
|
||||
{:name "content"
|
||||
:get (fn [_] (:content @data*))
|
||||
:set
|
||||
(fn [_ content]
|
||||
(let [profile (:profile @st/state)]
|
||||
(cond
|
||||
(or (not (string? content)) (empty? content))
|
||||
(u/display-not-valid :content "Not valid")
|
||||
|
||||
(not= (:id profile) (:owner-id data))
|
||||
(u/display-not-valid :content "Cannot change content from another user's comments")
|
||||
|
||||
(not (r/check-permission plugin-id "content:write"))
|
||||
(u/display-not-valid :content "Plugin doesn't have 'content:write' permission")
|
||||
|
||||
:else
|
||||
(->> (rp/cmd! :update-comment {:id (:id data) :content content})
|
||||
(rx/tap #(st/emit! (dc/retrieve-comment-threads file-id)))
|
||||
(rx/subs! #(swap! data* assoc :content content))))))})))
|
||||
|
||||
(deftype CommentThreadProxy [$plugin $file $page $users $id owner]
|
||||
Object
|
||||
(findComments
|
||||
[_]
|
||||
(p/create
|
||||
(fn [resolve reject]
|
||||
(->> (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
|
||||
[_ content]
|
||||
(cond
|
||||
(not (r/check-permission $plugin "content:write"))
|
||||
(u/display-not-valid :content "Plugin doesn't have 'content:write' permission")
|
||||
|
||||
(or (not (string? content)) (empty? content))
|
||||
(u/display-not-valid :content "Not valid")
|
||||
|
||||
:else
|
||||
(p/create
|
||||
(fn [resolve reject]
|
||||
(->> (rp/cmd! :create-comment {:thread-id $id :content content})
|
||||
(rx/subs! #(resolve (comment-proxy $plugin $file $page $id $users %)) reject))))))
|
||||
|
||||
(remove [_]
|
||||
(let [profile (:profile @st/state)]
|
||||
(cond
|
||||
(not (r/check-permission $plugin "content:write"))
|
||||
(u/display-not-valid :removeCommentThread "Plugin doesn't have 'content:write' permission")
|
||||
|
||||
(not= (:id profile) owner)
|
||||
(u/display-not-valid :content "Cannot change content from another user's comments")
|
||||
|
||||
:else
|
||||
(p/create
|
||||
(fn [resolve]
|
||||
(p/create
|
||||
(st/emit! (dc/delete-comment-thread-on-workspace {:id $id} #(resolve))))))))))
|
||||
|
||||
(defn comment-thread-proxy? [p]
|
||||
(instance? CommentThreadProxy p))
|
||||
|
||||
(defn comment-thread-proxy
|
||||
[plugin-id file-id page-id users data]
|
||||
(let [data* (atom data)]
|
||||
(crc/add-properties!
|
||||
(CommentThreadProxy. plugin-id file-id page-id users (:id data) (:owner-id data))
|
||||
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
|
||||
{:name "$file" :enumerable false :get (constantly file-id)}
|
||||
{:name "$page" :enumerable false :get (constantly page-id)}
|
||||
{:name "$id" :enumerable false :get (constantly (:id data))}
|
||||
{:name "$users" :enumerable false :get (constantly users)}
|
||||
{:name "page" :enumerable false :get (fn [_] (u/locate-page file-id page-id))}
|
||||
|
||||
{:name "seqNumber" :get (fn [_] (:seqn data))}
|
||||
{:name "owner" :get (fn [_] (user/user-proxy plugin-id (get users (:owner-id data))))}
|
||||
{:name "board" :get (fn [_] (shape/shape-proxy plugin-id file-id page-id (:frame-id data)))}
|
||||
|
||||
{:name "position"
|
||||
:get (fn [_] (format/format-point (:position @data*)))
|
||||
:set
|
||||
(fn [_ position]
|
||||
(let [position (parser/parse-point position)]
|
||||
(cond
|
||||
(or (not (us/safe-number? (:x position))) (not (us/safe-number? (:y position))))
|
||||
(u/display-not-valid :position "Not valid point")
|
||||
|
||||
(not (r/check-permission plugin-id "content:write"))
|
||||
(u/display-not-valid :content "Plugin doesn't have 'content:write' permission")
|
||||
|
||||
:else
|
||||
(do (st/emit! (dwc/update-comment-thread-position @data* [(:x position) (:y position)]))
|
||||
(swap! data* assoc :position (gpt/point position))))))}
|
||||
|
||||
{:name "resolved"
|
||||
:get (fn [_] (:is-resolved @data*))
|
||||
:set
|
||||
(fn [_ is-resolved]
|
||||
(cond
|
||||
(not (boolean? is-resolved))
|
||||
(u/display-not-valid :resolved "Not a boolean type")
|
||||
|
||||
(not (r/check-permission plugin-id "content:write"))
|
||||
(u/display-not-valid :resolved "Plugin doesn't have 'content:write' permission")
|
||||
|
||||
:else
|
||||
(do (st/emit! (dc/update-comment-thread (assoc @data* :is-resolved is-resolved)))
|
||||
(swap! data* assoc :is-resolved is-resolved))))})))
|
||||
|
|
@ -592,3 +592,9 @@
|
|||
:url (:url interaction)}
|
||||
|
||||
nil))))
|
||||
|
||||
(defn axis->orientation
|
||||
[axis]
|
||||
(case axis
|
||||
:y "horizontal"
|
||||
:x "vertical"))
|
||||
|
|
|
@ -5,23 +5,32 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.plugins.page
|
||||
"RPC for plugins runtime."
|
||||
(:require
|
||||
[app.common.colors :as cc]
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.files.helpers :as cfh]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.record :as crc]
|
||||
[app.common.spec :as us]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.comments :as dc]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.guides :as dwgu]
|
||||
[app.main.data.workspace.interactions :as dwi]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.store :as st]
|
||||
[app.plugins.comments :as pc]
|
||||
[app.plugins.format :as format]
|
||||
[app.plugins.parser :as parser]
|
||||
[app.plugins.register :as r]
|
||||
[app.plugins.ruler-guides :as rg]
|
||||
[app.plugins.shape :as shape]
|
||||
[app.plugins.utils :as u]
|
||||
[app.util.object :as obj]
|
||||
[cuerdas.core :as str]))
|
||||
[beicon.v2.core :as rx]
|
||||
[cuerdas.core :as str]
|
||||
[promesa.core :as p]))
|
||||
|
||||
(deftype FlowProxy [$plugin $file $page $id]
|
||||
Object
|
||||
|
@ -52,7 +61,7 @@
|
|||
:else
|
||||
(st/emit! (dwi/update-flow page-id id #(assoc % :name value)))))}
|
||||
|
||||
{:name "startingFrame"
|
||||
{:name "startingBoard"
|
||||
:get
|
||||
(fn [self]
|
||||
(let [frame (-> self u/proxy->flow :starting-frame)]
|
||||
|
@ -61,7 +70,7 @@
|
|||
(fn [_ value]
|
||||
(cond
|
||||
(not (shape/shape-proxy? value))
|
||||
(u/display-not-valid :startingFrame value)
|
||||
(u/display-not-valid :startingBoard value)
|
||||
|
||||
:else
|
||||
(st/emit! (dwi/update-flow page-id id #(assoc % :starting-frame (obj/get value "$id"))))))}))
|
||||
|
@ -75,8 +84,10 @@
|
|||
(u/display-not-valid :getShapeById shape-id)
|
||||
|
||||
:else
|
||||
(let [shape-id (uuid/uuid shape-id)]
|
||||
(shape/shape-proxy $plugin $file $id shape-id))))
|
||||
(let [shape-id (uuid/uuid shape-id)
|
||||
shape (u/locate-shape $file $id shape-id)]
|
||||
(when (some? shape)
|
||||
(shape/shape-proxy $plugin $file $id shape-id)))))
|
||||
|
||||
(getRoot
|
||||
[_]
|
||||
|
@ -209,7 +220,123 @@
|
|||
(u/display-not-valid :removeFlow-flow flow)
|
||||
|
||||
:else
|
||||
(st/emit! (dwi/remove-flow $id (obj/get flow "$id"))))))
|
||||
(st/emit! (dwi/remove-flow $id (obj/get flow "$id")))))
|
||||
|
||||
(addRulerGuide
|
||||
[_ orientation value board]
|
||||
(let [shape (u/proxy->shape board)]
|
||||
(cond
|
||||
(not (us/safe-number? value))
|
||||
(u/display-not-valid :addRulerGuide "Value not a safe number")
|
||||
|
||||
(not (contains? #{"vertical" "horizontal"} orientation))
|
||||
(u/display-not-valid :addRulerGuide "Orientation should be either 'vertical' or 'horizontal'")
|
||||
|
||||
(or (not (shape/shape-proxy? board))
|
||||
(not (cfh/frame-shape? shape)))
|
||||
(u/display-not-valid :addRulerGuide "The shape is not a board")
|
||||
|
||||
(not (r/check-permission $plugin "content:write"))
|
||||
(u/display-not-valid :addRulerGuide "Plugin doesn't have 'content:write' permission")
|
||||
|
||||
:else
|
||||
(let [id (uuid/next)]
|
||||
(st/emit!
|
||||
(dwgu/update-guides
|
||||
(d/without-nils
|
||||
{:id id
|
||||
:axis (parser/orientation->axis orientation)
|
||||
:position value
|
||||
:frame-id (when board (obj/get board "$id"))})))
|
||||
(rg/ruler-guide-proxy $plugin $file $id id)))))
|
||||
|
||||
(removeRulerGuide
|
||||
[_ value]
|
||||
(cond
|
||||
(not (rg/ruler-guide-proxy? value))
|
||||
(u/display-not-valid :removeRulerGuide "Guide not provided")
|
||||
|
||||
(not (r/check-permission $plugin "content:write"))
|
||||
(u/display-not-valid :removeRulerGuide "Plugin doesn't have 'content:write' permission")
|
||||
|
||||
:else
|
||||
(let [guide (u/proxy->ruler-guide value)]
|
||||
(st/emit! (dwgu/remove-guide guide)))))
|
||||
|
||||
(addCommentThread
|
||||
[_ content position board]
|
||||
(let [shape (when board (u/proxy->shape board))]
|
||||
(cond
|
||||
(or (not (string? content)) (empty? content))
|
||||
(u/display-not-valid :addCommentThread "Content not valid")
|
||||
|
||||
(or (not (us/safe-number? (:x position))) (not (us/safe-number? (:y position))))
|
||||
(u/display-not-valid :addCommentThread "Position not valid")
|
||||
|
||||
(and (some? board) (or (not (shape/shape-proxy? board)) (not (cfh/frame-shape? shape))))
|
||||
(u/display-not-valid :addCommentThread "Board not valid")
|
||||
|
||||
(not (r/check-permission $plugin "content:write"))
|
||||
(u/display-not-valid :addCommentThread "Plugin doesn't have 'content:write' permission")
|
||||
|
||||
:else
|
||||
(p/create
|
||||
(fn [resolve]
|
||||
(st/emit!
|
||||
(dc/create-thread-on-workspace
|
||||
{:file-id $file
|
||||
:page-id $id
|
||||
:position (gpt/point (parser/parse-point position))
|
||||
:content content}
|
||||
|
||||
(fn [data]
|
||||
(->> (rp/cmd! :get-team-users {:file-id $file})
|
||||
(rx/subs!
|
||||
(fn [users]
|
||||
(let [users (d/index-by :id users)]
|
||||
(resolve (pc/comment-thread-proxy $plugin $file $id users data)))))))
|
||||
false)))))))
|
||||
|
||||
(removeCommentThread
|
||||
[_ thread]
|
||||
(cond
|
||||
(not (pc/comment-thread-proxy? thread))
|
||||
(u/display-not-valid :removeCommentThread "Comment thread not valid")
|
||||
|
||||
(not (r/check-permission $plugin "content:write"))
|
||||
(u/display-not-valid :removeCommentThread "Plugin doesn't have 'content:write' permission")
|
||||
|
||||
:else
|
||||
(p/create
|
||||
(fn [resolve]
|
||||
(let [thread-id (obj/get thread "$id")]
|
||||
(p/create
|
||||
(st/emit! (dc/delete-comment-thread-on-workspace {:id thread-id} #(resolve)))))))))
|
||||
|
||||
(findCommentThreads
|
||||
[_ criteria]
|
||||
(let [only-yours (boolean (obj/get criteria "onlyYours" false))
|
||||
show-resolved (boolean (obj/get criteria "showResolved" true))
|
||||
user-id (-> @st/state :profile :id)]
|
||||
(p/create
|
||||
(fn [resolve reject]
|
||||
(->> (rx/zip (rp/cmd! :get-team-users {:file-id $file})
|
||||
(rp/cmd! :get-comment-threads {:file-id $file}))
|
||||
(rx/take 1)
|
||||
(rx/subs!
|
||||
(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!
|
||||
PageProxy
|
||||
|
@ -267,4 +394,13 @@
|
|||
:get
|
||||
(fn [self]
|
||||
(let [flows (d/nilv (-> (u/proxy->page self) :options :flows) [])]
|
||||
(format/format-array #(flow-proxy plugin-id file-id id (:id %)) flows)))}))
|
||||
(format/format-array #(flow-proxy plugin-id file-id id (:id %)) flows)))}
|
||||
|
||||
{:name "rulerGuides"
|
||||
:get
|
||||
(fn [self]
|
||||
(let [guides (-> (u/proxy->page self) :options :guides)]
|
||||
(->> guides
|
||||
(vals)
|
||||
(filter #(nil? (:frame-id %)))
|
||||
(format/format-array #(rg/ruler-guide-proxy plugin-id file-id id (:id %))))))}))
|
||||
|
|
|
@ -569,3 +569,9 @@
|
|||
action (parse-action action)]
|
||||
(d/without-nils
|
||||
(d/patch-object {:event-type trigger :delay delay} action)))))
|
||||
|
||||
(defn orientation->axis
|
||||
[axis]
|
||||
(case axis
|
||||
"horizontal" :y
|
||||
"vertical" :x))
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.types.plugins :as ctp]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.store :as st]
|
||||
|
@ -51,19 +53,26 @@
|
|||
(and (= name (:name plugin))
|
||||
(= origin (:host plugin))))))
|
||||
|
||||
plugin-id (d/nilv (:plugin-id prev-plugin) (str (uuid/next)))]
|
||||
{:plugin-id plugin-id
|
||||
:name name
|
||||
:description desc
|
||||
:host origin
|
||||
:code code
|
||||
:icon icon
|
||||
:permissions (into #{} (map str) permissions)}))
|
||||
plugin-id (d/nilv (:plugin-id prev-plugin) (str (uuid/next)))
|
||||
|
||||
manifest
|
||||
(d/without-nils
|
||||
{:plugin-id plugin-id
|
||||
:name name
|
||||
:description desc
|
||||
:host origin
|
||||
:code code
|
||||
:icon icon
|
||||
:permissions (into #{} (map str) permissions)})]
|
||||
(when (sm/validate ::ctp/registry-entry manifest)
|
||||
manifest)))
|
||||
|
||||
(defn save-to-store
|
||||
[]
|
||||
(->> (rp/cmd! :update-profile-props {:props {:plugins @registry}})
|
||||
(rx/subs! identity)))
|
||||
;; TODO: need this for the transition to the new schema. We can remove eventually
|
||||
(let [registry (update @registry :data d/update-vals d/without-nils)]
|
||||
(->> (rp/cmd! :update-profile-props {:props {:plugins registry}})
|
||||
(rx/subs! identity))))
|
||||
|
||||
(defn load-from-store
|
||||
[]
|
||||
|
|
99
frontend/src/app/plugins/ruler_guides.cljs
Normal file
99
frontend/src/app/plugins/ruler_guides.cljs
Normal file
|
@ -0,0 +1,99 @@
|
|||
;; 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.plugins.ruler-guides
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.files.helpers :as cfh]
|
||||
[app.common.record :as crc]
|
||||
[app.common.spec :as us]
|
||||
[app.main.data.workspace.guides :as dwgu]
|
||||
[app.main.store :as st]
|
||||
[app.plugins.format :as format]
|
||||
[app.plugins.register :as r]
|
||||
[app.plugins.utils :as u]
|
||||
[app.util.object :as obj]))
|
||||
|
||||
(def shape-proxy identity)
|
||||
(def shape-proxy? identity)
|
||||
|
||||
(deftype RulerGuideProxy [$plugin $file $page $id]
|
||||
Object
|
||||
(remove [self]
|
||||
(let [guide (u/proxy->ruler-guide self)]
|
||||
(st/emit! (dwgu/remove-guide guide)))))
|
||||
|
||||
(defn ruler-guide-proxy? [p]
|
||||
(instance? RulerGuideProxy p))
|
||||
|
||||
(defn ruler-guide-proxy
|
||||
[plugin-id file-id page-id id]
|
||||
(crc/add-properties!
|
||||
(RulerGuideProxy. plugin-id file-id page-id id)
|
||||
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
|
||||
{:name "$file" :enumerable false :get (constantly file-id)}
|
||||
{:name "$page" :enumerable false :get (constantly page-id)}
|
||||
{:name "$id" :enumerable false :get (constantly id)}
|
||||
|
||||
{:name "board" :enumerable false
|
||||
:get
|
||||
(fn [self]
|
||||
(let [board-id (-> self u/proxy->ruler-guide :frame-id)]
|
||||
(when board-id
|
||||
(shape-proxy plugin-id file-id page-id board-id))))
|
||||
|
||||
:set
|
||||
(fn [self value]
|
||||
(let [shape (u/locate-shape file-id page-id (obj/get value "$id"))]
|
||||
(cond
|
||||
(not (shape-proxy? value))
|
||||
(u/display-not-valid :board "The board is not a shape proxy")
|
||||
|
||||
(not (cfh/frame-shape? shape))
|
||||
(u/display-not-valid :board "The shape is not a board")
|
||||
|
||||
(not (r/check-permission plugin-id "content:write"))
|
||||
(u/display-not-valid :board "Plugin doesn't have 'content:write' permission")
|
||||
|
||||
:else
|
||||
(let [board-id (when value (obj/get value "$id"))
|
||||
guide (-> self u/proxy->ruler-guide)]
|
||||
(st/emit! (dwgu/update-guides (assoc guide :frame-id board-id)))))))}
|
||||
|
||||
{:name "orientation"
|
||||
:get #(-> % u/proxy->ruler-guide :axis format/axis->orientation)}
|
||||
|
||||
{:name "position"
|
||||
:get
|
||||
(fn [self]
|
||||
(let [guide (u/proxy->ruler-guide self)]
|
||||
(if (:frame-id guide)
|
||||
(let [objects (u/locate-objects file-id page-id)
|
||||
board-pos (dm/get-in objects [(:frame-id guide) (:axis guide)])
|
||||
position (:position guide)]
|
||||
(- position board-pos))
|
||||
|
||||
;; No frame
|
||||
(:position guide))))
|
||||
:set
|
||||
(fn [self value]
|
||||
(cond
|
||||
(not (us/safe-number? value))
|
||||
(u/display-not-valid :position "Not valid position")
|
||||
|
||||
(not (r/check-permission plugin-id "content:write"))
|
||||
(u/display-not-valid :position "Plugin doesn't have 'content:write' permission")
|
||||
|
||||
:else
|
||||
(let [guide (u/proxy->ruler-guide self)
|
||||
position
|
||||
(if (:frame-id guide)
|
||||
(let [objects (u/locate-objects file-id page-id)
|
||||
board-pos (dm/get-in objects [(:frame-id guide) (:axis guide)])]
|
||||
(+ board-pos value))
|
||||
|
||||
value)]
|
||||
(st/emit! (dwgu/update-guides (assoc guide :position position))))))}))
|
|
@ -5,7 +5,6 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.plugins.shape
|
||||
"RPC for plugins runtime."
|
||||
(:require
|
||||
[app.common.colors :as clr]
|
||||
[app.common.data :as d]
|
||||
|
@ -33,6 +32,7 @@
|
|||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.groups :as dwg]
|
||||
[app.main.data.workspace.guides :as dwgu]
|
||||
[app.main.data.workspace.interactions :as dwi]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
|
@ -46,6 +46,7 @@
|
|||
[app.plugins.grid :as grid]
|
||||
[app.plugins.parser :as parser]
|
||||
[app.plugins.register :as r]
|
||||
[app.plugins.ruler-guides :as rg]
|
||||
[app.plugins.text :as text]
|
||||
[app.plugins.utils :as u]
|
||||
[app.util.object :as obj]
|
||||
|
@ -571,7 +572,52 @@
|
|||
(u/display-not-valid :removeInteraction interaction)
|
||||
|
||||
:else
|
||||
(st/emit! (dwi/remove-interaction {:id $id} (obj/get interaction "$index"))))))
|
||||
(st/emit! (dwi/remove-interaction {:id $id} (obj/get interaction "$index")))))
|
||||
|
||||
;; Ruler guides
|
||||
(addRulerGuide
|
||||
[self orientation value]
|
||||
(let [shape (u/proxy->shape self)]
|
||||
(cond
|
||||
(not (us/safe-number? value))
|
||||
(u/display-not-valid :addRulerGuide "Value not a safe number")
|
||||
|
||||
(not (contains? #{"vertical" "horizontal"} orientation))
|
||||
(u/display-not-valid :addRulerGuide "Orientation should be either 'vertical' or 'horizontal'")
|
||||
|
||||
(not (cfh/frame-shape? shape))
|
||||
(u/display-not-valid :addRulerGuide "The shape is not a board")
|
||||
|
||||
(not (r/check-permission $plugin "content:write"))
|
||||
(u/display-not-valid :addRulerGuide "Plugin doesn't have 'content:write' permission")
|
||||
|
||||
:else
|
||||
(let [id (uuid/next)
|
||||
axis (parser/orientation->axis orientation)
|
||||
objects (u/locate-objects $file $page)
|
||||
frame (get objects $id)
|
||||
board-pos (get frame axis)
|
||||
position (+ board-pos value)]
|
||||
(st/emit!
|
||||
(dwgu/update-guides
|
||||
{:id id
|
||||
:axis axis
|
||||
:position position
|
||||
:frame-id $id}))
|
||||
(rg/ruler-guide-proxy $plugin $file $page id)))))
|
||||
|
||||
(removeRulerGuide
|
||||
[_ value]
|
||||
(cond
|
||||
(not (rg/ruler-guide-proxy? value))
|
||||
(u/display-not-valid :removeRulerGuide "Guide not provided")
|
||||
|
||||
(not (r/check-permission $plugin "content:write"))
|
||||
(u/display-not-valid :removeRulerGuide "Plugin doesn't have 'content:write' permission")
|
||||
|
||||
:else
|
||||
(let [guide (u/proxy->ruler-guide value)]
|
||||
(st/emit! (dwgu/remove-guide guide))))))
|
||||
|
||||
(defn shape-proxy? [p]
|
||||
(instance? ShapeProxy p))
|
||||
|
@ -1202,6 +1248,15 @@
|
|||
:else
|
||||
(st/emit! (dwsh/update-shapes [id] #(assoc % :grids value))))))}
|
||||
|
||||
{:name "rulerGuides"
|
||||
:get
|
||||
(fn [_]
|
||||
(let [guides (-> (u/locate-page file-id page-id) :options :guides)]
|
||||
(->> guides
|
||||
(vals)
|
||||
(filter #(= id (:frame-id %)))
|
||||
(format/format-array #(rg/ruler-guide-proxy plugin-id file-id page-id (:id %))))))}
|
||||
|
||||
{:name "horizontalSizing"
|
||||
:get #(-> % u/proxy->shape :layout-item-h-sizing (d/nilv :fix) d/name)
|
||||
:set
|
||||
|
|
|
@ -12,13 +12,13 @@
|
|||
[app.plugins.utils :as u]
|
||||
[app.util.object :as obj]))
|
||||
|
||||
(deftype CurrentUserProxy [$plugin $session])
|
||||
(deftype ActiveUserProxy [$plugin $session])
|
||||
(deftype CurrentUserProxy [$plugin])
|
||||
(deftype ActiveUserProxy [$plugin])
|
||||
(deftype UserProxy [$plugin])
|
||||
|
||||
(defn add-user-properties
|
||||
[user-proxy]
|
||||
(let [plugin-id (obj/get user-proxy "$plugin")
|
||||
session-id (obj/get user-proxy "$session")]
|
||||
(defn- add-session-properties
|
||||
[user-proxy session-id]
|
||||
(let [plugin-id (obj/get user-proxy "$plugin")]
|
||||
(crc/add-properties!
|
||||
user-proxy
|
||||
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
|
||||
|
@ -39,21 +39,43 @@
|
|||
{:name "sessionId"
|
||||
:get (fn [_] (str session-id))})))
|
||||
|
||||
|
||||
(defn current-user-proxy? [p]
|
||||
(instance? CurrentUserProxy p))
|
||||
|
||||
(defn current-user-proxy
|
||||
[plugin-id session-id]
|
||||
(-> (CurrentUserProxy. plugin-id session-id)
|
||||
(add-user-properties)))
|
||||
(-> (CurrentUserProxy. plugin-id)
|
||||
(add-session-properties session-id)))
|
||||
|
||||
(defn active-user-proxy? [p]
|
||||
(instance? ActiveUserProxy p))
|
||||
|
||||
(defn active-user-proxy
|
||||
[plugin-id session-id]
|
||||
(-> (ActiveUserProxy. plugin-id session-id)
|
||||
(add-user-properties)
|
||||
(-> (ActiveUserProxy. plugin-id)
|
||||
(add-session-properties session-id)
|
||||
(crc/add-properties!
|
||||
{:name "position" :get (fn [_] (-> (u/locate-presence session-id) :point format/format-point))}
|
||||
{:name "zoom" :get (fn [_] (-> (u/locate-presence session-id) :zoom))})))
|
||||
|
||||
(defn- add-user-properties
|
||||
[user-proxy data]
|
||||
(let [plugin-id (obj/get user-proxy "$plugin")]
|
||||
(crc/add-properties!
|
||||
user-proxy
|
||||
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
|
||||
|
||||
{:name "id"
|
||||
:get (fn [_] (-> data :id str))}
|
||||
|
||||
{:name "name"
|
||||
:get (fn [_] (-> data :fullname))}
|
||||
|
||||
{:name "avatarUrl"
|
||||
:get (fn [_] (cfg/resolve-profile-photo-url data))})))
|
||||
|
||||
(defn user-proxy
|
||||
[plugin-id data]
|
||||
(-> (UserProxy. plugin-id)
|
||||
(add-user-properties data)))
|
||||
|
|
|
@ -122,6 +122,15 @@
|
|||
(when (some? page)
|
||||
(d/seek #(= (:id %) flow-id) (-> page :options :flows)))))
|
||||
|
||||
(defn proxy->ruler-guide
|
||||
[proxy]
|
||||
(let [file-id (obj/get proxy "$file")
|
||||
page-id (obj/get proxy "$page")
|
||||
ruler-id (obj/get proxy "$id")
|
||||
page (locate-page file-id page-id)]
|
||||
(when (some? page)
|
||||
(d/seek #(= (:id %) ruler-id) (-> page :options :guides vals)))))
|
||||
|
||||
(defn proxy->interaction
|
||||
[proxy]
|
||||
(let [file-id (obj/get proxy "$file")
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.plugins.viewport
|
||||
"RPC for plugins runtime."
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.record :as crc]
|
||||
|
@ -20,6 +19,12 @@
|
|||
|
||||
(deftype ViewportProxy [$plugin]
|
||||
Object
|
||||
(zoomReset [_]
|
||||
(st/emit! dwz/reset-zoom))
|
||||
|
||||
(zoomToFitAll [_]
|
||||
(st/emit! dwz/zoom-to-fit-all))
|
||||
|
||||
(zoomIntoView [_ shapes]
|
||||
(let [ids
|
||||
(->> shapes
|
||||
|
|
|
@ -5548,10 +5548,12 @@ msgstr "Discover [more plugins](%s)"
|
|||
msgid "workspace.plugins.empty-plugins"
|
||||
msgstr "No plugins installed yet"
|
||||
|
||||
#: src/app/main/ui/workspace/plugins.cljs:175
|
||||
msgid "workspace.plugins.error.url"
|
||||
msgstr "The plugin doesn't exist or the URL is not correct."
|
||||
|
||||
msgid "workspace.plugins.error.manifest"
|
||||
msgstr "The plugin manifest is incorrect."
|
||||
|
||||
#: src/app/main/ui/workspace/plugins.cljs:171
|
||||
msgid "workspace.plugins.install"
|
||||
msgstr "Install"
|
||||
|
|
|
@ -5535,10 +5535,12 @@ msgstr "Descubre [más extensiones](%s)"
|
|||
msgid "workspace.plugins.empty-plugins"
|
||||
msgstr "No se encuentran extensiones"
|
||||
|
||||
#: src/app/main/ui/workspace/plugins.cljs:175
|
||||
msgid "workspace.plugins.error.url"
|
||||
msgstr "La extensión no existe o la url no es correcta."
|
||||
|
||||
msgid "workspace.plugins.error.manifest"
|
||||
msgstr "El manifiesto de la expansión es incorrecto."
|
||||
|
||||
#: src/app/main/ui/workspace/plugins.cljs:171
|
||||
msgid "workspace.plugins.install"
|
||||
msgstr "Instalar"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue