fix: lock canvas recovery while saving
This commit is contained in:
parent
ba48ece884
commit
e2128a4ad7
@ -39,7 +39,7 @@ export default function LocationMapCanvas({
|
|||||||
: 0;
|
: 0;
|
||||||
const hasNoVisibleObjects = objects.length > 0 && filters.showZones && visibleObjectCount === 0;
|
const hasNoVisibleObjects = objects.length > 0 && filters.showZones && visibleObjectCount === 0;
|
||||||
const canAddFirstArea =
|
const canAddFirstArea =
|
||||||
!editingLocked && mode === "edit" && objects.length === 0 && typeof onAddObject === "function";
|
mode === "edit" && objects.length === 0 && typeof onAddObject === "function";
|
||||||
const canRecoverHiddenAreas =
|
const canRecoverHiddenAreas =
|
||||||
mode === "edit" && hasNoVisibleObjects && hiddenAreaCount > 0 && typeof onShowHiddenAreas === "function";
|
mode === "edit" && hasNoVisibleObjects && hiddenAreaCount > 0 && typeof onShowHiddenAreas === "function";
|
||||||
const hasEmptyCanvasAction = canAddFirstArea || hiddenByZonesLayer || canRecoverHiddenAreas;
|
const hasEmptyCanvasAction = canAddFirstArea || hiddenByZonesLayer || canRecoverHiddenAreas;
|
||||||
@ -165,11 +165,13 @@ export default function LocationMapCanvas({
|
|||||||
|
|
||||||
const handleAddObject = (event) => {
|
const handleAddObject = (event) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
if (editingLocked) return;
|
||||||
onAddObject?.();
|
onAddObject?.();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleShowHiddenAreas = (event) => {
|
const handleShowHiddenAreas = (event) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
if (editingLocked) return;
|
||||||
onShowHiddenAreas?.();
|
onShowHiddenAreas?.();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -417,6 +419,7 @@ export default function LocationMapCanvas({
|
|||||||
{canAddFirstArea ? (
|
{canAddFirstArea ? (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
disabled={editingLocked}
|
||||||
onPointerDown={(event) => event.stopPropagation()}
|
onPointerDown={(event) => event.stopPropagation()}
|
||||||
onClick={handleAddObject}
|
onClick={handleAddObject}
|
||||||
>
|
>
|
||||||
@ -433,6 +436,7 @@ export default function LocationMapCanvas({
|
|||||||
) : canRecoverHiddenAreas ? (
|
) : canRecoverHiddenAreas ? (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
disabled={editingLocked}
|
||||||
onPointerDown={(event) => event.stopPropagation()}
|
onPointerDown={(event) => event.stopPropagation()}
|
||||||
onClick={handleShowHiddenAreas}
|
onClick={handleShowHiddenAreas}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -345,6 +345,11 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.location-map-empty-canvas button:disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: 0.55;
|
||||||
|
}
|
||||||
|
|
||||||
.location-map-bottom-sheet {
|
.location-map-bottom-sheet {
|
||||||
max-height: 43vh;
|
max-height: 43vh;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|||||||
@ -1049,6 +1049,83 @@ test("admin save progress locks draft controls", async ({ page }) => {
|
|||||||
await expect(page.getByRole("button", { name: "Save Draft" })).toBeDisabled();
|
await expect(page.getByRole("button", { name: "Save Draft" })).toBeDisabled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("admin save progress locks empty-canvas recovery actions", async ({ page }) => {
|
||||||
|
await mockMapShell(page);
|
||||||
|
|
||||||
|
let mapState = draftMapState([
|
||||||
|
{
|
||||||
|
id: 1362,
|
||||||
|
location_map_id: 900,
|
||||||
|
zone_id: 501,
|
||||||
|
zone_name: "Bakery",
|
||||||
|
type: "zone",
|
||||||
|
label: "Bakery",
|
||||||
|
x: 40,
|
||||||
|
y: 40,
|
||||||
|
width: 260,
|
||||||
|
height: 160,
|
||||||
|
rotation: 0,
|
||||||
|
locked: false,
|
||||||
|
visible: true,
|
||||||
|
sort_order: 1,
|
||||||
|
},
|
||||||
|
], true);
|
||||||
|
let releaseSave: () => void = () => {};
|
||||||
|
let saveStarted = false;
|
||||||
|
const saveGate = new Promise<void>((resolve) => {
|
||||||
|
releaseSave = resolve;
|
||||||
|
});
|
||||||
|
|
||||||
|
await page.route("**/households/1/locations/10/map", async (route) => {
|
||||||
|
await route.fulfill({
|
||||||
|
status: 200,
|
||||||
|
contentType: "application/json",
|
||||||
|
body: JSON.stringify(mapState),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
await page.route("**/households/1/locations/10/map/draft", async (route) => {
|
||||||
|
saveStarted = true;
|
||||||
|
const payload = await route.request().postDataJSON();
|
||||||
|
await saveGate;
|
||||||
|
const savedObjects = (payload.objects as Array<Record<string, unknown>>).map((object, index) => ({
|
||||||
|
...(mapState.draft_objects[index] || {}),
|
||||||
|
...object,
|
||||||
|
}));
|
||||||
|
mapState = draftMapState(savedObjects, true);
|
||||||
|
await route.fulfill({
|
||||||
|
status: 200,
|
||||||
|
contentType: "application/json",
|
||||||
|
body: JSON.stringify(mapState),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
await page.goto("/stores/100/locations/10/map");
|
||||||
|
await page.getByRole("button", { name: "Continue Editing" }).click();
|
||||||
|
await page.getByRole("button", { name: "Edit Objects" }).click();
|
||||||
|
await page.locator(".location-map-object", { hasText: "Bakery" }).locator("rect").first().click();
|
||||||
|
await page.getByLabel("Visible").click();
|
||||||
|
|
||||||
|
await expect(page.getByText("No visible map areas")).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
page.locator(".location-map-empty-canvas").getByRole("button", { name: "Show Hidden" })
|
||||||
|
).toBeEnabled();
|
||||||
|
await expect(page.getByRole("button", { name: "Show Hidden Areas (1)" })).toBeEnabled();
|
||||||
|
|
||||||
|
await page.getByRole("button", { name: "Save Draft" }).click();
|
||||||
|
await expect.poll(() => saveStarted).toBe(true);
|
||||||
|
await expect(
|
||||||
|
page.locator(".location-map-empty-canvas").getByRole("button", { name: "Show Hidden" })
|
||||||
|
).toBeDisabled();
|
||||||
|
await expect(page.getByRole("button", { name: "Show Hidden Areas (1)" })).toBeDisabled();
|
||||||
|
|
||||||
|
releaseSave();
|
||||||
|
await expect(page.locator(".location-map-status")).toHaveText("Draft");
|
||||||
|
await expect(
|
||||||
|
page.locator(".location-map-empty-canvas").getByRole("button", { name: "Show Hidden" })
|
||||||
|
).toBeEnabled();
|
||||||
|
});
|
||||||
|
|
||||||
test("admin hard navigation warns when draft edits are unsaved", async ({ page }) => {
|
test("admin hard navigation warns when draft edits are unsaved", async ({ page }) => {
|
||||||
await mockMapShell(page);
|
await mockMapShell(page);
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user