insert/delete/move slide #7
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
insert renames all slides to have new nr
and insert space for a slide
move moves it renamrs need
delete same
make sure not to lose history
so all needs to keep on working after the action
Implementation Spec: Insert / Delete / Move Slide (Issue #7)
Objective
Add three structural slide operations — insert, delete, and move — to hero_slides. Each operation must rename all affected slide
.mdsource files, their correspondingoutput/<name>.pngimages, and theiroutput/.versions/<name>/version history directories atomically so that no version history is lost. Themetadata.tomlhash entries must be updated to track the new names. The UI exposes these actions through the existing right-click context menu on slide cards.Background: How Slides Are Stored
Slides are
.mdfiles stored directly in the deck directory. Their ordering is determined purely by lexicographic sort order of their filenames. Existing examples use the patternNN_slug.md(e.g.01_the_shift.md,02_the_problem.md).The numeric prefix determines the slide's position. All three new operations require renaming files to change this prefix while keeping the slug suffix intact.
Associated artefacts that must be renamed in lockstep:
<deck>/<name>.md<deck>/output/<name>.png<deck>/output/.versions/<name>/metadata.toml[slides.<name>]sectionRequirements
deck_path, an insertion positionat(1-based integer), and aslugstring, create a new blank.mdfile at positionat, shifting all slides at or after that position up by 1.deck_pathand aslide_name, delete the.md,output/<name>.png(if present), andoutput/.versions/<name>/(if present), then renumber all slides after the deleted position downward by 1.deck_path, afrom_name(current slide name), and ato_position(1-based integer), move the slide to the new position by renaming it and shifting all slides between the old and new positions by 1 in the appropriate direction.metadata.toml: rename hash keys for any renamed slide; remove the key for a deleted slide.rpc.rswith matching entries inopenrpc.json.dashboard.js.Files to Modify or Create
crates/hero_slides_server/src/slide_ops.rscrates/hero_slides_server/src/rpc.rscrates/hero_slides_server/src/main.rsmod slide_opscrates/hero_slides_server/src/error.rsInvalidSlideNamevariantcrates/hero_slides_server/openrpc.jsoncrates/hero_slides_ui/static/js/dashboard.jsImplementation Steps
Step 1 — Create
slide_ops.rs(core rename logic)Files:
src/slide_ops.rs,src/error.rsparse_slides()→Vec<SlideEntry { name, number, slug }>rename_slide(): rename .md, output .png, .versions dir, and metadata keyinsert_slide(dir, at, slug): shift slides ≥ at upward (reverse order), create blank .mddelete_slide(dir, slide_name): delete files, shift slides after downward (forward order)move_slide(dir, slide_name, to_position): shift intermediates, place at targetStep 2 — Wire into
rpc.rsandmain.rsFiles:
src/rpc.rs,src/main.rsmod slide_ops;to main.rshandle_slide_insert,handle_slide_delete,handle_slide_movefunctionshandle_request()match blockStep 3 — Update
openrpc.jsonFile:
openrpc.jsonslide.insert(params: deck_path, at, slug)slide.delete(params: deck_path, slide_name)slide.move(params: deck_path, slide_name, to_position)Step 4 — Add UI actions in
dashboard.jsFile:
dashboard.jsinsertSlide(afterName),deleteSlide(name),moveSlide(name)async functionsattachSlideContextMenus()currentSlidesto avoid extra RPC callsAcceptance Criteria
slide.insertcreates a blank slide at the right position; all slides at/after renumbered +1; metadata updatedslide.deleteremoves .md, .png, .versions dir; all slides after renumbered -1; metadata key removedslide.moveplaces the slide at the target position; intermediates shift; metadata updatedNotes
git log --followhistory.output/.versions/<name>/contains PNG filesv001.png, etc. Just rename the directory.insertcreates a blank .md with placeholder heading# New Slide.prompt()andconfirm()— no dedicated modal needed for initial implementation.Test Results for Issue #7 (insert/delete/move slide)
Run Date: 2026-03-25
Build Status: SUCCESS (compiled cleanly)
Test Results
All Tests Passed
Slide Operations Tests (Issue #7 Coverage)
The following tests directly cover the insert/delete/move slide functionality from issue #7:
slide_ops::tests::test_parse_slides— parsing slide filesslide_ops::tests::test_delete_middle— deleting a slide from middle positionslide_ops::tests::test_insert_at_middle— inserting a slide at a middle positionslide_ops::tests::test_move_down— moving a slide downslide_ops::tests::test_move_up— moving a slide upAll slide operation tests passed.
Implementation Complete ✅
Changes Made
New file:
crates/hero_slides_server/src/slide_ops.rsparse_slides(dir)— reads all.mdfiles in deck dir, parsesNN_slugnaming, returns sortedVec<SlideEntry>rename_slide(dir, old, new, metadata)— renames.md,output/<name>.png,output/.versions/<name>/, and metadata key atomicallyinsert_slide(dir, at, slug)— shifts all slides ≥ at upward by 1 (reverse order, collision-safe), creates blank.mdat new positiondelete_slide(dir, name)— deletes.md/PNG/versions dir, shifts all subsequent slides down by 1 (forward order)move_slide(dir, name, to_position)— moves slide to target position, shifts intermediates in correct directionModified:
crates/hero_slides_server/src/error.rsInvalidSlideName(String)error variantModified:
crates/hero_slides_server/src/main.rspub mod slide_ops;declarationModified:
crates/hero_slides_server/src/rpc.rshandle_slide_insert,handle_slide_delete,handle_slide_movehandler functionshandle_request()dispatch match blockModified:
crates/hero_slides_server/openrpc.jsonslide.insert,slide.delete,slide.movemethod entries with full parameter and result schemasModified:
crates/hero_slides_ui/static/js/dashboard.jscurrentSlidesmodule-level variable, populated on every slide renderinsertSlide(afterName),deleteSlide(slideName),moveSlide(slideName)async functionsDesign Notes
output/.versions/<name>/directories are renamed in lockstep with the source —git log --followcontinues to work on both.mdand.pngfiles.Test Results
Implementation committed:
e88c1c4Browse:
e88c1c4