diff --git a/frontend/resources/images/icons/puzzle.svg b/frontend/resources/images/icons/puzzle.svg
index 6e978bac5..ceef3a54b 100644
--- a/frontend/resources/images/icons/puzzle.svg
+++ b/frontend/resources/images/icons/puzzle.svg
@@ -1 +1 @@
-
+
diff --git a/frontend/src/app/plugins/api.cljs b/frontend/src/app/plugins/api.cljs
index 2cd3938a7..076c9f0fa 100644
--- a/frontend/src/app/plugins/api.cljs
+++ b/frontend/src/app/plugins/api.cljs
@@ -23,6 +23,7 @@
[app.main.data.workspace.colors :as dwc]
[app.main.data.workspace.groups :as dwg]
[app.main.data.workspace.media :as dwm]
+ [app.main.data.workspace.selection :as dws]
[app.main.store :as st]
[app.plugins.events :as events]
[app.plugins.file :as file]
@@ -356,7 +357,19 @@
{:name "root" :get #(.getRoot ^js %)}
{:name "currentFile" :get #(.getFile ^js %)}
{:name "currentPage" :get #(.getPage ^js %)}
- {:name "selection" :get #(.getSelectedShapes ^js %)}
+
+ {:name "selection"
+ :get #(.getSelectedShapes ^js %)
+ :set
+ (fn [_ shapes]
+ (cond
+ (or (not (array? shapes)) (not (every? shape/shape-proxy? shapes)))
+ (u/display-not-valid :selection shapes)
+
+ :else
+ (let [ids (into (d/ordered-set) (map #(obj/get % "$id")) shapes)]
+ (st/emit! (dws/select-shapes ids)))))}
+
{:name "viewport" :get #(.getViewport ^js %)}
{:name "currentUser" :get #(.getCurrentUser ^js %)}
{:name "activeUsers" :get #(.getActiveUsers ^js %)}
diff --git a/frontend/src/app/plugins/parser.cljs b/frontend/src/app/plugins/parser.cljs
index 3180a0e4b..53092c569 100644
--- a/frontend/src/app/plugins/parser.cljs
+++ b/frontend/src/app/plugins/parser.cljs
@@ -229,8 +229,8 @@
(when (some? export)
(d/without-nils
{:type (-> (obj/get export "type") parse-keyword)
- :scale (obj/get export "scale")
- :suffix (obj/get export "suffix")})))
+ :scale (obj/get export "scale" 1)
+ :suffix (obj/get export "suffix" "")})))
(defn parse-exports
[^js exports]
diff --git a/frontend/src/app/plugins/shape.cljs b/frontend/src/app/plugins/shape.cljs
index 727b2c70c..2ae9b0d39 100644
--- a/frontend/src/app/plugins/shape.cljs
+++ b/frontend/src/app/plugins/shape.cljs
@@ -36,6 +36,7 @@
[app.main.data.workspace.shape-layout :as dwsl]
[app.main.data.workspace.shapes :as dwsh]
[app.main.data.workspace.texts :as dwt]
+ [app.main.repo :as rp]
[app.main.store :as st]
[app.plugins.flex :as flex]
[app.plugins.format :as format]
@@ -46,7 +47,9 @@
[app.plugins.utils :as u]
[app.util.object :as obj]
[app.util.path.format :as upf]
- [cuerdas.core :as str]))
+ [beicon.v2.core :as rx]
+ [cuerdas.core :as str]
+ [promesa.core :as p]))
(def lib-typography-proxy? nil)
(def lib-component-proxy nil)
@@ -436,7 +439,34 @@
shape (u/proxy->shape self)]
(when (ctn/in-any-component? objects shape)
(let [[root component] (u/locate-component objects shape)]
- (lib-component-proxy $plugin (:component-file root) (:id component)))))))
+ (lib-component-proxy $plugin (:component-file root) (:id component))))))
+
+ (export
+ [self value]
+ (let [value (parser/parse-export value)]
+ (cond
+ (not (sm/validate ::ctse/export value))
+ (u/display-not-valid :export value)
+
+ :else
+ (let [payload
+ {:cmd :export-shapes
+ :profile-id (:profile-id @st/state)
+ :wait true
+ :exports [{:file-id $file
+ :page-id $page
+ :object-id $id
+ :name (obj/get self "name")
+ :type (:type value :png)
+ :suffix (:suffix value "")
+ :scale (:scale value 1)}]}]
+ (p/create
+ (fn [resolve reject]
+ (->> (rp/cmd! :export payload)
+ (rx/mapcat #(rp/cmd! :export {:cmd :get-resource :wait true :id (:id %) :blob? true}))
+ (rx/mapcat #(.arrayBuffer %))
+ (rx/map #(js/Uint8Array. %))
+ (rx/subs! resolve reject)))))))))
(defn shape-proxy? [p]
(instance? ShapeProxy p))
@@ -886,6 +916,12 @@
{:name "height"
:get #(-> % u/proxy->shape :height)}
+ {:name "bounds"
+ :get #(-> % u/proxy->shape :points grc/points->rect format/format-bounds)}
+
+ {:name "center"
+ :get #(-> % u/proxy->shape gsh/shape->center format/format-point)}
+
{:name "rotation"
:get #(-> % u/proxy->shape :rotation)
:set
diff --git a/frontend/test/frontend_tests/helpers/state.cljs b/frontend/test/frontend_tests/helpers/state.cljs
index 6c3c7cb2c..37d245df5 100644
--- a/frontend/test/frontend_tests/helpers/state.cljs
+++ b/frontend/test/frontend_tests/helpers/state.cljs
@@ -39,21 +39,25 @@
store))
(defn run-store
- [store done events completed-cb]
- (let [stream (ptk/input-stream store)]
- (->> stream
- (rx/take-until (rx/filter #(= :the/end %) stream))
- (rx/last)
- (rx/tap (fn []
- (completed-cb @store)))
- (rx/subs! (fn [_] (done))
- (fn [cause]
- (js/console.log "[error]:" cause))
- (fn [_]
- (js/console.log "[complete]"))))
- (doall (for [event events]
- (ptk/emit! store event)))
- (ptk/emit! store :the/end)))
+ ([store done events completed-cb]
+ (run-store store done events completed-cb nil))
+ ([store done events completed-cb stopper]
+ (let [stream (ptk/input-stream store)]
+ (->> stream
+ (rx/take-until (if stopper
+ (stopper stream)
+ (rx/filter #(= :the/end %) stream)))
+ (rx/last)
+ (rx/tap (fn []
+ (completed-cb @store)))
+ (rx/subs! (fn [_] (done))
+ (fn [cause]
+ (js/console.log "[error]:" cause))
+ (fn [_]
+ (js/console.log "[complete]"))))
+ (doall (for [event events]
+ (ptk/emit! store event)))
+ (ptk/emit! store :the/end))))
(defn get-file-from-store
[store]
diff --git a/frontend/translations/en.po b/frontend/translations/en.po
index b05464a4c..5e90a1951 100644
--- a/frontend/translations/en.po
+++ b/frontend/translations/en.po
@@ -5281,6 +5281,9 @@ msgstr "Plugin correctly loaded."
msgid "workspace.plugins.menu.title"
msgstr "Plugins"
+msgid "workspace.toolbar.plugins"
+msgstr "Plugins"
+
msgid "workspace.plugins.menu.plugins-manager"
msgstr "Plugins manager"
diff --git a/frontend/translations/es.po b/frontend/translations/es.po
index c226af892..407f37cd5 100644
--- a/frontend/translations/es.po
+++ b/frontend/translations/es.po
@@ -5361,6 +5361,9 @@ msgstr "Pulsar para cerrar la ruta"
msgid "workspace.plugins.title"
msgstr "Extensiones"
+msgid "workspace.toolbar.plugins"
+msgstr "Extensiones"
+
msgid "workspace.plugins.search-placeholder"
msgstr "Intruduzca URL de la extensión"