mirror of
https://github.com/penpot/penpot.git
synced 2025-12-11 22:14:05 +01:00
✨ Add "advanced" events to variants
This commit is contained in:
@@ -444,7 +444,10 @@
|
||||
:fn (mg/resource "app/migrations/sql/0140-mod-file-change-table.sql")}
|
||||
|
||||
{:name "0140-add-locked-by-column-to-file-change-table"
|
||||
:fn (mg/resource "app/migrations/sql/0140-add-locked-by-column-to-file-change-table.sql")}])
|
||||
:fn (mg/resource "app/migrations/sql/0140-add-locked-by-column-to-file-change-table.sql")}
|
||||
|
||||
{:name "0141-add-idx-to-file_library_rel"
|
||||
:fn (mg/resource "app/migrations/sql/0141-add-idx-to-file_library_rel.sql")}])
|
||||
|
||||
(defn apply-migrations!
|
||||
[pool name migrations]
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
CREATE INDEX file_library_rel__library_file_id__idx
|
||||
ON file_library_rel (library_file_id);
|
||||
@@ -78,6 +78,7 @@
|
||||
|
||||
;; --- FILE PERMISSIONS
|
||||
|
||||
|
||||
(def ^:private sql:file-permissions
|
||||
"select fpr.is_owner,
|
||||
fpr.is_admin,
|
||||
@@ -460,8 +461,42 @@
|
||||
(:has-libraries row)))
|
||||
|
||||
|
||||
;; --- COMMAND QUERY: get-library-usage
|
||||
|
||||
|
||||
(declare get-library-usage)
|
||||
|
||||
(def schema:get-library-usage
|
||||
[:map {:title "get-library-usage"}
|
||||
[:file-id ::sm/uuid]])
|
||||
:sample
|
||||
(sv/defmethod ::get-library-usage
|
||||
"Gets the number of files that use the specified library."
|
||||
{::doc/added "2.10.0"
|
||||
::sm/params schema:get-library-usage
|
||||
::sm/result ::sm/int}
|
||||
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id]}]
|
||||
(dm/with-open [conn (db/open pool)]
|
||||
(check-read-permissions! pool profile-id file-id)
|
||||
(get-library-usage conn file-id)))
|
||||
|
||||
(def ^:private sql:get-library-usage
|
||||
"SELECT COUNT(*) AS used
|
||||
FROM file_library_rel AS flr
|
||||
JOIN file AS fl ON (flr.library_file_id = fl.id)
|
||||
WHERE flr.library_file_id = ?::uuid
|
||||
AND (fl.deleted_at IS NULL OR
|
||||
fl.deleted_at > now())")
|
||||
|
||||
(defn- get-library-usage
|
||||
[conn file-id]
|
||||
(let [row (db/exec-one! conn [sql:get-library-usage file-id])]
|
||||
{:used-in (:used row)}))
|
||||
|
||||
|
||||
;; --- QUERY COMMAND: get-page
|
||||
|
||||
|
||||
(defn- prune-objects
|
||||
"Given the page data and the object-id returns the page data with all
|
||||
other not needed objects removed from the `:objects` data
|
||||
@@ -551,6 +586,24 @@
|
||||
|
||||
;; --- COMMAND QUERY: get-team-shared-files
|
||||
|
||||
(defn- components-and-variants
|
||||
"Return a set with all the variant-ids, and a list of components, but with
|
||||
only one component by variant"
|
||||
[components]
|
||||
(let [{:keys [variant-ids components]}
|
||||
(reduce (fn [{:keys [variant-ids components] :as acc} {:keys [variant-id] :as component}]
|
||||
(cond
|
||||
(nil? variant-id)
|
||||
{:variant-ids variant-ids :components (conj components component)}
|
||||
(contains? variant-ids variant-id)
|
||||
acc
|
||||
:else
|
||||
{:variant-ids (conj variant-ids variant-id) :components (conj components component)}))
|
||||
{:variant-ids #{} :components []}
|
||||
components)]
|
||||
{:components components
|
||||
:variant-ids variant-ids}))
|
||||
|
||||
(def ^:private sql:team-shared-files
|
||||
"select f.id,
|
||||
f.revn,
|
||||
@@ -584,10 +637,13 @@
|
||||
:sample (into [] (take limit sorted-assets))}))]
|
||||
|
||||
(binding [pmap/*load-fn* (partial feat.fdata/load-pointer cfg id)]
|
||||
(let [load-objects (fn [component]
|
||||
(ctf/load-component-objects data component))
|
||||
components-sample (-> (assets-sample (ctkl/components data) 4)
|
||||
(update :sample #(mapv load-objects %)))]
|
||||
(let [load-objects (fn [component]
|
||||
(ctf/load-component-objects data component))
|
||||
comps-and-variants (components-and-variants (ctkl/components-seq data))
|
||||
components (into {} (map (juxt :id identity) (:components comps-and-variants)))
|
||||
components-sample (-> (assets-sample components 4)
|
||||
(update :sample #(mapv load-objects %))
|
||||
(assoc :variants-count (-> comps-and-variants :variant-ids count)))]
|
||||
{:components components-sample
|
||||
:media (assets-sample (:media data) 3)
|
||||
:colors (assets-sample (:colors data) 3)
|
||||
@@ -641,6 +697,7 @@
|
||||
|
||||
;; --- COMMAND QUERY: Files that use this File library
|
||||
|
||||
|
||||
(def ^:private sql:library-using-files
|
||||
"SELECT f.id,
|
||||
f.name
|
||||
@@ -713,6 +770,7 @@
|
||||
|
||||
;; --- COMMAND QUERY: get-file-summary
|
||||
|
||||
|
||||
(defn- get-file-summary
|
||||
[{:keys [::db/conn] :as cfg} {:keys [profile-id id project-id] :as params}]
|
||||
(check-read-permissions! conn profile-id id)
|
||||
@@ -730,11 +788,13 @@
|
||||
(cfeat/check-file-features! (:features file)))
|
||||
|
||||
(binding [pmap/*load-fn* (partial feat.fdata/load-pointer cfg id)]
|
||||
{:name (:name file)
|
||||
:components-count (count (ctkl/components-seq (:data file)))
|
||||
:graphics-count (count (get-in file [:data :media] []))
|
||||
:colors-count (count (get-in file [:data :colors] []))
|
||||
:typography-count (count (get-in file [:data :typographies] []))})))
|
||||
(let [components-and-variants (components-and-variants (ctkl/components-seq (:data file)))]
|
||||
{:name (:name file)
|
||||
:components-count (-> components-and-variants :components count)
|
||||
:variants-count (-> components-and-variants :variant-ids count)
|
||||
:graphics-count (count (get-in file [:data :media] []))
|
||||
:colors-count (count (get-in file [:data :colors] []))
|
||||
:typography-count (count (get-in file [:data :typographies] []))}))))
|
||||
|
||||
(sv/defmethod ::get-file-summary
|
||||
"Retrieve a file summary by its ID. Only authenticated users."
|
||||
@@ -746,6 +806,7 @@
|
||||
|
||||
;; --- COMMAND QUERY: get-file-info
|
||||
|
||||
|
||||
(defn- get-file-info
|
||||
[{:keys [::db/conn] :as cfg} {:keys [id] :as params}]
|
||||
(db/get* conn :file
|
||||
|
||||
@@ -438,8 +438,14 @@
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [params {:id id :is-shared is-shared}]
|
||||
(->> (rp/cmd! :set-file-shared params)
|
||||
(rx/ignore))))))
|
||||
(rx/concat
|
||||
(->> (rp/cmd! :set-file-shared params)
|
||||
(rx/ignore))
|
||||
(when is-shared
|
||||
(->> (rp/cmd! :get-file-summary {:id id})
|
||||
(rx/map (fn [summary]
|
||||
(when (pos? (:variants-count summary))
|
||||
(ptk/event ::ev/event {::ev/name "set-file-variants-shared" ::ev/origin "dashboard"})))))))))))
|
||||
|
||||
(defn set-file-thumbnail
|
||||
[file-id thumbnail-id]
|
||||
|
||||
@@ -895,7 +895,10 @@
|
||||
(let [parent-type (cfh/get-shape-type all-objects (:parent-id shape))
|
||||
external-lib? (not= file-id (:component-file shape))
|
||||
component (ctn/get-component-from-shape shape libraries)
|
||||
origin "workspace:paste"]
|
||||
origin "workspace:paste"
|
||||
any-parent-is-variant (->> (cfh/get-parents-with-self all-objects (:parent-id shape))
|
||||
(some ctc/is-variant?)
|
||||
boolean)]
|
||||
|
||||
;; NOTE: we don't emit the create-shape event all the time for
|
||||
;; avoid send a lot of events (that are not necessary); this
|
||||
@@ -906,7 +909,8 @@
|
||||
:is-external-library external-lib?
|
||||
:type (get shape :type)
|
||||
:parent-type parent-type
|
||||
:is-variant (ctc/is-variant? component)})
|
||||
:is-variant (ctc/is-variant? component)
|
||||
:any-parent-is-variant any-parent-is-variant})
|
||||
(if (cfh/has-layout? objects (:parent-id shape))
|
||||
(ev/event {::ev/name "layout-add-element"
|
||||
::ev/origin origin
|
||||
|
||||
@@ -592,6 +592,9 @@
|
||||
page
|
||||
libraries)
|
||||
component (ctn/get-component-from-shape new-shape libraries)
|
||||
any-parent-is-variant (->> (cfh/get-parents-with-self objects (:parent-id new-shape))
|
||||
(some ctk/is-variant?)
|
||||
boolean)
|
||||
|
||||
undo-id (js/Symbol)]
|
||||
|
||||
@@ -602,7 +605,8 @@
|
||||
{::ev/name "use-library-component"
|
||||
::ev/origin origin
|
||||
:external-library (not= file-id current-file-id)
|
||||
:is-variant (ctk/is-variant? component)})
|
||||
:is-variant (ctk/is-variant? component)
|
||||
:any-parent-is-variant any-parent-is-variant})
|
||||
(dwu/start-undo-transaction undo-id)
|
||||
(dch/commit-changes changes)
|
||||
(ptk/data-event :layout/update {:ids [(:id new-shape)]})
|
||||
@@ -1364,10 +1368,19 @@
|
||||
(update-in state [:files id] assoc :is-shared is-shared))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [params {:id id :is-shared is-shared}]
|
||||
(->> (rp/cmd! :set-file-shared params)
|
||||
(rx/ignore))))))
|
||||
(watch [_ state _]
|
||||
(let [params {:id id :is-shared is-shared}]
|
||||
(rx/concat
|
||||
(->> (rp/cmd! :set-file-shared params)
|
||||
(rx/ignore))
|
||||
(when is-shared
|
||||
(let [has-variants? (->> (dsh/lookup-file-data state)
|
||||
:components
|
||||
vals
|
||||
(some ctk/is-variant?))]
|
||||
(if has-variants?
|
||||
(rx/of (ptk/event ::ev/event {::ev/name "set-file-variants-shared" ::ev/origin "workspace"}))
|
||||
(rx/empty)))))))))
|
||||
|
||||
;; --- Link and unlink Files
|
||||
|
||||
@@ -1395,7 +1408,10 @@
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [features (get state :features)]
|
||||
(let [libraries (:shared-files state)
|
||||
library (get libraries library-id)
|
||||
features (get state :features)
|
||||
variants-count (-> library :library-summary :components :variants-count)]
|
||||
(rx/concat
|
||||
(rx/merge
|
||||
(->> (rp/cmd! :link-file-to-library {:file-id file-id :library-id library-id})
|
||||
@@ -1412,7 +1428,15 @@
|
||||
(rx/map (fn [thumbnails]
|
||||
(fn [state]
|
||||
(update state :thumbnails merge thumbnails))))))
|
||||
(rx/of (ptk/reify ::attach-library-finished)))))))
|
||||
(rx/of (ptk/reify ::attach-library-finished))
|
||||
(when (pos? variants-count)
|
||||
(->> (rp/cmd! :get-library-usage {:file-id library-id})
|
||||
(rx/map (fn [library-usage]
|
||||
(ptk/event ::ev/event {::ev/name "attach-library-variants"
|
||||
:file-id file-id
|
||||
:library-id library-id
|
||||
:variants-count variants-count
|
||||
:library-used-in (:used-in library-usage)}))))))))))
|
||||
|
||||
(defn unlink-file-from-library
|
||||
[file-id library-id]
|
||||
|
||||
@@ -486,7 +486,11 @@
|
||||
parent-type (cfh/get-shape-type objects (:parent-id shape))
|
||||
external-lib? (not= file-id (:component-file shape))
|
||||
component (ctn/get-component-from-shape shape libraries)
|
||||
origin "workspace:duplicate-shapes"]
|
||||
origin "workspace:duplicate-shapes"
|
||||
|
||||
any-parent-is-variant (->> (cfh/get-parents-with-self objects (:parent-id shape))
|
||||
(some ctk/is-variant?)
|
||||
boolean)]
|
||||
|
||||
;; NOTE: we don't emit the create-shape event all the time for
|
||||
;; avoid send a lot of events (that are not necessary); this
|
||||
@@ -497,7 +501,8 @@
|
||||
:is-external-library external-lib?
|
||||
:type (get shape :type)
|
||||
:parent-type parent-type
|
||||
:is-variant (ctk/is-variant? component)})
|
||||
:is-variant (ctk/is-variant? component)
|
||||
:any-parent-is-variant any-parent-is-variant})
|
||||
(if (cfh/has-layout? objects (:parent-id shape))
|
||||
(ev/event {::ev/name "layout-add-element"
|
||||
::ev/origin origin
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.files.tokens :as cft]
|
||||
[app.common.types.component :as ctk]
|
||||
[app.common.types.shape.layout :as ctsl]
|
||||
[app.common.types.shape.radius :as ctsr]
|
||||
[app.common.types.shape.token :as ctst]
|
||||
@@ -481,14 +482,14 @@
|
||||
objects (dsh/lookup-page-objects state)
|
||||
selected-shapes (select-keys objects shape-ids)
|
||||
|
||||
shape-ids (or (->> selected-shapes
|
||||
(filter (fn [[_ shape]]
|
||||
(or
|
||||
(and (ctsl/any-layout-immediate-child? objects shape)
|
||||
(some ctt/spacing-margin-keys attributes))
|
||||
(ctt/any-appliable-attr? attributes (:type shape)))))
|
||||
(keys))
|
||||
[])
|
||||
shapes (->> selected-shapes
|
||||
(filter (fn [[_ shape]]
|
||||
(or
|
||||
(and (ctsl/any-layout-immediate-child? objects shape)
|
||||
(some ctt/spacing-margin-keys attributes))
|
||||
(ctt/any-appliable-attr? attributes (:type shape))))))
|
||||
shape-ids (d/nilv (keys shapes) [])
|
||||
any-variant? (->> shapes (some ctk/is-variant?) boolean)
|
||||
|
||||
resolved-value (get-in resolved-tokens [(cft/token-identifier token) :resolved-value])
|
||||
tokenized-attributes (cft/attributes-map attributes token)
|
||||
@@ -497,7 +498,8 @@
|
||||
(rx/of
|
||||
(st/emit! (ev/event {::ev/name "apply-tokens"
|
||||
:type type
|
||||
:applyed-to attributes}))
|
||||
:applyed-to attributes
|
||||
:applied-to-variant any-variant?}))
|
||||
(dwu/start-undo-transaction undo-id)
|
||||
(dwsh/update-shapes shape-ids (fn [shape]
|
||||
(cond-> shape
|
||||
|
||||
@@ -577,7 +577,9 @@
|
||||
any-variant? (some ctk/is-variant? shapes)
|
||||
do-add-component (mf/use-fn #(st/emit! (dwl/add-component)))
|
||||
do-add-multiple-components (mf/use-fn #(st/emit! (dwl/add-multiple-components)))
|
||||
do-combine-as-variants (mf/use-fn #(st/emit! (dwv/combine-as-variants)))
|
||||
do-combine-as-variants (mf/use-fn #(st/emit!
|
||||
(ptk/event ::ev/event {::ev/name "combine-as-variants" :trigger "context-menu-component"})
|
||||
(dwv/combine-as-variants)))
|
||||
do-add-variant (mf/use-fn
|
||||
(mf/deps shapes)
|
||||
#(st/emit!
|
||||
|
||||
@@ -505,7 +505,9 @@
|
||||
ids (into #{} (map :main-instance-id comps))
|
||||
page-id (->> comps first :main-instance-page)]
|
||||
|
||||
(st/emit! (dwv/combine-as-variants ids {:page-id page-id})))))
|
||||
(st/emit!
|
||||
(ptk/event ::ev/event {::ev/name "combine-as-variants" :trigger "context-menu-assets-group"})
|
||||
(dwv/combine-as-variants ids {:page-id page-id})))))
|
||||
|
||||
|
||||
on-drag-start
|
||||
@@ -554,7 +556,9 @@
|
||||
(let [page-id (->> selected-and-current-full first :main-instance-page)
|
||||
ids (into #{} (map :main-instance-id selected-full))]
|
||||
|
||||
(st/emit! (dwv/combine-as-variants ids {:page-id page-id})))))]
|
||||
(st/emit!
|
||||
(ptk/event ::ev/event {::ev/name "combine-as-variants" :trigger "context-menu-assets"})
|
||||
(dwv/combine-as-variants ids {:page-id page-id})))))]
|
||||
|
||||
[:& cmm/asset-section {:file-id file-id
|
||||
:title (tr "workspace.assets.components")
|
||||
|
||||
@@ -909,7 +909,9 @@
|
||||
|
||||
on-combine-as-variants
|
||||
(mf/use-fn
|
||||
#(st/emit! (dwv/combine-as-variants)))
|
||||
#(st/emit!
|
||||
(ptk/event ::ev/event {::ev/name "combine-as-variants" :trigger "button-design-tab"})
|
||||
(dwv/combine-as-variants)))
|
||||
|
||||
;; NOTE: function needed for force rerender from the bottom
|
||||
;; components. This is because `component-annotation`
|
||||
|
||||
Reference in New Issue
Block a user