From f88bb4e2049dbd0f7e2065a5dce1341f86a78a74 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 10 Jun 2024 16:03:07 +0200 Subject: [PATCH] :bug: Fix problem moving layout to frame --- common/src/app/common/types/shape/layout.cljc | 29 +- .../data/workspace/get-file-7760.json | 49 +++ .../workspace/get-file-fragment-7760.json | 383 ++++++++++++++++++ frontend/playwright/ui/pages/WorkspacePage.js | 7 + .../playwright/ui/specs/design-tab.spec.js | 32 ++ .../playwright/ui/specs/workspace.spec.js | 1 - .../app/main/ui/components/radio_buttons.cljs | 2 +- frontend/src/app/main/ui/shapes/shape.cljs | 1 + .../sidebar/options/menus/layout_item.cljs | 4 +- 9 files changed, 492 insertions(+), 16 deletions(-) create mode 100644 frontend/playwright/data/workspace/get-file-7760.json create mode 100644 frontend/playwright/data/workspace/get-file-fragment-7760.json diff --git a/common/src/app/common/types/shape/layout.cljc b/common/src/app/common/types/shape/layout.cljc index 7f5e6e83a..f791eaee1 100644 --- a/common/src/app/common/types/shape/layout.cljc +++ b/common/src/app/common/types/shape/layout.cljc @@ -604,18 +604,23 @@ (defn remove-layout-item-data [shape] - (dissoc shape - :layout-item-margin - :layout-item-margin-type - :layout-item-h-sizing - :layout-item-v-sizing - :layout-item-max-h - :layout-item-min-h - :layout-item-max-w - :layout-item-min-w - :layout-item-align-self - :layout-item-absolute - :layout-item-z-index)) + (-> shape + (dissoc :layout-item-margin + :layout-item-margin-type + :layout-item-max-h + :layout-item-min-h + :layout-item-max-w + :layout-item-min-w + :layout-item-align-self + :layout-item-absolute + :layout-item-z-index) + (cond-> (or (not (any-layout? shape)) + (= :fill (:layout-item-h-sizing shape))) + (dissoc :layout-item-h-sizing) + + (or (not (any-layout? shape)) + (= :fill (:layout-item-v-sizing shape))) + (dissoc :layout-item-v-sizing)))) (defn update-flex-scale [shape scale] diff --git a/frontend/playwright/data/workspace/get-file-7760.json b/frontend/playwright/data/workspace/get-file-7760.json new file mode 100644 index 000000000..ff33a7a94 --- /dev/null +++ b/frontend/playwright/data/workspace/get-file-7760.json @@ -0,0 +1,49 @@ +{ + "~: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, + "~:can-read": true, + "~:is-logged": true + }, + "~:has-media-trimmed": false, + "~:comment-thread-seqn": 0, + "~:name": "New File 6", + "~:revn": 5, + "~:modified-at": "~m1718094617219", + "~:id": "~ucd90e028-326a-80b4-8004-7cdec16ffad5", + "~:is-shared": false, + "~:version": 48, + "~:project-id": "~u128636f9-5e78-812b-8004-350dd1a8869a", + "~:created-at": "~m1718094569923", + "~:data": { + "~:pages": [ + "~ucd90e028-326a-80b4-8004-7cdec16ffad6" + ], + "~:pages-index": { + "~ucd90e028-326a-80b4-8004-7cdec16ffad6": { + "~#penpot/pointer": [ + "~ucd90e028-326a-80b4-8004-7cdeefa23ece", + { + "~:created-at": "~m1718094617224" + } + ] + } + }, + "~:id": "~ucd90e028-326a-80b4-8004-7cdec16ffad5", + "~:options": { + "~:components-v2": true + } + } +} diff --git a/frontend/playwright/data/workspace/get-file-fragment-7760.json b/frontend/playwright/data/workspace/get-file-fragment-7760.json new file mode 100644 index 000000000..0c8011553 --- /dev/null +++ b/frontend/playwright/data/workspace/get-file-fragment-7760.json @@ -0,0 +1,383 @@ +{ + "~:id": "~ucd90e028-326a-80b4-8004-7cdeefa23ece", + "~:file-id": "~ucd90e028-326a-80b4-8004-7cdec16ffad5", + "~:created-at": "~m1718094617214", + "~:content": { + "~:options": {}, + "~:objects": { + "~u00000000-0000-0000-0000-000000000000": { + "~#shape": { + "~:y": 0, + "~:hide-fill-on-export": false, + "~:transform": { + "~#matrix": { + "~:a": 1.0, + "~:b": 0.0, + "~:c": 0.0, + "~:d": 1.0, + "~:e": 0.0, + "~:f": 0.0 + } + }, + "~:rotation": 0, + "~:name": "Root Frame", + "~:width": 0.01, + "~:type": "~:frame", + "~:points": [ + { + "~#point": { + "~:x": 0, + "~:y": 0 + } + }, + { + "~#point": { + "~:x": 0.01, + "~:y": 0 + } + }, + { + "~#point": { + "~:x": 0.01, + "~:y": 0.01 + } + }, + { + "~#point": { + "~:x": 0, + "~:y": 0.01 + } + } + ], + "~:proportion-lock": false, + "~:transform-inverse": { + "~#matrix": { + "~:a": 1.0, + "~:b": 0.0, + "~:c": 0.0, + "~:d": 1.0, + "~:e": 0.0, + "~:f": 0.0 + } + }, + "~:id": "~u00000000-0000-0000-0000-000000000000", + "~:parent-id": "~u00000000-0000-0000-0000-000000000000", + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [], + "~:x": 0, + "~:proportion": 1.0, + "~:selrect": { + "~#rect": { + "~:x": 0, + "~:y": 0, + "~:width": 0.01, + "~:height": 0.01, + "~:x1": 0, + "~:y1": 0, + "~:x2": 0.01, + "~:y2": 0.01 + } + }, + "~:fills": [ + { + "~:fill-color": "#FFFFFF", + "~:fill-opacity": 1 + } + ], + "~:flip-x": null, + "~:height": 0.01, + "~:flip-y": null, + "~:shapes": [ + "~u86087f92-9a17-8067-8004-7cdec45bee43", + "~u86087f92-9a17-8067-8004-7cded1cbe70e" + ] + } + }, + "~u86087f92-9a17-8067-8004-7cdec45bee43": { + "~#shape": { + "~:y": 341, + "~:hide-fill-on-export": false, + "~:layout-gap-type": "~:multiple", + "~:layout-padding": { + "~:p1": 34, + "~:p2": 36, + "~:p3": 34, + "~:p4": 36 + }, + "~:transform": { + "~#matrix": { + "~:a": 1.0, + "~:b": 0.0, + "~:c": 0.0, + "~:d": 1.0, + "~:e": 0.0, + "~:f": 0.0 + } + }, + "~:rotation": 0, + "~:layout-wrap-type": "~:nowrap", + "~:grow-type": "~:fixed", + "~:layout": "~:flex", + "~:hide-in-viewer": false, + "~:name": "Flex Board", + "~:layout-align-items": "~:start", + "~:width": 176, + "~:layout-padding-type": "~:simple", + "~:type": "~:frame", + "~:points": [ + { + "~#point": { + "~:x": 217, + "~:y": 341 + } + }, + { + "~#point": { + "~:x": 393, + "~:y": 341 + } + }, + { + "~#point": { + "~:x": 393, + "~:y": 511 + } + }, + { + "~#point": { + "~:x": 217, + "~:y": 511 + } + } + ], + "~:layout-item-h-sizing": "~:auto", + "~:proportion-lock": false, + "~:layout-gap": { + "~:row-gap": 0, + "~:column-gap": 0 + }, + "~:transform-inverse": { + "~#matrix": { + "~:a": 1.0, + "~:b": 0.0, + "~:c": 0.0, + "~:d": 1.0, + "~:e": 0.0, + "~:f": 0.0 + } + }, + "~:layout-item-v-sizing": "~:auto", + "~:layout-justify-content": "~:start", + "~:id": "~u86087f92-9a17-8067-8004-7cdec45bee43", + "~:parent-id": "~u00000000-0000-0000-0000-000000000000", + "~:layout-flex-dir": "~:row", + "~:layout-align-content": "~:stretch", + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [], + "~:x": 217, + "~:proportion": 1, + "~:selrect": { + "~#rect": { + "~:x": 217, + "~:y": 341, + "~:width": 176, + "~:height": 170, + "~:x1": 217, + "~:y1": 341, + "~:x2": 393, + "~:y2": 511 + } + }, + "~:fills": [ + { + "~:fill-color": "#FFFFFF", + "~:fill-opacity": 1 + } + ], + "~:flip-x": null, + "~:height": 170, + "~:flip-y": null, + "~:shapes": [ + "~u86087f92-9a17-8067-8004-7cdec98dfa7f" + ] + } + }, + "~u86087f92-9a17-8067-8004-7cdec98dfa7f": { + "~#shape": { + "~:y": 375, + "~:rx": 0, + "~:transform": { + "~#matrix": { + "~:a": 1.0, + "~:b": 0.0, + "~:c": 0.0, + "~:d": 1.0, + "~:e": 0.0, + "~:f": 0.0 + } + }, + "~:rotation": 0, + "~:grow-type": "~:fixed", + "~:hide-in-viewer": false, + "~:name": "Rectangle", + "~:width": 104, + "~:type": "~:rect", + "~:points": [ + { + "~#point": { + "~:x": 253, + "~:y": 375 + } + }, + { + "~#point": { + "~:x": 357, + "~:y": 375 + } + }, + { + "~#point": { + "~:x": 357, + "~:y": 477 + } + }, + { + "~#point": { + "~:x": 253, + "~:y": 477 + } + } + ], + "~:proportion-lock": false, + "~:transform-inverse": { + "~#matrix": { + "~:a": 1.0, + "~:b": 0.0, + "~:c": 0.0, + "~:d": 1.0, + "~:e": 0.0, + "~:f": 0.0 + } + }, + "~:id": "~u86087f92-9a17-8067-8004-7cdec98dfa7f", + "~:parent-id": "~u86087f92-9a17-8067-8004-7cdec45bee43", + "~:frame-id": "~u86087f92-9a17-8067-8004-7cdec45bee43", + "~:strokes": [], + "~:x": 253, + "~:proportion": 1, + "~:selrect": { + "~#rect": { + "~:x": 253, + "~:y": 375, + "~:width": 104, + "~:height": 102, + "~:x1": 253, + "~:y1": 375, + "~:x2": 357, + "~:y2": 477 + } + }, + "~:fills": [ + { + "~:fill-color": "#B1B2B5", + "~:fill-opacity": 1 + } + ], + "~:flip-x": null, + "~:ry": 0, + "~:height": 102, + "~:flip-y": null + } + }, + "~u86087f92-9a17-8067-8004-7cded1cbe70e": { + "~#shape": { + "~:y": 300, + "~:hide-fill-on-export": false, + "~:transform": { + "~#matrix": { + "~:a": 1.0, + "~:b": 0.0, + "~:c": 0.0, + "~:d": 1.0, + "~:e": 0.0, + "~:f": 0.0 + } + }, + "~:rotation": 0, + "~:grow-type": "~:fixed", + "~:hide-in-viewer": false, + "~:name": "Container Board", + "~:width": 434, + "~:type": "~:frame", + "~:points": [ + { + "~#point": { + "~:x": 689, + "~:y": 300 + } + }, + { + "~#point": { + "~:x": 1123, + "~:y": 300 + } + }, + { + "~#point": { + "~:x": 1123, + "~:y": 741 + } + }, + { + "~#point": { + "~:x": 689, + "~:y": 741 + } + } + ], + "~:proportion-lock": false, + "~:transform-inverse": { + "~#matrix": { + "~:a": 1.0, + "~:b": 0.0, + "~:c": 0.0, + "~:d": 1.0, + "~:e": 0.0, + "~:f": 0.0 + } + }, + "~:id": "~u86087f92-9a17-8067-8004-7cded1cbe70e", + "~:parent-id": "~u00000000-0000-0000-0000-000000000000", + "~:frame-id": "~u00000000-0000-0000-0000-000000000000", + "~:strokes": [], + "~:x": 689, + "~:proportion": 1, + "~:selrect": { + "~#rect": { + "~:x": 689, + "~:y": 300, + "~:width": 434, + "~:height": 441, + "~:x1": 689, + "~:y1": 300, + "~:x2": 1123, + "~:y2": 741 + } + }, + "~:fills": [ + { + "~:fill-color": "#FFFFFF", + "~:fill-opacity": 1 + } + ], + "~:flip-x": null, + "~:height": 441, + "~:flip-y": null, + "~:shapes": [] + } + } + }, + "~:id": "~ucd90e028-326a-80b4-8004-7cdec16ffad6", + "~:name": "Page 1" + } +} diff --git a/frontend/playwright/ui/pages/WorkspacePage.js b/frontend/playwright/ui/pages/WorkspacePage.js index 72e0fa9fd..4f045344b 100644 --- a/frontend/playwright/ui/pages/WorkspacePage.js +++ b/frontend/playwright/ui/pages/WorkspacePage.js @@ -102,6 +102,13 @@ export class WorkspacePage extends BaseWebSocketPage { await this.page.mouse.up(); } + async moveSelectionToShape(name) { + await this.page.locator('rect.viewport-selrect').hover(); + await this.page.mouse.down(); + await this.viewport.getByTestId(name).first().hover({ force: true }); + await this.page.mouse.up(); + } + async clickLeafLayer(name, clickOptions = {}) { const layer = this.layers.getByText(name); await layer.click(clickOptions); diff --git a/frontend/playwright/ui/specs/design-tab.spec.js b/frontend/playwright/ui/specs/design-tab.spec.js index 0d637bace..7dc23cd1f 100644 --- a/frontend/playwright/ui/specs/design-tab.spec.js +++ b/frontend/playwright/ui/specs/design-tab.spec.js @@ -44,3 +44,35 @@ test.describe("Constraints", () => { expect(false); }); }); + +test("BUG 7760 - Layout losing properties when changing parents", async ({ page }) => { + const workspacePage = new WorkspacePage(page); + await workspacePage.setupEmptyFile(); + await workspacePage.mockRPC(/get\-file\?/, "workspace/get-file-7760.json"); + await workspacePage.mockRPC( + "get-file-fragment?file-id=*&fragment-id=*", + "workspace/get-file-fragment-7760.json", + ); + await workspacePage.mockRPC("update-file?id=*", "workspace/update-file-create-rect.json"); + + await workspacePage.goToWorkspace({ + fileId: "cd90e028-326a-80b4-8004-7cdec16ffad5", + pageId: "cd90e028-326a-80b4-8004-7cdec16ffad6", + }); + + // Select the flex board and drag it into the other container board + await workspacePage.clickLeafLayer("Flex Board"); + + // Move the first board into the second + const hAuto = await workspacePage.page.getByTitle("Fit content (Horizontal)"); + const vAuto = await workspacePage.page.getByTitle("Fit content (Vertical)"); + + await expect(vAuto.locator("input")).toBeChecked(); + await expect(hAuto.locator("input")).toBeChecked(); + + await workspacePage.moveSelectionToShape("Container Board"); + + // The first board properties should still be auto width/height + await expect(vAuto.locator("input")).toBeChecked(); + await expect(hAuto.locator("input")).toBeChecked(); +}); diff --git a/frontend/playwright/ui/specs/workspace.spec.js b/frontend/playwright/ui/specs/workspace.spec.js index f391949b4..8f5e5c609 100644 --- a/frontend/playwright/ui/specs/workspace.spec.js +++ b/frontend/playwright/ui/specs/workspace.spec.js @@ -67,7 +67,6 @@ test("User adds a library and its automatically selected in the color palette", await expect(workspacePage.palette.getByText('There are no color styles in your library yet')).toBeVisible(); }); - test("User makes a group", async ({ page }) => { const workspacePage = new WorkspacePage(page); await workspacePage.setupEmptyFile(); diff --git a/frontend/src/app/main/ui/components/radio_buttons.cljs b/frontend/src/app/main/ui/components/radio_buttons.cljs index 0d7cce294..dbaffebb5 100644 --- a/frontend/src/app/main/ui/components/radio_buttons.cljs +++ b/frontend/src/app/main/ui/components/radio_buttons.cljs @@ -54,7 +54,7 @@ :name name :disabled disabled :value value - :checked checked?}]])) + :default-checked checked?}]])) (mf/defc radio-buttons {::mf/props :obj} diff --git a/frontend/src/app/main/ui/shapes/shape.cljs b/frontend/src/app/main/ui/shapes/shape.cljs index e4082b89c..c344ec857 100644 --- a/frontend/src/app/main/ui/shapes/shape.cljs +++ b/frontend/src/app/main/ui/shapes/shape.cljs @@ -96,6 +96,7 @@ (obj/unset! "disable-shadows?") (obj/set! "ref" ref) (obj/set! "id" (dm/fmt "shape-%" shape-id)) + (obj/set! "data-testid" (:name shape)) ;; TODO: This is added for backward compatibility. (cond-> (and (cfh/text-shape? shape) (empty? (:position-data shape))) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs index 5092d025b..681e879f3 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs @@ -250,7 +250,7 @@ [:& radio-button {:value "auto" :icon i/hug-content - :title "Fit content" + :title "Fit content (Horizontal)" :id "behaviour-h-auto"}])]]) (mf/defc element-behaviour-vertical @@ -288,7 +288,7 @@ {:value "auto" :icon i/hug-content :icon-class (stl/css :rotated) - :title "Fit content" + :title "Fit content (Vertical)" :id "behaviour-v-auto"}])]]) (mf/defc align-self-row