mirror of
https://github.com/penpot/penpot.git
synced 2026-08-01 10:56:20 +00:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
commit
54d76123d0
@ -68,6 +68,8 @@
|
|||||||
- Fix problem when changing between flex/grid layout [Taiga #11625](https://tree.taiga.io/project/penpot/issue/11625)
|
- Fix problem when changing between flex/grid layout [Taiga #11625](https://tree.taiga.io/project/penpot/issue/11625)
|
||||||
- Fix opacity on stroke gradients [Taiga #11646](https://tree.taiga.io/project/penpot/issue/11646)
|
- Fix opacity on stroke gradients [Taiga #11646](https://tree.taiga.io/project/penpot/issue/11646)
|
||||||
- Fix change from gradient to solid color [Taiga #11648](https://tree.taiga.io/project/penpot/issue/11648)
|
- Fix change from gradient to solid color [Taiga #11648](https://tree.taiga.io/project/penpot/issue/11648)
|
||||||
|
- Fix the context menu always closes after any action [Taiga #11624](https://tree.taiga.io/project/penpot/issue/11624)
|
||||||
|
- Fix font selector highlight inconsistency when using keyboard navigation [Taiga #11668](https://tree.taiga.io/project/penpot/issue/11668)
|
||||||
|
|
||||||
## 2.8.1 (Unreleased)
|
## 2.8.1 (Unreleased)
|
||||||
|
|
||||||
@ -75,6 +77,7 @@
|
|||||||
|
|
||||||
- Fix unexpected exception on processing old texts [Github #6889](https://github.com/penpot/penpot/pull/6889)
|
- Fix unexpected exception on processing old texts [Github #6889](https://github.com/penpot/penpot/pull/6889)
|
||||||
- Fix UI theme selection from main menu [Taiga #11567](https://tree.taiga.io/project/penpot/issue/11567)
|
- Fix UI theme selection from main menu [Taiga #11567](https://tree.taiga.io/project/penpot/issue/11567)
|
||||||
|
- Add missing migration information to file snapshots [Github #686](https://github.com/penpot/penpot/pull/6864)
|
||||||
|
|
||||||
## 2.8.0
|
## 2.8.0
|
||||||
|
|
||||||
|
|||||||
@ -10,18 +10,19 @@
|
|||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
[app.util.time :as dt]))
|
[app.util.time :as dt]))
|
||||||
|
|
||||||
|
(def ^:private canceled-status
|
||||||
|
#{"canceled" "unpaid"})
|
||||||
|
|
||||||
(defn get-deletion-delay
|
(defn get-deletion-delay
|
||||||
"Calculate the next deleted-at for a resource (file, team, etc) in function
|
"Calculate the next deleted-at for a resource (file, team, etc) in function
|
||||||
of team settings"
|
of team settings"
|
||||||
[team]
|
[team]
|
||||||
(if-let [subscription (get team :subscription)]
|
(if-let [{:keys [type status]} (get team :subscription)]
|
||||||
(cond
|
(cond
|
||||||
(and (= (:type subscription) "unlimited")
|
(and (= "unlimited" type) (not (contains? canceled-status status)))
|
||||||
(= (:status subscription) "active"))
|
|
||||||
(dt/duration {:days 30})
|
(dt/duration {:days 30})
|
||||||
|
|
||||||
(and (= (:type subscription) "enterprise")
|
(and (= "enterprise" type) (not (contains? canceled-status status)))
|
||||||
(= (:status subscription) "active"))
|
|
||||||
(dt/duration {:days 90})
|
(dt/duration {:days 90})
|
||||||
|
|
||||||
:else
|
:else
|
||||||
|
|||||||
@ -438,7 +438,10 @@
|
|||||||
:fn (mg/resource "app/migrations/sql/0138-mod-file-data-fragment-table.sql")}
|
:fn (mg/resource "app/migrations/sql/0138-mod-file-data-fragment-table.sql")}
|
||||||
|
|
||||||
{:name "0139-mod-file-change-table.sql"
|
{:name "0139-mod-file-change-table.sql"
|
||||||
:fn (mg/resource "app/migrations/sql/0139-mod-file-change-table.sql")}])
|
:fn (mg/resource "app/migrations/sql/0139-mod-file-change-table.sql")}
|
||||||
|
|
||||||
|
{:name "0140-mod-file-change-table.sql"
|
||||||
|
:fn (mg/resource "app/migrations/sql/0140-mod-file-change-table.sql")}])
|
||||||
|
|
||||||
(defn apply-migrations!
|
(defn apply-migrations!
|
||||||
[pool name migrations]
|
[pool name migrations]
|
||||||
|
|||||||
@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE file_change
|
||||||
|
ADD COLUMN migrations text[];
|
||||||
@ -8,6 +8,7 @@
|
|||||||
(:require
|
(:require
|
||||||
[app.binfile.common :as bfc]
|
[app.binfile.common :as bfc]
|
||||||
[app.common.exceptions :as ex]
|
[app.common.exceptions :as ex]
|
||||||
|
[app.common.files.migrations :as fmg]
|
||||||
[app.common.logging :as l]
|
[app.common.logging :as l]
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
@ -15,6 +16,7 @@
|
|||||||
[app.db :as db]
|
[app.db :as db]
|
||||||
[app.db.sql :as-alias sql]
|
[app.db.sql :as-alias sql]
|
||||||
[app.features.fdata :as feat.fdata]
|
[app.features.fdata :as feat.fdata]
|
||||||
|
[app.features.file-migrations :refer [reset-migrations!]]
|
||||||
[app.main :as-alias main]
|
[app.main :as-alias main]
|
||||||
[app.msgbus :as mbus]
|
[app.msgbus :as mbus]
|
||||||
[app.rpc :as-alias rpc]
|
[app.rpc :as-alias rpc]
|
||||||
@ -27,6 +29,13 @@
|
|||||||
[app.util.time :as dt]
|
[app.util.time :as dt]
|
||||||
[cuerdas.core :as str]))
|
[cuerdas.core :as str]))
|
||||||
|
|
||||||
|
(defn decode-row
|
||||||
|
[{:keys [migrations] :as row}]
|
||||||
|
(when row
|
||||||
|
(cond-> row
|
||||||
|
(some? migrations)
|
||||||
|
(assoc :migrations (db/decode-pgarray migrations)))))
|
||||||
|
|
||||||
(def sql:get-file-snapshots
|
(def sql:get-file-snapshots
|
||||||
"WITH changes AS (
|
"WITH changes AS (
|
||||||
SELECT id, label, revn, created_at, created_by, profile_id
|
SELECT id, label, revn, created_at, created_by, profile_id
|
||||||
@ -74,10 +83,7 @@
|
|||||||
(assert (#{:system :user :admin} created-by)
|
(assert (#{:system :user :admin} created-by)
|
||||||
"expected valid keyword for created-by")
|
"expected valid keyword for created-by")
|
||||||
|
|
||||||
(let [conn
|
(let [created-by
|
||||||
(db/get-connection cfg)
|
|
||||||
|
|
||||||
created-by
|
|
||||||
(name created-by)
|
(name created-by)
|
||||||
|
|
||||||
deleted-at
|
deleted-at
|
||||||
@ -101,12 +107,15 @@
|
|||||||
(blob/encode (:data file))
|
(blob/encode (:data file))
|
||||||
|
|
||||||
features
|
features
|
||||||
(db/encode-pgarray (:features file) conn "text")]
|
(into-array (:features file))
|
||||||
|
|
||||||
(l/debug :hint "creating file snapshot"
|
migrations
|
||||||
:file-id (str (:id file))
|
(into-array (:migrations file))]
|
||||||
:id (str snapshot-id)
|
|
||||||
:label label)
|
(l/dbg :hint "creating file snapshot"
|
||||||
|
:file-id (str (:id file))
|
||||||
|
:id (str snapshot-id)
|
||||||
|
:label label)
|
||||||
|
|
||||||
(db/insert! cfg :file-change
|
(db/insert! cfg :file-change
|
||||||
{:id snapshot-id
|
{:id snapshot-id
|
||||||
@ -114,6 +123,7 @@
|
|||||||
:data data
|
:data data
|
||||||
:version (:version file)
|
:version (:version file)
|
||||||
:features features
|
:features features
|
||||||
|
:migrations migrations
|
||||||
:profile-id profile-id
|
:profile-id profile-id
|
||||||
:file-id (:id file)
|
:file-id (:id file)
|
||||||
:label label
|
:label label
|
||||||
@ -159,7 +169,17 @@
|
|||||||
{:file-id file-id
|
{:file-id file-id
|
||||||
:id snapshot-id}
|
:id snapshot-id}
|
||||||
{::db/for-share true})
|
{::db/for-share true})
|
||||||
(feat.fdata/resolve-file-data cfg))]
|
(feat.fdata/resolve-file-data cfg)
|
||||||
|
(decode-row))
|
||||||
|
|
||||||
|
;; If snapshot has tracked applied migrations, we reuse them,
|
||||||
|
;; if not we take a safest set of migrations as starting
|
||||||
|
;; point. This is because, at the time of implementing
|
||||||
|
;; snapshots, migrations were not taken into account so we
|
||||||
|
;; need to make this backward compatible in some way.
|
||||||
|
file (assoc file :migrations
|
||||||
|
(or (:migrations snapshot)
|
||||||
|
(fmg/generate-migrations-from-version 67)))]
|
||||||
|
|
||||||
(when-not snapshot
|
(when-not snapshot
|
||||||
(ex/raise :type :not-found
|
(ex/raise :type :not-found
|
||||||
@ -180,12 +200,16 @@
|
|||||||
:label (:label snapshot)
|
:label (:label snapshot)
|
||||||
:snapshot-id (str (:id snapshot)))
|
:snapshot-id (str (:id snapshot)))
|
||||||
|
|
||||||
;; If the file was already offloaded, on restring the snapshot
|
;; If the file was already offloaded, on restoring the snapshot we
|
||||||
;; we are going to replace the file data, so we need to touch
|
;; are going to replace the file data, so we need to touch the old
|
||||||
;; the old referenced storage object and avoid possible leaks
|
;; referenced storage object and avoid possible leaks
|
||||||
(when (feat.fdata/offloaded? file)
|
(when (feat.fdata/offloaded? file)
|
||||||
(sto/touch-object! storage (:data-ref-id file)))
|
(sto/touch-object! storage (:data-ref-id file)))
|
||||||
|
|
||||||
|
;; In the same way, on reseting the file data, we need to restore
|
||||||
|
;; the applied migrations on the moment of taking the snapshot
|
||||||
|
(reset-migrations! conn file)
|
||||||
|
|
||||||
(db/update! conn :file
|
(db/update! conn :file
|
||||||
{:data (:data snapshot)
|
{:data (:data snapshot)
|
||||||
:revn (inc (:revn file))
|
:revn (inc (:revn file))
|
||||||
@ -253,7 +277,7 @@
|
|||||||
:deleted-at nil}
|
:deleted-at nil}
|
||||||
{:id snapshot-id}
|
{:id snapshot-id}
|
||||||
{::db/return-keys true})
|
{::db/return-keys true})
|
||||||
(dissoc :data :features)))
|
(dissoc :data :features :migrations)))
|
||||||
|
|
||||||
(defn- get-snapshot
|
(defn- get-snapshot
|
||||||
"Get a minimal snapshot from database and lock for update"
|
"Get a minimal snapshot from database and lock for update"
|
||||||
|
|||||||
@ -80,7 +80,7 @@
|
|||||||
(update :migrations set/union diff)
|
(update :migrations set/union diff)
|
||||||
(vary-meta assoc ::migrated (not-empty diff)))))
|
(vary-meta assoc ::migrated (not-empty diff)))))
|
||||||
|
|
||||||
(defn- generate-migrations-from-version
|
(defn generate-migrations-from-version
|
||||||
"A function that generates new format migration from the old,
|
"A function that generates new format migration from the old,
|
||||||
version based migration system"
|
version based migration system"
|
||||||
[version]
|
[version]
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
[app.common.files.helpers :as cfh]
|
[app.common.files.helpers :as cfh]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.logic.variant-properties :as clvp]
|
[app.common.logic.variant-properties :as clvp]
|
||||||
|
[app.common.text :as ct]
|
||||||
[app.common.types.component :as ctk]
|
[app.common.types.component :as ctk]
|
||||||
[app.common.types.container :as ctn]
|
[app.common.types.container :as ctn]
|
||||||
[app.common.types.pages-list :as ctpl]
|
[app.common.types.pages-list :as ctpl]
|
||||||
|
|||||||
@ -125,7 +125,7 @@ RUN set -ex; \
|
|||||||
|
|
||||||
COPY --from=build /opt/jre /opt/jre
|
COPY --from=build /opt/jre /opt/jre
|
||||||
COPY --from=build /opt/node /opt/node
|
COPY --from=build /opt/node /opt/node
|
||||||
COPY --from=penpotapp/imagemagick:7.1.1-47 /opt/imagick /opt/imagick
|
COPY --from=penpotapp/imagemagick:7.1.2-0 /opt/imagick /opt/imagick
|
||||||
COPY --chown=penpot:penpot ./bundle-backend/ /opt/penpot/backend/
|
COPY --chown=penpot:penpot ./bundle-backend/ /opt/penpot/backend/
|
||||||
|
|
||||||
USER penpot:penpot
|
USER penpot:penpot
|
||||||
|
|||||||
@ -205,6 +205,10 @@ title: 10· Design Tokens
|
|||||||
<h4>Y Position (dimension)</h4>
|
<h4>Y Position (dimension)</h4>
|
||||||
<p>The Y property specifies the position of the element on the Y axis of the canvas.</p>
|
<p>The Y property specifies the position of the element on the Y axis of the canvas.</p>
|
||||||
|
|
||||||
|
<h3 id="design-tokens-font-size">Font Size</h3>
|
||||||
|
<p>Font size tokens allow you to define and standardize font-size values across your design system. These tokens can be applied to the <strong>font-size</strong> property in text layers, ensuring consistent typography throughout your designs.</p>
|
||||||
|
<p class="advice">Font size token values are always computed as <strong>px</strong> (pixels).</p>
|
||||||
|
|
||||||
<h3 id="design-tokens-opacity">Opacity</h3>
|
<h3 id="design-tokens-opacity">Opacity</h3>
|
||||||
<p>Opacity tokens allow you to define the opacity of a layer, ranging from fully opaque to fully transparent.</p>
|
<p>Opacity tokens allow you to define the opacity of a layer, ranging from fully opaque to fully transparent.</p>
|
||||||
<p>Opacity tokens can be applied to any design element that supports transparency. You can use any decimal value between 0 and 1 to set varying levels of opacity or you can use any value between 0 and 100 with <strong>`%`</strong> sign at the end of the value. For example, you can use <strong>45%</strong> which would resolve to <strong>.45</strong>.</p>
|
<p>Opacity tokens can be applied to any design element that supports transparency. You can use any decimal value between 0 and 1 to set varying levels of opacity or you can use any value between 0 and 100 with <strong>`%`</strong> sign at the end of the value. For example, you can use <strong>45%</strong> which would resolve to <strong>.45</strong>.</p>
|
||||||
@ -378,7 +382,15 @@ title: 10· Design Tokens
|
|||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<h3 id="design-tokens-import-options">Import Options</h3>
|
<h3 id="design-tokens-import-options">Import Options</h3>
|
||||||
<h4>Single file</h4>
|
|
||||||
|
<h4>ZIP file</h4>
|
||||||
|
<p>You can import tokens from a <strong>.zip</strong> file. This file can either contain a single JSON file or a folder structure with multiple files. The ZIP import option provides flexibility for organizing your tokens before importing them into Penpot.</p>
|
||||||
|
<ul>
|
||||||
|
<li>If the ZIP contains a single JSON file, it will be imported as a single set of tokens.</li>
|
||||||
|
<li>If the ZIP contains a folder structure, each file and folder will be interpreted as separate token sets, following the same rules as the multifile import.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h4>Single JSON file</h4>
|
||||||
|
|
||||||
<p>You can import a JSON file comprising all tokens, token sets and token themes.</p>
|
<p>You can import a JSON file comprising all tokens, token sets and token themes.</p>
|
||||||
<p>When importing a single file, the first-level keys of the json file will be interpreted as the set name.</p>
|
<p>When importing a single file, the first-level keys of the json file will be interpreted as the set name.</p>
|
||||||
|
|||||||
@ -34,7 +34,13 @@ desc: Master layer basics with Penpot's user guide! Learn to create, manipulate,
|
|||||||
<p>Layers are displayed from the bottom to the top of the layer stack, with layers above on the stack being shown on top in the image.</p>
|
<p>Layers are displayed from the bottom to the top of the layer stack, with layers above on the stack being shown on top in the image.</p>
|
||||||
|
|
||||||
<h2 id="hide-lock">Hide and lock layers</h2>
|
<h2 id="hide-lock">Hide and lock layers</h2>
|
||||||
<p>Click on the eye icon to change the visibility of a layer. Click on the lock icon to lock or unlock a layer. A locked layer can not be modified.</p>
|
|
||||||
|
<h3>Hide and show layers</h3>
|
||||||
|
<p>You can control the visibility of any layer by clicking the eye icon next to it in the Layers panel. When a layer is hidden, it will not appear on the canvas, but you can still select it in the Layers panel, move its order, or modify its properties. The eye icon always indicates whether a layer is visible or hidden, making it easy to manage complex designs.</p>
|
||||||
|
|
||||||
|
<h3>Lock and unlock layers</h3>
|
||||||
|
<p>Locking a layer helps prevent accidental changes or movement on the canvas. When a layer is locked, it cannot be moved or edited directly in the canvas area. However, you can still select a locked layer in the Layers panel and adjust its properties, such as color, effects, or name. The lock icon next to the layer’s name shows its locked status, helping you keep your design organized and protected.</p>
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<video title="Layers hide and lock" muted="" playsinline="" controls="" width="auto" poster="/img/layers/layers-hide-lock.webp" height="auto">
|
<video title="Layers hide and lock" muted="" playsinline="" controls="" width="auto" poster="/img/layers/layers-hide-lock.webp" height="auto">
|
||||||
<source src="/img/layers/layers-hide-lock.mp4" type="video/mp4">
|
<source src="/img/layers/layers-hide-lock.mp4" type="video/mp4">
|
||||||
|
|||||||
@ -142,6 +142,11 @@ a design.</p>
|
|||||||
<source src="/img/objects/text-create.mp4" type="video/mp4">
|
<source src="/img/objects/text-create.mp4" type="video/mp4">
|
||||||
</video>
|
</video>
|
||||||
</figure>
|
</figure>
|
||||||
|
<p><strong>Tips for resizing</strong></p>
|
||||||
|
<ul>
|
||||||
|
<li>Double-click on the right side of the bounding box to set the resize setting to auto-width.</li>
|
||||||
|
<li>Double-click on the bottom side of the bounding box to set the resize setting to auto-height.</li>
|
||||||
|
</ul>
|
||||||
<h3>Edit and style text content</h3>
|
<h3>Edit and style text content</h3>
|
||||||
<p>Press <kbd>Enter</kbd> with a text layer selected to start editing the text content. You can style parts of the text content as rich text.</p>
|
<p>Press <kbd>Enter</kbd> with a text layer selected to start editing the text content. You can style parts of the text content as rich text.</p>
|
||||||
<figure>
|
<figure>
|
||||||
|
|||||||
@ -1098,15 +1098,24 @@
|
|||||||
(when (seq (:redo-changes changes))
|
(when (seq (:redo-changes changes))
|
||||||
(rx/of (dch/commit-changes changes)))
|
(rx/of (dch/commit-changes changes)))
|
||||||
(when-not (empty? updated-frames)
|
(when-not (empty? updated-frames)
|
||||||
(rx/merge
|
(let [frames-by-page (->> updated-frames
|
||||||
(rx/of (ptk/data-event :layout/update {:ids (map :id updated-frames) :undo-group undo-group}))
|
(group-by :page-id))]
|
||||||
(->> (rx/from updated-frames)
|
(rx/merge
|
||||||
(rx/mapcat
|
;; Emit one layout/update event for each page
|
||||||
(fn [shape]
|
(rx/from
|
||||||
(rx/of
|
(map (fn [[page-id frames]]
|
||||||
(dwt/clear-thumbnail file-id (:page-id shape) (:id shape) "frame")
|
(ptk/data-event :layout/update
|
||||||
(when-not (= (:frame-id shape) uuid/zero)
|
{:page-id page-id
|
||||||
(dwt/clear-thumbnail file-id (:page-id shape) (:frame-id shape) "frame"))))))))
|
:ids (map :id frames)
|
||||||
|
:undo-group undo-group}))
|
||||||
|
frames-by-page))
|
||||||
|
(->> (rx/from updated-frames)
|
||||||
|
(rx/mapcat
|
||||||
|
(fn [shape]
|
||||||
|
(rx/of
|
||||||
|
(dwt/clear-thumbnail file-id (:page-id shape) (:id shape) "frame")
|
||||||
|
(when-not (= (:frame-id shape) uuid/zero)
|
||||||
|
(dwt/clear-thumbnail file-id (:page-id shape) (:frame-id shape) "frame")))))))))
|
||||||
|
|
||||||
(when (not= file-id library-id)
|
(when (not= file-id library-id)
|
||||||
;; When we have just updated the library file, give some time for the
|
;; When we have just updated the library file, give some time for the
|
||||||
|
|||||||
@ -131,11 +131,12 @@
|
|||||||
;; they are process together. It will get a better performance.
|
;; they are process together. It will get a better performance.
|
||||||
(rx/buffer-time 100)
|
(rx/buffer-time 100)
|
||||||
(rx/filter #(d/not-empty? %))
|
(rx/filter #(d/not-empty? %))
|
||||||
(rx/map
|
(rx/mapcat
|
||||||
(fn [data]
|
(fn [data]
|
||||||
(let [page-id (->> data (keep :page-id) first)
|
(->> (group-by :page-id data)
|
||||||
ids (reduce #(into %1 (:ids %2)) #{} data)]
|
(map (fn [[page-id items]]
|
||||||
(update-layout-positions {:page-id page-id :ids ids}))))
|
(let [ids (reduce #(into %1 (:ids %2)) #{} items)]
|
||||||
|
(update-layout-positions {:page-id page-id :ids ids})))))))
|
||||||
(rx/take-until stopper))))))
|
(rx/take-until stopper))))))
|
||||||
|
|
||||||
(defn finalize-shape-layout
|
(defn finalize-shape-layout
|
||||||
|
|||||||
@ -304,7 +304,6 @@
|
|||||||
(when (string? value)
|
(when (string? value)
|
||||||
(generate-text-shape-update {:text-transform value} shape-ids page-id))))
|
(generate-text-shape-update {:text-transform value} shape-ids page-id))))
|
||||||
|
|
||||||
|
|
||||||
;; Events to apply / unapply tokens to shapes ------------------------------------------------------------
|
;; Events to apply / unapply tokens to shapes ------------------------------------------------------------
|
||||||
|
|
||||||
(defn apply-token
|
(defn apply-token
|
||||||
|
|||||||
@ -75,7 +75,7 @@
|
|||||||
[:> cta-power-up*
|
[:> cta-power-up*
|
||||||
{:top-title (tr "subscription.dashboard.power-up.your-subscription")
|
{:top-title (tr "subscription.dashboard.power-up.your-subscription")
|
||||||
:top-description (tr "subscription.dashboard.power-up.unlimited-plan")
|
:top-description (tr "subscription.dashboard.power-up.unlimited-plan")
|
||||||
:bottom-description (tr "subscription.dashboard.power-up.unlimited.bottom", subscription-href)
|
:bottom-description (tr "subscription.dashboard.power-up.unlimited.bottom-text", subscription-href)
|
||||||
:has-dropdown true}])
|
:has-dropdown true}])
|
||||||
|
|
||||||
"enterprise"
|
"enterprise"
|
||||||
|
|||||||
@ -365,17 +365,17 @@
|
|||||||
[:> plan-card* {:card-title (tr "subscription.settings.enterprise-trial")
|
[:> plan-card* {:card-title (tr "subscription.settings.enterprise-trial")
|
||||||
:card-title-icon i/character-e
|
:card-title-icon i/character-e
|
||||||
:benefits-title (tr "subscription.settings.benefits.all-professional-benefits")
|
:benefits-title (tr "subscription.settings.benefits.all-professional-benefits")
|
||||||
:benefits [(tr "subscription.settings.enterprise.security"),
|
:benefits [(tr "subscription.settings.enterprise.unlimited-storage"),
|
||||||
(tr "subscription.settings.enterprise.capped-bill"),
|
(tr "subscription.settings.enterprise.capped-bill"),
|
||||||
(tr "subscription.settings.enterprise.unlimited-storage")]
|
(tr "subscription.settings.enterprise.autosave")]
|
||||||
:cta-text (tr "subscription.settings.manage-your-subscription")
|
:cta-text (tr "subscription.settings.manage-your-subscription")
|
||||||
:cta-link go-to-payments}]
|
:cta-link go-to-payments}]
|
||||||
[:> plan-card* {:card-title (tr "subscription.settings.enterprise")
|
[:> plan-card* {:card-title (tr "subscription.settings.enterprise")
|
||||||
:card-title-icon i/character-e
|
:card-title-icon i/character-e
|
||||||
:benefits-title (tr "subscription.settings.benefits.all-professional-benefits")
|
:benefits-title (tr "subscription.settings.benefits.all-professional-benefits")
|
||||||
:benefits [(tr "subscription.settings.enterprise.security"),
|
:benefits [(tr "subscription.settings.enterprise.unlimited-storage"),
|
||||||
(tr "subscription.settings.enterprise.capped-bill"),
|
(tr "subscription.settings.enterprise.capped-bill"),
|
||||||
(tr "subscription.settings.enterprise.unlimited-storage")]
|
(tr "subscription.settings.enterprise.autosave")]
|
||||||
:cta-text (tr "subscription.settings.manage-your-subscription")
|
:cta-text (tr "subscription.settings.manage-your-subscription")
|
||||||
:cta-link go-to-payments}]))
|
:cta-link go-to-payments}]))
|
||||||
|
|
||||||
@ -425,9 +425,9 @@
|
|||||||
:price-value "$950"
|
:price-value "$950"
|
||||||
:price-period (tr "subscription.settings.price-organization-month")
|
:price-period (tr "subscription.settings.price-organization-month")
|
||||||
:benefits-title (tr "subscription.settings.benefits.all-unlimited-benefits")
|
:benefits-title (tr "subscription.settings.benefits.all-unlimited-benefits")
|
||||||
:benefits [(tr "subscription.settings.enterprise.security"),
|
:benefits [(tr "subscription.settings.enterprise.unlimited-storage"),
|
||||||
(tr "subscription.settings.enterprise.capped-bill"),
|
(tr "subscription.settings.enterprise.capped-bill"),
|
||||||
(tr "subscription.settings.enterprise.unlimited-storage")]
|
(tr "subscription.settings.enterprise.autosave")]
|
||||||
:cta-text (if subscription (tr "subscription.settings.subscribe") (tr "subscription.settings.try-it-free"))
|
:cta-text (if subscription (tr "subscription.settings.subscribe") (tr "subscription.settings.try-it-free"))
|
||||||
:cta-link #(open-subscription-modal "enterprise" subscription)
|
:cta-link #(open-subscription-modal "enterprise" subscription)
|
||||||
:cta-text-with-icon (tr "subscription.settings.more-information")
|
:cta-text-with-icon (tr "subscription.settings.more-information")
|
||||||
|
|||||||
@ -275,10 +275,8 @@
|
|||||||
|
|
||||||
handle-gradient-remove-stop
|
handle-gradient-remove-stop
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps state)
|
|
||||||
(fn [index]
|
(fn [index]
|
||||||
(when (> (count (:stops state)) 2)
|
(st/emit! (dc/remove-gradient-stop index))))
|
||||||
(st/emit! (dc/remove-gradient-stop index)))))
|
|
||||||
|
|
||||||
handle-stop-edit-start
|
handle-stop-edit-start
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
|||||||
@ -59,6 +59,14 @@
|
|||||||
on-unmount children is-selected icon disabled value]}]
|
on-unmount children is-selected icon disabled value]}]
|
||||||
(let [submenu-ref (mf/use-ref nil)
|
(let [submenu-ref (mf/use-ref nil)
|
||||||
hovering? (mf/use-ref false)
|
hovering? (mf/use-ref false)
|
||||||
|
|
||||||
|
on-click'
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps on-click)
|
||||||
|
(fn [event]
|
||||||
|
(st/emit! dw/hide-context-menu)
|
||||||
|
(when on-click (on-click event))))
|
||||||
|
|
||||||
on-pointer-enter
|
on-pointer-enter
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn []
|
(fn []
|
||||||
@ -96,7 +104,7 @@
|
|||||||
:disabled disabled
|
:disabled disabled
|
||||||
:data-value value
|
:data-value value
|
||||||
:ref set-dom-node
|
:ref set-dom-node
|
||||||
:on-click on-click
|
:on-click on-click'
|
||||||
:on-pointer-enter on-pointer-enter
|
:on-pointer-enter on-pointer-enter
|
||||||
:on-pointer-leave on-pointer-leave}
|
:on-pointer-leave on-pointer-leave}
|
||||||
[:span
|
[:span
|
||||||
@ -110,7 +118,7 @@
|
|||||||
:disabled disabled
|
:disabled disabled
|
||||||
:ref set-dom-node
|
:ref set-dom-node
|
||||||
:data-value value
|
:data-value value
|
||||||
:on-click on-click
|
:on-click on-click'
|
||||||
:on-pointer-enter on-pointer-enter
|
:on-pointer-enter on-pointer-enter
|
||||||
:on-pointer-leave on-pointer-leave}
|
:on-pointer-leave on-pointer-leave}
|
||||||
[:span {:class (stl/css :title)} title]
|
[:span {:class (stl/css :title)} title]
|
||||||
|
|||||||
@ -41,25 +41,9 @@
|
|||||||
""
|
""
|
||||||
(ust/format-precision value 2)))
|
(ust/format-precision value 2)))
|
||||||
|
|
||||||
(defn- get-next-font
|
|
||||||
[{:keys [id] :as current} fonts]
|
|
||||||
(if (seq fonts)
|
|
||||||
(let [index (d/index-of-pred fonts #(= (:id %) id))
|
|
||||||
index (or index -1)
|
|
||||||
next (ex/ignoring (nth fonts (inc index)))]
|
|
||||||
(or next (first fonts)))
|
|
||||||
current))
|
|
||||||
|
|
||||||
(defn- get-prev-font
|
|
||||||
[{:keys [id] :as current} fonts]
|
|
||||||
(if (seq fonts)
|
|
||||||
(let [index (d/index-of-pred fonts #(= (:id %) id))
|
|
||||||
next (ex/ignoring (nth fonts (dec index)))]
|
|
||||||
(or next (peek fonts)))
|
|
||||||
current))
|
|
||||||
|
|
||||||
(mf/defc font-item*
|
(mf/defc font-item*
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]
|
||||||
|
::mf/private true}
|
||||||
[{:keys [font is-current on-click style]}]
|
[{:keys [font is-current on-click style]}]
|
||||||
(let [item-ref (mf/use-ref)
|
(let [item-ref (mf/use-ref)
|
||||||
on-click (mf/use-fn (mf/deps font) #(on-click font))]
|
on-click (mf/use-fn (mf/deps font) #(on-click font))]
|
||||||
@ -83,7 +67,7 @@
|
|||||||
|
|
||||||
(declare row-renderer)
|
(declare row-renderer)
|
||||||
|
|
||||||
(defn filter-fonts
|
(defn- filter-fonts
|
||||||
[{:keys [term backends]} fonts]
|
[{:keys [term backends]} fonts]
|
||||||
(let [term (str/lower term)
|
(let [term (str/lower term)
|
||||||
xform (cond-> (map identity)
|
xform (cond-> (map identity)
|
||||||
@ -96,8 +80,7 @@
|
|||||||
|
|
||||||
(mf/defc font-selector*
|
(mf/defc font-selector*
|
||||||
[{:keys [on-select on-close current-font show-recent full-size]}]
|
[{:keys [on-select on-close current-font show-recent full-size]}]
|
||||||
(let [selected (mf/use-state current-font)
|
(let [state* (mf/use-state
|
||||||
state* (mf/use-state
|
|
||||||
#(do {:term "" :backends #{}}))
|
#(do {:term "" :backends #{}}))
|
||||||
state (deref state*)
|
state (deref state*)
|
||||||
|
|
||||||
@ -112,23 +95,41 @@
|
|||||||
recent-fonts (mf/with-memo [state recent-fonts]
|
recent-fonts (mf/with-memo [state recent-fonts]
|
||||||
(filter-fonts state recent-fonts))
|
(filter-fonts state recent-fonts))
|
||||||
|
|
||||||
full-size? (boolean (and full-size show-recent))
|
;; Combine recent fonts with filtered fonts, avoiding duplicates
|
||||||
|
combined-fonts
|
||||||
|
(mf/with-memo [recent-fonts fonts]
|
||||||
|
(let [recent-ids (into #{} d/xf:map-id recent-fonts)]
|
||||||
|
(into recent-fonts (remove #(contains? recent-ids (:id %))) fonts)))
|
||||||
|
|
||||||
|
;; Initialize selected with current font index
|
||||||
|
selected-index
|
||||||
|
(mf/use-state
|
||||||
|
(fn []
|
||||||
|
(or (some (fn [[idx font]]
|
||||||
|
(when (= (:id current-font) (:id font)) idx))
|
||||||
|
(map-indexed vector combined-fonts))
|
||||||
|
0)))
|
||||||
|
|
||||||
|
full-size?
|
||||||
|
(boolean (and full-size show-recent))
|
||||||
|
|
||||||
select-next
|
select-next
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps fonts)
|
(mf/deps combined-fonts)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(swap! selected get-next-font fonts)))
|
(let [next-idx (mod (inc @selected-index) (count combined-fonts))]
|
||||||
|
(reset! selected-index next-idx))))
|
||||||
|
|
||||||
select-prev
|
select-prev
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps fonts)
|
(mf/deps combined-fonts)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(swap! selected get-prev-font fonts)))
|
(let [prev-idx (mod (dec @selected-index) (count combined-fonts))]
|
||||||
|
(reset! selected-index prev-idx))))
|
||||||
|
|
||||||
on-select-and-close
|
on-select-and-close
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
@ -139,35 +140,32 @@
|
|||||||
|
|
||||||
on-key-down
|
on-key-down
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps fonts)
|
(mf/deps combined-fonts)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(cond
|
(cond
|
||||||
(kbd/up-arrow? event) (select-prev event)
|
(kbd/up-arrow? event) (select-prev event)
|
||||||
(kbd/down-arrow? event) (select-next event)
|
(kbd/down-arrow? event) (select-next event)
|
||||||
(kbd/esc? event) (on-close)
|
(kbd/esc? event) (on-close)
|
||||||
(kbd/enter? event) (do (on-select-and-close @selected))
|
(kbd/enter? event) (do
|
||||||
|
(let [selected-font (nth combined-fonts @selected-index)]
|
||||||
|
(on-select-and-close selected-font)))
|
||||||
:else (dom/focus! (mf/ref-val input)))))
|
:else (dom/focus! (mf/ref-val input)))))
|
||||||
|
|
||||||
on-filter-change
|
on-filter-change
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(swap! state* assoc :term event)))
|
(swap! state* assoc :term event)
|
||||||
|
;; Reset selection to first item when filter changes
|
||||||
on-select-and-close
|
(reset! selected-index 0)))]
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps on-select on-close)
|
|
||||||
(fn [font]
|
|
||||||
(on-select font)
|
|
||||||
(on-close)))]
|
|
||||||
|
|
||||||
(mf/with-effect [fonts]
|
(mf/with-effect [fonts]
|
||||||
(let [key (events/listen js/document "keydown" on-key-down)]
|
(let [key (events/listen js/document "keydown" on-key-down)]
|
||||||
#(events/unlistenByKey key)))
|
#(events/unlistenByKey key)))
|
||||||
|
|
||||||
(mf/with-effect [@selected]
|
(mf/with-effect [@selected-index]
|
||||||
(when-let [inst (mf/ref-val flist)]
|
(when-let [inst (mf/ref-val flist)]
|
||||||
(when-let [index (:index @selected)]
|
(when (and (>= @selected-index 0) (< @selected-index (count combined-fonts)))
|
||||||
(.scrollToRow ^js inst index))))
|
(.scrollToRow ^js inst @selected-index))))
|
||||||
|
|
||||||
(mf/with-effect []
|
(mf/with-effect []
|
||||||
(st/emit! (dsc/push-shortcuts :typography {}))
|
(st/emit! (dsc/push-shortcuts :typography {}))
|
||||||
@ -175,15 +173,12 @@
|
|||||||
(st/emit! (dsc/pop-shortcuts :typography))))
|
(st/emit! (dsc/pop-shortcuts :typography))))
|
||||||
|
|
||||||
(mf/with-effect []
|
(mf/with-effect []
|
||||||
(let [index (d/index-of-pred fonts #(= (:id %) (:id current-font)))
|
(let [index (d/index-of-pred combined-fonts #(= (:id %) (:id current-font)))
|
||||||
inst (mf/ref-val flist)]
|
inst (mf/ref-val flist)]
|
||||||
(tm/schedule
|
(when (and index (>= index 0))
|
||||||
#(let [offset (.getOffsetForRow ^js inst #js {:alignment "center" :index index})]
|
(tm/schedule
|
||||||
(.scrollToPosition ^js inst offset)))))
|
#(let [offset (.getOffsetForRow ^js inst #js {:alignment "center" :index index})]
|
||||||
|
(.scrollToPosition ^js inst offset))))))
|
||||||
(mf/with-effect [(:term state) fonts]
|
|
||||||
(when (and (seq fonts) (not= (:id @selected) (:id (first fonts))))
|
|
||||||
(reset! selected (first fonts))))
|
|
||||||
|
|
||||||
[:div {:class (stl/css :font-selector)}
|
[:div {:class (stl/css :font-selector)}
|
||||||
[:div {:class (stl/css-case :font-selector-dropdown true :font-selector-dropdown-full-size full-size?)}
|
[:div {:class (stl/css-case :font-selector-dropdown true :font-selector-dropdown-full-size full-size?)}
|
||||||
@ -200,7 +195,7 @@
|
|||||||
:font font
|
:font font
|
||||||
:style {}
|
:style {}
|
||||||
:on-click on-select-and-close
|
:on-click on-select-and-close
|
||||||
:is-current (= (:id font) (:id @selected))}])])]
|
:is-current (= idx @selected-index)}])])]
|
||||||
|
|
||||||
[:div {:class (stl/css-case :fonts-list true
|
[:div {:class (stl/css-case :fonts-list true
|
||||||
:fonts-list-full-size full-size?)}
|
:fonts-list-full-size full-size?)}
|
||||||
@ -208,17 +203,17 @@
|
|||||||
(fn [props]
|
(fn [props]
|
||||||
(let [width (unchecked-get props "width")
|
(let [width (unchecked-get props "width")
|
||||||
height (unchecked-get props "height")
|
height (unchecked-get props "height")
|
||||||
render #(row-renderer fonts @selected on-select-and-close %)]
|
render #(row-renderer combined-fonts @selected-index on-select-and-close %)]
|
||||||
(mf/html
|
(mf/html
|
||||||
[:> rvt/List #js {:height height
|
[:> rvt/List #js {:height height
|
||||||
:ref flist
|
:ref flist
|
||||||
:width width
|
:width width
|
||||||
:rowCount (count fonts)
|
:rowCount (count combined-fonts)
|
||||||
:rowHeight 36
|
:rowHeight 36
|
||||||
:rowRenderer render}])))]]]]))
|
:rowRenderer render}])))]]]]))
|
||||||
|
|
||||||
(defn row-renderer
|
(defn row-renderer
|
||||||
[fonts selected on-select props]
|
[fonts selected-index on-select props]
|
||||||
(let [index (unchecked-get props "index")
|
(let [index (unchecked-get props "index")
|
||||||
key (unchecked-get props "key")
|
key (unchecked-get props "key")
|
||||||
style (unchecked-get props "style")
|
style (unchecked-get props "style")
|
||||||
@ -228,7 +223,7 @@
|
|||||||
:font font
|
:font font
|
||||||
:style style
|
:style style
|
||||||
:on-click on-select
|
:on-click on-select
|
||||||
:is-current (= (:id font) (:id selected))}])))
|
:is-current (= index selected-index)}])))
|
||||||
|
|
||||||
(mf/defc font-options
|
(mf/defc font-options
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap-props false}
|
||||||
|
|||||||
@ -4313,11 +4313,6 @@ msgstr "Please upgrade to match your usage. Contact with the team owner: %s"
|
|||||||
msgid "subscription.dashboard.power-up.enterprise-plan"
|
msgid "subscription.dashboard.power-up.enterprise-plan"
|
||||||
msgstr "Enterprise plan"
|
msgstr "Enterprise plan"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:77
|
|
||||||
#, unused
|
|
||||||
msgid "subscription.dashboard.power-up.enterprise.description"
|
|
||||||
msgstr "Advanced security, activity logs, dedicated support and more."
|
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:60
|
#: src/app/main/ui/dashboard/subscription.cljs:60
|
||||||
#, markdown
|
#, markdown
|
||||||
msgid "subscription.dashboard.power-up.professional.bottom"
|
msgid "subscription.dashboard.power-up.professional.bottom"
|
||||||
@ -4357,9 +4352,9 @@ msgstr "Enterprise plan (trial)"
|
|||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:74
|
#: src/app/main/ui/dashboard/subscription.cljs:74
|
||||||
#, markdown
|
#, markdown
|
||||||
msgid "subscription.dashboard.power-up.unlimited.bottom"
|
msgid "subscription.dashboard.power-up.unlimited.bottom-text"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Get extra editors, more storage and backup, advanced security and more. "
|
"Get extra editors, more backup, unlimited storage and more. "
|
||||||
"[Take a look to the Enterprise plan.|target:self](%s)"
|
"[Take a look to the Enterprise plan.|target:self](%s)"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:70
|
#: src/app/main/ui/dashboard/subscription.cljs:70
|
||||||
@ -4417,9 +4412,8 @@ msgstr "Enterprise (trial)"
|
|||||||
msgid "subscription.settings.enterprise.unlimited-storage"
|
msgid "subscription.settings.enterprise.unlimited-storage"
|
||||||
msgstr "Unlimited storage and 90-day autosave versions and file recovery"
|
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.autosave"
|
||||||
msgid "subscription.settings.enterprise.security"
|
msgstr "90-day autosave versions and file recovery"
|
||||||
msgstr "Advanced security"
|
|
||||||
|
|
||||||
#: src/app/main/ui/settings/subscription.cljs:269, src/app/main/ui/settings/subscription.cljs:318
|
#: src/app/main/ui/settings/subscription.cljs:269, src/app/main/ui/settings/subscription.cljs:318
|
||||||
msgid "subscription.settings.enterprise.capped-bill"
|
msgid "subscription.settings.enterprise.capped-bill"
|
||||||
|
|||||||
@ -4340,11 +4340,6 @@ msgstr "Por favor, mejóralo para adaptarlo a tu uso. Contacta con el "
|
|||||||
msgid "subscription.dashboard.power-up.enterprise-plan"
|
msgid "subscription.dashboard.power-up.enterprise-plan"
|
||||||
msgstr "Plan Enterprise"
|
msgstr "Plan Enterprise"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:77
|
|
||||||
#, unused
|
|
||||||
msgid "subscription.dashboard.power-up.enterprise.description"
|
|
||||||
msgstr "Seguridad avanzada, registros de actividad, asistencia dedicada y mucho más."
|
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:60
|
#: src/app/main/ui/dashboard/subscription.cljs:60
|
||||||
#, markdown
|
#, markdown
|
||||||
msgid "subscription.dashboard.power-up.professional.bottom"
|
msgid "subscription.dashboard.power-up.professional.bottom"
|
||||||
@ -4388,9 +4383,9 @@ msgstr "Plan Unlimited"
|
|||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:74
|
#: src/app/main/ui/dashboard/subscription.cljs:74
|
||||||
#, markdown
|
#, markdown
|
||||||
msgid "subscription.dashboard.power-up.unlimited.bottom"
|
msgid "subscription.dashboard.power-up.unlimited.bottom-text"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Consigue editores adicionales, más almacenamiento y copias de seguridad, seguridad avanzada y mucho más. "
|
"Consigue editores adicionales, copias de seguridad, almacenamiento ilimitado y mucho más. "
|
||||||
"[Echa un ojo al Plan Enterprise|target:self](%s)"
|
"[Echa un ojo al Plan Enterprise|target:self](%s)"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:70
|
#: src/app/main/ui/dashboard/subscription.cljs:70
|
||||||
@ -4445,9 +4440,8 @@ msgstr "Enterprise (prueba)"
|
|||||||
msgid "subscription.settings.enterprise.unlimited-storage"
|
msgid "subscription.settings.enterprise.unlimited-storage"
|
||||||
msgstr "Almacenamiento ilimitado y versiones de autoguardado de 90 días y recuperación de archivos"
|
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.autosave"
|
||||||
msgid "subscription.settings.enterprise.security"
|
msgstr "Versiones guardadas automáticamente cada 90 días y recuperación de archivos"
|
||||||
msgstr "Seguridad avanzada"
|
|
||||||
|
|
||||||
#: src/app/main/ui/settings/subscription.cljs:269, src/app/main/ui/settings/subscription.cljs:318
|
#: src/app/main/ui/settings/subscription.cljs:269, src/app/main/ui/settings/subscription.cljs:318
|
||||||
msgid "subscription.settings.enterprise.capped-bill"
|
msgid "subscription.settings.enterprise.capped-bill"
|
||||||
|
|||||||
@ -7,7 +7,7 @@ export DEVENV_PNAME="penpotdev";
|
|||||||
export CURRENT_USER_ID=$(id -u);
|
export CURRENT_USER_ID=$(id -u);
|
||||||
export CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD);
|
export CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD);
|
||||||
|
|
||||||
export IMAGEMAGICK_VERSION=7.1.1-47
|
export IMAGEMAGICK_VERSION=7.1.2-0
|
||||||
|
|
||||||
# Safe directory to avoid ownership errors with Git
|
# Safe directory to avoid ownership errors with Git
|
||||||
git config --global --add safe.directory /home/penpot/penpot || true
|
git config --global --add safe.directory /home/penpot/penpot || true
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user