feat(documents): pré-visualização em PDF do rascunho via Chromium
Novo endpoint POST /documents/templates/:id/draft/preview: renderiza o
conteúdo atual (ainda não salvo) do editor com placeholders {{variavel}}
substituídos por [variavel], via Chromium real, sem persistir nada
(sem generation, sem upload S3) — permite validar visualmente o
resultado antes do "Publicar", que é uma ação permanente.
Corrige de passagem um bug real: css_content do template nunca chegava
ao renderPdf na geração real de documento (createGeneration), sendo
descartado silenciosamente.
No frontend, a pré-visualização aparece embutida num iframe na própria
tela (não em nova aba): abrir em nova aba se mostrou não-confiável ao
vivo — a navegação tardia de uma aba pré-aberta pode ser ignorada pelo
navegador quando o gesto do usuário que a autorizou já expirou no tempo
que o Chromium leva pra renderizar.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -208,6 +208,41 @@ export async function downloadGenerationPdf(id: string, accessToken: string, fil
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the CURRENT (possibly unsaved) draft content to PDF via Chromium
|
||||
* — nothing is persisted server-side. Same raw-fetch pattern as
|
||||
* `downloadGenerationPdf` (binary response, still needs the bearer token).
|
||||
* Every `{{variavel}}` shows as `[variavel]` in the result (no real
|
||||
* client/reseller context at this stage).
|
||||
*
|
||||
* Returns an object URL for the caller to show inline (`<iframe>`), rather
|
||||
* than opening a new tab: a Chromium render is slow enough (real
|
||||
* server-side rendering, not instant) that by the time the blob is ready,
|
||||
* the browser's "this navigation is tied to a user gesture" grace window
|
||||
* has often already expired — `window.open()` (even pre-opened and
|
||||
* navigated later) can then be silently ignored, leaving a blank tab.
|
||||
* Confirmed live: a synchronous in-memory blob navigates the pre-opened
|
||||
* tab fine, but the real (few-hundred-ms) round trip through this
|
||||
* endpoint does not. Showing the PDF in the same page sidesteps the whole
|
||||
* class of popup-timing issues.
|
||||
*/
|
||||
export async function previewDraft(
|
||||
templateId: string,
|
||||
input: { plainText: string; cssContent?: string },
|
||||
accessToken: string,
|
||||
): Promise<string> {
|
||||
const response = await fetch(`${API_BASE_URL}/documents/templates/${templateId}/draft/preview`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json", Authorization: `Bearer ${accessToken}` },
|
||||
body: JSON.stringify({ editorContent: { plainText: input.plainText }, cssContent: input.cssContent }),
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error("Não foi possível gerar a pré-visualização.");
|
||||
}
|
||||
const blob = await response.blob();
|
||||
return URL.createObjectURL(blob);
|
||||
}
|
||||
|
||||
/** Extracts `{{variavel}}` references from a plain-text template body — used to auto-build the generation context form. */
|
||||
export function extractTemplateVariables(plainText: string): string[] {
|
||||
const found = new Set<string>();
|
||||
|
||||
Reference in New Issue
Block a user