Compare commits

..

33 Commits

Author SHA1 Message Date
Alejandro
3007aa19a2 Merge pull request #6046 from penpot/eva-fix-storybook-icons-list
🐛 Fix storybook icons list scroll
2025-03-11 09:59:42 +01:00
Eva Marco
e20adda766 🐛 Fix storybook icons list scroll 2025-03-11 09:43:35 +01:00
Alejandro
3d9fda7a21 Merge pull request #6025 from penpot/eva-fix-storybook-scroll
🐛 Fix scroll on storybook doc files
2025-03-07 07:52:30 +01:00
Alejandro
7a5dea5cfe Merge pull request #6023 from penpot/marina-consolidate-empty-workspace-board-tool
🎉 Consolidate when workspace empty, board tool selected
2025-03-07 07:49:27 +01:00
alonso.torres
b47df2c230 🐛 Fix problem with components and grid layout 2025-03-06 15:43:55 +01:00
Marina López
b8b3cc641a 🎉 Consolidate when workspace empty, board tool selected 2025-03-06 13:31:12 +01:00
Eva Marco
09ff7372da 🐛 Fix scroll on storybook doc filesç 2025-03-06 12:29:48 +01:00
Alejandro
f45fa95935 Merge pull request #6017 from penpot/alotor-bugfix
🐛 Fix problem with selection colors
2025-03-06 07:35:26 +01:00
alonso.torres
ce02cbc3f1 🐛 Fix problem with selection colors 2025-03-05 14:34:08 +01:00
Alejandro Alonso
b386403fa8 🐛 Fix multiple nav events when open workspace 2025-03-05 12:09:05 +01:00
Alejandro Alonso
0a6e884584 🐛 Remove unnecesary console.log 2025-03-05 12:09:05 +01:00
Alejandro
06f6a49bce Merge pull request #6008 from penpot/superalex-fix-multiple-nav-events-when-open-workspace
🐛 Fix multiple nav events when open workspace
2025-03-05 10:57:51 +01:00
Alejandro Alonso
afd309c62b 🐛 Fix multiple nav events when open workspace 2025-03-05 10:50:47 +01:00
Alejandro Alonso
214a89e20d 📎 Update CHANGES.md file 2025-03-03 07:13:23 +01:00
Yamila Moreno
e64cf9f283 Merge pull request #5908 from penpot/yms-proxy-documentation
📚 Document how to use a proxy
2025-02-28 17:18:46 +01:00
Marina López
3a34c51e43 Add pricing page event 2025-02-28 13:04:15 +01:00
Yamila Moreno
0ff9c44246 🐳 Improve nginx resolvers (#5967) 2025-02-28 09:02:40 +01:00
Yamila Moreno
5bfab454f5 📚 Document how to use a proxy - caddy 2025-02-28 08:43:40 +01:00
Yamila Moreno
5ebde405ea 📚 Document how to use a proxy - nginx 2025-02-28 08:43:40 +01:00
Alejandro
531b002a5c Merge pull request #5976 from penpot/hotfix-texts
🐛 Fix problems with empty position-data
2025-02-27 15:33:25 +01:00
alonso.torres
3eae3178a2 🐛 Fix problems with empty position-data 2025-02-27 14:31:49 +01:00
luisδμ
2cf3e37b7a 🐛 Fix comment update fails in viewer (#5958)
* 🐛 Fix comment update fails in viewer

* 🐛 Reload team members in workspace but not in viewer
2025-02-26 14:29:51 +01:00
luisδμ
e0b9751b16 Merge pull request #5947 from penpot/luis-fix-design-panel-draft-comment-open
🐛 Fix design panel does not reappear if comment draft is open
2025-02-26 11:33:06 +01:00
Alejandro
ccea9b1564 Merge pull request #5962 from penpot/elenatorro-9339-fix-typo-libraries-es
🐛 Fix typo at libraries modal
2025-02-26 09:32:23 +01:00
luisδμ
5fcf889d3c Merge pull request #5960 from penpot/luis-fix-avoid-post-blank-comment
🐛 Fix avoid enabling post button if blank comment
2025-02-26 09:28:59 +01:00
luisδμ
7247db14b2 Merge pull request #5957 from penpot/luis-fix-mention-users-in-viewer
🐛 Fix mention users in viewer
2025-02-26 09:28:29 +01:00
elenatorro
658e5dce22 🐛 Fix ES typo in libraries modal 2025-02-26 09:22:45 +01:00
Elena Torró
f27cbfa0ec Merge pull request #5953 from penpot/marina-fix-typo-libraries
🐛 Fix typo at libraries modal
2025-02-26 09:12:21 +01:00
Luis de Dios
5754c393b9 🐛 Fix avoid enabling post button if blank comment 2025-02-25 18:09:22 +01:00
Luis de Dios
c618efc29e 🐛 Fix mention users in viewer 2025-02-25 15:43:29 +01:00
Marina López
3685f7b32b 🐛 Fix typo at libraries modal 2025-02-25 13:41:26 +01:00
andrés gonzález
06b5304926 📚 New section for Your account (#5941)
* 📚 New section for Your account

* Update docs/user-guide/the-interface/index.njk

Co-authored-by: Madalena Melo <madalena.melo@kaleidos.net>

* Update docs/user-guide/the-interface/index.njk

Co-authored-by: Madalena Melo <madalena.melo@kaleidos.net>

* Update docs/user-guide/the-interface/index.njk

Co-authored-by: Madalena Melo <madalena.melo@kaleidos.net>

---------

Co-authored-by: Madalena Melo <madalena.melo@kaleidos.net>
2025-02-25 13:05:49 +01:00
Luis de Dios
91efcd17a2 🐛 Fix design panel does not reappear if comment draft is open 2025-02-25 10:30:11 +01:00
34 changed files with 373 additions and 187 deletions

View File

@@ -1,6 +1,38 @@
# CHANGELOG
## 2.5.0 (Unreleased)
## 2.5.2
### :rocket: Epics and highlights
### :boom: Breaking changes & Deprecations
### :heart: Community contributions (Thank you!)
### :sparkles: New features
- When the workspace is empty, set default the board creation tool [Taiga #9425](https://tree.taiga.io/project/penpot/us/9425)
### :bug: Bugs fixed
- Fix scroll on storybook docs [taiga #9962](https://tree.taiga.io/project/penpot/issue/9962)
- Navigate tracking event firing multiple times [Taiga #10415](https://tree.taiga.io/project/penpot/issue/10415)
- Fix problem with selection colors [Taiga #10376](https://tree.taiga.io/project/penpot/issue/10376)
- Fix scroll on storybook icons list [taiga #9962](https://tree.taiga.io/project/penpot/issue/9962)
## 2.5.1
### :rocket: Epics and highlights
### :boom: Breaking changes & Deprecations
### :heart: Community contributions (Thank you!)
### :sparkles: New features
- Improve Nginx entryponit to get the resolvers dinamically by default
### :bug: Bugs fixed
## 2.5.0
### :rocket: Epics and highlights

View File

@@ -154,7 +154,7 @@
(let [data (::file-data (meta changes))]
(dm/get-in data [:pages-index uuid/zero :objects])))
(defn- apply-changes-local
(defn apply-changes-local
[changes]
(dm/assert!
"expected valid changes"

View File

@@ -747,42 +747,35 @@
(let [omit-touched? (not reset?)
clear-remote-synced? (and initial-root? reset?)
set-remote-synced? (and (not initial-root?) reset?)
changes (cond-> changes
:always
(update-attrs shape-inst
shape-main
root-inst
root-main
container
omit-touched?)
changes
(cond-> changes
:always
(update-attrs shape-inst
shape-main
root-inst
root-main
container
omit-touched?)
(ctl/flex-layout? shape-main)
(update-flex-child-copy-attrs shape-main
shape-inst
library
component
container
omit-touched?)
(ctl/flex-layout? shape-main)
(update-flex-child-copy-attrs shape-main
shape-inst
library
component
container
omit-touched?)
(ctl/grid-layout? shape-main)
(update-grid-copy-attrs shape-main
shape-inst
library
component
container
omit-touched?)
reset?
(change-touched shape-inst
shape-main
container
{:reset-touched? true})
reset?
(change-touched shape-inst
shape-main
container
{:reset-touched? true})
clear-remote-synced?
(change-remote-synced shape-inst container nil)
clear-remote-synced?
(change-remote-synced shape-inst container nil)
set-remote-synced?
(change-remote-synced shape-inst container true))
set-remote-synced?
(change-remote-synced shape-inst container true))
component-container (find-main-container container shape-inst shape-main library component)
@@ -859,23 +852,36 @@
(d/index-of children-inst child-inst)
(d/index-of children-main child-main)
container
omit-touched?))]
omit-touched?))
(compare-children changes
children-inst
children-main
container
component-container
file
libraries
only-inst
only-main
both
swapped
moved
false
reset?
components-v2))))
changes
(compare-children changes
children-inst
children-main
container
component-container
file
libraries
only-inst
only-main
both
swapped
moved
false
reset?
components-v2)
changes
(cond-> changes
(ctl/grid-layout? shape-inst)
(update-grid-copy-attrs
(:id shape-inst)
shape-main
library
component
omit-touched?))]
changes)))
(defn generate-rename-component
"Generate the changes for rename the component with the given id, in the current file library."
@@ -1710,30 +1716,36 @@
(defn- update-grid-copy-attrs
"Synchronizes the `layout-grid-cells` property from the main shape to the copies"
[changes shape-main shape-copy main-container main-component copy-container omit-touched?]
(let [ids-map
(into {}
(comp
(map #(dm/get-in copy-container [:objects %]))
(keep
(fn [copy-shape]
(let [main-shape (ctf/get-ref-shape main-container main-component copy-shape)]
[(:id main-shape) (:id copy-shape)]))))
(:shapes shape-copy))
[changes shape-copy-id shape-main main-container main-component omit-touched?]
(-> changes
(pcb/apply-changes-local)
(pcb/update-shapes
[shape-copy-id]
(fn [shape-copy objects]
(let [ids-map
(into {}
(comp
(map #(get objects %))
(keep
(fn [copy-shape]
(let [main-shape (ctf/get-ref-shape main-container main-component copy-shape)]
[(:id main-shape) (:id copy-shape)]))))
(:shapes shape-copy))
new-changes
(-> (pcb/empty-changes)
(pcb/with-container copy-container)
(pcb/with-objects (:objects copy-container))
(pcb/update-shapes
[(:id shape-copy)]
(fn [shape-copy]
remove-orphan-cells
(fn [cells {:keys [shapes]}]
(let [child? (set shapes)]
(-> cells
(update-vals
(fn [cell]
(update cell :shapes #(filterv child? %)))))))
;; Take cells from main and remap the shapes to assign it to the copy
(let [copy-cells (:layout-grid-cells shape-copy)
main-cells (-> (ctl/remap-grid-cells shape-main ids-map) :layout-grid-cells)]
(assoc shape-copy :layout-grid-cells (ctl/merge-cells copy-cells main-cells omit-touched?))))
{:ignore-touched true}))]
(pcb/concat-changes changes new-changes)))
copy-cells (-> shape-copy :layout-grid-cells (remove-orphan-cells shape-copy))
main-cells (-> shape-main (ctl/remap-grid-cells ids-map) :layout-grid-cells)]
(-> shape-copy
(assoc :layout-grid-cells
(ctl/merge-cells copy-cells main-cells omit-touched?)))))
{:ignore-touched true :with-objects? true})))
(defn- update-grid-main-attrs
"Synchronizes the `layout-grid-cells` property from the copy to the main shape"

View File

@@ -1642,11 +1642,16 @@
"Given target cells update with source cells while trying to keep target as
untouched as possible"
[target-cells source-cells omit-touched?]
(if (not omit-touched?)
source-cells
(if omit-touched?
(letfn [(get-data [cells id]
(dissoc (get cells id) :shapes :row :column :row-span :column-span))]
(dissoc (get cells id) :row :column :row-span :column-span))
(merge-cells [source-cell target-cell]
(-> source-cell
(d/patch-object
(dissoc target-cell :shapes :row :column :row-span :column-span))
(cond-> (d/not-empty? (:shapes target-cell))
(assoc :shapes (:shapes target-cell)))))]
(let [deleted-cells
(into #{}
(filter #(not (contains? source-cells %)))
@@ -1664,5 +1669,6 @@
(reduce
(fn [cells id]
(-> cells
(d/update-when id d/patch-object (get-data target-cells id))))
source-cells))))))
(d/update-when id merge-cells (get target-cells id))))
source-cells))))
source-cells))

View File

@@ -11,6 +11,7 @@ RUN set -ex; \
ADD ./bundle-frontend/ /var/www/app/
ADD ./files/config.js /var/www/app/js/config.js
ADD ./files/nginx.conf /etc/nginx/nginx.conf.template
ADD ./files/resolvers.conf /etc/nginx/overrides.d/resolvers.conf.template
ADD ./files/nginx-mime.types /etc/nginx/mime.types
ADD ./files/nginx-entrypoint.sh /entrypoint.sh

View File

@@ -21,10 +21,14 @@ update_flags /var/www/app/js/config.js
export PENPOT_BACKEND_URI=${PENPOT_BACKEND_URI:-http://penpot-backend:6060};
export PENPOT_EXPORTER_URI=${PENPOT_EXPORTER_URI:-http://penpot-exporter:6061};
export PENPOT_INTERNAL_RESOLVER=${PENPOT_INTERNAL_RESOLVER:-127.0.0.11};
PENPOT_DEFAULT_INTERNAL_RESOLVER="$(awk 'BEGIN{ORS=" "} $1=="nameserver" { sub(/%.*$/,"",$2); print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf)";
export PENPOT_INTERNAL_RESOLVER=${PENPOT_INTERNAL_RESOLVER:-$PENPOT_DEFAULT_INTERNAL_RESOLVER};
export PENPOT_HTTP_SERVER_MAX_MULTIPART_BODY_SIZE=${PENPOT_HTTP_SERVER_MAX_MULTIPART_BODY_SIZE:-367001600}; # Default to 350MiB
envsubst "\$PENPOT_BACKEND_URI,\$PENPOT_EXPORTER_URI,\$PENPOT_INTERNAL_RESOLVER,\$PENPOT_HTTP_SERVER_MAX_MULTIPART_BODY_SIZE" \
< /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf
envsubst "\$PENPOT_BACKEND_URI,\$PENPOT_EXPORTER_URI,\$PENPOT_HTTP_SERVER_MAX_MULTIPART_BODY_SIZE" \
< /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf;
envsubst "\$PENPOT_INTERNAL_RESOLVER" \
< /etc/nginx/overrides.d/resolvers.conf.template > /etc/nginx/overrides.d/resolvers.conf;
exec "$@";

View File

@@ -46,7 +46,6 @@ http {
proxy_buffer_size 16k;
proxy_busy_buffers_size 24k; # essentially, proxy_buffer_size + 2 small buffers of 4k
proxy_buffers 32 4k;
resolver $PENPOT_INTERNAL_RESOLVER ipv6=off;
map $http_upgrade $connection_upgrade {
default upgrade;

View File

@@ -0,0 +1 @@
resolver $PENPOT_INTERNAL_RESOLVER ipv6=off valid=10s;

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -280,6 +280,67 @@ Postgres database and another one for the assets uploaded by your users (images
clips). There may be more volumes if you enable other features, as explained in the file
itself.
### Configure the proxy
Your host configuration needs to make a proxy to http://localhost:9001.
#### Example with NGINX
```bash
server {
listen 80;
server_name penpot.mycompany.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name penpot.mycompany.com;
# This value should be in sync with the corresponding in the docker-compose.yml
# PENPOT_HTTP_SERVER_MAX_BODY_SIZE: 31457280
client_max_body_size 31457280;
# Logs: Configure your logs following the best practices inside your company
access_log /path/to/penpot.access.log;
error_log /path/to/penpot.error.log;
# TLS: Configure your TLS following the best practices inside your company
ssl_certificate /path/to/fullchain;
ssl_certificate_key /path/to/privkey;
# Websockets
location /ws/notifications {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_pass http://localhost:9001/ws/notifications;
}
# Proxy pass
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
proxy_pass http://localhost:9001/;
}
}
```
#### Example with CADDY SERVER
```bash
penpot.mycompany.com {
reverse_proxy :9001
tls /path/to/fullchain.pem /path/to/privkey.pem
log {
output file /path/to/penpot.log
}
}
```
### Troubleshooting
Knowing how to do Penpot troubleshooting can be very useful; on the one hand, it helps to create issues easier to resolve, since they include relevant information from the beginning which also makes them get solved faster; on the other hand, many times troubleshooting gives the necessary information to resolve a problem autonomously, without even creating an issue.
@@ -350,7 +411,6 @@ you need.
Therefore, your prerequisite will be to have a Kubernetes cluster on which we can install
Helm.
### What is Helm
*Helm* is the package manager for Kubernetes. A *Chart* is a Helm package. It contains

View File

@@ -5,52 +5,6 @@ title: 02· The interface
<h1 id="the-interface">The interface</h1>
<p class="main-paragraph">The Penpot interface has three main areas: Dashboard, Workspace and View mode. Lets take a look at their composition and main features.</p>
<h2 id="interface-dashboard">Dashboard</h2>
<p>The Dashboard is the place where you will be able to organize your files, libraries, projects and teams.</p>
<figure>
<a href="/img/interface/dashboard-dark.webp" target="_blank">
<img src="/img/interface/dashboard-dark.webp" alt="Penpot's dashboard" />
</a>
</figure>
<p class="hint">
<strong>1)</strong> Teams
<strong>2)</strong> Search files
<strong>3)</strong> Projects
<strong>4)</strong> Drafts
<strong>5)</strong> Shared Libraries
<strong>6)</strong> Custom fonts
<strong>7)</strong> Pinned projects
<strong>8)</strong> User area
<strong>9)</strong> Comment notifications
<strong>10)</strong> Create project
<strong>11)</strong> File card
<strong>12)</strong> Libraries & Templates module
</p>
<ol>
<li><strong>Teams:</strong> A team allows you to collaborate with other Penpot users. Team members are allowed to work with any project or file within the team depending on their permissions. Members with admin permissions can also invite other members. Create or join as many teams as you need with different groups of people.</li>
<li><strong>Search:</strong> If you are looking for a specific file just type its title at the search box.</li>
<li><strong>Projects:</strong> A project allows you to group design files. It works pretty much like a folder in a file system. You can create as many projects as you need. If you are going to work with more people in a project, you should create it inside a team.</li>
<li><strong>Drafts:</strong> The drafts section is where you can find the design files that are not inside any project.</li>
<li><strong>Shared Libraries:</strong> In this section you will find all the design files that have been added as shared libraries. That way you will be able to better control the files that are sharing their assets. </li>
<li><strong>Custom fonts:</strong> If you have purchased or own personal fonts that are not included in the catalog provided by Penpot, you can upload them from your computer and use them across the files of a team.</li>
<li><strong>Pinned projects:</strong> If you want to keep some projects handy (for instance because youre currently working on them) you can pin them to make them quickly available at the sidebar.</li>
<li><strong>User area:</strong> This must be you! Access your profile settings, Penpot tutorials, the Penpot Community and more. You can also find here a way to leave us feedback. Wed love to read your thoughts :)</li>
<li><strong>Comments notifications:</strong> Here you will be able to see if you have unread comments inside the files of the team.</li>
<li><strong>Create project:</strong> Create as many projects as you need to organize your designs.</li>
<li><strong>File card:</strong> Basic information about a file at plain sight. A preview, update info or if its added as a Shared Library. From there you can perform several actions over the file (rename, duplicate, move, download, delete).</li>
<li><strong>Libraries & Templates module:</strong> A curated selection of Libraries & Templates files ready to import.</li>
</ol>
<h3 id="your-account">Your account</h3>
<p>Your account settings can be changed at the user area, in <b>Your account</b>. Here you can make changes to your profile, password or account language, as well as generate personal access tokens and access release notes.</p>
<p>If you want to change the email address associated to your account or remove your account entirely, this can be done in the <b>Profile</b> section.</p>
<h2 id="interface-workspace">Workspace</h2>
<p>The Workspace is where you actually create your designs. You have an infinite canvas where you can work directly but you also have the ability to create and work inside boards that will help you to create pages and exportation units.</p>
@@ -102,8 +56,6 @@ title: 02· The interface
<li><strong>Assets panel:</strong> Each file has a default library (File Library) where you can store elements and styles that are likely to be reused within a project. That includes components, colors and typographies. To add an asset to a library just click the “+” button at the header of each asset group.</li>
</ol>
<h2 id="interface-viewmode">View mode</h2>
<p>Launch the view mode to present and share your designs, comment on them and play with the interactions set at the workspace. You also have an Inspect mode where you can get properties specifications and code snippets. <a href="/user-guide/view-mode/">More about the View mode.</a></p>
@@ -145,6 +97,83 @@ title: 02· The interface
<li><strong>Navigation buttons:</strong> Forward and backwards buttons.</li>
</ol>
<h2 id="interface-dashboard">Dashboard</h2>
<p>The Dashboard is the place where you will be able to organize your files, libraries, projects and teams.</p>
<figure>
<a href="/img/interface/dashboard-dark.webp" target="_blank">
<img src="/img/interface/dashboard-dark.webp" alt="Penpot's dashboard" />
</a>
</figure>
<p class="hint">
<strong>1)</strong> Teams
<strong>2)</strong> Search files
<strong>3)</strong> Projects
<strong>4)</strong> Drafts
<strong>5)</strong> Shared Libraries
<strong>6)</strong> Custom fonts
<strong>7)</strong> Pinned projects
<strong>8)</strong> User area
<strong>9)</strong> Comment notifications
<strong>10)</strong> Create project
<strong>11)</strong> File card
<strong>12)</strong> Libraries & Templates module
</p>
<ol>
<li><strong>Teams:</strong> A team allows you to collaborate with other Penpot users. Team members are allowed to work with any project or file within the team depending on their permissions. Members with admin permissions can also invite other members. Create or join as many teams as you need with different groups of people.</li>
<li><strong>Search:</strong> If you are looking for a specific file just type its title at the search box.</li>
<li><strong>Projects:</strong> A project allows you to group design files. It works pretty much like a folder in a file system. You can create as many projects as you need. If you are going to work with more people in a project, you should create it inside a team.</li>
<li><strong>Drafts:</strong> The drafts section is where you can find the design files that are not inside any project.</li>
<li><strong>Shared Libraries:</strong> In this section you will find all the design files that have been added as shared libraries. That way you will be able to better control the files that are sharing their assets. </li>
<li><strong>Custom fonts:</strong> If you have purchased or own personal fonts that are not included in the catalog provided by Penpot, you can upload them from your computer and use them across the files of a team.</li>
<li><strong>Pinned projects:</strong> If you want to keep some projects handy (for instance because youre currently working on them) you can pin them to make them quickly available at the sidebar.</li>
<li><strong>User area:</strong> This must be you! Access your profile settings, Penpot tutorials, the Penpot Community and more. You can also find here a way to leave us feedback. Wed love to read your thoughts :)</li>
<li><strong>Comments notifications:</strong> Here you will be able to see if you have unread comments inside the files of the team.</li>
<li><strong>Create project:</strong> Create as many projects as you need to organize your designs.</li>
<li><strong>File card:</strong> Basic information about a file at plain sight. A preview, update info or if its added as a Shared Library. From there you can perform several actions over the file (rename, duplicate, move, download, delete).</li>
<li><strong>Libraries & Templates module:</strong> A curated selection of Libraries & Templates files ready to import.</li>
</ol>
<h3 id="your-account">Your account</h3>
<p>Your account settings can be changed at the user area, in <b>Your account</b>. Here you can make changes to your profile, password or account language, as well as generate personal access tokens and access release notes.</p>
<h4 id="your-account-profile">Profile
<a class="direct-link" href="#your-account-profile">#</a>
</h3>
<p>If you want to change the email address associated to your account or remove your account entirely, this can be done in the <b>Profile</b> section.</p>
<figure>
<img src="/img/interface/youraccount-profile.webp" alt="Penpot's profile" />
</figure>
<h4 id="your-account-password">Password
<a class="direct-link" href="#your-account-password">#</a>
</h3>
<p>If you want to change your password to a new one, this can be done in the <b>Password</b> section.</p>
<figure>
<img src="/img/interface/youraccount-password.webp" alt="Penpot's password" />
</figure>
<h4 id="your-account-notifications">Notifications
<a class="direct-link" href="#your-account-notifications">#</a>
</h3>
<p>At the <strong>Notifications</strong> section you can configure the email and dashboard notifications.</p>
<figure>
<img src="/img/interface/youraccount-notifications.webp" alt="Penpot's notifications" />
</figure>
<h4 id="your-account-settings">Settings
<a class="direct-link" href="#your-account-settings">#</a>
</h3>
<p>At the <strong>Settings</strong> section you can change the language and the UI color theme.</p>
<figure>
<img src="/img/interface/youraccount-settings.webp" alt="Penpot's settings" />
</figure>
<h4 id="your-account-accesstokens">Access tokens
<a class="direct-link" href="#your-account-accesstokens">#</a>
</h3>
<p>At the <strong>Asset tokens</strong> section you can manage your access tokens. <a href="https://help.penpot.app/technical-guide/integration/#access-tokens" target="_blank">Read more about access tokens here</a>.</p>
<h2 id="interface-ui-theme">UI Theme</h2>
<p>Penpot's default interface is dark but you can switch anytime to a light option. You have 2 ways to change the theme:</p>
@@ -170,4 +199,4 @@ title: 02· The interface
<img src="/img/interface/viewmode-light.webp" alt="Penpot's view mode" />
</a>
<figcaption>Penpot's view mode in light mode</figcaption>
</figure>
</figure>

