Merge remote-tracking branch 'origin/staging' into develop

This commit is contained in:
Andrey Antukh 2025-07-22 13:04:57 +02:00
commit d914314c1c
12 changed files with 334 additions and 218 deletions

View File

@ -205,9 +205,8 @@
[:trial-start [:maybe ::sm/timestamp]]
[:cancel-at [:maybe ::sm/timestamp]]
[:canceled-at [:maybe ::sm/timestamp]]
[:current-period-end ::sm/timestamp]
[:current-period-start ::sm/timestamp]
[:current-period-end [:maybe ::sm/timestamp]]
[:current-period-start [:maybe ::sm/timestamp]]
[:cancel-at-period-end :boolean]
[:cancellation-details

View File

@ -1665,27 +1665,62 @@
:shapes all-parents})]))))
(defn- text-partial-change-value
[touched-content untouched-content touched]
(cond
(touched :text-content-structure-same-attrs)
(if (touched :text-content-attribute)
;; Both structure and attrs has been touched, keep the
(defn- text-change-value
[touched-content ;; The :content of the copy text before updating
untouched-content ;; The :content of the main component
touched]
(let [main-comps-diff (cttx/get-diff-type touched-content untouched-content)
diff-structure? (contains? main-comps-diff :text-content-structure)
touched-attrs (cttx/get-first-paragraph-text-attrs touched-content)
;; Have touched content an uniform style?
thed-unif-style? (cttx/equal-attrs? touched-content touched-attrs)
untouched-attrs (cttx/get-first-paragraph-text-attrs untouched-content)
;; Have untouched content an uniform style?
untched-unif-style? (cttx/equal-attrs? untouched-content untouched-attrs)]
(cond
;; Both text and attrs has been touched, keep the
;; touched-content
(and (touched :text-content-text) (touched :text-content-attribute))
touched-content
;; Keep the touched-content structure and texts, update
;; its attrs to make them like the untouched-content
(cttx/copy-attrs-keys touched-content (cttx/get-first-paragraph-text-attrs untouched-content)))
(touched :text-content-text)
;; Keep the texts touched in touched-content, so copy the
;; texts from touched-content into untouched-content
(cttx/copy-text-keys touched-content untouched-content)
(touched :text-content-structure)
;; Special case for adding or removing paragraphs:
;; If the structure has been touched, but the attrs don't,
;; and both have uniform attributes, we keep the touched-content structure and
;; texts, updating its attrs to make them like the untouched-content
(if (and (not (touched :text-content-attribute)) thed-unif-style? untched-unif-style?)
(cttx/copy-attrs-keys touched-content untouched-attrs)
;; In other case, we keep the touched content
touched-content)
(touched :text-content-text)
;; Keep the texts touched in touched-content, so copy the
;; texts from touched-content into untouched-content
(cttx/copy-text-keys touched-content untouched-content)
(touched :text-content-attribute)
;; The untouched content has a different structure, but the touched content had't
;; touched the structure
(if diff-structure?
;; If both have uniform attributes, we keep the untouched-content structure and
;; texts, updating its attrs to make them like the touched-content
(if (and thed-unif-style? untched-unif-style?)
(cttx/copy-attrs-keys untouched-content touched-attrs)
;; In other case, we keep the touched content
touched-content)
;; Keep the attrs touched in touched-content, so copy the
;; texts from untouched-content into touched-content
(cttx/copy-text-keys untouched-content touched-content))
;; Nothing is touched
:else
untouched-content)))
(touched :text-content-attribute)
;; Keep the attrs touched in touched-content, so copy the
;; texts from untouched-content into touched-content
(cttx/copy-text-keys untouched-content touched-content)))
(defn- add-update-attr-operations
[attr dest-shape roperations uoperations attr-val]
@ -1700,34 +1735,6 @@
[(conj roperations roperation)
(conj uoperations uoperation)]))
(defn- is-text-partial-change?
"Check if the attr update is a text partial change"
[untouched-shape touched-shape]
(let [touched (get touched-shape :touched #{})
partial-text-keys [:text-content-attribute :text-content-text]
active-keys (filter touched partial-text-keys)
untouched-content (:content untouched-shape)
untouched-attrs (cttx/get-first-paragraph-text-attrs untouched-content)
eq-untouched-attrs? (cttx/equal-attrs? untouched-content untouched-attrs)]
(and
(or
;; One and only one of the keys is pressent
(= 1 (count active-keys))
(and
(not (touched :text-content-attribute))
(touched :text-content-structure-same-attrs)))
(or
;; Both has the same structure
(cttx/equal-structure? untouched-content (:content touched-shape))
;; The origin and destiny have different structures, but each have the same attrs
;; for all the items on its content tree
(and
eq-untouched-attrs?
(touched :text-content-structure-same-attrs))))))
(defn- update-attrs
"The main function that implements the attribute sync algorithm. Copy
attributes that have changed in the origin shape to the dest shape.
@ -1784,13 +1791,13 @@
;; and attrs (bold, font, etc) are in the same attr :content.
;; If only one of them is touched, we want to adress this case and
;; only update the untouched one
text-partial-change?
(when (and
omit-touched?
(cfh/text-shape? origin-shape)
(= :content attr)
(touched attr-group))
(is-text-partial-change? origin-shape dest-shape))
text-content-change?
(and
omit-touched?
(cfh/text-shape? origin-shape)
(= :content attr)
(touched attr-group))
skip-operations?
(or (= (get origin-shape attr) (get dest-shape attr))
@ -1799,7 +1806,7 @@
;; When it is a text-partial-change, we should generate operations
;; even when omit-touched? is true, but updating only the text or
;; the attributes, omiting the other part
(not text-partial-change?)))
(not text-content-change?)))
attr-val (when-not skip-operations?
(cond
@ -1808,10 +1815,10 @@
reset-pos-data?
nil
text-partial-change?
(text-partial-change-value (:content dest-shape)
(:content origin-shape)
touched)
text-content-change?
(text-change-value (:content dest-shape)
(:content origin-shape)
touched)
:else
(get origin-shape attr)))
@ -1824,7 +1831,7 @@
;; On a text-partial-change, we want to force a position-data reset
;; so it's calculated again
[roperations uoperations]
(if (and text-partial-change? (not skip-operations?))
(if (and text-content-change? (not skip-operations?))
(add-update-attr-operations :position-data dest-shape roperations uoperations nil)
[roperations uoperations])

View File

@ -83,21 +83,12 @@
compare them, and returns a set with the type of differences.
The possibilities are
:text-content-text
:text-content-attribute,
:text-content-structure
:text-content-structure-same-attrs."
:text-content-attribute
:text-content-structure"
[a b]
(let [diff-type (compare-text-content a b
{:text-cb (fn [acc] (conj acc :text-content-text))
:attribute-cb (fn [acc _] (conj acc :text-content-attribute))})]
(if-not (contains? diff-type :text-content-structure)
diff-type
(let [;; get attrs of the first paragraph of the first paragraph-set
attrs (get-first-paragraph-text-attrs a)]
(if (and (equal-attrs? a attrs)
(equal-attrs? b attrs))
#{:text-content-structure :text-content-structure-same-attrs}
diff-type)))))
(compare-text-content a b
{:text-cb (fn [acc] (conj acc :text-content-text))
:attribute-cb (fn [acc _] (conj acc :text-content-attribute))}))
(defn get-diff-attrs
"Given two content text structures, conformed by maps and vectors,

View File

@ -103,7 +103,7 @@
file' (thf/apply-changes file changes)
copy-child' (ths/get-shape file' :copy-child)]
(t/is (= #{:content-group :text-content-structure :text-content-structure-same-attrs} (:touched copy-child')))))
(t/is (= #{:content-group :text-content-structure} (:touched copy-child')))))
(t/deftest test-text-copy-changed-structure-diff-attrs
(let [;; ==== Setup

View File

@ -39,7 +39,7 @@
(t/is (= #{:text-content-attribute} diff-attr))
(t/is (= #{:text-content-text :text-content-attribute} diff-both))
(t/is (= #{:text-content-structure} diff-structure))
(t/is (= #{:text-content-structure :text-content-structure-same-attrs} diff-structure-same-attrs))))
(t/is (= #{:text-content-structure} diff-structure-same-attrs))))
(t/deftest test-get-diff-attrs

View File

@ -0,0 +1,91 @@
FROM ubuntu:24.04
LABEL maintainer="Penpot <docker@penpot.app>"
ENV LANG='C.UTF-8' \
LC_ALL='C.UTF-8' \
DEBIAN_FRONTEND=noninteractive \
TZ=Etc/UTC
ARG IMAGEMAGICK_VERSION=7.1.1-47
RUN set -e; \
apt-get -qq update; \
apt-get -qq upgrade; \
apt-get -qqy --no-install-recommends install \
autoconf \
binutils \
build-essential \
ca-certificates \
curl \
libfftw3-dev \
libheif-dev \
libjpeg-dev \
liblcms2-dev \
libltdl-dev \
liblzma-dev \
libopenexr-dev \
libpng-dev \
librsvg2-dev \
libtiff-dev \
libtool \
libwebp-dev \
libzip-dev \
libzstd-dev \
pkg-config \
; \
curl -LfsSo /tmp/magick.tar.gz https://github.com/ImageMagick/ImageMagick/archive/refs/tags/${IMAGEMAGICK_VERSION}.tar.gz; \
mkdir -p /tmp/magick; \
cd /tmp/magick; \
tar -xf /tmp/magick.tar.gz --strip-components=1; \
./configure --prefix=/opt/imagick; \
make -j 2; \
make install; \
rm -rf /opt/imagick/lib/libMagick++*; \
rm -rf /opt/imagick/include; \
rm -rf /opt/imagick/share; \
apt-get -qqy --autoremove purge \
autoconf \
binutils \
build-essential \
ca-certificates \
curl \
libfftw3-dev \
libheif-dev \
libjpeg-dev \
liblcms2-dev \
libltdl-dev \
liblzma-dev \
libopenexr-dev \
libpng-dev \
librsvg2-dev \
libtiff-dev \
libtool\
libwebp-dev \
libzip-dev \
libzstd-dev \
pkg-config \
;\
apt-get -qqy --no-install-recommends install \
libfontconfig1 \
libfreetype6 \
libglib2.0-0 \
libgomp1 \
libheif1 \
libjpeg-turbo8 \
liblcms2-2 \
libopenexr-3-1-30 \
libopenjp2-7 \
libpng16-16 \
librsvg2-2 \
libtiff6 \
libwebp7 \
libwebpdemux2 \
libwebpmux3 \
libxml2 \
libzip4t64 \
libzstd1 \
;\
apt-get -qqy clean; \
rm -rf /var/lib/apt/lists/*;
ENTRYPOINT ["/opt/imagick/bin/magick"]

View File

@ -6,37 +6,18 @@ ENV LANG='C.UTF-8' \
JAVA_HOME="/opt/jdk" \
DEBIAN_FRONTEND=noninteractive \
NODE_VERSION=v22.16.0 \
IMAGEMAGICK_VERSION=7.1.1-47 \
TZ=Etc/UTC
RUN set -ex; \
apt-get -qq update; \
apt-get -qq upgrade; \
apt-get -qqy --no-install-recommends install \
curl \
ca-certificates \
binutils \
build-essential autoconf libtool pkg-config \
libltdl-dev \
libpng-dev libjpeg-dev libtiff-dev libwebp-dev libopenexr-dev libfftw3-dev \
libzip-dev \
liblcms2-dev liblzma-dev libzstd-dev \
libheif-dev librsvg2-dev \
ca-certificates \
curl \
; \
rm -rf /var/lib/apt/lists/*
RUN set -eux; \
curl -LfsSo /tmp/magick.tar.gz https://github.com/ImageMagick/ImageMagick/archive/refs/tags/${IMAGEMAGICK_VERSION}.tar.gz; \
mkdir -p /tmp/magick; \
cd /tmp/magick; \
tar -xf /tmp/magick.tar.gz --strip-components=1; \
./configure --prefix=/opt/imagick; \
make -j 2; \
make install; \
rm -rf /opt/imagick/lib/libMagick++*; \
rm -rf /opt/imagick/include; \
rm -rf /opt/imagick/share;
RUN set -eux; \
ARCH="$(dpkg --print-architecture)"; \
case "${ARCH}" in \
@ -105,33 +86,33 @@ RUN set -ex; \
apt-get -qq update; \
apt-get -qq upgrade; \
apt-get -qqy --no-install-recommends install \
tzdata \
ca-certificates \
fontconfig \
woff-tools \
woff2 \
fontforge \
python3 \
python3-tabulate \
fontforge \
tzdata \
woff-tools \
woff2 \
\
libpng16-16 \
libfontconfig1 \
libfreetype6 \
libglib2.0-0 \
libgomp1 \
libheif1 \
libjpeg-turbo8 \
liblcms2-2 \
libopenexr-3-1-30 \
libopenjp2-7 \
libpng16-16 \
librsvg2-2 \
libtiff6 \
libwebp7 \
libopenexr-3-1-30 \
libfreetype6 \
libfontconfig1 \
libglib2.0-0 \
libxml2 \
liblcms2-2 \
libheif1 \
libopenjp2-7 \
libzstd1 \
librsvg2-2 \
libgomp1 \
libwebpmux3 \
libwebpdemux2 \
libwebpmux3 \
libxml2 \
libzip4t64 \
libzstd1 \
; \
find tmp/usr/share/zoneinfo/* -type d ! -name 'Etc' |xargs rm -rf; \
rm -rf /var/lib /var/cache; \
@ -144,7 +125,7 @@ RUN set -ex; \
COPY --from=build /opt/jre /opt/jre
COPY --from=build /opt/node /opt/node
COPY --from=build /opt/imagick /opt/imagick
COPY --from=penpotapp/imagemagick:7.1.1-47 /opt/imagick /opt/imagick
COPY --chown=penpot:penpot ./bundle-backend/ /opt/penpot/backend/
USER penpot:penpot

View File

@ -61,7 +61,7 @@
[:> cta-power-up*
{:top-title (tr "subscription.dashboard.power-up.your-subscription")
:top-description (tr "subscription.dashboard.power-up.professional.top-title")
:bottom-description (tr "subscription.dashboard.power-up.professional.bottom-description", subscription-href)
:bottom-description (tr "subscription.dashboard.power-up.professional.bottom", subscription-href)
:has-dropdown true}]
"unlimited"
@ -75,7 +75,7 @@
[:> cta-power-up*
{:top-title (tr "subscription.dashboard.power-up.your-subscription")
:top-description (tr "subscription.dashboard.power-up.unlimited-plan")
:bottom-description (tr "subscription.dashboard.power-up.unlimited.bottom-description", subscription-href)
:bottom-description (tr "subscription.dashboard.power-up.unlimited.bottom", subscription-href)
:has-dropdown true}])
"enterprise"

View File

@ -62,7 +62,7 @@
(mf/defc subscribe-management-dialog
{::mf/register modal/components
::mf/register-as :management-dialog}
[{:keys [subscription-type teams subscribe-to-trial]}]
[{:keys [subscription-type current-subscription teams subscribe-to-trial]}]
(let [subscription-name (if subscribe-to-trial
(if (= subscription-type "unlimited")
@ -127,12 +127,15 @@
(tr "subscription.settings.management.dialog.no-teams")])
(when (and
(or (= subscription-type "professional") (= subscription-type "unlimited"))
(or (and (= subscription-type "professional") (contains? #{"unlimited" "enterprise"} (:type current-subscription)))
(and (= subscription-type "unlimited") (= (:type current-subscription) "enterprise")))
(not (contains? #{"unpaid" "canceled"} (:status current-subscription)))
(not subscribe-to-trial))
[:div {:class (stl/css :modal-text)}
(tr "subscription.settings.management.dialog.downgrade")])
(if (and (= subscription-type "unlimited") subscribe-to-trial)
(if (and (= subscription-type "unlimited")
(or subscribe-to-trial (contains? #{"unpaid" "canceled"} (:status current-subscription))))
[:& fm/form {:on-submit subscribe-to-unlimited
:class (stl/css :seats-form)
:form form}
@ -161,7 +164,7 @@
:on-click handle-close-dialog}]
[:> fm/submit-button*
{:label (tr "subscription.settings.start-trial")
{:label (if subscribe-to-trial (tr "subscription.settings.start-trial") (tr "labels.continue"))
:class (stl/css :primary-button)}]]]]
[:div {:class (stl/css :modal-footer)}
@ -232,6 +235,9 @@
(or (= params-subscription "subscribed-to-penpot-unlimited")
(= params-subscription "subscribed-to-penpot-enterprise"))
success-modal-is-trial?
(-> route :params :query :trial)
subscription
(-> profile :props :subscription)
@ -269,12 +275,13 @@
open-subscription-modal
(mf/use-fn
(mf/deps teams)
(fn [subscription-type]
(fn [subscription-type current-subscription]
(st/emit! (ev/event {::ev/name "open-subscription-modal"
::ev/origin "settings:in-app"}))
(st/emit!
(modal/show :management-dialog
{:subscription-type subscription-type
:current-subscription current-subscription
:teams teams :subscribe-to-trial (not subscription)}))))]
(mf/with-effect []
@ -285,7 +292,7 @@
(mf/with-effect []
(dom/set-html-title (tr "subscription.labels")))
(mf/with-effect [authenticated? show-subscription-success-modal? show-trial-subscription-modal? subscription]
(mf/with-effect [authenticated? show-subscription-success-modal? show-trial-subscription-modal? success-modal-is-trial? subscription]
(when ^boolean authenticated?
(cond
^boolean show-trial-subscription-modal?
@ -297,6 +304,7 @@
{:subscription-type (if (= params-subscription "subscription-to-penpot-unlimited")
"unlimited"
"enterprise")
:current-subscription subscription
:teams teams
:subscribe-to-trial (not subscription)})
(rt/nav :settings-subscription {} {::rt/replace true}))
@ -305,8 +313,12 @@
(st/emit!
(modal/show :subscription-success
{:subscription-name (if (= params-subscription "subscribed-to-penpot-unlimited")
(tr "subscription.settings.unlimited-trial")
(tr "subscription.settings.enterprise-trial"))})
(if (= success-modal-is-trial? "true")
(tr "subscription.settings.unlimited-trial")
(tr "subscription.settings.unlimited"))
(if (= success-modal-is-trial? "true")
(tr "subscription.settings.enterprise-trial")
(tr "subscription.settings.enterprise")))})
(du/update-profile-props {:subscription
(-> subscription
(assoc :type (if (= params-subscription "subscribed-to-penpot-unlimited")
@ -327,7 +339,7 @@
[:> plan-card* {:card-title (tr "subscription.settings.professional")
:benefits [(tr "subscription.settings.professional.projects-files"),
(tr "subscription.settings.professional.teams-editors"),
(tr "subscription.settings.professional.storage")]}]
(tr "subscription.settings.professional.storage-autosave")]}]
"unlimited"
(if subscription-is-trial?
@ -336,7 +348,7 @@
:benefits-title (tr "subscription.settings.benefits.all-professional-benefits")
:benefits [(tr "subscription.settings.unlimited.teams"),
(tr "subscription.settings.unlimited.bill"),
(tr "subscription.settings.unlimited.storage")]
(tr "subscription.settings.unlimited.storage-autosave")]
:cta-text (tr "subscription.settings.manage-your-subscription")
:cta-link go-to-payments
:cta-text-trial (tr "subscription.settings.add-payment-to-continue")
@ -348,7 +360,7 @@
:benefits-title (tr "subscription.settings.benefits.all-unlimited-benefits")
:benefits [(tr "subscription.settings.unlimited.teams"),
(tr "subscription.settings.unlimited.bill"),
(tr "subscription.settings.unlimited.storage")]
(tr "subscription.settings.unlimited.storage-autosave")]
:cta-text (tr "subscription.settings.manage-your-subscription")
:cta-link go-to-payments
:editors (-> profile :props :subscription :quantity)}])
@ -358,22 +370,22 @@
[:> plan-card* {:card-title (tr "subscription.settings.enterprise-trial")
:card-title-icon i/character-e
:benefits-title (tr "subscription.settings.benefits.all-professional-benefits")
:benefits [(tr "subscription.settings.enterprise.support"),
(tr "subscription.settings.enterprise.security"),
(tr "subscription.settings.enterprise.logs")]
:benefits [(tr "subscription.settings.enterprise.security"),
(tr "subscription.settings.enterprise.capped-bill"),
(tr "subscription.settings.enterprise.unlimited-storage")]
:cta-text (tr "subscription.settings.manage-your-subscription")
:cta-link go-to-payments}]
[:> plan-card* {:card-title (tr "subscription.settings.enterprise")
:card-title-icon i/character-e
:benefits-title (tr "subscription.settings.benefits.all-professional-benefits")
:benefits [(tr "subscription.settings.enterprise.support"),
(tr "subscription.settings.enterprise.security"),
(tr "subscription.settings.enterprise.logs")]
:benefits [(tr "subscription.settings.enterprise.security"),
(tr "subscription.settings.enterprise.capped-bill"),
(tr "subscription.settings.enterprise.unlimited-storage")]
:cta-text (tr "subscription.settings.manage-your-subscription")
:cta-link go-to-payments}]))
[:div {:class (stl/css :membership-container)}
(when subscribed-since
(when (and subscribed-since (not= subscription-type "professional"))
[:div {:class (stl/css :membership)}
[:span {:class (stl/css :subscription-member)} i/crown]
[:span {:class (stl/css :membership-date)}
@ -392,7 +404,7 @@
:price-period (tr "subscription.settings.price-editor-month")
:benefits [(tr "subscription.settings.professional.projects-files"),
(tr "subscription.settings.professional.teams-editors"),
(tr "subscription.settings.professional.storage")]
(tr "subscription.settings.professional.storage-autosave")]
:cta-text (tr "subscription.settings.subscribe")
:cta-link #(open-subscription-modal "professional")
:cta-text-with-icon (tr "subscription.settings.more-information")
@ -406,9 +418,9 @@
:benefits-title (tr "subscription.settings.benefits.all-professional-benefits")
:benefits [(tr "subscription.settings.unlimited.teams"),
(tr "subscription.settings.unlimited.bill"),
(tr "subscription.settings.unlimited.storage")]
(tr "subscription.settings.unlimited.storage-autosave")]
:cta-text (if subscription (tr "subscription.settings.subscribe") (tr "subscription.settings.try-it-free"))
:cta-link #(open-subscription-modal "unlimited")
:cta-link #(open-subscription-modal "unlimited" subscription-type)
:cta-text-with-icon (tr "subscription.settings.more-information")
:cta-link-with-icon go-to-pricing-page}])
@ -417,10 +429,10 @@
:card-title-icon i/character-e
:price-value "$950"
:price-period (tr "subscription.settings.price-organization-month")
:benefits-title (tr "subscription.settings.benefits.all-professional-benefits")
:benefits [(tr "subscription.settings.enterprise.support"),
(tr "subscription.settings.enterprise.security"),
(tr "subscription.settings.enterprise.logs")]
:benefits-title (tr "subscription.settings.benefits.all-unlimited-benefits")
:benefits [(tr "subscription.settings.enterprise.security"),
(tr "subscription.settings.enterprise.capped-bill"),
(tr "subscription.settings.enterprise.unlimited-storage")]
:cta-text (if subscription (tr "subscription.settings.subscribe") (tr "subscription.settings.try-it-free"))
:cta-link #(open-subscription-modal "enterprise")
:cta-text-with-icon (tr "subscription.settings.more-information")

View File

@ -4320,10 +4320,10 @@ msgstr "Advanced security, activity logs, dedicated support and more."
#: src/app/main/ui/dashboard/subscription.cljs:60
#, markdown
msgid "subscription.dashboard.power-up.professional.bottom-description"
msgid "subscription.dashboard.power-up.professional.bottom"
msgstr ""
"Get extra editors and storage, file backup and more with the Unlimited "
"plan[Power up|target:self](%s)"
"Get extra editors and storage, file recovery and more with the Unlimited "
"plan. [Power up|target:self](%s)"
#: src/app/main/ui/dashboard/subscription.cljs:59
msgid "subscription.dashboard.power-up.professional.top-title"
@ -4357,10 +4357,10 @@ msgstr "Enterprise plan (trial)"
#: src/app/main/ui/dashboard/subscription.cljs:74
#, markdown
msgid "subscription.dashboard.power-up.unlimited.bottom-description"
msgid "subscription.dashboard.power-up.unlimited.bottom"
msgstr ""
"Get advanced security, activity logs, dedicated support and more. Take a "
"look to the[Enterprise plan.|target:self](%s)"
"Get extra editors, more storage and backup, advanced security and more. "
"[Take a look to the Enterprise plan.|target:self](%s)"
#: src/app/main/ui/dashboard/subscription.cljs:70
#, unused
@ -4414,16 +4414,16 @@ msgid "subscription.settings.enterprise-trial"
msgstr "Enterprise (trial)"
#: src/app/main/ui/settings/subscription.cljs:271, src/app/main/ui/settings/subscription.cljs:320
msgid "subscription.settings.enterprise.logs"
msgstr "Activity logs"
msgid "subscription.settings.enterprise.unlimited-storage"
msgstr "Unlimited storage and 90-day autosave versions and file recovery"
#: src/app/main/ui/settings/subscription.cljs:270, src/app/main/ui/settings/subscription.cljs:319
msgid "subscription.settings.enterprise.security"
msgstr "Advanced security"
#: src/app/main/ui/settings/subscription.cljs:269, src/app/main/ui/settings/subscription.cljs:318
msgid "subscription.settings.enterprise.support"
msgstr "Dedicated support"
msgid "subscription.settings.enterprise.capped-bill"
msgstr "Capped monthly bill"
#: src/app/main/ui/dashboard/subscription.cljs:114, src/app/main/ui/settings/subscription.cljs:251, src/app/main/ui/settings/subscription.cljs:262, src/app/main/ui/settings/subscription.cljs:272
msgid "subscription.settings.manage-your-subscription"
@ -4492,8 +4492,8 @@ msgid "subscription.settings.professional.projects-files"
msgstr "Unlimited projects, files and drafts"
#: src/app/main/ui/settings/subscription.cljs:241, src/app/main/ui/settings/subscription.cljs:292
msgid "subscription.settings.professional.storage"
msgstr "10GB of storage and 7-day autosave versions"
msgid "subscription.settings.professional.storage-autosave"
msgstr "10GB of storage and 7-day autosave versions and file recovery"
#: src/app/main/ui/settings/subscription.cljs:240, src/app/main/ui/settings/subscription.cljs:291
msgid "subscription.settings.professional.teams-editors"
@ -4537,11 +4537,6 @@ msgstr "You've been supporting us with this plan since: %s"
msgid "subscription.settings.try-it-free"
msgstr "Try it free for 14 days"
#: src/app/main/ui/settings/subscription.cljs:119
#, unused
msgid "subscription.settings.ulimited.try-it-free"
msgstr "Try it free for 14 days"
#: src/app/main/ui/dashboard/subscription.cljs:108, src/app/main/ui/settings/subscription.cljs:56, src/app/main/ui/settings/subscription.cljs:256, src/app/main/ui/settings/subscription.cljs:299
msgid "subscription.settings.unlimited"
msgstr "Unlimited"
@ -4555,8 +4550,8 @@ msgid "subscription.settings.unlimited.bill"
msgstr "Capped monthly bill"
#: src/app/main/ui/settings/subscription.cljs:250, src/app/main/ui/settings/subscription.cljs:261, src/app/main/ui/settings/subscription.cljs:306
msgid "subscription.settings.unlimited.storage"
msgstr "25GB of storage and 30-day autosave versions and file backup"
msgid "subscription.settings.unlimited.storage-autosave"
msgstr "25GB of storage and 30-day autosave versions and file recovery"
#: src/app/main/ui/settings/subscription.cljs:248, src/app/main/ui/settings/subscription.cljs:259, src/app/main/ui/settings/subscription.cljs:304
msgid "subscription.settings.unlimited.teams"

View File

@ -4347,9 +4347,9 @@ msgstr "Seguridad avanzada, registros de actividad, asistencia dedicada y mucho
#: src/app/main/ui/dashboard/subscription.cljs:60
#, markdown
msgid "subscription.dashboard.power-up.professional.bottom-description"
msgid "subscription.dashboard.power-up.professional.bottom"
msgstr ""
"Consigue editores y almacenamiento adicionales, copias de seguridad de "
"Consigue editores y almacenamiento adicionales, recuperación de "
"archivos y mucho más con el Plan Unlimited[Mejóralo|target:self](%s)"
#: src/app/main/ui/dashboard/subscription.cljs:59
@ -4388,10 +4388,10 @@ msgstr "Plan Unlimited"
#: src/app/main/ui/dashboard/subscription.cljs:74
#, markdown
msgid "subscription.dashboard.power-up.unlimited.bottom-description"
msgid "subscription.dashboard.power-up.unlimited.bottom"
msgstr ""
"Obtenga seguridad avanzada, registros de actividad, asistencia dedicada y "
"mucho más. Echa un ojo al[Plan Enterprise|target:self](%s)"
"Consigue editores adicionales, más almacenamiento y copias de seguridad, seguridad avanzada y mucho más. "
"[Echa un ojo al Plan Enterprise|target:self](%s)"
#: src/app/main/ui/dashboard/subscription.cljs:70
#, unused
@ -4442,16 +4442,16 @@ msgid "subscription.settings.enterprise-trial"
msgstr "Enterprise (prueba)"
#: src/app/main/ui/settings/subscription.cljs:271, src/app/main/ui/settings/subscription.cljs:320
msgid "subscription.settings.enterprise.logs"
msgstr "Registros de actividad"
msgid "subscription.settings.enterprise.unlimited-storage"
msgstr "Almacenamiento ilimitado y versiones de autoguardado de 90 días y recuperación de archivos"
#: src/app/main/ui/settings/subscription.cljs:270, src/app/main/ui/settings/subscription.cljs:319
msgid "subscription.settings.enterprise.security"
msgstr "Seguridad avanzada"
#: src/app/main/ui/settings/subscription.cljs:269, src/app/main/ui/settings/subscription.cljs:318
msgid "subscription.settings.enterprise.support"
msgstr "Apoyo específico"
msgid "subscription.settings.enterprise.capped-bill"
msgstr "Factura mensual limitada"
#: src/app/main/ui/dashboard/subscription.cljs:114, src/app/main/ui/settings/subscription.cljs:251, src/app/main/ui/settings/subscription.cljs:262, src/app/main/ui/settings/subscription.cljs:272
msgid "subscription.settings.manage-your-subscription"
@ -4516,8 +4516,8 @@ msgid "subscription.settings.professional.projects-files"
msgstr "Proyectos, archivos y borradores ilimitados"
#: src/app/main/ui/settings/subscription.cljs:241, src/app/main/ui/settings/subscription.cljs:292
msgid "subscription.settings.professional.storage"
msgstr "10 GB de almacenamiento y versiones de autoguardado de 7 días"
msgid "subscription.settings.professional.storage-autosave"
msgstr "10 GB de almacenamiento y versiones de autoguardado de 7 días y recuperación de archivos"
#: src/app/main/ui/settings/subscription.cljs:240, src/app/main/ui/settings/subscription.cljs:291
msgid "subscription.settings.professional.teams-editors"
@ -4560,11 +4560,6 @@ msgstr "Nos has estado apoyando con este plan desde: %s"
msgid "subscription.settings.try-it-free"
msgstr "Pruébalo gratis durante 14 días"
#: src/app/main/ui/settings/subscription.cljs:119
#, unused
msgid "subscription.settings.ulimited.try-it-free"
msgstr "Pruébalo gratis durante 14 días"
#: src/app/main/ui/dashboard/subscription.cljs:108, src/app/main/ui/settings/subscription.cljs:56, src/app/main/ui/settings/subscription.cljs:256, src/app/main/ui/settings/subscription.cljs:299
msgid "subscription.settings.unlimited"
msgstr "Unlimited"
@ -4578,10 +4573,10 @@ msgid "subscription.settings.unlimited.bill"
msgstr "Factura mensual limitada"
#: src/app/main/ui/settings/subscription.cljs:250, src/app/main/ui/settings/subscription.cljs:261, src/app/main/ui/settings/subscription.cljs:306
msgid "subscription.settings.unlimited.storage"
msgid "subscription.settings.unlimited.storage-autosave"
msgstr ""
"25 GB de almacenamiento y 30 días de autoguardado de versiones y copias de "
"seguridad de archivos"
"25 GB de almacenamiento y 30 días de autoguardado de versiones y recuperación "
"de archivos"
#: src/app/main/ui/settings/subscription.cljs:248, src/app/main/ui/settings/subscription.cljs:259, src/app/main/ui/settings/subscription.cljs:304
msgid "subscription.settings.unlimited.teams"

119
manage.sh
View File

@ -7,6 +7,7 @@ export DEVENV_PNAME="penpotdev";
export CURRENT_USER_ID=$(id -u);
export CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD);
export IMAGEMAGICK_VERSION=7.1.1-47
# Safe directory to avoid ownership errors with Git
git config --global --add safe.directory /home/penpot/penpot || true
@ -16,16 +17,23 @@ export JAVA_OPTS=${JAVA_OPTS:-"-Xmx1000m -Xms50m"};
set -e
ARCH=$(uname -m)
if [[ "$ARCH" == "x86_64" || "$ARCH" == "i386" || "$ARCH" == "i686" ]]; then
ARCH="amd64"
elif [[ "$ARCH" == "aarch64" || "$ARCH" == "arm64" ]]; then
ARCH="arm64"
else
echo "Unknown architecture $ARCH"
exit -1
fi
function print-current-version {
echo -n "$(git describe --tags --match "*.*.*")";
}
function build-devenv {
set +e;
echo "Building development image $DEVENV_IMGNAME:latest..."
pushd docker/devenv;
function setup-buildx {
docker run --privileged --rm tonistiigi/binfmt --install all
docker buildx inspect penpot > /dev/null 2>&1;
@ -36,19 +44,28 @@ function build-devenv {
docker buildx use penpot;
docker buildx inspect --bootstrap > /dev/null 2>&1;
fi
# docker build -t $DEVENV_IMGNAME:latest .
docker buildx build --platform linux/amd64,linux/arm64 --push -t $DEVENV_IMGNAME:latest .;
docker pull $DEVENV_IMGNAME:latest;
popd;
}
function build-devenv-local {
echo "Building local only development image $DEVENV_IMGNAME:latest..."
function build-devenv {
set +e;
pushd docker/devenv;
docker build -t $DEVENV_IMGNAME:latest .;
if [ "$1" = "--local" ]; then
echo "Build local only $DEVENV_IMGNAME:latest image";
docker build -t $DEVENV_IMGNAME:latest .;
else
echo "Build and push $DEVENV_IMGNAME:latest image";
setup-buildx;
docker buildx build \
--platform linux/amd64,linux/arm64 \
--output type=registry \
-t $DEVENV_IMGNAME:latest .;
docker pull $DEVENV_IMGNAME:latest;
fi
popd;
}
@ -124,6 +141,32 @@ function run-devenv-isolated-shell {
$DEVENV_IMGNAME:latest sudo -EH -u penpot bash
}
function build-imagemagick-docker-image {
set +e;
echo "Building image penpotapp/imagemagick:$IMAGEMAGICK_VERSION"
pushd docker/imagemagick;
output_option="type=registry";
platform="linux/amd64,linux/arm64";
if [ "$1" = "--local" ]; then
output_option="type=docker";
platform="linux/$ARCH"
fi
setup-buildx;
docker buildx build \
--build-arg IMAGEMAGICK_VERSION=$IMAGEMAGICK_VERSION \
--platform $platform \
--output $output_option \
-t penpotapp/imagemagick:latest \
-t penpotapp/imagemagick:$IMAGEMAGICK_VERSION .;
popd;
}
function build {
echo ">> build start: $1"
local version=$(print-current-version);
@ -219,21 +262,21 @@ function build-docs-bundle {
echo ">> bundle docs end";
}
function build-frontend-docker-images {
function build-frontend-docker-image {
rsync -avr --delete ./bundles/frontend/ ./docker/images/bundle-frontend/;
pushd ./docker/images;
docker build -t penpotapp/frontend:$CURRENT_BRANCH -t penpotapp/frontend:latest -f Dockerfile.frontend .;
popd;
}
function build-backend-docker-images {
function build-backend-docker-image {
rsync -avr --delete ./bundles/backend/ ./docker/images/bundle-backend/;
pushd ./docker/images;
docker build -t penpotapp/backend:$CURRENT_BRANCH -t penpotapp/backend:latest -f Dockerfile.backend .;
popd;
}
function build-exporter-docker-images {
function build-exporter-docker-image {
rsync -avr --delete ./bundles/exporter/ ./docker/images/bundle-exporter/;
pushd ./docker/images;
docker build -t penpotapp/exporter:$CURRENT_BRANCH -t penpotapp/exporter:latest -f Dockerfile.exporter .;
@ -246,7 +289,7 @@ function usage {
echo "Options:"
echo "- pull-devenv Pulls docker development oriented image"
echo "- build-devenv Build docker development oriented image"
echo "- build-devenv-local Build a local docker development oriented image"
echo "- build-devenv --local Build a local docker development oriented image"
echo "- create-devenv Create the development oriented docker compose service."
echo "- start-devenv Start the development oriented docker compose service."
echo "- stop-devenv Stops the development oriented docker compose service."
@ -263,9 +306,9 @@ function usage {
echo "- build-docs-bundle Build docs bundle."
echo ""
echo "- build-docker-images Build all docker images (frontend, backend and exporter)."
echo "- build-frontend-docker-images Build frontend docker images."
echo "- build-backend-docker-images Build backend docker images."
echo "- build-exporter-docker-images Build exporter docker images."
echo "- build-frontend-docker-image Build frontend docker images."
echo "- build-backend-docker-image Build backend docker images."
echo "- build-exporter-docker-image Build exporter docker images."
echo ""
echo "- version Show penpot's version."
}
@ -281,11 +324,8 @@ case $1 in
;;
build-devenv)
build-devenv ${@:2}
;;
build-devenv-local)
build-devenv-local ${@:2}
shift;
build-devenv $@;
;;
create-devenv)
@ -339,25 +379,30 @@ case $1 in
build-docs-bundle;
;;
build-imagemagick-docker-image)
shift;
build-imagemagick-docker-image $@;
;;
build-docker-images)
build-frontend-docker-images
build-backend-docker-images
build-exporter-docker-images
build-frontend-docker-image
build-backend-docker-image
build-exporter-docker-image
;;
build-frontend-docker-images)
build-frontend-docker-images
build-frontend-docker-image)
build-frontend-docker-image
;;
build-backend-docker-images)
build-backend-docker-images
build-backend-docker-image)
build-backend-docker-image
;;
build-exporter-docker-images)
build-exporter-docker-images
build-exporter-docker-image)
build-exporter-docker-image
;;
*)
usage
;;
esac
esac