mirror of
https://github.com/TautvydasDerzinskas/Thingport.git
synced 2026-10-19 05:10:01 -05:00
fix: allow replacing a model's only file in the edit dialog
Saving deleted removed files before uploading new ones, so swapping a model's only file failed with "Cannot remove the only plate of a print". New files are now uploaded first, then removed ones deleted, and a replacement that got a " (2)" suffix while the old file existed is renamed back to its own name.
This commit is contained in:
1 parent
32710f25e7
commit
fc3f3efd48
2 files changed
+39
-9
No files matched your search
@@ -273,6 +273,25 @@ describe("plate add/remove/reorder/rename", () => {
|
||||
res = await auth(request(app).delete(`/api/print/${printId}/plates/${lastPlateId}`));
|
||||
expect(res.status).toBe(409);
|
||||
});
|
||||
|
||||
// The Edit dialog's order for swapping a model's only file for an edited copy of the same name.
|
||||
it("replaces the only plate with a same-named file: upload, delete the old one, rename back", async () => {
|
||||
let res = await auth(request(app).get(`/api/print/${printId}`));
|
||||
const [original] = res.body.plates;
|
||||
|
||||
res = await auth(request(app).post(`/api/print/${printId}/plates`)).attach(
|
||||
"files",
|
||||
tmpFile(original.filename, "solid replacement endsolid"),
|
||||
);
|
||||
const added = res.body.print.plates.find((p: any) => p.id !== original.id);
|
||||
expect(added.filename).not.toBe(original.filename); // suffixed while the old one exists
|
||||
|
||||
res = await auth(request(app).delete(`/api/print/${printId}/plates/${original.id}`));
|
||||
expect(res.status).toBe(200);
|
||||
res = await auth(request(app).post(`/api/print/${printId}/plate/${added.id}/rename`)).send({ filename: original.filename });
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.body.print.plates).toEqual([expect.objectContaining({ id: added.id, filename: original.filename })]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("category CRUD + cycle rejection", () => {
|
||||
|
||||
@@ -247,26 +247,37 @@ export default function EditModelModal({ print, onClose, onUnauthorized, onUpdat
|
||||
latest = reorderRes.print ?? latest;
|
||||
}
|
||||
|
||||
// Model files (plates): same delete -> upload -> reorder sequence. Always at least one
|
||||
// plate stays staged locally (removePlateItem refuses to drop the last one), matching the
|
||||
// backend's own "can't remove the only plate" rule.
|
||||
const keptPlateIds = new Set(plateItems.filter((p) => p.kind === "existing").map((p) => p.id));
|
||||
for (const original of print.plates) {
|
||||
if (keptPlateIds.has(original.id)) continue;
|
||||
const res = await printsApi.deletePlate(print.id, original.id);
|
||||
latest = res.print ?? latest;
|
||||
}
|
||||
// Model files (plates): upload -> delete -> rename -> reorder. Uploading first is what lets
|
||||
// a model's only file be swapped for a new one in a single save -- deleting first would
|
||||
// briefly leave it with none, which the backend refuses ("can't remove the only plate").
|
||||
const newPlateFiles = plateItems.filter((p) => p.kind === "new").map((p) => p.file);
|
||||
let newPlateIdsInOrder: string[] = [];
|
||||
if (newPlateFiles.length) {
|
||||
const beforeIds = new Set(latest.plates.map((p) => p.id));
|
||||
const uploadRes = await printsApi.addPlates(print.id, newPlateFiles);
|
||||
latest = uploadRes.print;
|
||||
// The backend appends them in upload order, so this lines up with newPlateFiles.
|
||||
newPlateIdsInOrder = latest.plates
|
||||
.filter((p) => !beforeIds.has(p.id))
|
||||
.toSorted((a, b) => a.position - b.position)
|
||||
.map((p) => p.id);
|
||||
}
|
||||
const keptPlateIds = new Set(plateItems.filter((p) => p.kind === "existing").map((p) => p.id));
|
||||
for (const original of print.plates) {
|
||||
if (keptPlateIds.has(original.id)) continue;
|
||||
const res = await printsApi.deletePlate(print.id, original.id);
|
||||
latest = res.print ?? latest;
|
||||
}
|
||||
// A replacement usually has the same name as the file it replaces, and while that one still
|
||||
// existed the backend gave it a " (2)" suffix. Now it's gone, ask for the name as uploaded:
|
||||
// the backend keeps the suffix if another of the model's files still has that name.
|
||||
for (const [index, plateId] of newPlateIdsInOrder.entries()) {
|
||||
const wanted = newPlateFiles[index].name;
|
||||
const current = latest.plates.find((p) => p.id === plateId);
|
||||
if (!current || current.filename === wanted) continue;
|
||||
const res = await printsApi.renamePlate(print.id, plateId, wanted);
|
||||
latest = res.print ?? latest;
|
||||
}
|
||||
{
|
||||
let nextNew = 0;
|
||||
const finalOrder = plateItems.map((p) => (p.kind === "existing" ? p.id : newPlateIdsInOrder[nextNew++]));
|
||||
|
||||
Reference in new issue
Block a user