View File

@@ -70,6 +70,7 @@ export class WorkspacePage extends BaseWebSocketPage {
);
this.toolbarOptions = page.getByTestId("toolbar-options");
this.rectShapeButton = page.getByRole("button", { name: "Rectangle (R)" });
this.moveButton = page.getByRole("button", { name: "Move (V)" });
this.boardButton = page.getByRole("button", { name: "Board (B)" });
this.toggleToolbarButton = page.getByRole("button", {
name: "Toggle toolbar",

View File

@@ -13,6 +13,7 @@ test("Bug 7549 - User clicks on color swatch to display the color picker next to
await workspacePage.setupEmptyFile(page);
await workspacePage.goToWorkspace();
await workspacePage.moveButton.click();
const swatch = workspacePage.page.getByRole("button", { name: "E8E9EA" });
const swatchBox = await swatch.boundingBox();
await swatch.click();
@@ -171,6 +172,7 @@ test("Bug 9900 - Color picker has no inputs for HSV values", async ({
await workspacePage.setupEmptyFile(page);
await workspacePage.goToWorkspace();
await workspacePage.moveButton.click();
const swatch = workspacePage.page.getByRole("button", { name: "E8E9EA" });
await swatch.click();

View File

@@ -178,6 +178,7 @@ test("Bug 10179 - Drag & drop doesn't add colors to the Recent Colors palette",
const workspacePage = new WorkspacePage(page);
await workspacePage.setupEmptyFile();
await workspacePage.goToWorkspace();
await workspacePage.moveButton.click();
await workspacePage.page.keyboard.press("Alt+p");

View File

@@ -0,0 +1,10 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) KALEIDOS INC
.sb-show-main.sb-main-fullscreen,
.sb-show-main.sb-main-padded {
overflow-y: auto;
}

View File

@@ -13,6 +13,7 @@
@import "common/dependencies/fonts";
@import "common/dependencies/animations";
@import "common/dependencies/highlight.scss";
@import "common/dependencies/storybook.scss";
@import "common/refactor/themes.scss";
@import "common/refactor/design-tokens.scss";

View File

@@ -90,7 +90,6 @@
(update :comments-local assoc :open id))
(update :comments-local assoc :options nil)
(update :comments-local dissoc :draft)
(update :workspace-drawing dissoc :comment)
(update-in [:comments id] assoc (:id comment) comment))))
ptk/WatchEvent
@@ -146,7 +145,6 @@
(update :comments-local assoc :open id)
(update :comments-local assoc :options nil)
(update :comments-local dissoc :draft)
(update :workspace-drawing dissoc :comment)
(update-in [:comments id] assoc (:id comment) comment))))
ptk/WatchEvent
@@ -415,8 +413,8 @@
(->> (rp/cmd! :get-comment-threads {:file-id file-id :share-id share-id})
(rx/map comment-threads-fetched))
;; Refresh team members
(rx/of (dtm/fetch-members)))))))
(when (:workspace-local state)
(rx/of (dtm/fetch-members))))))))
(defn retrieve-comments
[thread-id]
@@ -474,7 +472,7 @@
(-> state
(update :comments-local assoc :open id)
(update :comments-local assoc :options nil)
(update :workspace-drawing dissoc :comment)))))
(update :comments-local dissoc :draft)))))
(defn close-thread
[]
@@ -482,8 +480,7 @@
ptk/UpdateEvent
(update [_ state]
(-> state
(update :comments-local dissoc :open :draft :options)
(update :workspace-drawing dissoc :comment)))))
(update :comments-local dissoc :open :draft :options)))))
(defn update-filters
[{:keys [mode show list] :as params}]
@@ -524,7 +521,6 @@
ptk/UpdateEvent
(update [_ state]
(-> state
(update :workspace-drawing assoc :comment params)
(update :comments-local assoc :draft params)))))
(defn update-draft-thread
@@ -533,7 +529,6 @@
ptk/UpdateEvent
(update [_ state]
(-> state
(d/update-in-when [:workspace-drawing :comment] merge data)
(d/update-in-when [:comments-local :draft] merge data)))))
(defn toggle-comment-options

View File

@@ -171,7 +171,7 @@
(declare go-to-frame-auto)
(defn bundle-fetched
[{:keys [project file share-links libraries users permissions thumbnails] :as bundle}]
[{:keys [project file team share-links libraries users permissions thumbnails] :as bundle}]
(let [pages (->> (dm/get-in file [:data :pages])
(map (fn [page-id]
(let [data (get-in file [:data :pages-index page-id])]
@@ -183,15 +183,19 @@
(ptk/reify ::bundle-fetched
ptk/UpdateEvent
(update [_ state]
(-> state
(assoc :share-links share-links)
(assoc :viewer {:libraries (d/index-by :id libraries)
:users (d/index-by :id users)
:permissions permissions
:project project
:pages pages
:thumbnails thumbnails
:file file})))
(let [team-id (:id team)
team {:members users}]
(-> state
(assoc :share-links share-links)
(assoc :current-team-id team-id)
(assoc :teams {team-id team})
(assoc :viewer {:libraries (d/index-by :id libraries)
:users (d/index-by :id users)
:permissions permissions
:project project
:pages pages
:thumbnails thumbnails
:file file}))))
ptk/WatchEvent
(watch [_ state _]

View File

@@ -478,8 +478,7 @@
(rx/of (initialize-page* file-id page-id page)
(dwth/watch-state-changes file-id page-id)
(dwl/watch-component-changes)
(when (cf/external-feature-flag "boards-02" "test")
(select-frame-tool file-id page-id)))
(select-frame-tool file-id page-id))
(rx/of (dcm/go-to-workspace :file-id file-id ::rt/replace true))))))
(defn finalize-page

View File

@@ -62,18 +62,21 @@
;; --- Navigate (Event)
(defn navigated
[match]
[match send-event-info?]
(ptk/reify ::navigated
IDeref
(-deref [_] match)
ev/Event
(-data [_]
(let [route (dm/get-in match [:data :name])
params (get match :path-params)]
(assoc params
::ev/name "navigate"
:route (name route))))
ptk/WatchEvent
(watch [_ _ _]
(when send-event-info?
(let [route (dm/get-in match [:data :name])
params (get match :query-params)]
(rx/of (ptk/event
::ev/event
(assoc params
::ev/name "navigate"
:route (name route)))))))
ptk/UpdateEvent
(update [_ state]
@@ -186,6 +189,21 @@
;; --- History API
;; Check the urls to see if we need to send the navigated event.
;; If two paths are the same we only send the event when there is a
;; change in the parameters `file-id`, `page-id` or `team-id`
(defn- send-event-info?
[old-url new-url]
(let [params [:file-id :page-id :team-id]
new-uri (u/uri new-url)
new-path (:path new-uri)
new-params (-> new-uri :query u/query-string->map (select-keys params))
old-uri (u/uri old-url)
old-path (:path old-uri)
old-params (-> old-uri :query u/query-string->map (select-keys params))]
(or (not= old-path new-path)
(not= new-params old-params))))
(defn initialize-history
[on-change]
(ptk/reify ::initialize-history
@@ -200,11 +218,19 @@
(let [stopper (rx/filter (ptk/type? ::initialize-history) stream)
history (:history state)
router (:router state)]
(ts/schedule #(on-change router (.getToken ^js history)))
(->> (rx/create (fn [subs]
(let [key (e/listen history "navigate" (fn [o] (rx/push! subs (.-token ^js o))))]
(fn []
(bhistory/disable! history)
(e/unlistenByKey key)))))
(ts/schedule #(on-change router (.getToken ^js history) true))
(->> (rx/concat
(rx/of nil nil)
(rx/create
(fn [subs]
(let [key (e/listen history "navigate" (fn [o] (rx/push! subs (.-token ^js o))))]
(fn []
(bhistory/disable! history)
(e/unlistenByKey key))))))
(rx/buffer 2 1)
(rx/take-until stopper)
(rx/subs! #(on-change router %)))))))
(rx/subs!
(fn [[old-url new-url]]
(when (some? new-url)
(let [send? (or (nil? old-url) (send-event-info? old-url new-url))]
(on-change router new-url send?))))))))))

View File

@@ -132,10 +132,11 @@
(defn- blank-content?
[content]
(or (str/blank? content)
(str/empty? content)
;; If only one char and it's the zero-width whitespace
(and (= 1 (count content)) (= (first content) zero-width-space))))
(let [content (str/trim content)]
(or (str/blank? content)
(str/empty? content)
(and (= (count content) 1)
(= (first content) zero-width-space)))))
;; Component that renders the component content
(mf/defc comment-content*

View File

@@ -959,6 +959,7 @@
on-power-up-click
(mf/use-fn
(fn []
(st/emit! (ptk/event ::ev/event {::ev/name "explore-pricing-click" ::ev/origin "dashboard" :section "sidebar"}))
(dom/open-new-window "https://penpot.app/pricing")))]
[:*

View File

@@ -88,7 +88,7 @@
:plugin-url plugin))))
(defn on-navigate
[router path]
[router path send-event-info?]
(let [location (.-location js/document)
[base-path qs] (str/split path "?")
location-path (dm/str (.-origin location) (.-pathname location))
@@ -102,7 +102,7 @@
(st/emit! (rt/assign-exception {:type :not-found}))
(some? match)
(st/emit! (rt/navigated match))
(st/emit! (rt/navigated match send-event-info?))
:else
;; We just recheck with an additional profile request; this

View File

@@ -35,5 +35,8 @@
;; Old components can have texts without position data that must be rendered via foreign key
(cond
(some? position-data) [:> svg/text-shape props]
is-component? [:> fo/text-shape props])))
(some? position-data)
[:> svg/text-shape props]
(or (nil? position-data) is-component?)
[:> fo/text-shape props])))

View File

@@ -25,7 +25,7 @@
[rumext.v2 :as mf]))
(mf/defc options*
[{:keys [shape file-id shapes-with-children shared-libs] :as props}]
[{:keys [shape file-id shapes-with-children libraries] :as props}]
(let [shape-id (dm/get-prop shape :id)
shape-type (dm/get-prop shape :type)
@@ -116,7 +116,7 @@
[:> color-selection-menu* {:type shape-type
:shapes shapes-with-children
:file-id file-id
:libraries shared-libs}]
:libraries libraries}]
[:> shadow-menu* {:ids ids :values (get shape :shadow)}]
[:& blur-menu {:ids ids
:values (select-keys shape [:blur])}]

View File

@@ -292,7 +292,7 @@
page-id (unchecked-get props "page-id")
file-id (unchecked-get props "file-id")
shared-libs (unchecked-get props "shared-libs")
shared-libs (unchecked-get props "libraries")
show-caps (some #(and (= :path (:type %)) (gsh/open-path? %)) shapes)

View File

@@ -304,8 +304,7 @@
:page-id page-id
:file-id file-id
:vport vport
:zoom zoom
:drawing drawing}])
:zoom zoom}])
(when picking-color?
[:& pixel-overlay/pixel-overlay {:vport vport

View File

@@ -16,7 +16,7 @@
[rumext.v2 :as mf]))
(mf/defc comments-layer*
[{:keys [vbox vport zoom drawing file-id page-id]}]
[{:keys [vbox vport zoom file-id page-id]}]
(let [vbox-x (dm/get-prop vbox :x)
vbox-y (dm/get-prop vbox :y)
vport-w (dm/get-prop vport :width)
@@ -73,7 +73,7 @@
:viewport viewport
:zoom zoom}])))
(when-let [draft (:comment drawing)]
(when-let [draft (:draft local)]
[:> cmt/comment-floating-thread-draft*
{:draft draft
:on-cancel on-draft-cancel

View File

@@ -350,8 +350,7 @@
[:> comments/comments-layer* {:vbox vbox
:page-id page-id
:vport vport
:zoom zoom
:drawing drawing}])
:zoom zoom}])
(when picking-color?
[:& pixel-overlay/pixel-overlay {:vport vport

View File

@@ -4754,7 +4754,7 @@ msgstr "Or add some of these to try:"
#: src/app/main/ui/workspace/libraries.cljs:368
msgid "workspace.libraries.empty.no-libraries"
msgstr "There are no Shared Libraries at you team, you can look for"
msgstr "There are no Shared Libraries at your team, you can look for"
#: src/app/main/ui/workspace/libraries.cljs:372
msgid "workspace.libraries.empty.some-templates"

View File

@@ -4772,7 +4772,7 @@ msgstr "O añadir algunas de éstas para probar:"
#: src/app/main/ui/workspace/libraries.cljs:368
msgid "workspace.libraries.empty.no-libraries"
msgstr "No hay Biblioteacas Compartidas en tu equipo, puedes buscar"
msgstr "No hay Bibliotecas Compartidas en tu equipo, puedes buscar"
#: src/app/main/ui/workspace/libraries.cljs:372
msgid "workspace.libraries.empty.some-templates"