mirror of
https://github.com/penpot/penpot.git
synced 2026-06-09 17:02:05 +00:00
🐛 Fix locked flex and grid elements cannot be selected in viewer role (#9865)
* 🐛 Fix locked flex and grid elements cannot be selected in viewer role * ✨ Add playwright test
This commit is contained in:
parent
a5c8bcaf9e
commit
0b56fd2f77
@ -313,6 +313,9 @@
|
||||
(top-nested-frame objects position nil))
|
||||
|
||||
([objects position excluded]
|
||||
(top-nested-frame objects position excluded false))
|
||||
|
||||
([objects position excluded read-only?]
|
||||
(assert (or (nil? excluded) (set? excluded)))
|
||||
|
||||
(let [frames (cond->> (get-frames-by-position objects position)
|
||||
@ -323,7 +326,8 @@
|
||||
|
||||
:always
|
||||
(remove #(or ^boolean (true? (:hidden %))
|
||||
^boolean (true? (:blocked %)))))
|
||||
^boolean (and (true? (:blocked %))
|
||||
(not read-only?)))))
|
||||
|
||||
frame-set (into #{} (map #(dm/get-prop % :id)) frames)]
|
||||
|
||||
|
||||
144
frontend/playwright/data/workspace/get-file-14250.json
Normal file
144
frontend/playwright/data/workspace/get-file-14250.json
Normal file
@ -0,0 +1,144 @@
|
||||
{
|
||||
"~:features": {
|
||||
"~#set": [
|
||||
"fdata/path-data",
|
||||
"plugins/runtime",
|
||||
"design-tokens/v1",
|
||||
"variants/v1",
|
||||
"layout/grid",
|
||||
"styles/v2",
|
||||
"fdata/objects-map",
|
||||
"tokens/numeric-input",
|
||||
"render-wasm/v1",
|
||||
"components/v2",
|
||||
"fdata/shape-data-type"
|
||||
]
|
||||
},
|
||||
"~:team-id": "~uc7ce0794-0992-8105-8004-38e630f7920a",
|
||||
"~:permissions": {
|
||||
"~:type": "~:membership",
|
||||
"~:is-owner": false,
|
||||
"~:is-admin": false,
|
||||
"~:can-edit": false,
|
||||
"~:can-read": true,
|
||||
"~:is-logged": true
|
||||
},
|
||||
"~:has-media-trimmed": false,
|
||||
"~:comment-thread-seqn": 0,
|
||||
"~:name": "New File 1",
|
||||
"~:revn": 35,
|
||||
"~:modified-at": "~m1779815420126",
|
||||
"~:vern": 0,
|
||||
"~:id": "~u35e4ba42-fc4e-817d-8008-12287202d225",
|
||||
"~:is-shared": false,
|
||||
"~:migrations": {
|
||||
"~#ordered-set": [
|
||||
"legacy-2",
|
||||
"legacy-3",
|
||||
"legacy-5",
|
||||
"legacy-6",
|
||||
"legacy-7",
|
||||
"legacy-8",
|
||||
"legacy-9",
|
||||
"legacy-10",
|
||||
"legacy-11",
|
||||
"legacy-12",
|
||||
"legacy-13",
|
||||
"legacy-14",
|
||||
"legacy-16",
|
||||
"legacy-17",
|
||||
"legacy-18",
|
||||
"legacy-19",
|
||||
"legacy-25",
|
||||
"legacy-26",
|
||||
"legacy-27",
|
||||
"legacy-28",
|
||||
"legacy-29",
|
||||
"legacy-31",
|
||||
"legacy-32",
|
||||
"legacy-33",
|
||||
"legacy-34",
|
||||
"legacy-36",
|
||||
"legacy-37",
|
||||
"legacy-38",
|
||||
"legacy-39",
|
||||
"legacy-40",
|
||||
"legacy-41",
|
||||
"legacy-42",
|
||||
"legacy-43",
|
||||
"legacy-44",
|
||||
"legacy-45",
|
||||
"legacy-46",
|
||||
"legacy-47",
|
||||
"legacy-48",
|
||||
"legacy-49",
|
||||
"legacy-50",
|
||||
"legacy-51",
|
||||
"legacy-52",
|
||||
"legacy-53",
|
||||
"legacy-54",
|
||||
"legacy-55",
|
||||
"legacy-56",
|
||||
"legacy-57",
|
||||
"legacy-59",
|
||||
"legacy-62",
|
||||
"legacy-65",
|
||||
"legacy-66",
|
||||
"legacy-67",
|
||||
"0001-remove-tokens-from-groups",
|
||||
"0002-normalize-bool-content-v2",
|
||||
"0002-clean-shape-interactions",
|
||||
"0003-fix-root-shape",
|
||||
"0003-convert-path-content-v2",
|
||||
"0005-deprecate-image-type",
|
||||
"0006-fix-old-texts-fills",
|
||||
"0008-fix-library-colors-v4",
|
||||
"0009-clean-library-colors",
|
||||
"0009-add-partial-text-touched-flags",
|
||||
"0010-fix-swap-slots-pointing-non-existent-shapes",
|
||||
"0011-fix-invalid-text-touched-flags",
|
||||
"0012-fix-position-data",
|
||||
"0013-fix-component-path",
|
||||
"0013-clear-invalid-strokes-and-fills",
|
||||
"0014-fix-tokens-lib-duplicate-ids",
|
||||
"0014-clear-components-nil-objects",
|
||||
"0015-fix-text-attrs-blank-strings",
|
||||
"0015-clean-shadow-color",
|
||||
"0016-copy-fills-from-position-data-to-text-node",
|
||||
"0017-fix-layout-flex-dir",
|
||||
"0018-remove-unneeded-objects-from-components",
|
||||
"0019-fix-missing-swap-slots",
|
||||
"0020-sync-component-id-with-near-main",
|
||||
"0021-fix-shape-svg-attrs",
|
||||
"0022-normalize-component-root-and-resync",
|
||||
"0021-repair-bad-tokens"
|
||||
]
|
||||
},
|
||||
"~:version": 67,
|
||||
"~:project-id": "~u35e4ba42-fc4e-817d-8008-12286b51ef68",
|
||||
"~:created-at": "~m1779652715531",
|
||||
"~:backend": "legacy-db",
|
||||
"~:data": {
|
||||
"~:pages": [
|
||||
"~u35e4ba42-fc4e-817d-8008-12287202d226"
|
||||
],
|
||||
"~:pages-index": {
|
||||
"~u35e4ba42-fc4e-817d-8008-12287202d226": {
|
||||
"~:objects": {
|
||||
"~#penpot/objects-map/v2": {
|
||||
"~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.0,\"~:y\",0.0]],[\"^:\",[\"^ \",\"~:x\",0.01,\"~:y\",0.0]],[\"^:\",[\"^ \",\"~:x\",0.01,\"~:y\",0.01]],[\"^:\",[\"^ \",\"~:x\",0.0,\"~:y\",0.01]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",0,\"~:r1\",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,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",0,\"~:y\",0,\"^6\",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,\"^H\",0.01,\"~:flip-y\",null,\"~:shapes\",[\"~u76c88c49-9f53-80db-8008-1494b9c81dca\",\"~u76c88c49-9f53-80db-8008-1494bf3f9d6f\"]]]",
|
||||
"~u76c88c49-9f53-80db-8008-1494b9c81dca": "[\"~#shape\",[\"^ \",\"~:y\",-243,\"~:layout-grid-columns\",[[\"^ \",\"~:type\",\"~:flex\",\"~:value\",1],[\"^ \",\"^2\",\"^3\",\"^4\",1]],\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",0,\"~:p3\",0,\"~:p4\",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\",\"~:layout\",\"~:grid\",\"~:hide-in-viewer\",false,\"~:name\",\"Unlocked board with Grid\",\"~:layout-align-items\",\"~:start\",\"~:width\",462,\"~:layout-grid-cells\",[\"^ \",\"~u76c88c49-9f53-80db-8008-1495083eb543\",[\"^ \",\"~:justify-self\",\"~:auto\",\"~:column\",1,\"~:id\",\"~u76c88c49-9f53-80db-8008-1495083eb543\",\"~:position\",\"^L\",\"~:column-span\",1,\"~:align-self\",\"^L\",\"~:row\",1,\"~:row-span\",1,\"~:shapes\",[]],\"~u76c88c49-9f53-80db-8008-1495083eb544\",[\"^ \",\"^K\",\"^L\",\"^M\",2,\"^N\",\"~u76c88c49-9f53-80db-8008-1495083eb544\",\"^O\",\"^L\",\"^P\",1,\"^Q\",\"^L\",\"^R\",1,\"^S\",1,\"^T\",[]],\"~u76c88c49-9f53-80db-8008-1495083eb545\",[\"^ \",\"^K\",\"^L\",\"^M\",1,\"^N\",\"~u76c88c49-9f53-80db-8008-1495083eb545\",\"^O\",\"^L\",\"^P\",1,\"^Q\",\"^L\",\"^R\",2,\"^S\",1,\"^T\",[]],\"~u76c88c49-9f53-80db-8008-1495083eb546\",[\"^ \",\"^K\",\"^L\",\"^M\",2,\"^N\",\"~u76c88c49-9f53-80db-8008-1495083eb546\",\"^O\",\"^L\",\"^P\",1,\"^Q\",\"^L\",\"^R\",2,\"^S\",1,\"^T\",[]]],\"~:layout-padding-type\",\"~:simple\",\"^2\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",241.99999451637268,\"~:y\",-243]],[\"^10\",[\"^ \",\"~:x\",703.9999945163727,\"~:y\",-243]],[\"^10\",[\"^ \",\"~:x\",703.9999945163727,\"~:y\",-53]],[\"^10\",[\"^ \",\"~:x\",241.99999451637268,\"~:y\",-53]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",0,\"~:column-gap\",0],\"~:transform-inverse\",[\"^>\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",0,\"~:layout-justify-content\",\"~:stretch\",\"~:r1\",0,\"^N\",\"~u76c88c49-9f53-80db-8008-1494b9c81dca\",\"~:layout-justify-items\",\"^G\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:layout-align-content\",\"^19\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",241.99999451637268,\"~:proportion\",1,\"~:r4\",0,\"~:layout-grid-rows\",[[\"^ \",\"^2\",\"^3\",\"^4\",1],[\"^ \",\"^2\",\"^3\",\"^4\",1]],\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",241.99999451637268,\"~:y\",-243,\"^H\",462,\"~:height\",190,\"~:x1\",241.99999451637268,\"~:y1\",-243,\"~:x2\",703.9999945163727,\"~:y2\",-53]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#FFFFFF\",\"~:fill-opacity\",1]],\"~:layout-grid-dir\",\"^R\",\"~:flip-x\",null,\"^1E\",190,\"~:flip-y\",null,\"^T\",[]]]",
|
||||
"~u76c88c49-9f53-80db-8008-1494bf3f9d6f": "[\"~#shape\",[\"^ \",\"~:y\",-412,\"~:layout-grid-columns\",[[\"^ \",\"~:type\",\"~:flex\",\"~:value\",1],[\"^ \",\"^2\",\"^3\",\"^4\",1]],\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",0,\"~:p3\",0,\"~:p4\",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\",\"~:layout\",\"~:grid\",\"~:hide-in-viewer\",false,\"~:name\",\"Locked Board with Grid\",\"~:layout-align-items\",\"~:start\",\"~:width\",459.00002002716064,\"~:layout-grid-cells\",[\"^ \",\"~u76c88c49-9f53-80db-8008-1495048fa9c0\",[\"^ \",\"~:justify-self\",\"~:auto\",\"~:column\",1,\"~:id\",\"~u76c88c49-9f53-80db-8008-1495048fa9c0\",\"~:position\",\"^L\",\"~:column-span\",1,\"~:align-self\",\"^L\",\"~:row\",1,\"~:row-span\",1,\"~:shapes\",[]],\"~u76c88c49-9f53-80db-8008-1495048fa9c1\",[\"^ \",\"^K\",\"^L\",\"^M\",2,\"^N\",\"~u76c88c49-9f53-80db-8008-1495048fa9c1\",\"^O\",\"^L\",\"^P\",1,\"^Q\",\"^L\",\"^R\",1,\"^S\",1,\"^T\",[]],\"~u76c88c49-9f53-80db-8008-1495048fa9c2\",[\"^ \",\"^K\",\"^L\",\"^M\",1,\"^N\",\"~u76c88c49-9f53-80db-8008-1495048fa9c2\",\"^O\",\"^L\",\"^P\",1,\"^Q\",\"^L\",\"^R\",2,\"^S\",1,\"^T\",[]],\"~u76c88c49-9f53-80db-8008-1495048fa9c3\",[\"^ \",\"^K\",\"^L\",\"^M\",2,\"^N\",\"~u76c88c49-9f53-80db-8008-1495048fa9c3\",\"^O\",\"^L\",\"^P\",1,\"^Q\",\"^L\",\"^R\",2,\"^S\",1,\"^T\",[]]],\"~:layout-padding-type\",\"~:simple\",\"^2\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",241.99999445676804,\"~:y\",-412]],[\"^10\",[\"^ \",\"~:x\",701.0000144839287,\"~:y\",-412]],[\"^10\",[\"^ \",\"~:x\",701.0000144839287,\"~:y\",-283]],[\"^10\",[\"^ \",\"~:x\",241.99999445676804,\"~:y\",-283]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",0,\"~:column-gap\",0],\"~:transform-inverse\",[\"^>\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",0,\"~:layout-justify-content\",\"~:stretch\",\"~:r1\",0,\"^N\",\"~u76c88c49-9f53-80db-8008-1494bf3f9d6f\",\"~:layout-justify-items\",\"^G\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:layout-align-content\",\"^19\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",241.99999445676804,\"~:blocked\",true,\"~:proportion\",1,\"~:r4\",0,\"~:layout-grid-rows\",[[\"^ \",\"^2\",\"^3\",\"^4\",1],[\"^ \",\"^2\",\"^3\",\"^4\",1]],\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",241.99999445676804,\"~:y\",-412,\"^H\",459.00002002716064,\"~:height\",129,\"~:x1\",241.99999445676804,\"~:y1\",-412,\"~:x2\",701.0000144839287,\"~:y2\",-283]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#FFFFFF\",\"~:fill-opacity\",1]],\"~:layout-grid-dir\",\"^R\",\"~:flip-x\",null,\"^1F\",129,\"~:flip-y\",null,\"^T\",[]]]"
|
||||
}
|
||||
},
|
||||
"~:id": "~u35e4ba42-fc4e-817d-8008-12287202d226",
|
||||
"~:name": "Page 1"
|
||||
}
|
||||
},
|
||||
"~:id": "~u35e4ba42-fc4e-817d-8008-12287202d225",
|
||||
"~:options": {
|
||||
"~:components-v2": true,
|
||||
"~:base-font-size": "16px"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -521,3 +521,39 @@ test("BUG 13822 - Problems with z-index", async({
|
||||
await workspacePage.waitForFirstRenderWithoutUI();
|
||||
await expect(workspacePage.canvas).toHaveScreenshot();
|
||||
});
|
||||
|
||||
test("Bug 14250 - User with viewer role can select a locked board with a grid", async ({
|
||||
page,
|
||||
}) => {
|
||||
const workspacePage = new WasmWorkspacePage(page);
|
||||
await workspacePage.setupEmptyFile();
|
||||
await workspacePage.mockRPC("get-teams", "get-teams-role-viewer.json");
|
||||
await workspacePage.mockRPC(
|
||||
/get\-file\?/,
|
||||
"workspace/get-file-14250.json",
|
||||
);
|
||||
|
||||
await workspacePage.goToWorkspace();
|
||||
|
||||
// Select the board from the layer tree to reveal its position
|
||||
// on the canvas via the selection rectangle overlay
|
||||
await workspacePage.clickLeafLayer("Locked Board with Grid");
|
||||
await page.waitForSelector(".viewport-selrect");
|
||||
|
||||
// Get the selection rectangle bounding box (page coordinates)
|
||||
// and calculate its center relative to the viewport element
|
||||
const selrectBox = await page.locator(".viewport-selrect").boundingBox();
|
||||
const viewportBox = await workspacePage.viewport.boundingBox();
|
||||
|
||||
const centerX = selrectBox.x + selrectBox.width / 2 - viewportBox.x;
|
||||
const centerY = selrectBox.y + selrectBox.height / 2 - viewportBox.y;
|
||||
|
||||
// Deselect by pressing Escape
|
||||
await page.keyboard.press("Escape");
|
||||
|
||||
// Click on the canvas at the board's center
|
||||
await workspacePage.clickAt(centerX, centerY);
|
||||
|
||||
// Verify the board is now selected in the layers bar
|
||||
await workspacePage.expectSelectedLayer("Locked Board with Grid");
|
||||
});
|
||||
|
||||
@ -185,6 +185,7 @@
|
||||
hover-disabled-ref (mf/use-ref hover-disabled?)
|
||||
focus-ref (mf/use-ref focus)
|
||||
transform-ref (mf/use-ref transform)
|
||||
read-only-ref (mf/use-ref read-only?)
|
||||
|
||||
last-point-ref (mf/use-var nil)
|
||||
mod-str (mf/use-memo #(rx/subject))
|
||||
@ -256,11 +257,15 @@
|
||||
(mf/deps transform)
|
||||
#(mf/set-ref-val! transform-ref transform))
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps read-only?)
|
||||
#(mf/set-ref-val! read-only-ref read-only?))
|
||||
|
||||
(hooks/use-stream
|
||||
over-shapes-stream-debounced
|
||||
(mf/deps objects)
|
||||
(fn [_]
|
||||
(reset! hover-top-frame-id (ctt/top-nested-frame objects (deref last-point-ref)))))
|
||||
(reset! hover-top-frame-id (ctt/top-nested-frame objects (deref last-point-ref) nil (mf/ref-val read-only-ref)))))
|
||||
|
||||
;; This ref is a cache of sorted ids. Sorting is expensive so we save the list
|
||||
(let [sorted-ids-cache (mf/use-ref {})]
|
||||
|
||||
@ -113,7 +113,8 @@
|
||||
(mf/use-fn
|
||||
(mf/deps (:id frame) on-frame-select workspace-read-only? blocked?)
|
||||
(fn [event]
|
||||
(when (and (dom/left-mouse? event) (not blocked?))
|
||||
(when (and (dom/left-mouse? event)
|
||||
(or (not blocked?) workspace-read-only?))
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(on-frame-select event (:id frame)))))
|
||||
@ -198,7 +199,7 @@
|
||||
[:g.frame-title {:id (dm/str "frame-title-" (:id frame))
|
||||
:data-edit-grid is-grid-edition
|
||||
:transform (vwu/title-transform frame zoom is-grid-edition)
|
||||
:pointer-events (when (:blocked frame) "none")}
|
||||
:pointer-events (when (and (:blocked frame) (not workspace-read-only?)) "none")}
|
||||
(when show-icon?
|
||||
[:svg {:x 0
|
||||
:y -9
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user