mirror of
https://github.com/penpot/penpot.git
synced 2025-04-05 03:21:26 -05:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
commit
654c070976
12 changed files with 205 additions and 63 deletions
|
@ -77,6 +77,9 @@ is a number of cores)
|
|||
- Added upload svg with images method [#5489](https://github.com/penpot/penpot/issues/5489)
|
||||
- Fix problem with root frame parent reference [Taiga #9437](https://tree.taiga.io/project/penpot/issue/9437)
|
||||
- Fix change flex direction using plugins API [Taiga #9407](https://tree.taiga.io/project/penpot/issue/9407)
|
||||
- Fix problem opening url when page-id didn't exist [Taiga #10157](https://tree.taiga.io/project/penpot/issue/10157)
|
||||
- Fix problem with onboarding to a team [Taiga #10143](https://tree.taiga.io/project/penpot/issue/10143)
|
||||
- Fix problem with grid layout crashing [Taiga #10127](https://tree.taiga.io/project/penpot/issue/10127)
|
||||
|
||||
## 2.4.3
|
||||
|
||||
|
|
|
@ -212,8 +212,10 @@
|
|||
(if (= type :column)
|
||||
[:column :column-span]
|
||||
[:row :row-span])
|
||||
from-idx (dec (get cell prop))
|
||||
to-idx (+ (dec (get cell prop)) (get cell prop-span))
|
||||
from-idx (-> (dec (get cell prop))
|
||||
(mth/clamp 0 (dec (count track-list))))
|
||||
to-idx (-> (+ (dec (get cell prop)) (get cell prop-span))
|
||||
(mth/clamp 0 (dec (count track-list))))
|
||||
tracks (subvec track-list from-idx to-idx)]
|
||||
(some? (->> tracks (d/seek #(= :flex (:type %)))))))
|
||||
|
||||
|
@ -291,8 +293,10 @@
|
|||
(fn [allocated cell]
|
||||
(let [shape-id (first (:shapes cell))
|
||||
|
||||
from-idx (dec (get cell prop))
|
||||
to-idx (+ (dec (get cell prop)) (get cell prop-span))
|
||||
from-idx (-> (dec (get cell prop))
|
||||
(mth/clamp 0 (dec (count track-list))))
|
||||
to-idx (-> (+ (dec (get cell prop)) (get cell prop-span))
|
||||
(mth/clamp 0 (dec (count track-list))))
|
||||
|
||||
indexed-tracks (subvec (d/enumerate track-list) from-idx to-idx)
|
||||
to-allocate (size-to-allocate type parent (get children-map shape-id) cell bounds objects)
|
||||
|
@ -597,11 +601,10 @@
|
|||
row (nth row-tracks (dec (:row grid-cell)) nil)
|
||||
|
||||
column-start-p (:start-p column)
|
||||
row-start-p (:start-p row)
|
||||
|
||||
start-p (gpt/add origin
|
||||
(gpt/add
|
||||
(gpt/to-vec origin column-start-p)
|
||||
(gpt/to-vec origin row-start-p)))]
|
||||
|
||||
(assoc grid-cell :start-p start-p)))))
|
||||
row-start-p (:start-p row)]
|
||||
(when (and (some? column-start-p) (some? row-start-p))
|
||||
(let [start-p (gpt/add origin
|
||||
(gpt/add
|
||||
(gpt/to-vec origin column-start-p)
|
||||
(gpt/to-vec origin row-start-p)))]
|
||||
(assoc grid-cell :start-p start-p)))))))
|
||||
|
|
|
@ -114,61 +114,62 @@
|
|||
|
||||
(defn child-position-delta
|
||||
[parent child child-bounds child-width child-height layout-data cell-data]
|
||||
(let [cell-bounds (cell-bounds layout-data cell-data)
|
||||
child-origin (gpo/origin child-bounds)
|
||||
(if-let [cell-bounds (cell-bounds layout-data cell-data)]
|
||||
(let [child-origin (gpo/origin child-bounds)
|
||||
|
||||
align (:layout-align-items parent)
|
||||
justify (:layout-justify-items parent)
|
||||
align-self (:align-self cell-data)
|
||||
justify-self (:justify-self cell-data)
|
||||
align (:layout-align-items parent)
|
||||
justify (:layout-justify-items parent)
|
||||
align-self (:align-self cell-data)
|
||||
justify-self (:justify-self cell-data)
|
||||
|
||||
align-self (when (and align-self (not= align-self :auto)) align-self)
|
||||
justify-self (when (and justify-self (not= justify-self :auto)) justify-self)
|
||||
align-self (when (and align-self (not= align-self :auto)) align-self)
|
||||
justify-self (when (and justify-self (not= justify-self :auto)) justify-self)
|
||||
|
||||
align (or align-self align)
|
||||
justify (or justify-self justify)
|
||||
align (or align-self align)
|
||||
justify (or justify-self justify)
|
||||
|
||||
origin-h (gpo/project-point cell-bounds :h child-origin)
|
||||
origin-v (gpo/project-point cell-bounds :v child-origin)
|
||||
hv (partial gpo/start-hv cell-bounds)
|
||||
vv (partial gpo/start-vv cell-bounds)
|
||||
origin-h (gpo/project-point cell-bounds :h child-origin)
|
||||
origin-v (gpo/project-point cell-bounds :v child-origin)
|
||||
hv (partial gpo/start-hv cell-bounds)
|
||||
vv (partial gpo/start-vv cell-bounds)
|
||||
|
||||
[top-m right-m bottom-m left-m] (ctl/child-margins child)
|
||||
[top-m right-m bottom-m left-m] (ctl/child-margins child)
|
||||
|
||||
;; Adjust alignment/justify
|
||||
[from-h to-h]
|
||||
(case justify
|
||||
:end
|
||||
[(gpt/add origin-h (hv child-width))
|
||||
(gpt/subtract (nth cell-bounds 1) (hv right-m))]
|
||||
;; Adjust alignment/justify
|
||||
[from-h to-h]
|
||||
(case justify
|
||||
:end
|
||||
[(gpt/add origin-h (hv child-width))
|
||||
(gpt/subtract (nth cell-bounds 1) (hv right-m))]
|
||||
|
||||
:center
|
||||
[(gpt/add origin-h (hv (/ child-width 2)))
|
||||
(-> (gpo/project-point cell-bounds :h (gpo/center cell-bounds))
|
||||
(gpt/add (hv (/ left-m 2)))
|
||||
(gpt/subtract (hv (/ right-m 2))))]
|
||||
:center
|
||||
[(gpt/add origin-h (hv (/ child-width 2)))
|
||||
(-> (gpo/project-point cell-bounds :h (gpo/center cell-bounds))
|
||||
(gpt/add (hv (/ left-m 2)))
|
||||
(gpt/subtract (hv (/ right-m 2))))]
|
||||
|
||||
[origin-h
|
||||
(gpt/add (first cell-bounds) (hv left-m))])
|
||||
[origin-h
|
||||
(gpt/add (first cell-bounds) (hv left-m))])
|
||||
|
||||
[from-v to-v]
|
||||
(case align
|
||||
:end
|
||||
[(gpt/add origin-v (vv child-height))
|
||||
(gpt/subtract (nth cell-bounds 3) (vv bottom-m))]
|
||||
[from-v to-v]
|
||||
(case align
|
||||
:end
|
||||
[(gpt/add origin-v (vv child-height))
|
||||
(gpt/subtract (nth cell-bounds 3) (vv bottom-m))]
|
||||
|
||||
:center
|
||||
[(gpt/add origin-v (vv (/ child-height 2)))
|
||||
(-> (gpo/project-point cell-bounds :v (gpo/center cell-bounds))
|
||||
(gpt/add (vv top-m))
|
||||
(gpt/subtract (vv bottom-m)))]
|
||||
:center
|
||||
[(gpt/add origin-v (vv (/ child-height 2)))
|
||||
(-> (gpo/project-point cell-bounds :v (gpo/center cell-bounds))
|
||||
(gpt/add (vv top-m))
|
||||
(gpt/subtract (vv bottom-m)))]
|
||||
|
||||
[origin-v
|
||||
(gpt/add (first cell-bounds) (vv top-m))])]
|
||||
[origin-v
|
||||
(gpt/add (first cell-bounds) (vv top-m))])]
|
||||
|
||||
(-> (gpt/point)
|
||||
(gpt/add (gpt/to-vec from-h to-h))
|
||||
(gpt/add (gpt/to-vec from-v to-v)))))
|
||||
(-> (gpt/point)
|
||||
(gpt/add (gpt/to-vec from-h to-h))
|
||||
(gpt/add (gpt/to-vec from-v to-v))))
|
||||
(gpt/point 0 0)))
|
||||
|
||||
(defn child-modifiers
|
||||
[parent parent-bounds child child-bounds layout-data cell-data]
|
||||
|
|
1
frontend/playwright/data/dashboard/delete-team.json
Normal file
1
frontend/playwright/data/dashboard/delete-team.json
Normal file
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -0,0 +1,48 @@
|
|||
[
|
||||
{
|
||||
"~:features": {
|
||||
"~#set": [
|
||||
"layout/grid",
|
||||
"styles/v2",
|
||||
"fdata/pointer-map",
|
||||
"fdata/objects-map",
|
||||
"components/v2",
|
||||
"fdata/shape-data-type"
|
||||
]
|
||||
},
|
||||
"~:permissions": {
|
||||
"~:type": "~:membership",
|
||||
"~:is-owner": true,
|
||||
"~:is-admin": true,
|
||||
"~:can-edit": true
|
||||
},
|
||||
"~:name": "Default",
|
||||
"~:modified-at": "~m1713533116375",
|
||||
"~:id": "~uc7ce0794-0992-8105-8004-38e630f40f6d",
|
||||
"~:created-at": "~m1713533116375",
|
||||
"~:is-default": true
|
||||
},
|
||||
{
|
||||
"~:features": {
|
||||
"~#set": [
|
||||
"layout/grid",
|
||||
"styles/v2",
|
||||
"fdata/pointer-map",
|
||||
"fdata/objects-map",
|
||||
"components/v2",
|
||||
"fdata/shape-data-type"
|
||||
]
|
||||
},
|
||||
"~:permissions": {
|
||||
"~:type": "~:membership",
|
||||
"~:is-owner": true,
|
||||
"~:is-admin": true,
|
||||
"~:can-edit": true
|
||||
},
|
||||
"~:name": "Second team",
|
||||
"~:modified-at": "~m1701164272671",
|
||||
"~:id": "~udd33ff88-f4e5-8033-8003-8096cc07bdf3",
|
||||
"~:created-at": "~m1701164272671",
|
||||
"~:is-default": false
|
||||
}
|
||||
]
|
|
@ -155,6 +155,9 @@ export class DashboardPage extends BaseWebSocketPage {
|
|||
await this.mockRPC("search-files", "dashboard/search-files.json", {
|
||||
method: "POST",
|
||||
});
|
||||
await this.mockRPC("delete-team", "dashboard/delete-team.json", {
|
||||
method: "POST",
|
||||
});
|
||||
await this.mockRPC("search-files", "dashboard/search-files.json");
|
||||
await this.mockRPC("get-teams", "logged-in-user/get-teams-complete.json");
|
||||
}
|
||||
|
|
|
@ -84,6 +84,33 @@ test("User has context menu options for edit file", async ({ page }) => {
|
|||
await expect(dashboardPage.page.getByText("delete")).toBeVisible();
|
||||
});
|
||||
|
||||
test("Multiple elements in context", async ({ page }) => {
|
||||
await DashboardPage.mockRPC(
|
||||
page,
|
||||
"get-all-projects",
|
||||
"dashboard/get-all-projects.json",
|
||||
);
|
||||
|
||||
const dashboardPage = new DashboardPage(page);
|
||||
await dashboardPage.setupDrafts();
|
||||
await dashboardPage.goToDrafts();
|
||||
|
||||
const button = dashboardPage.page.getByRole("button", { name: /New File 1/ });
|
||||
await button.click();
|
||||
|
||||
const button2 = dashboardPage.page.getByRole("button", {
|
||||
name: /New File 2/,
|
||||
});
|
||||
await button2.click({ modifiers: ["Shift"] });
|
||||
|
||||
await button.click({ button: "right" });
|
||||
|
||||
await expect(button.getByTestId("duplicate-multi")).toBeVisible();
|
||||
await expect(button.getByTestId("file-move-multi")).toBeVisible();
|
||||
await expect(button.getByTestId("file-binary-export-multi")).toBeVisible();
|
||||
await expect(button.getByTestId("file-delete-multi")).toBeVisible();
|
||||
});
|
||||
|
||||
test("User has create file button", async ({ page }) => {
|
||||
const dashboardPage = new DashboardPage(page);
|
||||
await dashboardPage.setupDrafts();
|
||||
|
@ -131,3 +158,31 @@ test("Bug 9927, Don't show the banner to invite team members if the user has dis
|
|||
await expect(page.getByText("Second team")).toBeVisible();
|
||||
await expect(page.getByText("Team Up")).not.toBeVisible();
|
||||
});
|
||||
|
||||
test("Bug 10141, The team does not disappear from the team list after deletion", async ({
|
||||
page,
|
||||
}) => {
|
||||
const dashboardPage = new DashboardPage(page);
|
||||
await dashboardPage.setupDashboardFull();
|
||||
await DashboardPage.mockRPC(
|
||||
page,
|
||||
"get-teams",
|
||||
"logged-in-user/get-teams-complete-owner.json",
|
||||
);
|
||||
await dashboardPage.goToDashboard();
|
||||
await dashboardPage.teamDropdown.click();
|
||||
await expect(page.getByText("Second Team")).toBeVisible();
|
||||
await page.getByText("Second Team").click();
|
||||
await page.getByRole("button", { name: "team-management" }).click();
|
||||
await page.getByTestId("delete-team").click();
|
||||
|
||||
await DashboardPage.mockRPC(
|
||||
page,
|
||||
"get-teams",
|
||||
"logged-in-user/get-teams-default.json",
|
||||
);
|
||||
|
||||
await page.getByRole("button", { name: "Delete team" }).click();
|
||||
await dashboardPage.teamDropdown.click();
|
||||
await expect(page.getByText("Second Team")).not.toBeVisible();
|
||||
});
|
||||
|
|
|
@ -15,6 +15,17 @@ test("User loads worskpace with empty file", async ({ page }) => {
|
|||
await expect(workspacePage.pageName).toHaveText("Page 1");
|
||||
});
|
||||
|
||||
test("User opens a file with a bad page id", async ({ page }) => {
|
||||
const workspacePage = new WorkspacePage(page);
|
||||
await workspacePage.setupEmptyFile(page);
|
||||
|
||||
await workspacePage.goToWorkspace({
|
||||
pageId: "badpage",
|
||||
});
|
||||
|
||||
await expect(workspacePage.pageName).toHaveText("Page 1");
|
||||
});
|
||||
|
||||
test("User receives presence notifications updates in the workspace", async ({
|
||||
page,
|
||||
}) => {
|
||||
|
|
|
@ -474,6 +474,13 @@
|
|||
(rx/tap on-success)
|
||||
(rx/catch on-error))))))
|
||||
|
||||
(defn- team-deleted
|
||||
[id]
|
||||
(ptk/reify ::team-deleted
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :teams dissoc id))))
|
||||
|
||||
(defn delete-team
|
||||
[{:keys [id] :as params}]
|
||||
(ptk/reify ::delete-team
|
||||
|
@ -485,7 +492,10 @@
|
|||
(meta params)]
|
||||
|
||||
(->> (rp/cmd! :delete-team {:id id})
|
||||
(rx/mapcat on-success)
|
||||
(rx/mapcat (fn [result]
|
||||
(rx/concat
|
||||
(rx/of (team-deleted id))
|
||||
(on-success result))))
|
||||
(rx/catch on-error))))))
|
||||
|
||||
(defn delete-webhook
|
||||
|
|
|
@ -450,10 +450,12 @@
|
|||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [file-id (:current-file-id state)]
|
||||
(rx/of (preload-data-uris page-id)
|
||||
(dwth/watch-state-changes file-id page-id)
|
||||
(dwl/watch-component-changes))))))
|
||||
(if (dsh/lookup-page state page-id)
|
||||
(let [file-id (:current-file-id state)]
|
||||
(rx/of (preload-data-uris page-id)
|
||||
(dwth/watch-state-changes file-id page-id)
|
||||
(dwl/watch-component-changes)))
|
||||
(rx/of (dcm/go-to-workspace))))))
|
||||
|
||||
(defn finalize-page
|
||||
[page-id]
|
||||
|
|
|
@ -333,7 +333,7 @@
|
|||
|
||||
on-context-menu
|
||||
(mf/use-fn
|
||||
(mf/deps is-library-view)
|
||||
(mf/deps on-menu-click is-library-view)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(dom/prevent-default event)
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
[app.main.data.event :as-alias ev]
|
||||
[app.main.data.notifications :as ntf]
|
||||
[app.main.data.profile :as du]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
|
@ -22,6 +23,7 @@
|
|||
(let [state* (mf/use-state #(do {:newsletter-updates false
|
||||
:newsletter-news false}))
|
||||
state (deref state*)
|
||||
team (mf/deref refs/team)
|
||||
|
||||
on-change
|
||||
(mf/use-fn
|
||||
|
@ -33,7 +35,7 @@
|
|||
|
||||
on-next
|
||||
(mf/use-fn
|
||||
(mf/deps state)
|
||||
(mf/deps state team)
|
||||
(fn []
|
||||
(when (or (:newsletter-updates state)
|
||||
(:newsletter-news state))
|
||||
|
@ -44,7 +46,10 @@
|
|||
(assoc :label "newsletter:subscriptions")
|
||||
(assoc :step 6))]
|
||||
(st/emit! (ptk/data-event ::ev/event params)
|
||||
(du/update-profile-props state)))))]
|
||||
(du/update-profile-props
|
||||
(cond-> state
|
||||
(not (:is-default team))
|
||||
(assoc :onboarding-viewed true)))))))]
|
||||
|
||||
[:div {:class (stl/css-case
|
||||
:modal-overlay true)}
|
||||
|
|
Loading…
Add table
Reference in a new issue