1
Fork 0
mirror of https://github.com/thegeneralist01/archivr synced 2026-07-22 11:15:41 +02:00

feat(server,frontend): expose children endpoint + expand UI for container entries

server:
- add GET /api/archives/:id/entries/:uid/children → list_entry_children,
  calling list_child_entries with caller_bits so visibility model is enforced
- fix capture_handler: use result.status ("completed"/"failed") to set job
  status rather than always "completed", mirroring rearchive_handler; this
  surfaces partial playlist failures to the polling client

frontend:
- api.js: add fetchEntryChildren(archiveId, entryUid)
- EntryRow: one outer div.entry-row-outer (display:block) keeps nth-child
  striping correct; inner div.entry-row-main is the flex row with all column
  cells and event handling; .child-entries sits below inside the outer wrapper
- expand chevron appears when entry.child_count > 0; clicking fetches children
  lazily and renders ChildRow components reusing .col-* flex widths
- child-count badge shown next to title on container entries
- styles.css: scoped CSS with #entries-body > .entry-row-outer selectors
  (higher specificity than > div) to override flex on outer wrapper; inner row
  and column rules replicated at correct depth; nth-child, is-selected,
  is-multi-selected, url-cell hover all handled
This commit is contained in:
TheGeneralist 2026-07-20 16:07:16 +02:00
parent ccdacfd582
commit 08087a4d6b
Signed by: thegeneralist01
SSH key fingerprint: SHA256:pp9qddbCNmVNoSjevdvQvM5z0DHN7LTa8qBMbcMq/R4
4 changed files with 265 additions and 36 deletions

View file

@ -241,6 +241,10 @@ pub fn app_with_state(state: AppState) -> Router {
.patch(patch_entry_handler)
.delete(delete_entry_handler),
)
.route(
"/api/archives/:archive_id/entries/:entry_uid/children",
get(list_entry_children),
)
.route(
"/api/archives/:archive_id/entries/:entry_uid/artifacts/:artifact_index",
get(serve_artifact),
@ -404,6 +408,18 @@ async fn list_entries(
Ok(Json(archive::list_root_entries(&conn, caller_bits)?))
}
async fn list_entry_children(
State(state): State<AppState>,
auth: AuthUser,
Path((archive_id, entry_uid)): Path<(String, String)>,
) -> Result<Json<Vec<archive::EntrySummary>>, ApiError> {
auth.require_auth()?;
let mounted = mounted_archive(&state, &archive_id)?;
let conn = database::open_or_initialize(&mounted.archive_path)?;
let caller_bits = auth_to_caller_bits(&auth);
Ok(Json(archive::list_child_entries(&conn, &entry_uid, caller_bits)?))
}
async fn search_entries_handler(
State(state): State<AppState>,
auth: AuthUser,
@ -902,10 +918,11 @@ async fn capture_handler(
notes_str = serde_json::Value::Object(notes_map).to_string();
Some(&notes_str)
};
let job_status = if result.status == "completed" { "completed" } else { "failed" };
database::update_capture_job_status(
&conn,
&job_uid_bg,
"completed",
job_status,
Some(&result.run_uid),
None,
notes,