mirror of
https://github.com/penpot/penpot.git
synced 2026-02-12 22:53:02 +00:00
Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
@@ -30,6 +30,7 @@
|
||||
- Fix issue where Alt + arrow keys shortcut interferes with letter-spacing when moving text layers [Taiga #11552](https://tree.taiga.io/project/penpot/issue/11771)
|
||||
- Fix consistency issues on how font variants are visualized [Taiga #11499](https://tree.taiga.io/project/penpot/us/11499)
|
||||
- Fix parsing rx and ry SVG values for rect radius [Taiga #11861](https://tree.taiga.io/project/penpot/issue/11861)
|
||||
- Misleading affordance in saved versions [Taiga #11887](https://tree.taiga.io/project/penpot/issue/11887)
|
||||
|
||||
|
||||
## 2.9.0
|
||||
|
||||
@@ -821,6 +821,13 @@
|
||||
(let [path-split (split-path path)]
|
||||
(merge-path-item (first path-split) name)))
|
||||
|
||||
(defn inside-path? [child parent]
|
||||
(let [child-path (split-path child)
|
||||
parent-path (split-path parent)]
|
||||
(and (<= (count parent-path) (count child-path))
|
||||
(= parent-path (take (count parent-path) child-path)))))
|
||||
|
||||
|
||||
|
||||
(defn split-by-last-period
|
||||
"Splits a string into two parts:
|
||||
|
||||
@@ -131,7 +131,8 @@
|
||||
:hide-release-modal
|
||||
:subscriptions
|
||||
:subscriptions-old
|
||||
:frontend-binary-fills})
|
||||
:frontend-binary-fills
|
||||
:inspect-styles})
|
||||
|
||||
(def all-flags
|
||||
(set/union email login varia))
|
||||
|
||||
@@ -569,57 +569,56 @@
|
||||
combine
|
||||
(fn [current-page]
|
||||
(let [objects (dsh/lookup-page-objects state current-page)
|
||||
selected (or selected
|
||||
(->> (dsh/lookup-selected state)
|
||||
(cfh/clean-loops objects)
|
||||
(remove (fn [id]
|
||||
(let [shape (get objects id)]
|
||||
(or (not (ctc/main-instance? shape))
|
||||
(ctc/is-variant? shape)))))))
|
||||
shapes (mapv #(get objects %) selected)
|
||||
rect (bounding-rect shapes)
|
||||
prefix (->> shapes
|
||||
(mapv #(cfh/split-path (:name %)))
|
||||
(common-prefix))
|
||||
;; When the common parent is root, add a wrapper
|
||||
add-wrapper? (= prefix [])
|
||||
first-shape (first shapes)
|
||||
delta (gpt/point (- (:x rect) (:x first-shape) 30)
|
||||
(- (:y rect) (:y first-shape) 30))
|
||||
common-parent (->> selected
|
||||
(mapv #(-> (cfh/get-parent-ids objects %) reverse))
|
||||
common-prefix
|
||||
last)
|
||||
index (-> (get objects common-parent)
|
||||
:shapes
|
||||
count
|
||||
inc)
|
||||
variant-id (uuid/next)
|
||||
undo-id (js/Symbol)]
|
||||
selected (->> (or selected (dsh/lookup-selected state))
|
||||
(cfh/clean-loops objects)
|
||||
(remove (fn [id]
|
||||
(let [shape (get objects id)]
|
||||
(or (not (ctc/main-instance? shape))
|
||||
(ctc/is-variant? shape))))))]
|
||||
(when (> (count selected) 1)
|
||||
(let [shapes (mapv #(get objects %) selected)
|
||||
rect (bounding-rect shapes)
|
||||
prefix (->> shapes
|
||||
(mapv #(cfh/split-path (:name %)))
|
||||
(common-prefix))
|
||||
;; When the common parent is root, add a wrapper
|
||||
add-wrapper? (empty? prefix)
|
||||
first-shape (first shapes)
|
||||
delta (gpt/point (- (:x rect) (:x first-shape) 30)
|
||||
(- (:y rect) (:y first-shape) 30))
|
||||
common-parent (->> selected
|
||||
(mapv #(-> (cfh/get-parent-ids objects %) reverse))
|
||||
common-prefix
|
||||
last)
|
||||
index (-> (get objects common-parent)
|
||||
:shapes
|
||||
count
|
||||
inc)
|
||||
variant-id (uuid/next)
|
||||
undo-id (js/Symbol)]
|
||||
|
||||
(rx/concat
|
||||
(if (and page-id (not= current-page page-id))
|
||||
(rx/of (dcm/go-to-workspace :page-id page-id))
|
||||
(rx/empty))
|
||||
(rx/concat
|
||||
(if (and page-id (not= current-page page-id))
|
||||
(rx/of (dcm/go-to-workspace :page-id page-id))
|
||||
(rx/empty))
|
||||
|
||||
(rx/of (dwu/start-undo-transaction undo-id)
|
||||
(transform-in-variant (first selected) variant-id delta prefix add-wrapper? false false)
|
||||
(dwsh/relocate-shapes (into #{} (-> selected rest reverse)) variant-id 0)
|
||||
(dwsh/update-shapes selected #(-> %
|
||||
(assoc :constraints-h :left)
|
||||
(assoc :constraints-v :top)
|
||||
(assoc :fixed-scroll false)))
|
||||
(dwsh/relocate-shapes #{variant-id} common-parent index)
|
||||
(dwt/update-dimensions [variant-id] :width (+ (:width rect) 60))
|
||||
(dwt/update-dimensions [variant-id] :height (+ (:height rect) 60)))
|
||||
(rx/of (dwu/start-undo-transaction undo-id)
|
||||
(transform-in-variant (first selected) variant-id delta prefix add-wrapper? false false)
|
||||
(dwsh/relocate-shapes (into #{} (-> selected rest reverse)) variant-id 0)
|
||||
(dwsh/update-shapes selected #(-> %
|
||||
(assoc :constraints-h :left)
|
||||
(assoc :constraints-v :top)
|
||||
(assoc :fixed-scroll false)))
|
||||
(dwsh/relocate-shapes #{variant-id} common-parent index)
|
||||
(dwt/update-dimensions [variant-id] :width (+ (:width rect) 60))
|
||||
(dwt/update-dimensions [variant-id] :height (+ (:height rect) 60)))
|
||||
|
||||
;; NOTE: we need to schedule a commit into a
|
||||
;; microtask for ensure that all the scheduled
|
||||
;; microtask of previous events execute before the
|
||||
;; commit
|
||||
|
||||
(->> (rx/of (dwu/commit-undo-transaction undo-id))
|
||||
(rx/observe-on :async)))))
|
||||
;; NOTE: we need to schedule a commit into a
|
||||
;; microtask for ensure that all the scheduled
|
||||
;; microtask of previous events execute before the
|
||||
;; commit
|
||||
(->> (rx/of (dwu/commit-undo-transaction undo-id))
|
||||
(rx/observe-on :async)))))))
|
||||
|
||||
redirect-to-page
|
||||
(fn [page-id]
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
border: $b-1 solid var(--border-color, transparent);
|
||||
border-radius: $br-8;
|
||||
|
||||
cursor: pointer;
|
||||
background: var(--color-background-primary);
|
||||
|
||||
display: grid;
|
||||
@@ -74,3 +73,7 @@
|
||||
display: flex;
|
||||
padding-right: var(--sp-xs);
|
||||
}
|
||||
|
||||
.menu-button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
border: $b-1 solid var(--border-color, transparent);
|
||||
border-radius: $br-8;
|
||||
|
||||
cursor: pointer;
|
||||
background: var(--color-background-primary);
|
||||
|
||||
display: grid;
|
||||
|
||||
@@ -8,15 +8,18 @@
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.types.component :as ctk]
|
||||
[app.config :as cf]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.ds.controls.select :refer [select*]]
|
||||
[app.main.ui.ds.foundations.assets.icon :refer [icon*]]
|
||||
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.inspect.attributes :refer [attributes]]
|
||||
[app.main.ui.inspect.code :refer [code]]
|
||||
[app.main.ui.inspect.selection-feedback :refer [resolve-shapes]]
|
||||
[app.main.ui.inspect.styles :refer [styles-tab*]]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :refer [tr]]
|
||||
[app.util.shape-icon :as usi]
|
||||
@@ -39,11 +42,13 @@
|
||||
(mf/defc right-sidebar
|
||||
[{:keys [frame page objects file selected shapes page-id file-id share-id from on-change-section on-expand]
|
||||
:or {from :viewer}}]
|
||||
(let [section (mf/use-state #(do :info))
|
||||
(let [color-space* (mf/use-state "hex")
|
||||
color-space (deref color-space*)
|
||||
|
||||
section (mf/use-state #(if (contains? cf/flags :inspect-styles) :styles :info))
|
||||
objects (or objects (:objects page))
|
||||
shapes (or shapes
|
||||
(resolve-shapes objects selected))
|
||||
|
||||
first-shape (first shapes)
|
||||
page-id (or page-id (:id page))
|
||||
file-id (or file-id (:id file))
|
||||
@@ -82,20 +87,42 @@
|
||||
(fn []
|
||||
(dom/open-new-window "https://help.penpot.app/user-guide/inspect/")))
|
||||
|
||||
handle-change-color-space
|
||||
(mf/use-fn
|
||||
(fn [color-space]
|
||||
(reset! color-space* color-space)))
|
||||
|
||||
color-spaces
|
||||
(mf/with-memo []
|
||||
[{:label (tr "inspect.attributes.color.hex")
|
||||
:id "hex"}
|
||||
{:label (tr "inspect.attributes.color.rgba")
|
||||
:id "rgba"}
|
||||
{:label (tr "inspect.attributes.color.hsla")
|
||||
:id "hsla"}])
|
||||
|
||||
tabs
|
||||
(mf/with-memo []
|
||||
[{:label (tr "inspect.tabs.info")
|
||||
:id "info"}
|
||||
{:label (tr "inspect.tabs.code")
|
||||
:data-testid "code"
|
||||
:id "code"}])]
|
||||
(if (contains? cf/flags :inspect-styles)
|
||||
[{:label (tr "inspect.tabs.styles")
|
||||
:id "styles"}
|
||||
{:label (tr "inspect.tabs.computed")
|
||||
:id "computed"}
|
||||
{:label (tr "inspect.tabs.code")
|
||||
:data-testid "code"
|
||||
:id "code"}]
|
||||
[{:label (tr "inspect.tabs.info")
|
||||
:id "info"}
|
||||
{:label (tr "inspect.tabs.code")
|
||||
:data-testid "code"
|
||||
:id "code"}]))]
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps shapes handle-change-tab)
|
||||
(fn []
|
||||
(if (seq shapes)
|
||||
(st/emit! (ptk/event ::ev/event {::ev/name "inspect-mode-click-element"}))
|
||||
(handle-change-tab :info))))
|
||||
(handle-change-tab (if (contains? cf/flags :inspect-styles) :styles :info)))))
|
||||
|
||||
[:aside {:class (stl/css-case :settings-bar-right true
|
||||
:viewer-code (= from :viewer))}
|
||||
@@ -133,27 +160,63 @@
|
||||
[:div {:class (stl/css :layer-title)} (:name first-shape)]])]])]
|
||||
|
||||
[:div {:class (stl/css :inspect-content)}
|
||||
(if (contains? cf/flags :inspect-styles)
|
||||
[:div {:class (stl/css :inspect-tab-switcher)}
|
||||
[:span {:class (stl/css :inspect-tab-switcher-label)} (tr "inspect.tabs.switcher.label")]
|
||||
[:div {:class (stl/css :inspect-tab-switcher-controls)}
|
||||
[:div {:class (stl/css :inspect-tab-switcher-controls-color-space)}
|
||||
[:> select* {:options color-spaces
|
||||
:default-selected "hex"
|
||||
:on-change handle-change-color-space}]]
|
||||
[:div {:class (stl/css :inspect-tab-switcher-controls-tab)}
|
||||
[:> select* {:options tabs
|
||||
:default-selected (name @section)
|
||||
:on-change handle-change-tab}]]]]
|
||||
nil)
|
||||
|
||||
[:> tab-switcher* {:tabs tabs
|
||||
:selected (name @section)
|
||||
:on-change handle-change-tab
|
||||
:class (stl/css :viewer-tab-switcher)}
|
||||
(case @section
|
||||
:info
|
||||
[:& attributes {:page-id page-id
|
||||
:objects objects
|
||||
:file-id file-id
|
||||
:frame frame
|
||||
:shapes shapes
|
||||
:from from
|
||||
:libraries libraries
|
||||
:share-id share-id}]
|
||||
(if (contains? cf/flags :inspect-styles)
|
||||
[:div {:class (stl/css :inspect-tab :viewer-tab-switcher :viewer-tab-switcher-layout)}
|
||||
(case @section
|
||||
:styles
|
||||
[:> styles-tab* {:color-space color-space
|
||||
:shapes shapes
|
||||
:libraries libraries
|
||||
:file-id file-id}]
|
||||
:computed
|
||||
[:& attributes {:page-id page-id
|
||||
:objects objects
|
||||
:file-id file-id
|
||||
:frame frame
|
||||
:shapes shapes
|
||||
:from from
|
||||
:libraries libraries
|
||||
:share-id share-id}]
|
||||
|
||||
:code
|
||||
[:& code {:frame frame
|
||||
:shapes shapes
|
||||
:on-expand handle-expand
|
||||
:from from}])]]]
|
||||
:code
|
||||
[:& code {:frame frame
|
||||
:shapes shapes
|
||||
:on-expand handle-expand
|
||||
:from from}])]
|
||||
[:> tab-switcher* {:tabs tabs
|
||||
:selected (name @section)
|
||||
:on-change handle-change-tab
|
||||
:class (stl/css :viewer-tab-switcher)}
|
||||
(case @section
|
||||
:info
|
||||
[:& attributes {:page-id page-id
|
||||
:objects objects
|
||||
:file-id file-id
|
||||
:frame frame
|
||||
:shapes shapes
|
||||
:from from
|
||||
:libraries libraries
|
||||
:share-id share-id}]
|
||||
|
||||
:code
|
||||
[:& code {:frame frame
|
||||
:shapes shapes
|
||||
:on-expand handle-expand
|
||||
:from from}])])]]
|
||||
[:div {:class (stl/css :empty)}
|
||||
[:div {:class (stl/css :code-info)}
|
||||
[:span {:class (stl/css :placeholder-icon)}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@use "../ds/typography.scss" as *;
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.settings-bar-right {
|
||||
@@ -106,6 +107,34 @@
|
||||
padding: $s-8 $s-24;
|
||||
}
|
||||
|
||||
.inspect-tab-switcher {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-block: var(--sp-s);
|
||||
padding-inline-end: var(--sp-m);
|
||||
}
|
||||
|
||||
.inspect-tab-switcher-label {
|
||||
@include use-typography("body-medium");
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.inspect-tab-switcher-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 2;
|
||||
gap: var(--sp-s);
|
||||
}
|
||||
|
||||
.inspect-tab-switcher-controls-color-space {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.inspect-tab-switcher-controls-tab {
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
.inspect-content {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
@@ -115,3 +144,7 @@
|
||||
--tabs-nav-padding-inline-start: 0;
|
||||
--tabs-nav-padding-inline-end: var(--sp-m);
|
||||
}
|
||||
|
||||
.viewer-tab-switcher-layout {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
61
frontend/src/app/main/ui/inspect/styles.cljs
Normal file
61
frontend/src/app/main/ui/inspect/styles.cljs
Normal file
@@ -0,0 +1,61 @@
|
||||
(ns app.main.ui.inspect.styles
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.types.component :as ctc]
|
||||
[app.common.types.components-list :as ctkl]
|
||||
[app.main.ui.inspect.styles.style-box :refer [style-box*]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
|
||||
(def type->options
|
||||
{:multiple [:fill :stroke :text :shadow :blur :layout-element]
|
||||
:frame [:visibility :geometry :fill :stroke :shadow :blur :layout :layout-element]
|
||||
:group [:visibility :geometry :svg :layout-element]
|
||||
:rect [:visibility :geometry :fill :stroke :shadow :blur :svg :layout-element]
|
||||
:circle [:visibility :geometry :fill :stroke :shadow :blur :svg :layout-element]
|
||||
:path [:visibility :geometry :fill :stroke :shadow :blur :svg :layout-element]
|
||||
:text [:visibility :geometry :text :shadow :blur :stroke :layout-element]
|
||||
:variant [:variant :geometry :fill :stroke :shadow :blur :layout :layout-element]})
|
||||
|
||||
(defn- get-shape-type
|
||||
[shapes first-shape first-component]
|
||||
(cond
|
||||
(and (= (count shapes) 1)
|
||||
(or (ctc/is-variant-container? first-shape)
|
||||
(ctc/is-variant? first-component)))
|
||||
:variant
|
||||
|
||||
(= (count shapes) 1)
|
||||
(:type first-shape)
|
||||
|
||||
:else
|
||||
:multiple))
|
||||
|
||||
(mf/defc styles-tab*
|
||||
[{:keys [color-space shapes libraries file-id]}]
|
||||
(let [data (dm/get-in libraries [file-id :data])
|
||||
first-shape (first shapes)
|
||||
first-component (ctkl/get-component data (:component-id first-shape))
|
||||
type (get-shape-type shapes first-shape first-component)
|
||||
options (type->options type)]
|
||||
|
||||
[:div {:class (stl/css :element-options)}
|
||||
(for [[idx option] (map-indexed vector options)]
|
||||
[:> style-box* {:key idx :attribute option} color-space])]))
|
||||
|
||||
|
||||
;; WIP
|
||||
;; Panel list as stylebox children
|
||||
#_(case option
|
||||
:geometry [:> geometry-panel {}]
|
||||
:layout [:> layout-panel {}]
|
||||
:layout-element [:> layout-element-panel {}]
|
||||
:fill [:> fill-panel {:color-space color-space}]
|
||||
:stroke [:> stroke-panel {:color-space color-space}]
|
||||
:text [:> text-panel {:color-space color-space}]
|
||||
:shadow [:> shadow-panel {}]
|
||||
:blur [:> blur-panel {}]
|
||||
:svg [:> svg-panel {}]
|
||||
:variant [:> variant-panel* {}]
|
||||
:visibility [:> visibility-panel* {}])
|
||||
26
frontend/src/app/main/ui/inspect/styles/style_box.cljs
Normal file
26
frontend/src/app/main/ui/inspect/styles/style_box.cljs
Normal file
@@ -0,0 +1,26 @@
|
||||
(ns app.main.ui.inspect.styles.style-box
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defn- attribute->title
|
||||
[type]
|
||||
(case type
|
||||
:variant "Variant properties"
|
||||
:token "Token Sets & Themes"
|
||||
:geometry "Size & Position"
|
||||
:fill "Fill"
|
||||
:stroke "Stroke"
|
||||
:text "Text"
|
||||
:shadow "Shadow"
|
||||
:layout "Layout"
|
||||
:layout-element "Layout Element"
|
||||
:visibility "Visibility"
|
||||
:svg "SVG"
|
||||
nil))
|
||||
|
||||
(mf/defc style-box*
|
||||
[{:keys [attribute children]}]
|
||||
[:div {:class (stl/css :style-box)}
|
||||
[:h3 {:class (stl/css :style-box-header)} (attribute->title attribute)]
|
||||
[:div {:class (stl/css :style-box-content)} children]])
|
||||
@@ -460,7 +460,7 @@
|
||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||
(run! st/emit!
|
||||
(->> components
|
||||
(filter #(str/starts-with? (:path %) path))
|
||||
(filter #(cfh/inside-path? (:path %) path))
|
||||
(map #(dwv/rename-comp-or-variant-and-main
|
||||
(:id %)
|
||||
(cmm/rename-group % path last-path)))))
|
||||
@@ -491,7 +491,7 @@
|
||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||
(run! st/emit!
|
||||
(->> components
|
||||
(filter #(str/starts-with? (:path %) path))
|
||||
(filter #(cfh/inside-path? (:path %) path))
|
||||
(map #(dwv/rename-comp-or-variant-and-main (:id %) (cmm/ungroup % path)))))
|
||||
(st/emit! (dwu/commit-undo-transaction undo-id)))))
|
||||
|
||||
@@ -501,7 +501,7 @@
|
||||
(fn [path]
|
||||
(on-clear-selection)
|
||||
(let [comps (->> components
|
||||
(filter #(str/starts-with? (:path %) path)))
|
||||
(filter #(cfh/inside-path? (:path %) path)))
|
||||
ids (into #{} (map :main-instance-id comps))
|
||||
page-id (->> comps first :main-instance-page)]
|
||||
|
||||
|
||||
@@ -1761,8 +1761,12 @@ msgid "inspect.subtitle.main"
|
||||
msgstr "Main component"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:59
|
||||
msgid "inspect.subtitle.variant"
|
||||
msgstr "Variant"
|
||||
msgid "inspect.tabs.switcher.label"
|
||||
msgstr "Layer info"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:101
|
||||
msgid "inspect.tabs.computed"
|
||||
msgstr "Computed"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:105
|
||||
msgid "inspect.tabs.code"
|
||||
@@ -1820,6 +1824,10 @@ msgstr "Text"
|
||||
msgid "inspect.tabs.info"
|
||||
msgstr "Info"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:101
|
||||
msgid "inspect.tabs.styles"
|
||||
msgstr "Styles"
|
||||
|
||||
#: src/app/main/ui/dashboard/comments.cljs:95
|
||||
msgid "label.mark-all-as-read"
|
||||
msgstr "Mark all as read"
|
||||
|
||||
@@ -1768,6 +1768,14 @@ msgstr "Componente principal"
|
||||
msgid "inspect.subtitle.variant"
|
||||
msgstr "Variante"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:59
|
||||
msgid "inspect.tabs.switcher.label"
|
||||
msgstr "Información sobre la capa"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:101
|
||||
msgid "inspect.tabs.computed"
|
||||
msgstr "Calculado"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:105
|
||||
msgid "inspect.tabs.code"
|
||||
msgstr "Código"
|
||||
@@ -1824,6 +1832,10 @@ msgstr "Texto"
|
||||
msgid "inspect.tabs.info"
|
||||
msgstr "Información"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:101
|
||||
msgid "inspect.tabs.styles"
|
||||
msgstr "Estilos"
|
||||
|
||||
#: src/app/main/ui/dashboard/comments.cljs:95
|
||||
msgid "label.mark-all-as-read"
|
||||
msgstr "Marcar todo como leído"
|
||||
|
||||
Reference in New Issue
Block a user