0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-12 07:41:43 -05:00

🎉 Show changed assets when updating libraries

This commit is contained in:
Andrés Moya 2023-08-21 17:53:26 +02:00
parent 96a5444357
commit ca88314524
19 changed files with 475 additions and 50 deletions

View file

@ -51,4 +51,6 @@
(->> (ctc/get-all-colors shape) (->> (ctc/get-all-colors shape)
(keep #(get-ref-color (:data library) %)) (keep #(get-ref-color (:data library) %))
(remove #(< (:modified-at %) since-date)) ;; Note that :modified-at may be nil (remove #(< (:modified-at %) since-date)) ;; Note that :modified-at may be nil
(map #(vector (:id shape) (:id %) :color)))) (map (fn [color] {:shape-id (:id shape)
:asset-id (:id color)
:asset-type :color}))))

View file

@ -116,7 +116,9 @@
(let [component (get-component (:data library) (:component-id shape))] (let [component (get-component (:data library) (:component-id shape))]
(if (< (:modified-at component) since-date) ;; Note that :modified-at may be nil (if (< (:modified-at component) since-date) ;; Note that :modified-at may be nil
[] []
[[(:id shape) (:component-id shape) :component]])) [{:shape-id (:id shape)
:asset-id (:component-id shape)
:asset-type :component}]))
[])) []))
(defn get-component-annotation (defn get-component-annotation

View file

@ -223,7 +223,7 @@
"Add an :objects property to the component, with only the shapes that belong to it" "Add an :objects property to the component, with only the shapes that belong to it"
[file-data component] [file-data component]
(let [components-v2 (dm/get-in file-data [:options :components-v2])] (let [components-v2 (dm/get-in file-data [:options :components-v2])]
(if (and components-v2 component (nil? (:objects component))) ;; This operation may be called twice, e.g. in an idempotent change (if (and components-v2 component (empty? (:objects component))) ;; This operation may be called twice, e.g. in an idempotent change
(let [component-page (get-component-page file-data component) (let [component-page (get-component-page file-data component)
page-objects (:objects component-page) page-objects (:objects component-page)
objects (->> (cons (:main-instance-id component) objects (->> (cons (:main-instance-id component)
@ -324,14 +324,15 @@
been modified after the given date." been modified after the given date."
[file-data library since-date] [file-data library since-date]
(letfn [(used-assets-shape [shape] (letfn [(used-assets-shape [shape]
(concat (concat
(ctkl/used-components-changed-since shape library since-date) (ctkl/used-components-changed-since shape library since-date)
(ctcl/used-colors-changed-since shape library since-date) (ctcl/used-colors-changed-since shape library since-date)
(ctyl/used-typographies-changed-since shape library since-date))) (ctyl/used-typographies-changed-since shape library since-date)))
(used-assets-container [container] (used-assets-container [container]
(->> (mapcat used-assets-shape (ctn/shapes-seq container)) (->> (ctn/shapes-seq container)
(map #(cons (:id container) %))))] (mapcat used-assets-shape)
(map #(assoc % :container-id (:id container)))))]
(mapcat used-assets-container (containers-seq file-data)))) (mapcat used-assets-container (containers-seq file-data))))

View file

@ -53,4 +53,6 @@
txt/node-seq txt/node-seq
(keep #(get-ref-typography (:data library) %)) (keep #(get-ref-typography (:data library) %))
(remove #(< (:modified-at %) since-date)) ;; Note that :modified-at may be nil (remove #(< (:modified-at %) since-date)) ;; Note that :modified-at may be nil
(map #(vector (:id shape) (:id %) :typography)))) (map (fn [node] {:shape-id (:id shape)
:asset-id (:id node)
:asset-type :typography}))))

View file

@ -62,6 +62,16 @@
} }
.btn-warning { .btn-warning {
@extend %btn;
background: $color-warning;
color: $color-white;
&:hover {
background: $color-warning-dark;
color: $color-white;
}
}
.btn-danger {
@extend %btn; @extend %btn;
background: $color-danger; background: $color-danger;
color: $color-white; color: $color-white;
@ -1093,6 +1103,10 @@ input[type="range"]:focus::-ms-fill-upper {
} }
} }
} }
.link {
color: $color-info;
}
} }
.btn-close { .btn-close {
@ -1215,7 +1229,7 @@ input[type="range"]:focus::-ms-fill-upper {
top: 70px; top: 70px;
left: 0; left: 0;
right: 0; right: 0;
width: 35rem; width: 40rem;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
z-index: 20; z-index: 20;

View file

@ -723,6 +723,22 @@
color: $color-primary; color: $color-primary;
background: $color-black; background: $color-black;
} }
&.btn-gray {
background: $color-gray-10;
border-color: $color-gray-10;
color: $color-black;
cursor: unset;
&:hover {
color: $color-black;
}
}
&.btn-warning {
background: $color-warning;
border-color: $color-warning;
}
} }
} }
} }
@ -791,6 +807,67 @@
} }
} }
} }
.libraries-updates {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
grid-gap: $size-5;
font-size: $fs12;
margin-top: $size-4;
.libraries-updates-item {
display: flex;
align-items: center;
&:not(:first-child) {
margin-top: $size-2;
}
& svg {
background-color: $color-canvas;
border-radius: $br4;
border: 2px solid transparent;
height: 24px;
width: 24px;
min-height: 24px;
min-width: 24px;
margin-right: $size-2;
}
& .color-bullet {
margin-right: $size-2;
}
& .typography-sample {
margin-right: $size-2;
}
& .name-block {
color: $color-gray-20;
width: calc(100% - 24px - #{$size-2});
&.ellipsis {
padding-left: calc(24px + #{$size-2});
}
}
& .item-name {
display: block;
margin: 0;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
}
.libraries-updates-see-all {
margin-top: $size-2;
text-align: right;
cursor: pointer;
color: $color-info;
text-decoration: underline;
}
} }
} }

