slides: Multiple UX issues reported by Robert #87

Open
opened 2026-05-21 10:22:59 +00:00 by marionrvrn · 3 comments
Member

Robert generated an 8-slide deck from a Dutch PDF business plan. Generation worked well, but he hit several blockers:

  • Slides stuck "in progress" even though the Jobs panel shows all jobs as Done (it works only when refreshing the page)
  • Create PDF fails with errors, no working export.
  • No PPTX or ODP download option, deck can't be used offline.
  • Buttons in the lower sections point to non-existing destinations.

see doc attached

Robert generated an 8-slide deck from a Dutch PDF business plan. Generation worked well, but he hit several blockers: - Slides stuck "in progress" even though the Jobs panel shows all jobs as Done (it works only when refreshing the page) - Create PDF fails with errors, no working export. - No PPTX or ODP download option, deck can't be used offline. - Buttons in the lower sections point to non-existing destinations. see doc attached
Member

Investigation findings (on current development branch)

Bug 1 — Slides stuck "Generating" after jobs complete Fixed

Root cause: _generatingSlides is a client-side optimistic-tracking Set that is populated when generation is submitted. It was only cleared when has_png became true in the auto-refresh timer. Two failure modes:

  1. If a slide job fails (job state = done, but PNG was not written), has_png stays false forever → badge stuck in "Generating" indefinitely
  2. If SSE fires onSlideJobChanged before the timer clears the set, the badge stays "Generating" until the 2s timer fires

Fix applied in two places:

  • onSlideJobChanged: now calls _generatingSlides.delete(slug) immediately when a job transitions to a terminal state (done/failed/cancelled/timed_out), before refreshing the deck view
  • Auto-refresh timer: now also clears slides from _generatingSlides when !slideJobActive(s.name) (job is no longer active in the panel), not only when has_png is true
  • Timer completion toast now distinguishes between full success and partial failure

Bug 2 — Create PDF fails with errors

No code bug found. The PDF creation is pure Rust (printpdf 0.7) and reads PNGs from output/. Possible causes on the deployed instance:

  • Corrupted or incomplete PNG files in output/ (partial write during generation)
  • Insufficient disk space
  • Bug 1 above: if slides appeared "Done" in the jobs panel but the PNG was never written, PDF would have 0 slides and silently return Ok(())

The fix for Bug 1 might indirectly help here — if slides that "failed" are now correctly shown as Pending instead of Done, the user will know to regenerate before creating a PDF.

Needs error log from the deployed instance to diagnose further.

Bug 3 — No PPTX or ODP download option

Confirmed missing feature. Only PDF export is implemented. PPTX/ODP would require a new export pipeline. Tracking as a separate feature request.

Bug 4 — Buttons in lower sections point to non-existing destinations

Unable to reproduce without the attached document. Investigation found:

  • The inline slide editor overlay in index.html references 6 functions (fixSlideContent, rewriteSlideContent, toggleInstructPanel, startInstructRecording, stopInstructRecording, executeInstruct) that are not defined in dashboard.js — but this overlay is dead code (never activated in current code flow, openEditor() navigates to the full-page editor instead)
  • All navigateTo() routes in the template are handled by the router
  • No other obviously broken navigation buttons found

Please share the attached document or screenshot so we can identify the specific buttons.

## Investigation findings (on current `development` branch) ### Bug 1 — Slides stuck "Generating" after jobs complete ✅ Fixed Root cause: `_generatingSlides` is a client-side optimistic-tracking Set that is populated when generation is submitted. It was only cleared when `has_png` became `true` in the auto-refresh timer. Two failure modes: 1. If a slide job **fails** (job state = done, but PNG was not written), `has_png` stays `false` forever → badge stuck in "Generating" indefinitely 2. If SSE fires `onSlideJobChanged` before the timer clears the set, the badge stays "Generating" until the 2s timer fires Fix applied in two places: - `onSlideJobChanged`: now calls `_generatingSlides.delete(slug)` immediately when a job transitions to a terminal state (done/failed/cancelled/timed_out), before refreshing the deck view - Auto-refresh timer: now also clears slides from `_generatingSlides` when `!slideJobActive(s.name)` (job is no longer active in the panel), not only when `has_png` is true - Timer completion toast now distinguishes between full success and partial failure ### Bug 2 — Create PDF fails with errors No code bug found. The PDF creation is pure Rust (`printpdf` 0.7) and reads PNGs from `output/`. Possible causes on the deployed instance: - Corrupted or incomplete PNG files in `output/` (partial write during generation) - Insufficient disk space - Bug 1 above: if slides appeared "Done" in the jobs panel but the PNG was never written, PDF would have 0 slides and silently return `Ok(())` The fix for Bug 1 might indirectly help here — if slides that "failed" are now correctly shown as Pending instead of Done, the user will know to regenerate before creating a PDF. Needs error log from the deployed instance to diagnose further. ### Bug 3 — No PPTX or ODP download option Confirmed missing feature. Only PDF export is implemented. PPTX/ODP would require a new export pipeline. Tracking as a separate feature request. ### Bug 4 — Buttons in lower sections point to non-existing destinations Unable to reproduce without the attached document. Investigation found: - The inline slide editor overlay in `index.html` references 6 functions (`fixSlideContent`, `rewriteSlideContent`, `toggleInstructPanel`, `startInstructRecording`, `stopInstructRecording`, `executeInstruct`) that are not defined in `dashboard.js` — but this overlay is dead code (never activated in current code flow, `openEditor()` navigates to the full-page editor instead) - All `navigateTo()` routes in the template are handled by the router - No other obviously broken navigation buttons found Please share the attached document or screenshot so we can identify the specific buttons.
Author
Member

