diff --git a/src/routes/events/ae_comp__event_file_obj_tbl.svelte b/src/routes/events/ae_comp__event_file_obj_tbl.svelte index fd1202fd..dc19c7ba 100644 --- a/src/routes/events/ae_comp__event_file_obj_tbl.svelte +++ b/src/routes/events/ae_comp__event_file_obj_tbl.svelte @@ -65,6 +65,53 @@ let horiz_scroll_warning: boolean = $state(false); let horiz_check_element: HTMLElement | null = $state(null); + // PDF → Image conversion state (keyed by event_file_id) + // WHY: Poster sessions display files in the Launcher modal via tag — PDFs can't render there. + // Presenters upload PDFs which must be converted server-side to high-res webp images. + // Button is only shown in edit_mode for PDF files linked to a poster-type session. + // Backend: /v3/action/hosted_file/{id}/convert_file runs pdf2image (3840px wide, first page only) + // and saves the result as a new hosted_file record linked to the same parent object. + type ConvertStatus = 'idle' | 'converting' | 'done' | 'error'; + let convert_status_kv: Record = $state({}); + let convert_result_kv: Record = $state({}); + + async function handle_convert_pdf_to_image(event_file_obj: any) { + const file_id = event_file_obj.event_file_id; + convert_status_kv[file_id] = 'converting'; + try { + // Link the new image to the most specific parent available + const link_to_type = event_file_obj.event_session_id ? 'event_session' + : event_file_obj.event_presentation_id ? 'event_presentation' + : 'event'; + const link_to_id = event_file_obj.event_session_id + || event_file_obj.event_presentation_id + || event_file_obj.event_id; + const filename_no_ext = (event_file_obj.filename ?? 'poster_image').replace(/\.pdf$/i, ''); + const url = `${$ae_api.base_url}/v3/action/hosted_file/${event_file_obj.hosted_file_id}/convert_file` + + `?link_to_type=${encodeURIComponent(link_to_type)}` + + `&link_to_id=${encodeURIComponent(link_to_id)}` + + `&filename_no_ext=${encodeURIComponent(filename_no_ext)}` + + `&to_type=webp`; + const resp = await fetch(url, { + headers: { + 'x-aether-api-key': $ae_api.api_secret_key, + 'x-account-id': String($ae_api.account_id ?? '') + } + }); + const body = await resp.json(); + if (resp.ok && body?.data) { + convert_result_kv[file_id] = body.data; + convert_status_kv[file_id] = 'done'; + } else { + console.error('[convert_pdf] API error:', body); + convert_status_kv[file_id] = 'error'; + } + } catch (err) { + console.error('[convert_pdf] Fetch failed:', err); + convert_status_kv[file_id] = 'error'; + } + } + // Check if element is scrolling horizontally $effect(() => { if ( @@ -437,7 +484,44 @@ max_filename={50} classes="btn btn-sm preset-tonal-primary hover:preset-filled-primary-500 min-w-72" /> - + + {#if $ae_loc.edit_mode && event_file_obj?.extension === 'pdf' && event_file_obj?.event_session_type_code === 'poster'} +
+ {#if !convert_status_kv[event_file_obj.event_file_id] || convert_status_kv[event_file_obj.event_file_id] === 'idle'} + + {:else if convert_status_kv[event_file_obj.event_file_id] === 'converting'} + + + Converting… + + {:else if convert_status_kv[event_file_obj.event_file_id] === 'done'} + + + Done — {convert_result_kv[event_file_obj.event_file_id]?.filename ?? 'image created'} + + {:else if convert_status_kv[event_file_obj.event_file_id] === 'error'} + + {/if} +
+ {/if}