View file

@ -34,7 +34,8 @@
} }
.btn-primary, .btn-primary,
.btn-warning { .btn-warning,
.btn-danger {
font-size: $fs12; font-size: $fs12;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
padding: 8px $size-2; padding: 8px $size-2;

View file

@ -70,7 +70,8 @@
} }
.btn-primary, .btn-primary,
.btn-secondary, .btn-secondary,
.btn-warning { .btn-warning,
.btn-danger {
width: 126px; width: 126px;
margin-bottom: 0px; margin-bottom: 0px;

View file

@ -32,6 +32,11 @@
[:timeout {:optional true} [:timeout {:optional true}
[:maybe :int]] [:maybe :int]]
[:actions {:optional true} [:actions {:optional true}
[:vector
[:map
[:label :string]
[:callback ::sm/fn]]]]
[:links {:optional true}
[:vector [:vector
[:map [:map
[:label :string] [:label :string]
@ -132,12 +137,13 @@
:tag tag}))) :tag tag})))
(defn info-dialog (defn info-dialog
([content controls actions] [& {:keys [content controls links actions tag]
(info-dialog content controls actions nil)) :or {controls :none links nil tag nil}}]
([content controls actions tag] (show (d/without-nils
(show {:content content {:content content
:type :info :type :info
:position :floating :position :floating
:controls controls :controls controls
:links links
:actions actions :actions actions
:tag tag}))) :tag tag})))

View file