@casper-stevens those buttons I assume (document is attached in my issue above)

@casper-stevens those buttons I assume (document is attached in my issue above)
Member

Follow-up investigation

Bug 1 — Slides stuck "Generating" Fixed (d2e9c27)

Already resolved in the previous comment. 30+ commits ahead of the deployed instance.

Bug 2 — PDF creation fails with missing field 'src' Fixed (d55b8d4)

Root cause confirmed: handle_deck_pdf_job_logs used the typed hero_proc SDK job_logs() call, which deserializes log line objects with a required src field. hero_proc occasionally omits src from log entries, causing the entire poll to fail with a deserialization error, which the JS client displayed as the repeating Poll error (retrying): job.logs: Deserialization error: Failed to deserialize result: missing field 'src' loop visible in the screenshot.

Fix: replaced the typed call with a raw tolerant deserialization that uses #[serde(default)] on all fields. Deploying current development to the devslides VM will fix both Bug 1 and Bug 2.

Bug 3 — No PPTX / ODP export

Still a missing feature. Only PDF export is implemented. Would require a new export pipeline. Keeping open as a feature request.

Bug 4 — Job card ⧉ button points to a non-existing destination

The external-link button in each job card links to /hero_proc/ui#jobs/<id>. This path works on a full Hero OS install (routed by hero_router), but is a 404 on the standalone devslides VM where hero_proc admin is not exposed at that path.

The clipboard (□) button is unrelated — it copies the job ID and works fine.

Fix: inject HERO_PROC_UI_BASE from the Rust server instead of hardcoding /hero_proc/ui in JS. It would read from a hero_proc secret (e.g. HERO_PROC_ADMIN_URL), default to empty string on standalone deployments, and suppress the button entirely when empty.

## Follow-up investigation ### Bug 1 — Slides stuck "Generating" ✅ Fixed (`d2e9c27`) Already resolved in the previous comment. 30+ commits ahead of the deployed instance. ### Bug 2 — PDF creation fails with `missing field 'src'` ✅ Fixed (`d55b8d4`) Root cause confirmed: `handle_deck_pdf_job_logs` used the typed hero_proc SDK `job_logs()` call, which deserializes log line objects with a required `src` field. hero_proc occasionally omits `src` from log entries, causing the entire poll to fail with a deserialization error, which the JS client displayed as the repeating `Poll error (retrying): job.logs: Deserialization error: Failed to deserialize result: missing field 'src'` loop visible in the screenshot. Fix: replaced the typed call with a raw tolerant deserialization that uses `#[serde(default)]` on all fields. **Deploying current `development` to the devslides VM will fix both Bug 1 and Bug 2.** ### Bug 3 — No PPTX / ODP export Still a missing feature. Only PDF export is implemented. Would require a new export pipeline. Keeping open as a feature request. ### Bug 4 — Job card ⧉ button points to a non-existing destination The external-link button in each job card links to `/hero_proc/ui#jobs/<id>`. This path works on a full Hero OS install (routed by `hero_router`), but is a 404 on the standalone devslides VM where hero_proc admin is not exposed at that path. The clipboard (□) button is unrelated — it copies the job ID and works fine. Fix: inject `HERO_PROC_UI_BASE` from the Rust server instead of hardcoding `/hero_proc/ui` in JS. It would read from a hero_proc secret (e.g. `HERO_PROC_ADMIN_URL`), default to empty string on standalone deployments, and suppress the button entirely when empty.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_slides#87
No description provided.