mirror of
https://github.com/penpot/penpot.git
synced 2025-12-12 06:24:17 +01:00
🐛 Load dependant libraries, and don't allow unload them
This commit is contained in:
@@ -41,6 +41,7 @@
|
||||
- Fix long font names overlap [Taiga #11844](https://tree.taiga.io/project/penpot/issue/11844)
|
||||
- Fix paste behavior according to the selected element [Taiga #11979](https://tree.taiga.io/project/penpot/issue/11979)
|
||||
- Fix problem with export size [#7160](https://github.com/penpot/penpot/issues/7160)
|
||||
- Fix multi level library dependencies [Taiga #12155](https://tree.taiga.io/project/penpot/issue/12155)
|
||||
|
||||
## 2.10.0
|
||||
|
||||
|
||||
@@ -608,8 +608,16 @@
|
||||
{:components components
|
||||
:variant-ids variant-ids}))
|
||||
|
||||
;;coalesce(string_agg(flr.library_file_id::text, ','), '') as library_file_ids
|
||||
(def ^:private sql:team-shared-files
|
||||
"select f.id,
|
||||
"with file_library_agg as (
|
||||
select flr.file_id,
|
||||
coalesce(array_agg(flr.library_file_id) filter (where flr.library_file_id is not null), '{}') as library_file_ids
|
||||
from file_library_rel flr
|
||||
group by flr.file_id
|
||||
)
|
||||
|
||||
select f.id,
|
||||
f.revn,
|
||||
f.vern,
|
||||
f.data,
|
||||
@@ -622,10 +630,12 @@
|
||||
f.version,
|
||||
f.is_shared,
|
||||
ft.media_id,
|
||||
p.team_id
|
||||
p.team_id,
|
||||
fla.library_file_ids
|
||||
from file as f
|
||||
inner join project as p on (p.id = f.project_id)
|
||||
left join file_thumbnail as ft on (ft.file_id = f.id and ft.revn = f.revn and ft.deleted_at is null)
|
||||
left join file_library_agg as fla on fla.file_id = f.id
|
||||
where f.is_shared = true
|
||||
and f.deleted_at is null
|
||||
and p.deleted_at is null
|
||||
@@ -669,6 +679,8 @@
|
||||
(dissoc :media-id)
|
||||
(assoc :thumbnail-id media-id))
|
||||
(dissoc row :media-id))))
|
||||
(map (fn [row]
|
||||
(update row :library-file-ids db/decode-pgarray #{})))
|
||||
(map #(assoc % :library-summary (get-library-summary cfg %)))
|
||||
(map #(dissoc % :data))))))
|
||||
|
||||
@@ -1065,6 +1077,7 @@
|
||||
[:library-id ::sm/uuid]])
|
||||
|
||||
(sv/defmethod ::link-file-to-library
|
||||
"Link a file to a library. Returns the recursive list of libraries used by that library"
|
||||
{::doc/added "1.17"
|
||||
::webhooks/event? true
|
||||
::sm/params schema:link-file-to-library}
|
||||
@@ -1078,7 +1091,8 @@
|
||||
(fn [{:keys [::db/conn]}]
|
||||
(check-edition-permissions! conn profile-id file-id)
|
||||
(check-edition-permissions! conn profile-id library-id)
|
||||
(link-file-to-library conn params))))
|
||||
(link-file-to-library conn params)
|
||||
(bfc/get-libraries cfg [library-id]))))
|
||||
|
||||
;; --- MUTATION COMMAND: unlink-file-from-library
|
||||
|
||||
|
||||
@@ -90,7 +90,6 @@
|
||||
|
||||
(declare ^:private workspace-initialized)
|
||||
(declare ^:private fetch-libraries)
|
||||
(declare ^:private libraries-fetched)
|
||||
|
||||
;; --- Initialize Workspace
|
||||
|
||||
@@ -185,16 +184,6 @@
|
||||
(update [_ state]
|
||||
(update state :files assoc (:id library) library))))
|
||||
|
||||
(defn- libraries-fetched
|
||||
[file-id libraries]
|
||||
(ptk/reify ::libraries-fetched
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :files merge
|
||||
(->> libraries
|
||||
(map #(assoc % :library-of file-id))
|
||||
(d/index-by :id))))))
|
||||
|
||||
(defn- fetch-libraries
|
||||
[file-id features]
|
||||
(ptk/reify ::fetch-libries
|
||||
@@ -204,7 +193,7 @@
|
||||
(rx/mapcat
|
||||
(fn [libraries]
|
||||
(rx/concat
|
||||
(rx/of (libraries-fetched file-id libraries))
|
||||
(rx/of (dwl/libraries-fetched file-id libraries))
|
||||
(rx/merge
|
||||
(->> (rx/from libraries)
|
||||
(rx/merge-map
|
||||
|
||||
@@ -1381,6 +1381,32 @@
|
||||
|
||||
;; --- Link and unlink Files
|
||||
|
||||
(defn libraries-fetched
|
||||
[file-id libraries]
|
||||
(ptk/reify ::libraries-fetched
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :files merge
|
||||
(->> libraries
|
||||
(map #(assoc % :library-of file-id))
|
||||
(d/index-by :id))))))
|
||||
|
||||
(defn- load-library-file
|
||||
[file-id library-id]
|
||||
(ptk/reify ::load-library-file
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [features (get state :features)]
|
||||
(rx/merge
|
||||
(->> (rp/cmd! :get-file {:id library-id :features features})
|
||||
(rx/merge-map fpmap/resolve-file)
|
||||
(rx/map (fn [file]
|
||||
(libraries-fetched file-id [file]))))
|
||||
(->> (rp/cmd! :get-file-object-thumbnails {:file-id library-id :tag "component"})
|
||||
(rx/map (fn [thumbnails]
|
||||
(fn [state]
|
||||
(update state :thumbnails merge thumbnails))))))))))
|
||||
|
||||
(defn link-file-to-library
|
||||
[file-id library-id]
|
||||
(ptk/reify ::attach-library
|
||||
@@ -1390,41 +1416,26 @@
|
||||
:file-id file-id
|
||||
:library-id library-id})
|
||||
|
||||
;; NOTE: this event implements UpdateEvent protocol for perform an
|
||||
;; optimistic update state for make the UI feel more responsive.
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [libraries (:workspace-shared-files state)
|
||||
library (d/seek #(= (:id %) library-id) libraries)]
|
||||
(if library
|
||||
(update state :files assoc library-id
|
||||
(-> library
|
||||
(dissoc :library-summary)
|
||||
(assoc :library-of file-id)))
|
||||
state)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [libraries (:shared-files state)
|
||||
library (get libraries library-id)
|
||||
features (get state :features)
|
||||
variants-count (-> library :library-summary :components :variants-count)]
|
||||
variants-count (-> library :library-summary :components :variants-count)
|
||||
|
||||
loaded-libraries (->> (dsh/lookup-libraries state)
|
||||
(remove (fn [[_ lib]]
|
||||
(or (nil? (:data lib))
|
||||
(empty? (:data lib)))))
|
||||
(map first)
|
||||
set)]
|
||||
(rx/concat
|
||||
(rx/merge
|
||||
(->> (rp/cmd! :link-file-to-library {:file-id file-id :library-id library-id})
|
||||
(rx/ignore))
|
||||
(->> (rp/cmd! :get-file {:id library-id :features features})
|
||||
(rx/merge-map fpmap/resolve-file)
|
||||
;; FIXME: this should call the libraries-fetched event instead of ad-hoc assoc event
|
||||
(rx/map (fn [file]
|
||||
(assoc file :library-of file-id)))
|
||||
(rx/map (fn [file]
|
||||
(fn [state]
|
||||
(assoc-in state [:files library-id] file)))))
|
||||
(->> (rp/cmd! :get-file-object-thumbnails {:file-id library-id :tag "component"})
|
||||
(rx/map (fn [thumbnails]
|
||||
(fn [state]
|
||||
(update state :thumbnails merge thumbnails))))))
|
||||
(rx/merge-map (fn [libraries-to-load]
|
||||
(as-> libraries-to-load $
|
||||
(remove loaded-libraries $)
|
||||
(conj $ library-id)
|
||||
(map #(load-library-file file-id %) $))))))
|
||||
(rx/of (ptk/reify ::attach-library-finished))
|
||||
(when (pos? variants-count)
|
||||
(->> (rp/cmd! :get-library-usage {:file-id library-id})
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
[app.main.ui.components.search-bar :refer [search-bar*]]
|
||||
[app.main.ui.components.title-bar :refer [title-bar*]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||
[app.main.ui.ds.foundations.assets.icon :as i]
|
||||
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
|
||||
[app.main.ui.hooks :as h]
|
||||
@@ -48,9 +49,6 @@
|
||||
(def ^:private add-icon
|
||||
(deprecated-icon/icon-xref :add (stl/css :add-icon)))
|
||||
|
||||
(def ^:private detach-icon
|
||||
(deprecated-icon/icon-xref :detach (stl/css :detach-icon)))
|
||||
|
||||
(def ^:private library-icon
|
||||
(deprecated-icon/icon-xref :library (stl/css :library-icon)))
|
||||
|
||||
@@ -199,7 +197,20 @@
|
||||
empty-library? (empty-library? summary)
|
||||
|
||||
selected (h/use-shared-state mdc/colorpalette-selected-broadcast-key :recent)
|
||||
dependencies (mf/with-memo [shared-libraries]
|
||||
(into {} (map (juxt :id :library-file-ids) (vals shared-libraries))))
|
||||
|
||||
library-names (mf/with-memo [shared-libraries]
|
||||
(into {} (map (fn [{:keys [id name]}]
|
||||
[id name])
|
||||
(vals shared-libraries))))
|
||||
|
||||
find-connected-to
|
||||
(mf/use-fn
|
||||
(mf/deps dependencies)
|
||||
(fn [library-id]
|
||||
(->> dependencies
|
||||
(keep (fn [[k v]] (when (contains? v library-id) k))))))
|
||||
|
||||
shared-libraries
|
||||
(mf/with-memo [shared-libraries linked-libraries file-id search-term]
|
||||
@@ -208,18 +219,29 @@
|
||||
(remove #(= (:id %) file-id))
|
||||
(remove #(contains? linked-libraries (:id %)))
|
||||
(filter #(matches-search (:name %) search-term))
|
||||
(map #(assoc % :connected-to (find-connected-to (:id %))))
|
||||
(map #(assoc % :connected-to-names (->> (:connected-to %)
|
||||
(keep library-names))))
|
||||
(sort-by (comp str/lower :name)))))
|
||||
|
||||
linked-libraries
|
||||
(mf/with-memo [linked-libraries]
|
||||
(mf/with-memo [linked-libraries find-connected-to library-names]
|
||||
(->> (vals linked-libraries)
|
||||
(map #(assoc % :connected-to (find-connected-to (:id %))))
|
||||
(map #(assoc % :connected-to-names (->> (:connected-to %)
|
||||
(keep library-names))))
|
||||
(sort-by (comp str/lower :name))))
|
||||
|
||||
linked-libraries-ids (mf/with-memo [linked-libraries]
|
||||
(into #{} (map :id) linked-libraries))
|
||||
|
||||
|
||||
importing* (mf/use-state nil)
|
||||
sample-libraries [{:id "penpot-design-system", :name "Design system example"}
|
||||
{:id "wireframing-kit", :name "Wireframe library"}
|
||||
{:id "whiteboarding-kit", :name "Whiteboarding Kit"}]
|
||||
|
||||
|
||||
change-search-term
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
@@ -311,7 +333,8 @@
|
||||
:value (tr "common.publish")
|
||||
:on-click publish}])]
|
||||
|
||||
(for [{:keys [id name data] :as library} linked-libraries]
|
||||
(for [{:keys [id name data connected-to connected-to-names] :as library} linked-libraries]
|
||||
(let [disabled? (some #(contains? linked-libraries-ids %) connected-to)]
|
||||
[:div {:class (stl/css :section-list-item)
|
||||
:key (dm/str id)
|
||||
:data-testid "library-item"}
|
||||
@@ -319,14 +342,21 @@
|
||||
[:div {:class (stl/css :item-name)} name]
|
||||
[:ul {:class (stl/css :item-contents)}
|
||||
(let [summary (get-library-summary data)]
|
||||
[:> library-description* {:summary summary}])]]
|
||||
[:*
|
||||
[:> library-description* {:summary summary}]
|
||||
(when (seq connected-to)
|
||||
[:div {:class (stl/css :connected-to-wrapper)}
|
||||
[:span "(" (tr "workspace.libraries.connected-to") " "]
|
||||
[:span {:class (stl/css :connected-to-values)} (str/join ", " connected-to-names)]
|
||||
[:span ")"]])])]]
|
||||
|
||||
[:button {:class (stl/css :item-button)
|
||||
:type "button"
|
||||
:title (tr "workspace.libraries.unlink-library-btn")
|
||||
[:> icon-button* {:type "button"
|
||||
:aria-label (tr "workspace.libraries.unlink-library-btn")
|
||||
:icon i/detach
|
||||
:data-library-id (dm/str id)
|
||||
:on-click unlink-library}
|
||||
detach-icon]])]]
|
||||
:variant "secondary"
|
||||
:disabled disabled?
|
||||
:on-click unlink-library}]]))]]
|
||||
|
||||
[:div {:class (stl/css :shared-section)}
|
||||
[:> title-bar* {:collapsable false
|
||||
|
||||
@@ -319,6 +319,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
.connected-to-wrapper {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.connected-to-values {
|
||||
color: var(--color-foreground-primary);
|
||||
}
|
||||
|
||||
// Modal Component v2 update
|
||||
.modal-v2-info {
|
||||
width: px2rem(664);
|
||||
|
||||
@@ -5554,6 +5554,9 @@ msgstr "see all changes"
|
||||
msgid "workspace.libraries.updates"
|
||||
msgstr "UPDATES"
|
||||
|
||||
msgid "workspace.libraries.connected-to"
|
||||
msgstr "Connected to"
|
||||
|
||||
#: src/app/main/ui/ds/notifications/shared/notification_pill.cljs:67, src/app/main/ui/ds/notifications/shared/notification_pill.cljs:72
|
||||
msgid "workspace.notification-pill.detail"
|
||||
msgstr "Details"
|
||||
|
||||
@@ -5583,6 +5583,9 @@ msgstr "ver todos los cambios"
|
||||
msgid "workspace.libraries.updates"
|
||||
msgstr "ACTUALIZACIONES"
|
||||
|
||||
msgid "workspace.libraries.connected-to"
|
||||
msgstr "Conectada con"
|
||||
|
||||
#: src/app/main/ui/ds/notifications/shared/notification_pill.cljs:67, src/app/main/ui/ds/notifications/shared/notification_pill.cljs:72
|
||||
msgid "workspace.notification-pill.detail"
|
||||
msgstr "Detalles"
|
||||
|
||||
Reference in New Issue
Block a user