@ -24,6 +24,7 @@
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.main.data.events :as ev] [app.main.data.events :as ev]
[app.main.data.messages :as msg] [app.main.data.messages :as msg]
[app.main.data.modal :as modal]
[app.main.data.workspace :as-alias dw] [app.main.data.workspace :as-alias dw]
[app.main.data.workspace.changes :as dch] [app.main.data.workspace.changes :as dch]
[app.main.data.workspace.groups :as dwg] [app.main.data.workspace.groups :as dwg]
@ -821,9 +822,7 @@
(defn assets-need-sync (defn assets-need-sync
"Get a lazy sequence of all the assets of each type in the library that have "Get a lazy sequence of all the assets of each type in the library that have
been modified after the last sync of the library. The sync date may be been modified after the last sync of the library. The sync date may be
overriden by providing a ignore-until parameter. overriden by providing a ignore-until parameter."
The sequence items are tuples of (page-id shape-id asset-id asset-type)."
([library file-data] (assets-need-sync library file-data nil)) ([library file-data] (assets-need-sync library file-data nil))
([library file-data ignore-until] ([library file-data ignore-until]
(let [sync-date (max (:synced-at library) (or ignore-until 0))] (let [sync-date (max (:synced-at library) (or ignore-until 0))]
@ -840,6 +839,8 @@
ignore-until (dm/get-in state [:workspace-file :ignore-sync-until]) ignore-until (dm/get-in state [:workspace-file :ignore-sync-until])
libraries-need-sync (filter #(seq (assets-need-sync % file-data ignore-until)) libraries-need-sync (filter #(seq (assets-need-sync % file-data ignore-until))
(vals (get state :workspace-libraries))) (vals (get state :workspace-libraries)))
do-more-info #(do (modal/show! :libraries-dialog {:starting-tab :updates})
(st/emit! msg/hide))
do-update #(do (apply st/emit! (map (fn [library] do-update #(do (apply st/emit! (map (fn [library]
(sync-file (:current-file-id state) (sync-file (:current-file-id state)
(:id library))) (:id library)))
@ -850,13 +851,15 @@
(when (seq libraries-need-sync) (when (seq libraries-need-sync)
(rx/of (msg/info-dialog (rx/of (msg/info-dialog
(tr "workspace.updates.there-are-updates") :content (tr "workspace.updates.there-are-updates")
:inline-actions :controls :inline-actions
[{:label (tr "workspace.updates.update") :links [{:label (tr "workspace.updates.more-info")
:callback do-update} :callback do-more-info}]
{:label (tr "workspace.updates.dismiss") :actions [{:label (tr "workspace.updates.update")
:callback do-dismiss}] :callback do-update}
:sync-dialog))))))) {:label (tr "workspace.updates.dismiss")
:callback do-dismiss}]
:tag :sync-dialog)))))))
(defn watch-component-changes (defn watch-component-changes
"Watch the state for changes that affect to any main instance. If a change is detected will throw "Watch the state for changes that affect to any main instance. If a change is detected will throw

View file

@ -15,7 +15,7 @@
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
(mf/defc banner (mf/defc banner
[{:keys [type position status controls content actions on-close data-test role] :as props}] [{:keys [type position status controls content links actions on-close data-test role] :as props}]
[:div.banner {:class (dom/classnames [:div.banner {:class (dom/classnames
:warning (= type :warning) :warning (= type :warning)
:error (= type :error) :error (= type :error)
@ -37,7 +37,12 @@
:bottom-actions (= controls :bottom-actions)) :bottom-actions (= controls :bottom-actions))
:data-test data-test :data-test data-test
:role role} :role role}
content [:span
content
(for [link links]
[:* {:key (uuid/next)}
" " [:a.link {:on-click (:callback link)}
(:label link)]])]
(when (or (= controls :bottom-actions) (= controls :inline-actions)) (when (or (= controls :bottom-actions) (= controls :inline-actions))
[:div.actions [:div.actions
(for [action actions] (for [action actions]

View file

@ -51,7 +51,7 @@
[:div.modal-footer [:div.modal-footer
[:div.action-buttons [:div.action-buttons
[:button.btn-warning.btn-large {:on-click on-accept [:button.btn-danger.btn-large {:on-click on-accept
:data-test "delete-account-btn"} :data-test "delete-account-btn"}
(tr "modals.delete-account.confirm")] (tr "modals.delete-account.confirm")]
[:button.btn-secondary.btn-large {:on-click on-close} [:button.btn-secondary.btn-large {:on-click on-close}

View file

@ -193,7 +193,7 @@
{:type "button" {:type "button"
:on-click #(reset! confirm* false) :on-click #(reset! confirm* false)
:value (tr "labels.cancel")}] :value (tr "labels.cancel")}]
[:input.btn-warning [:input.btn-danger
{:type "button" {:type "button"
:on-click delete-link :on-click delete-link
:value (tr "common.share-link.destroy-link")}]]] :value (tr "common.share-link.destroy-link")}]]]

View file

@ -9,17 +9,24 @@
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.types.colors-list :as ctcl]
[app.common.types.components-list :as ctkl] [app.common.types.components-list :as ctkl]
[app.common.types.file :as ctf]
[app.common.types.typographies-list :as ctyl]
[app.common.uuid :as uuid]
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
[app.main.data.workspace.libraries :as dwl] [app.main.data.workspace.libraries :as dwl]
[app.main.features :as features] [app.main.features :as features]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.render :refer [component-svg]]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.color-bullet :as bc]
[app.main.ui.components.search-bar :refer [search-bar]] [app.main.ui.components.search-bar :refer [search-bar]]
[app.main.ui.components.tab-container :refer [tab-container tab-element]] [app.main.ui.components.tab-container :refer [tab-container tab-element]]
[app.main.ui.components.title-bar :refer [title-bar]] [app.main.ui.components.title-bar :refer [title-bar]]
[app.main.ui.context :as ctx] [app.main.ui.context :as ctx]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.color :as uc]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[app.util.keyboard :as kbd] [app.util.keyboard :as kbd]
@ -390,8 +397,65 @@
(mf/defc updates-tab (mf/defc updates-tab
{::mf/wrap-props false} {::mf/wrap-props false}
[{:keys [file-id file-data libraries]}] [{:keys [file-id file-data libraries]}]
(let [libraries (mf/with-memo [file-data libraries] (let [summary?* (mf/use-state true)
(filter #(seq (dwl/assets-need-sync % file-data)) (vals libraries))) updating?* (mf/use-state false)
summary? (deref summary?*)
updating? (deref updating?*)
see-all-assets
(fn []
(reset! summary?* false))
extract-assets
(fn [library]
(let [exceeded (volatile! {:components false
:colors false
:typographies false})
truncate (fn [asset-type items]
(if (and summary? (> (count items) 5))
(do
(vswap! exceeded assoc asset-type true)
(take 5 items))
items))
assets (dwl/assets-need-sync library file-data)
component-ids (into #{} (->> assets
(filter #(= (:asset-type %) :component))
(map :asset-id)))
color-ids (into #{} (->> assets
(filter #(= (:asset-type %) :color))
(map :asset-id)))
typography-ids (into #{} (->> assets
(filter #(= (:asset-type %) :typography))
(map :asset-id)))
components (->> component-ids
(map #(ctkl/get-component (:data library) %))
(sort-by #(str/lower (:name %)))
(truncate :components))
colors (->> color-ids
(map #(ctcl/get-color (:data library) %))
(sort-by #(str/lower (:name %)))
(truncate :colors))
typographies (->> typography-ids
(map #(ctyl/get-typography (:data library) %))
(sort-by #(str/lower (:name %)))
(truncate :typographies))]
[library @exceeded {:components components
:colors colors
:typographies typographies}]))
libs-assets (mf/with-memo [file-data libraries summary?*]
(->> (vals libraries)
(map extract-assets)
(filter (fn [[_ _ {:keys [components colors typographies]}]]
(or (seq components)
(seq colors)
(seq typographies))))))
new-css-system (mf/use-ctx ctx/new-css-system) new-css-system (mf/use-ctx ctx/new-css-system)
update (mf/use-fn update (mf/use-fn
@ -400,51 +464,205 @@
(let [library-id (some-> (dom/get-target event) (let [library-id (some-> (dom/get-target event)
(dom/get-data "library-id") (dom/get-data "library-id")
(parse-uuid))] (parse-uuid))]
(reset! updating?* true)
(st/emit! (dwl/sync-file file-id library-id)))))] (st/emit! (dwl/sync-file file-id library-id)))))]
(if new-css-system (if new-css-system
[:div {:class (css :section)} [:div {:class (css :section)}
(if (empty? libraries) (if (empty? libs-assets)
[:div {:class (css :section-list-empty)} [:div {:class (css :section-list-empty)}
(tr "workspace.libraries.no-libraries-need-sync")] (tr "workspace.libraries.no-libraries-need-sync")]
[:* [:*
[:div {:class (css :section-title)} (tr "workspace.libraries.library")] [:div {:class (css :section-title)} (tr "workspace.libraries.library-updates")]
[:div {:class (css :section-list)} [:div {:class (css :section-list)}
(for [{:keys [id name] :as library} libraries] (for [[{:keys [id name] :as library}
exceeded
{:keys [components colors typographies]}] libs-assets]
[:div {:class (css :section-list-item) [:div {:class (css :section-list-item)
:key (dm/str id)} :key (dm/str id)}
[:div [:div
[:div {:class (css :item-name)} name] [:div {:class (css :item-name)} name]
[:div {:class (css :item-contents)} (describe-external-library library)]] [:div {:class (css :item-contents)} (describe-library
[:input {:class (css :item-update) (count components)
:type "button" 0
(count colors)
(count typographies))]]
[:input {:type "button"
:class (dom/classnames (css :item-update) true
(css :btn-gray) updating?
(css :btn-warning) (not updating?))
:value (tr "workspace.libraries.update") :value (tr "workspace.libraries.update")
:data-library-id (dm/str id) :data-library-id (dm/str id)
:on-click update}]])]])] :on-click update}]
[:div {:class (css :libraries-updates)}
(when-not (empty? components)
[:div {:class (css :libraries-updates-column)}
(for [component components]
[:div {:class (css :libraries-updates-item)
:key (dm/str (:id component))}
(let [component (ctf/load-component-objects (:data library) component)
root-shape (ctf/get-component-root (:data library) component)]
[:*
[:& component-svg {:root-shape root-shape
:objects (:objects component)}]
[:div {:class (css :name-block)}
[:span {:class (css :item-name)
:title (:name component)}
(:name component)]]])])
(when (:components exceeded)
[:div {:class (css :libraries-updates-item)
:key (uuid/next)}
[:div {:class (css :name-block.ellipsis)}
[:span {:class (css :item-name)} "(...)"]]])])
(when-not (empty? colors)
[:div {:class (css :libraries-updates-column)
:style #js {"--bullet-size" "24px"}}
(for [color colors]
(let [default-name (cond
(:gradient color) (uc/gradient-type->string (get-in color [:gradient :type]))
(:color color) (:color color)
:else (:value color))]
[:div {:class (css :libraries-updates-item)
:key (dm/str (:id color))}
[:*
[:& bc/color-bullet {:color {:color (:color color)
:opacity (:opacity color)}}]
[:div {:class (css :name-block)}
[:span {:class (css :item-name)
:title (:name color)}
(:name color)]
(when-not (= (:name color) default-name)
[:span.color-value (:color color)])]]]))
(when (:colors exceeded)
[:div {:class (css :libraries-updates-item)
:key (uuid/next)}
[:div {:class (css :name-block.ellipsis)}
[:span {:class (css :item-name)} "(...)"]]])])
(when-not (empty? typographies)
[:div {:class (css :libraries-updates-column)}
(for [typography typographies]
[:div {:class (css :libraries-updates-item)
:key (dm/str (:id typography))}
[:*
[:div {:style {:font-family (:font-family typography)
:font-weight (:font-weight typography)
:font-style (:font-style typography)}}
(tr "workspace.assets.typography.sample")]
[:div {:class (css :name-block)}
[:span {:class (css :item-name)
:title (:name typography)}
(:name typography)]]]])
(when (:typographies exceeded)
[:div {:class (css :libraries-updates-item)
:key (uuid/next)}
[:div {:class (css :name-block.ellipsis)}
[:span {:class (css :item-name)} "(...)"]]])])]
(when (or (pos? (:components exceeded))
(pos? (:colors exceeded))
(pos? (:typographies exceeded)))
[:div {:class (css :libraries-updates-see-all)
:on-click see-all-assets}
"(" (tr "workspace.libraries.update.see-all-changes") ")"])])]])]
[:div.section [:div.section
(if (empty? libraries) (if (empty? libs-assets)
[:div.section-list-empty [:div.section-list-empty
i/library i/library
(tr "workspace.libraries.no-libraries-need-sync")] (tr "workspace.libraries.no-libraries-need-sync")]
[:* [:*
[:div.section-title (tr "workspace.libraries.library")] [:div.section-title (tr "workspace.libraries.library-updates")]
[:div.section-list [:div.section-list
(for [{:keys [id name] :as library} libraries] (for [[{:keys [id name] :as library}
exceeded
{:keys [components colors typographies]}] libs-assets]
[:div.section-list-item {:key (dm/str id)} [:div.section-list-item {:key (dm/str id)}
[:div.item-name name] [:div.item-name name]
[:div.item-contents (describe-external-library library)] [:div.item-contents (describe-library
(count components)
0
(count colors)
(count typographies))]
[:input.item-button {:type "button" [:input.item-button {:type "button"
:class (dom/classnames :btn-gray updating?
:btn-warning (not updating?))
:value (tr "workspace.libraries.update") :value (tr "workspace.libraries.update")
:data-library-id (dm/str id) :data-library-id (dm/str id)
:on-click update}]])]])]))) :on-click update}]
[:div.libraries-updates
(when-not (empty? components)
[:div.libraries-updates-column
(for [component components]
[:div.libraries-updates-item {:key (dm/str (:id component))}
(let [component (ctf/load-component-objects (:data library) component)
root-shape (ctf/get-component-root (:data library) component)]
[:*
[:& component-svg {:root-shape root-shape
:objects (:objects component)}]
[:div.name-block
[:span.item-name {:title (:name component)}
(:name component)]]])])
(when (:components exceeded)
[:div.libraries-updates-item {:key (uuid/next)}
[:div.name-block.ellipsis
[:span.item-name "(...)"]]])])
(when-not (empty? colors)
[:div.libraries-updates-column {:style #js {"--bullet-size" "24px"}}
(for [color colors]
(let [default-name (cond
(:gradient color) (uc/gradient-type->string (get-in color [:gradient :type]))
(:color color) (:color color)
:else (:value color))]
[:div.libraries-updates-item {:key (dm/str (:id color))}
[:*
[:& bc/color-bullet {:color {:color (:color color)
:opacity (:opacity color)}}]
[:div.name-block
[:span.item-name {:title (:name color)}
(:name color)]
(when-not (= (:name color) default-name)
[:span.color-value (:color color)])]]]))
(when (:colors exceeded)
[:div.libraries-updates-item {:key (uuid/next)}
[:div.name-block.ellipsis
[:span.item-name "(...)"]]])])
(when-not (empty? typographies)
[:div.libraries-updates-column
(for [typography typographies]
[:div.libraries-updates-item {:key (dm/str (:id typography))}
[:*
[:div.typography-sample
{:style {:font-family (:font-family typography)
:font-weight (:font-weight typography)
:font-style (:font-style typography)}}
(tr "workspace.assets.typography.sample")]
[:div.name-block
[:span.item-name {:title (:name typography)}
(:name typography)]]]])
(when (:typographies exceeded)
[:div.libraries-updates-item {:key (uuid/next)}
[:div.name-block.ellipsis
[:span.item-name "(...)"]]])])]
(when (or (pos? (:components exceeded))
(pos? (:colors exceeded))
(pos? (:typographies exceeded)))
[:div.libraries-updates-see-all {:on-click see-all-assets}
"(" (tr "workspace.libraries.update.see-all-changes") ")"])])]])])))
(mf/defc libraries-dialog (mf/defc libraries-dialog
{::mf/register modal/components {::mf/register modal/components
::mf/register-as :libraries-dialog} ::mf/register-as :libraries-dialog}
[] [{:keys [starting-tab] :as props :or {starting-tab :libraries}}]
(let [new-css-system (features/use-feature :new-css-system) (let [new-css-system (features/use-feature :new-css-system)
project (mf/deref refs/workspace-project) project (mf/deref refs/workspace-project)
file-data (mf/deref refs/workspace-data) file-data (mf/deref refs/workspace-data)
file (mf/deref ref:workspace-file) file (mf/deref ref:workspace-file)
@ -453,7 +671,7 @@
file-id (:id file) file-id (:id file)
shared? (:is-shared file) shared? (:is-shared file)
selected-tab* (mf/use-state :libraries) selected-tab* (mf/use-state starting-tab)
selected-tab (deref selected-tab*) selected-tab (deref selected-tab*)
libraries (mf/deref refs/workspace-libraries) libraries (mf/deref refs/workspace-libraries)

View file

@ -1 +1 @@
{"button-primary":"workspace_libraries_button-primary_Hsioh","modal-overlay":"workspace_libraries_modal-overlay_qC-df","modal-dialog":"workspace_libraries_modal-dialog_Kj293","modal-content":"workspace_libraries_modal-content_4EVEQ","libraries-content":"workspace_libraries_libraries-content_ycQdm","section":"workspace_libraries_section_SUsgi","section-list":"workspace_libraries_section-list_lGSrM","section-list-item":"workspace_libraries_section-list-item_hwASN","item-publish":"workspace_libraries_item-publish_ZMopF","item-unpublish":"workspace_libraries_item-unpublish_1seca","item-update":"workspace_libraries_item-update_GklIE","section-list-shared":"workspace_libraries_section-list-shared_XZE10","updates-content":"workspace_libraries_updates-content_lqMoE","button-secondary":"workspace_libraries_button-secondary_l5M0x","item-button":"workspace_libraries_item-button_dKUeX","item-button-shared":"workspace_libraries_item-button-shared_hxOmT","button-tertiary":"workspace_libraries_button-tertiary_C54rH","close":"workspace_libraries_close_bED7B","button-tag":"workspace_libraries_button-tag_wAh-s","button-icon":"workspace_libraries_button-icon_kxS7q","item-button-icon":"workspace_libraries_item-button-icon_CeJWg","button-icon-small":"workspace_libraries_button-icon-small_Q9eo3","section-list-empty":"workspace_libraries_section-list-empty_mOKkJ","libraries-search":"workspace_libraries_libraries-search_JS70w","search-icon":"workspace_libraries_search-icon_y7N9S","asset-element":"workspace_libraries_asset-element_-FuJl","new-scrollbar":"workspace_libraries_new-scrollbar_9V-Nb","menu-dropdown":"workspace_libraries_menu-dropdown_frrTQ","menu-item":"workspace_libraries_menu-item_1PSqe","shortcut":"workspace_libraries_shortcut_ZBbd3","shortcut-key":"workspace_libraries_shortcut-key_qBs5D","user-icon":"workspace_libraries_user-icon_IjCsd","modal-title":"workspace_libraries_modal-title_Z1xKU","libraries-header":"workspace_libraries_libraries-header_-W6bJ","item-name":"workspace_libraries_item-name_Zjbsw","item-contents":"workspace_libraries_item-contents_EPTF6","section-title":"workspace_libraries_section-title_7rsm7","element-count":"workspace_libraries_element-count_07SV2","spin-animation":"workspace_libraries_spin-animation_mW-An"} {"button-primary":"workspace_libraries_button-primary_Hsioh","modal-overlay":"workspace_libraries_modal-overlay_qC-df","modal-dialog":"workspace_libraries_modal-dialog_Kj293","modal-content":"workspace_libraries_modal-content_4EVEQ","libraries-content":"workspace_libraries_libraries-content_ycQdm","section":"workspace_libraries_section_SUsgi","section-list":"workspace_libraries_section-list_lGSrM","section-list-item":"workspace_libraries_section-list-item_hwASN","item-publish":"workspace_libraries_item-publish_ZMopF","item-unpublish":"workspace_libraries_item-unpublish_1seca","item-update":"workspace_libraries_item-update_GklIE","section-list-shared":"workspace_libraries_section-list-shared_XZE10","updates-content":"workspace_libraries_updates-content_lqMoE","button-secondary":"workspace_libraries_button-secondary_l5M0x","item-button":"workspace_libraries_item-button_dKUeX","item-button-shared":"workspace_libraries_item-button-shared_hxOmT","button-tertiary":"workspace_libraries_button-tertiary_C54rH","close":"workspace_libraries_close_bED7B","button-tag":"workspace_libraries_button-tag_wAh-s","button-icon":"workspace_libraries_button-icon_kxS7q","item-button-icon":"workspace_libraries_item-button-icon_CeJWg","button-icon-small":"workspace_libraries_button-icon-small_Q9eo3","section-list-empty":"workspace_libraries_section-list-empty_mOKkJ","libraries-search":"workspace_libraries_libraries-search_JS70w","search-icon":"workspace_libraries_search-icon_y7N9S","asset-element":"workspace_libraries_asset-element_-FuJl","new-scrollbar":"workspace_libraries_new-scrollbar_9V-Nb","menu-dropdown":"workspace_libraries_menu-dropdown_frrTQ","menu-item":"workspace_libraries_menu-item_1PSqe","shortcut":"workspace_libraries_shortcut_ZBbd3","shortcut-key":"workspace_libraries_shortcut-key_qBs5D","user-icon":"workspace_libraries_user-icon_IjCsd","modal-title":"workspace_libraries_modal-title_Z1xKU","libraries-header":"workspace_libraries_libraries-header_-W6bJ","item-name":"workspace_libraries_item-name_Zjbsw","item-contents":"workspace_libraries_item-contents_EPTF6","btn-gray":"workspace_libraries_btn-gray_F54JC","btn-warning":"workspace_libraries_btn-warning_abcYL","section-title":"workspace_libraries_section-title_7rsm7","libraries-updates":"workspace_libraries_libraries-updates_RLtH8","libraries-updates-item":"workspace_libraries_libraries-updates-item_QwZMY","name-block":"workspace_libraries_name-block_RcVh4","ellipsis":"workspace_libraries_ellipsis_I5JtE","libraries-updates-see-all":"workspace_libraries_libraries-updates-see-all_-G5EO","element-count":"workspace_libraries_element-count_07SV2","spin-animation":"workspace_libraries_spin-animation_mW-An"}

View file

@ -96,6 +96,22 @@
padding: $s-8 $s-24; padding: $s-8 $s-24;
border-radius: $br-8; border-radius: $br-8;
} }
.item-update {
margin-right: $s-2;
&.btn-gray {
background: var(--light-gray-4);
border-color: var(--light-gray-4);
color: var(--dark-gray-4);
cursor: unset;
&:hover {
color: var(--dark-gray-4);
}
}
&.btn-warning {
background: var(--light-warning-color);
border-color: var(--light-warning-color);
}
}
.item-unpublish { .item-unpublish {
@extend .button-secondary; @extend .button-secondary;
} }
@ -153,6 +169,60 @@
} }
} }
} }
.libraries-updates {
display: grid;
grid-column: span 3;
grid-template-columns: repeat(auto-fill, minmax($s-160, 1fr));
grid-gap: $s-24;
font-size: $fs12;
margin-top: $s-16;
.libraries-updates-item {
display: flex;
align-items: center;
&:not(:first-child) {
margin-top: $s-8;
}
& svg {
background-color: var(--canvas-color);
border-radius: $br-4;
border: $s-2 solid transparent;
height: $s-24;
width: $s-24;
min-height: $s-24;
min-width: $s-24;
}
& .name-block {
color: var(--gray-20-color);
margin-left: $s-8;
width: $s-168;
&.ellipsis {
padding-left: calc($s-24 + #{$s-8});
}
}
& .item-name {
display: block;
margin: 0;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
}
.libraries-updates-see-all {
grid-column: span 3;
margin-top: $s-8;
margin-right: $s-8;
text-align: right;
cursor: pointer;
color: var (--info-color);
text-decoration: underline;
}
} }
.updates-content { .updates-content {
grid-template-columns: 1fr; grid-template-columns: 1fr;

View file

@ -45,7 +45,6 @@
(:value color) (dissoc :value) (:value color) (dissoc :value)
true (assoc :file-id file-id))) true (assoc :file-id file-id)))
color-id (:id color) color-id (:id color)
item-ref (mf/use-ref) item-ref (mf/use-ref)

View file

@ -3351,6 +3351,10 @@ msgstr "LIBRARIES"
msgid "workspace.libraries.library" msgid "workspace.libraries.library"
msgstr "LIBRARY" msgstr "LIBRARY"
#: src/app/main/ui/workspace/libraries.cljs
msgid "workspace.libraries.library-updates"
msgstr "LIBRARY UPDATES"
#: src/app/main/ui/workspace/libraries.cljs #: src/app/main/ui/workspace/libraries.cljs
msgid "workspace.libraries.no-libraries-need-sync" msgid "workspace.libraries.no-libraries-need-sync"
msgstr "There are no Shared Libraries that need update" msgstr "There are no Shared Libraries that need update"
@ -3391,6 +3395,10 @@ msgstr "Update"
msgid "workspace.libraries.updates" msgid "workspace.libraries.updates"
msgstr "UPDATES" msgstr "UPDATES"
#: src/app/main/data/workspace/libraries.cljs
msgid "workspace.libraries.update.see-all-changes"
msgstr "see all changes"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs #: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.add-interaction" msgid "workspace.options.add-interaction"
msgstr "Click the + button to add interactions." msgstr "Click the + button to add interactions."
@ -4784,6 +4792,10 @@ msgstr "Operation over %s"
msgid "workspace.undo.title" msgid "workspace.undo.title"
msgstr "History" msgstr "History"
#: src/app/main/data/workspace/libraries.cljs
msgid "workspace.updates.more-info"
msgstr "More info"
#: src/app/main/data/workspace/libraries.cljs #: src/app/main/data/workspace/libraries.cljs
msgid "workspace.updates.dismiss" msgid "workspace.updates.dismiss"
msgstr "Dismiss" msgstr "Dismiss"

View file

@ -3440,6 +3440,10 @@ msgstr "BIBLIOTECAS"
msgid "workspace.libraries.library" msgid "workspace.libraries.library"
msgstr "BIBLIOTECA" msgstr "BIBLIOTECA"
#: src/app/main/ui/workspace/libraries.cljs
msgid "workspace.libraries.library-updates"
msgstr "ACTUALIZACIONES DE BIBLIOTECAS"
#: src/app/main/ui/workspace/libraries.cljs #: src/app/main/ui/workspace/libraries.cljs
msgid "workspace.libraries.no-libraries-need-sync" msgid "workspace.libraries.no-libraries-need-sync"
msgstr "No hay bibliotecas que necesiten ser actualizadas" msgstr "No hay bibliotecas que necesiten ser actualizadas"
@ -3480,6 +3484,10 @@ msgstr "Actualizar"
msgid "workspace.libraries.updates" msgid "workspace.libraries.updates"
msgstr "ACTUALIZACIONES" msgstr "ACTUALIZACIONES"
#: src/app/main/data/workspace/libraries.cljs
msgid "workspace.updates.see-all-changes"
msgstr "ver todos los cambios"
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs #: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.add-interaction" msgid "workspace.options.add-interaction"
msgstr "Pulsa el botón + para añadir interacciones." msgstr "Pulsa el botón + para añadir interacciones."
@ -4902,6 +4910,10 @@ msgstr "Operación sobre %s"
msgid "workspace.undo.title" msgid "workspace.undo.title"
msgstr "Histórico" msgstr "Histórico"
#: src/app/main/data/workspace/libraries.cljs
msgid "workspace.updates.more-info"
msgstr "Más información"
#: src/app/main/data/workspace/libraries.cljs #: src/app/main/data/workspace/libraries.cljs
msgid "workspace.updates.dismiss" msgid "workspace.updates.dismiss"
msgstr "Ignorar" msgstr "Ignorar"