mirror of
https://github.com/penpot/penpot.git
synced 2025-06-02 17:31:38 +02:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
commit
df0909483e
11 changed files with 206096 additions and 17 deletions
|
@ -57,6 +57,9 @@ is a number of cores)
|
||||||
- Copy text content to clipboard [Taiga #9970](https://tree.taiga.io/project/penpot/us/9970?milestone=424203)
|
- Copy text content to clipboard [Taiga #9970](https://tree.taiga.io/project/penpot/us/9970?milestone=424203)
|
||||||
- Resize board to fit content option [Taiga #4707](https://tree.taiga.io/project/penpot/us/4707)
|
- Resize board to fit content option [Taiga #4707](https://tree.taiga.io/project/penpot/us/4707)
|
||||||
- Rename selected layer via Board name [Taiga #9430](https://tree.taiga.io/project/penpot/us/9430)
|
- Rename selected layer via Board name [Taiga #9430](https://tree.taiga.io/project/penpot/us/9430)
|
||||||
|
- [COMMENTS] Mention Functionality with and Sidebar Filters [Taiga #9237](https://tree.taiga.io/project/penpot/us/9237)
|
||||||
|
- [COMMENTS] Visual Changes in Comments [Taiga #9234](https://tree.taiga.io/project/penpot/us/9234)
|
||||||
|
- [COMMENTS] Notifications in Backend, Profile Section, and Mention Email Notification [Taiga #9233](https://tree.taiga.io/project/penpot/us/9233)
|
||||||
|
|
||||||
### :bug: Bugs fixed
|
### :bug: Bugs fixed
|
||||||
|
|
||||||
|
|
|
@ -427,7 +427,7 @@ are using during you setup).
|
||||||
There are some other options, **NOT SUPPORTED BY PENPOT**:
|
There are some other options, **NOT SUPPORTED BY PENPOT**:
|
||||||
|
|
||||||
* Install with <a href="https://community.penpot.app/t/how-to-develop-penpot-with-podman-penpotman/2113" target="_blank">Podman</a> instead of Docker.
|
* Install with <a href="https://community.penpot.app/t/how-to-develop-penpot-with-podman-penpotman/2113" target="_blank">Podman</a> instead of Docker.
|
||||||
* Try the under development <a href="https://community.penpot.app/t/introducing-penpot-desktop/1468" target="_blank">Penpot Desktop app</a>.
|
* Try the under development <a href="https://github.com/author-more/penpot-desktop/releases/latest" target="_blank">Penpot Desktop app</a>.
|
||||||
* Try a simple Kubernetes Deployment option <a href="https://github.com/degola/penpot-kubernetes" target="_blank">penpot-kubernetes</a>.
|
* Try a simple Kubernetes Deployment option <a href="https://github.com/degola/penpot-kubernetes" target="_blank">penpot-kubernetes</a>.
|
||||||
* Or try a fully manual installation if you have a really specific use case.. For help, you can look at the [Architecture][2] section and the <a href="https://github.com/penpot/penpot/tree/develop/docker/images" target="_blank">Docker configuration files</a>.
|
* Or try a fully manual installation if you have a really specific use case.. For help, you can look at the [Architecture][2] section and the <a href="https://github.com/penpot/penpot/tree/develop/docker/images" target="_blank">Docker configuration files</a>.
|
||||||
|
|
||||||
|
|
205906
frontend/playwright/data/workspace/get-file-9930.json
Normal file
205906
frontend/playwright/data/workspace/get-file-9930.json
Normal file
File diff suppressed because it is too large
Load diff
|
@ -321,6 +321,55 @@ test("[Taiga #9929] Paste text in workspace", async ({ page, context }) => {
|
||||||
.getByText("Lorem ipsum dolor");
|
.getByText("Lorem ipsum dolor");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("[Taiga #9930] Zoom fit all doesn't fits all", async ({
|
||||||
|
page,
|
||||||
|
context,
|
||||||
|
}) => {
|
||||||
|
const workspacePage = new WorkspacePage(page);
|
||||||
|
await workspacePage.setupEmptyFile(page);
|
||||||
|
await workspacePage.mockRPC(/get\-file\?/, "workspace/get-file-9930.json");
|
||||||
|
await workspacePage.goToWorkspace({
|
||||||
|
fileId: "8f843b59-7fbb-81ce-8005-aa6d47ae3111",
|
||||||
|
pageId: "fb9798e7-a547-80ae-8005-9ffda4a13e2c",
|
||||||
|
});
|
||||||
|
|
||||||
|
const zoom = await page.getByTitle("Zoom");
|
||||||
|
await zoom.click();
|
||||||
|
|
||||||
|
const zoomIn = await page.getByTitle("Zoom in");
|
||||||
|
await zoomIn.click();
|
||||||
|
await zoomIn.click();
|
||||||
|
await zoomIn.click();
|
||||||
|
|
||||||
|
// Zoom fit all
|
||||||
|
await page.keyboard.press("Shift+1");
|
||||||
|
|
||||||
|
const ids = [
|
||||||
|
"shape-165d1e5a-5873-8010-8005-9ffdbeaeec59",
|
||||||
|
"shape-165d1e5a-5873-8010-8005-9ffdbeaf8d8a",
|
||||||
|
"shape-165d1e5a-5873-8010-8005-9ffdbeaf8d9e",
|
||||||
|
"shape-165d1e5a-5873-8010-8005-9ffdbeb053d9",
|
||||||
|
"shape-165d1e5a-5873-8010-8005-9ffdbeb09738",
|
||||||
|
"shape-165d1e5a-5873-8010-8005-9ffdbeb0f3fc",
|
||||||
|
];
|
||||||
|
|
||||||
|
function contains(container, contained) {
|
||||||
|
return (
|
||||||
|
container.x <= contained.x &&
|
||||||
|
container.y <= contained.y &&
|
||||||
|
container.width >= contained.width &&
|
||||||
|
container.height >= contained.height
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const viewportBoundingBox = await workspacePage.viewport.boundingBox();
|
||||||
|
for (const id of ids) {
|
||||||
|
const shape = await page.locator(`.ws-shape-wrapper > g#${id}`);
|
||||||
|
const shapeBoundingBox = await shape.boundingBox();
|
||||||
|
expect(contains(viewportBoundingBox, shapeBoundingBox)).toBeTruthy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test("Bug 9877, user navigation to dashboard from header goes to blank page", async ({
|
test("Bug 9877, user navigation to dashboard from header goes to blank page", async ({
|
||||||
page,
|
page,
|
||||||
}) => {
|
}) => {
|
||||||
|
|
|
@ -90,7 +90,7 @@
|
||||||
state
|
state
|
||||||
(update state :workspace-local
|
(update state :workspace-local
|
||||||
(fn [{:keys [vport] :as local}]
|
(fn [{:keys [vport] :as local}]
|
||||||
(let [srect (gal/adjust-to-viewport vport srect {:padding 40})
|
(let [srect (gal/adjust-to-viewport vport srect {:padding 160})
|
||||||
zoom (/ (:width vport) (:width srect))]
|
zoom (/ (:width vport) (:width srect))]
|
||||||
(-> local
|
(-> local
|
||||||
(assoc :zoom zoom)
|
(assoc :zoom zoom)
|
||||||
|
|
|
@ -511,7 +511,9 @@
|
||||||
{:limit limit
|
{:limit limit
|
||||||
:can-edit can-edit
|
:can-edit can-edit
|
||||||
:create-fn create-fn
|
:create-fn create-fn
|
||||||
:origin origin}])]))
|
:origin origin
|
||||||
|
:project-id project-id
|
||||||
|
:on-finish-import on-finish-import}])]))
|
||||||
|
|
||||||
(mf/defc line-grid-row
|
(mf/defc line-grid-row
|
||||||
[{:keys [files selected-files dragging? limit can-edit] :as props}]
|
[{:keys [files selected-files dragging? limit can-edit] :as props}]
|
||||||
|
@ -635,4 +637,6 @@
|
||||||
{:dragging? @dragging?
|
{:dragging? @dragging?
|
||||||
:limit limit
|
:limit limit
|
||||||
:can-edit can-edit
|
:can-edit can-edit
|
||||||
:create-fn create-fn}])]))
|
:create-fn create-fn
|
||||||
|
:project-id project-id
|
||||||
|
:on-finish-import on-finish-import}])]))
|
||||||
|
|
|
@ -8,14 +8,40 @@
|
||||||
(:require-macros [app.main.style :as stl])
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
|
[app.main.ui.dashboard.import :as udi]
|
||||||
[app.main.ui.ds.product.empty-placeholder :refer [empty-placeholder*]]
|
[app.main.ui.ds.product.empty-placeholder :refer [empty-placeholder*]]
|
||||||
[app.main.ui.ds.product.loader :refer [loader*]]
|
[app.main.ui.ds.product.loader :refer [loader*]]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
(mf/defc empty-placeholder-projects*
|
||||||
|
{::mf/wrap-props false}
|
||||||
|
[{:keys [on-create on-finish-import project-id] :as props}]
|
||||||
|
(let [file-input (mf/use-ref nil)
|
||||||
|
on-add-library (mf/use-fn #(dom/open-new-window "https://penpot.app/penpothub/libraries-templates"))
|
||||||
|
on-import-files (mf/use-fn #(dom/click (mf/ref-val file-input)))]
|
||||||
|
|
||||||
|
[:div {:class (stl/css :empty-project-container)}
|
||||||
|
[:div {:class (stl/css :empty-project-card) :on-click on-create :title (tr "dashboard.add-file")}
|
||||||
|
[:div {:class (stl/css :empty-project-card-title)} (tr "dashboard.empty-project.create")]
|
||||||
|
[:div {:class (stl/css :empty-project-card-subtitle)} (tr "dashboard.empty-project.start")]]
|
||||||
|
|
||||||
|
[:div {:class (stl/css :empty-project-card) :on-click on-import-files :title (tr "dashboard.empty-project.import")}
|
||||||
|
[:div {:class (stl/css :empty-project-card-title)} (tr "dashboard.empty-project.import")]
|
||||||
|
[:div {:class (stl/css :empty-project-card-subtitle)} (tr "dashboard.empty-project.import-penpot")]]
|
||||||
|
|
||||||
|
[:div {:class (stl/css :empty-project-card) :on-click on-add-library :title (tr "dashboard.empty-project.go-to-libraries")}
|
||||||
|
[:div {:class (stl/css :empty-project-card-title)} (tr "dashboard.empty-project.add-library")]
|
||||||
|
[:div {:class (stl/css :empty-project-card-subtitle)} (tr "dashboard.empty-project.explore")]]
|
||||||
|
|
||||||
|
[:& udi/import-form {:ref file-input
|
||||||
|
:project-id project-id
|
||||||
|
:on-finish-import on-finish-import}]]))
|
||||||
|
|
||||||
(mf/defc empty-placeholder
|
(mf/defc empty-placeholder
|
||||||
[{:keys [dragging? limit origin create-fn can-edit]}]
|
[{:keys [dragging? limit origin create-fn can-edit project-id on-finish-import]}]
|
||||||
(let [on-click
|
(let [on-click
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps create-fn)
|
(mf/deps create-fn)
|
||||||
|
@ -45,16 +71,18 @@
|
||||||
:tag-name "span"}])]
|
:tag-name "span"}])]
|
||||||
|
|
||||||
:else
|
:else
|
||||||
[:div {:class (stl/css :grid-empty-placeholder)}
|
(if (cf/external-feature-flag "add-file-02" "test")
|
||||||
(if (cf/external-feature-flag "add-file-01" "test")
|
[:> empty-placeholder-projects* {:on-create on-click :on-finish-import on-finish-import :project-id project-id}]
|
||||||
[:button {:class (stl/css :create-new)
|
[:div {:class (stl/css :grid-empty-placeholder)}
|
||||||
:on-click on-click
|
(if (cf/external-feature-flag "add-file-01" "test")
|
||||||
:on-mouse-enter on-mouse-enter
|
[:button {:class (stl/css :create-new)
|
||||||
:on-mouse-leave on-mouse-leave}
|
:on-click on-click
|
||||||
(if @show-text (tr "dashboard.add-file") i/add)]
|
:on-mouse-enter on-mouse-enter
|
||||||
[:button {:class (stl/css :create-new)
|
:on-mouse-leave on-mouse-leave}
|
||||||
:on-click on-click}
|
(if @show-text (tr "dashboard.add-file") i/add)]
|
||||||
i/add])])))
|
[:button {:class (stl/css :create-new)
|
||||||
|
:on-click on-click}
|
||||||
|
i/add])]))))
|
||||||
|
|
||||||
(mf/defc loading-placeholder
|
(mf/defc loading-placeholder
|
||||||
[]
|
[]
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
a {
|
a {
|
||||||
color: var(--color-foreground-primary);
|
color: var(--color-foreground-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
max-width: $s-360;
|
max-width: $s-360;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -92,6 +93,7 @@
|
||||||
|
|
||||||
.placeholder-markdown {
|
.placeholder-markdown {
|
||||||
@include t.use-typography("body-large");
|
@include t.use-typography("body-large");
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: var(--color-accent-primary);
|
color: var(--color-accent-primary);
|
||||||
}
|
}
|
||||||
|
@ -100,3 +102,43 @@
|
||||||
.empty-placeholder-libraries {
|
.empty-placeholder-libraries {
|
||||||
margin: $s-16;
|
margin: $s-16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.empty-project-container {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
gap: $s-16;
|
||||||
|
margin-top: $s-12;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-project-card {
|
||||||
|
@include t.use-typography("body-small");
|
||||||
|
--color-card-background: var(--color-background-tertiary);
|
||||||
|
--color-card-title: var(--color-foreground-primary);
|
||||||
|
--color-card-subtitle: var(--color-foreground-secondary);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
background-color: var(--color-card-background);
|
||||||
|
border: $s-2 solid var(--color-background-quaternary);
|
||||||
|
border-radius: $br-8;
|
||||||
|
padding: var(--sp-m) 0;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
--color-card-background: var(--color-accent-primary);
|
||||||
|
--color-card-title: var(--color-background-secondary);
|
||||||
|
--color-card-subtitle: var(--color-background-secondary);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-project-card-title {
|
||||||
|
color: var(--color-card-title);
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-project-card-subtitle {
|
||||||
|
color: var(--color-card-subtitle);
|
||||||
|
}
|
||||||
|
|
|
@ -1047,6 +1047,7 @@ export class SelectionController extends EventTarget {
|
||||||
if (fragment.children.length === 1
|
if (fragment.children.length === 1
|
||||||
&& fragment.firstElementChild?.dataset?.inline === "force"
|
&& fragment.firstElementChild?.dataset?.inline === "force"
|
||||||
) {
|
) {
|
||||||
|
const collapseNode = fragment.lastElementChild.firstChild
|
||||||
if (this.isInlineStart) {
|
if (this.isInlineStart) {
|
||||||
this.focusInline.before(...fragment.firstElementChild.children)
|
this.focusInline.before(...fragment.firstElementChild.children)
|
||||||
} else if (this.isInlineEnd) {
|
} else if (this.isInlineEnd) {
|
||||||
|
@ -1058,9 +1059,12 @@ export class SelectionController extends EventTarget {
|
||||||
)
|
)
|
||||||
this.focusInline.after(...fragment.firstElementChild.children, newInline)
|
this.focusInline.after(...fragment.firstElementChild.children, newInline)
|
||||||
}
|
}
|
||||||
return;
|
return this.collapse(
|
||||||
|
collapseNode,
|
||||||
|
collapseNode.nodeValue.length
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
const collapseNode = fragment.lastElementChild.lastElementChild.firstChild
|
||||||
if (this.isParagraphStart) {
|
if (this.isParagraphStart) {
|
||||||
this.focusParagraph.before(fragment);
|
this.focusParagraph.before(fragment);
|
||||||
} else if (this.isParagraphEnd) {
|
} else if (this.isParagraphEnd) {
|
||||||
|
@ -1073,6 +1077,7 @@ export class SelectionController extends EventTarget {
|
||||||
);
|
);
|
||||||
this.focusParagraph.after(fragment, newParagraph);
|
this.focusParagraph.after(fragment, newParagraph);
|
||||||
}
|
}
|
||||||
|
return this.collapse(collapseNode, collapseNode.nodeValue.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -759,6 +759,27 @@ msgstr "+ New project"
|
||||||
msgid "dashboard.new-project-prefix"
|
msgid "dashboard.new-project-prefix"
|
||||||
msgstr "New Project"
|
msgstr "New Project"
|
||||||
|
|
||||||
|
msgid "dashboard.empty-project.create"
|
||||||
|
msgstr "Create new file"
|
||||||
|
|
||||||
|
msgid "dashboard.empty-project.start"
|
||||||
|
msgstr "Start building amazing stuff"
|
||||||
|
|
||||||
|
msgid "dashboard.empty-project.import"
|
||||||
|
msgstr "Import a file"
|
||||||
|
|
||||||
|
msgid "dashboard.empty-project.import-penpot"
|
||||||
|
msgstr "Import a .penpot file"
|
||||||
|
|
||||||
|
msgid "dashboard.empty-project.add-library"
|
||||||
|
msgstr "Add a Library or a Template"
|
||||||
|
|
||||||
|
msgid "dashboard.empty-project.explore"
|
||||||
|
msgstr "Explore some to add"
|
||||||
|
|
||||||
|
msgid "dashboard.empty-project.go-to-libraries"
|
||||||
|
msgstr "Go to Libraries and Templates"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/search.cljs:77
|
#: src/app/main/ui/dashboard/search.cljs:77
|
||||||
msgid "dashboard.no-matches-for"
|
msgid "dashboard.no-matches-for"
|
||||||
msgstr "No matches found for “%s“"
|
msgstr "No matches found for “%s“"
|
||||||
|
|
|
@ -767,6 +767,27 @@ msgstr "+ Nuevo proyecto"
|
||||||
msgid "dashboard.new-project-prefix"
|
msgid "dashboard.new-project-prefix"
|
||||||
msgstr "Nuevo Proyecto"
|
msgstr "Nuevo Proyecto"
|
||||||
|
|
||||||
|
msgid "dashboard.empty-project.create"
|
||||||
|
msgstr "Crear un nuevo archivo"
|
||||||
|
|
||||||
|
msgid "dashboard.empty-project.start"
|
||||||
|
msgstr "Empieza a crear cosas increíbles"
|
||||||
|
|
||||||
|
msgid "dashboard.empty-project.import"
|
||||||
|
msgstr "Importa un fichero"
|
||||||
|
|
||||||
|
msgid "dashboard.empty-project.import-penpot"
|
||||||
|
msgstr "Importa un fichero .penpot"
|
||||||
|
|
||||||
|
msgid "dashboard.empty-project.add-library"
|
||||||
|
msgstr "Añade una Biblioteca o Plantilla"
|
||||||
|
|
||||||
|
msgid "dashboard.empty-project.explore"
|
||||||
|
msgstr "Explora algunas para añadir"
|
||||||
|
|
||||||
|
msgid "dashboard.empty-project.go-to-libraries"
|
||||||
|
msgstr "Ir a Bibliotecas y Plantillas"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/search.cljs:77
|
#: src/app/main/ui/dashboard/search.cljs:77
|
||||||
msgid "dashboard.no-matches-for"
|
msgid "dashboard.no-matches-for"
|
||||||
msgstr "No se encuentra “%s“"
|
msgstr "No se encuentra “%s“"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue