pxengine 0.1.114 → 0.1.116
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +307 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.mjs +307 -36
- package/dist/index.mjs.map +1 -1
- package/dist/registry.json +26 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -3556,6 +3556,8 @@ interface DeckOutlineSlide {
|
|
|
3556
3556
|
n?: number;
|
|
3557
3557
|
type?: string;
|
|
3558
3558
|
message?: string;
|
|
3559
|
+
/** Informational review flag (DEV-194) — never gates Approve & Build. */
|
|
3560
|
+
approved?: boolean;
|
|
3559
3561
|
[key: string]: unknown;
|
|
3560
3562
|
}
|
|
3561
3563
|
/** The planned deck outline (deck_plan) shown for approval before rendering. */
|
|
@@ -3633,6 +3635,18 @@ interface PresentationJobCardProps {
|
|
|
3633
3635
|
* `/api/presentations/{job_id}/approve-outline`. Proceeds to render the deck.
|
|
3634
3636
|
*/
|
|
3635
3637
|
approveOutlineUrl?: string;
|
|
3638
|
+
/**
|
|
3639
|
+
* Reorder-slides endpoint (POST), DEV-194. Defaults to
|
|
3640
|
+
* `/api/presentations/{job_id}/outline/reorder-slides`. Called from the
|
|
3641
|
+
* outline-review phase's move-up/move-down controls.
|
|
3642
|
+
*/
|
|
3643
|
+
reorderSlidesUrl?: string;
|
|
3644
|
+
/**
|
|
3645
|
+
* Approve-slide endpoint (POST), DEV-194. Defaults to
|
|
3646
|
+
* `/api/presentations/{job_id}/outline/approve-slide`. Informational only —
|
|
3647
|
+
* never gates the whole-outline Approve & Build action.
|
|
3648
|
+
*/
|
|
3649
|
+
approveSlideUrl?: string;
|
|
3636
3650
|
/** Regenerate endpoint (POST). Defaults to `/api/presentations/{job_id}/regenerate`. */
|
|
3637
3651
|
regenerateUrl?: string;
|
|
3638
3652
|
/**
|
|
@@ -3671,6 +3685,8 @@ interface ReportOutlineSection {
|
|
|
3671
3685
|
heading?: string;
|
|
3672
3686
|
body?: string;
|
|
3673
3687
|
takeaway?: string;
|
|
3688
|
+
/** Informational review flag (DEV-194) — never gates Approve & Build. */
|
|
3689
|
+
approved?: boolean;
|
|
3674
3690
|
[key: string]: unknown;
|
|
3675
3691
|
}
|
|
3676
3692
|
/** The planned report outline (report_data) shown for approval. */
|
|
@@ -3725,6 +3741,8 @@ interface ResearchReportJobCardProps {
|
|
|
3725
3741
|
key_findings?: string[];
|
|
3726
3742
|
/** HTML report URL */
|
|
3727
3743
|
html_url?: string;
|
|
3744
|
+
/** PDF export URL (paginated print export; may be absent if PDF rendering failed) */
|
|
3745
|
+
pdf_url?: string;
|
|
3728
3746
|
/** How the report was generated: template (default) or legacy */
|
|
3729
3747
|
generation_mode?: "template" | "legacy" | string;
|
|
3730
3748
|
/** Built-in template id used to render the report */
|
|
@@ -3763,6 +3781,18 @@ interface ResearchReportJobCardProps {
|
|
|
3763
3781
|
* phase to proceed to rendering the full report.
|
|
3764
3782
|
*/
|
|
3765
3783
|
approveOutlineUrl?: string;
|
|
3784
|
+
/**
|
|
3785
|
+
* Reorder-sections endpoint (POST), DEV-194. Defaults to
|
|
3786
|
+
* `/api/reports/{job_id}/outline/reorder-sections`. Called from the
|
|
3787
|
+
* outline-review phase's move-up/move-down controls.
|
|
3788
|
+
*/
|
|
3789
|
+
reorderSectionsUrl?: string;
|
|
3790
|
+
/**
|
|
3791
|
+
* Approve-section endpoint (POST), DEV-194. Defaults to
|
|
3792
|
+
* `/api/reports/{job_id}/outline/approve-section`. Informational only —
|
|
3793
|
+
* never gates the whole-outline Approve & Build action.
|
|
3794
|
+
*/
|
|
3795
|
+
approveSectionUrl?: string;
|
|
3766
3796
|
/** Regenerate endpoint (POST). Defaults to `/api/reports/{job_id}/regenerate`. */
|
|
3767
3797
|
regenerateUrl?: string;
|
|
3768
3798
|
/**
|
|
@@ -3795,6 +3825,7 @@ interface ResearchReportJobOutput {
|
|
|
3795
3825
|
key_findings?: string[];
|
|
3796
3826
|
theme?: ReportTheme;
|
|
3797
3827
|
html_url?: string;
|
|
3828
|
+
pdf_url?: string;
|
|
3798
3829
|
generation_mode?: string;
|
|
3799
3830
|
template_id?: string;
|
|
3800
3831
|
template_version_id?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -3556,6 +3556,8 @@ interface DeckOutlineSlide {
|
|
|
3556
3556
|
n?: number;
|
|
3557
3557
|
type?: string;
|
|
3558
3558
|
message?: string;
|
|
3559
|
+
/** Informational review flag (DEV-194) — never gates Approve & Build. */
|
|
3560
|
+
approved?: boolean;
|
|
3559
3561
|
[key: string]: unknown;
|
|
3560
3562
|
}
|
|
3561
3563
|
/** The planned deck outline (deck_plan) shown for approval before rendering. */
|
|
@@ -3633,6 +3635,18 @@ interface PresentationJobCardProps {
|
|
|
3633
3635
|
* `/api/presentations/{job_id}/approve-outline`. Proceeds to render the deck.
|
|
3634
3636
|
*/
|
|
3635
3637
|
approveOutlineUrl?: string;
|
|
3638
|
+
/**
|
|
3639
|
+
* Reorder-slides endpoint (POST), DEV-194. Defaults to
|
|
3640
|
+
* `/api/presentations/{job_id}/outline/reorder-slides`. Called from the
|
|
3641
|
+
* outline-review phase's move-up/move-down controls.
|
|
3642
|
+
*/
|
|
3643
|
+
reorderSlidesUrl?: string;
|
|
3644
|
+
/**
|
|
3645
|
+
* Approve-slide endpoint (POST), DEV-194. Defaults to
|
|
3646
|
+
* `/api/presentations/{job_id}/outline/approve-slide`. Informational only —
|
|
3647
|
+
* never gates the whole-outline Approve & Build action.
|
|
3648
|
+
*/
|
|
3649
|
+
approveSlideUrl?: string;
|
|
3636
3650
|
/** Regenerate endpoint (POST). Defaults to `/api/presentations/{job_id}/regenerate`. */
|
|
3637
3651
|
regenerateUrl?: string;
|
|
3638
3652
|
/**
|
|
@@ -3671,6 +3685,8 @@ interface ReportOutlineSection {
|
|
|
3671
3685
|
heading?: string;
|
|
3672
3686
|
body?: string;
|
|
3673
3687
|
takeaway?: string;
|
|
3688
|
+
/** Informational review flag (DEV-194) — never gates Approve & Build. */
|
|
3689
|
+
approved?: boolean;
|
|
3674
3690
|
[key: string]: unknown;
|
|
3675
3691
|
}
|
|
3676
3692
|
/** The planned report outline (report_data) shown for approval. */
|
|
@@ -3725,6 +3741,8 @@ interface ResearchReportJobCardProps {
|
|
|
3725
3741
|
key_findings?: string[];
|
|
3726
3742
|
/** HTML report URL */
|
|
3727
3743
|
html_url?: string;
|
|
3744
|
+
/** PDF export URL (paginated print export; may be absent if PDF rendering failed) */
|
|
3745
|
+
pdf_url?: string;
|
|
3728
3746
|
/** How the report was generated: template (default) or legacy */
|
|
3729
3747
|
generation_mode?: "template" | "legacy" | string;
|
|
3730
3748
|
/** Built-in template id used to render the report */
|
|
@@ -3763,6 +3781,18 @@ interface ResearchReportJobCardProps {
|
|
|
3763
3781
|
* phase to proceed to rendering the full report.
|
|
3764
3782
|
*/
|
|
3765
3783
|
approveOutlineUrl?: string;
|
|
3784
|
+
/**
|
|
3785
|
+
* Reorder-sections endpoint (POST), DEV-194. Defaults to
|
|
3786
|
+
* `/api/reports/{job_id}/outline/reorder-sections`. Called from the
|
|
3787
|
+
* outline-review phase's move-up/move-down controls.
|
|
3788
|
+
*/
|
|
3789
|
+
reorderSectionsUrl?: string;
|
|
3790
|
+
/**
|
|
3791
|
+
* Approve-section endpoint (POST), DEV-194. Defaults to
|
|
3792
|
+
* `/api/reports/{job_id}/outline/approve-section`. Informational only —
|
|
3793
|
+
* never gates the whole-outline Approve & Build action.
|
|
3794
|
+
*/
|
|
3795
|
+
approveSectionUrl?: string;
|
|
3766
3796
|
/** Regenerate endpoint (POST). Defaults to `/api/reports/{job_id}/regenerate`. */
|
|
3767
3797
|
regenerateUrl?: string;
|
|
3768
3798
|
/**
|
|
@@ -3795,6 +3825,7 @@ interface ResearchReportJobOutput {
|
|
|
3795
3825
|
key_findings?: string[];
|
|
3796
3826
|
theme?: ReportTheme;
|
|
3797
3827
|
html_url?: string;
|
|
3828
|
+
pdf_url?: string;
|
|
3798
3829
|
generation_mode?: string;
|
|
3799
3830
|
template_id?: string;
|
|
3800
3831
|
template_version_id?: string;
|
package/dist/index.mjs
CHANGED
|
@@ -15801,6 +15801,8 @@ var SlideTypeIcon = () => /* @__PURE__ */ jsxs108("svg", { width: "14", height:
|
|
|
15801
15801
|
/* @__PURE__ */ jsx147("rect", { x: "3", y: "4", width: "18", height: "14", rx: "2" }),
|
|
15802
15802
|
/* @__PURE__ */ jsx147("line", { x1: "3", y1: "10", x2: "21", y2: "10" })
|
|
15803
15803
|
] });
|
|
15804
|
+
var ChevronUpIcon = () => /* @__PURE__ */ jsx147("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx147("polyline", { points: "18 15 12 9 6 15" }) });
|
|
15805
|
+
var ChevronDownIcon = () => /* @__PURE__ */ jsx147("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx147("polyline", { points: "6 9 12 15 18 9" }) });
|
|
15804
15806
|
function formatTemplateLabel(templateId) {
|
|
15805
15807
|
if (!templateId) return null;
|
|
15806
15808
|
return templateId.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
@@ -16026,6 +16028,8 @@ var PresentationJobCard = ({
|
|
|
16026
16028
|
shareUrl,
|
|
16027
16029
|
approveUrl,
|
|
16028
16030
|
approveOutlineUrl,
|
|
16031
|
+
reorderSlidesUrl,
|
|
16032
|
+
approveSlideUrl,
|
|
16029
16033
|
regenerateUrl,
|
|
16030
16034
|
hideApproval = false,
|
|
16031
16035
|
className,
|
|
@@ -16057,6 +16061,8 @@ var PresentationJobCard = ({
|
|
|
16057
16061
|
const [messageEdits, setMessageEdits] = useState10({});
|
|
16058
16062
|
const [approvingOutline, setApprovingOutline] = useState10(false);
|
|
16059
16063
|
const [outlineWritePollUrl, setOutlineWritePollUrl] = useState10(null);
|
|
16064
|
+
const [rowBusyIndex, setRowBusyIndex] = useState10(null);
|
|
16065
|
+
const [rowError, setRowError] = useState10(null);
|
|
16060
16066
|
const [regenPollUrl, setRegenPollUrl] = useState10(null);
|
|
16061
16067
|
const [currentSlide, setCurrentSlide] = useState10(1);
|
|
16062
16068
|
const [previewScale, setPreviewScale] = useState10(1);
|
|
@@ -16289,6 +16295,76 @@ var PresentationJobCard = ({
|
|
|
16289
16295
|
});
|
|
16290
16296
|
return changed ? { ...outline, slides } : void 0;
|
|
16291
16297
|
};
|
|
16298
|
+
const moveOutlineSlide = async (index, delta) => {
|
|
16299
|
+
if (!outline || !Array.isArray(outline.slides) || rowBusyIndex !== null) return;
|
|
16300
|
+
const slides = outline.slides;
|
|
16301
|
+
const target = index + delta;
|
|
16302
|
+
if (target < 0 || target >= slides.length) return;
|
|
16303
|
+
const order = slides.map((_, i) => i);
|
|
16304
|
+
[order[index], order[target]] = [order[target], order[index]];
|
|
16305
|
+
const reordered = order.map((i, newIndex) => ({ ...slides[i], n: newIndex + 1 }));
|
|
16306
|
+
const previousOutline = outline;
|
|
16307
|
+
const previousEdits = messageEdits;
|
|
16308
|
+
setOutline({ ...outline, slides: reordered });
|
|
16309
|
+
setMessageEdits((prev) => {
|
|
16310
|
+
const remapped = {};
|
|
16311
|
+
order.forEach((originalIndex, newIndex) => {
|
|
16312
|
+
if (prev[originalIndex] !== void 0) remapped[newIndex] = prev[originalIndex];
|
|
16313
|
+
});
|
|
16314
|
+
return remapped;
|
|
16315
|
+
});
|
|
16316
|
+
setRowBusyIndex(index);
|
|
16317
|
+
setRowError(null);
|
|
16318
|
+
try {
|
|
16319
|
+
const endpoint = reorderSlidesUrl || `/api/presentations/${_job_id}/outline/reorder-slides`;
|
|
16320
|
+
const headers = { "Content-Type": "application/json" };
|
|
16321
|
+
if (authToken) headers.Authorization = `Bearer ${authToken}`;
|
|
16322
|
+
const res = await fetch(endpoint, {
|
|
16323
|
+
method: "POST",
|
|
16324
|
+
headers,
|
|
16325
|
+
body: JSON.stringify({ order })
|
|
16326
|
+
});
|
|
16327
|
+
if (!res.ok) {
|
|
16328
|
+
const err = await res.json().catch(() => ({}));
|
|
16329
|
+
throw new Error(err.detail || err.error || `Reorder failed (${res.status})`);
|
|
16330
|
+
}
|
|
16331
|
+
} catch (e) {
|
|
16332
|
+
setOutline(previousOutline);
|
|
16333
|
+
setMessageEdits(previousEdits);
|
|
16334
|
+
setRowError(e instanceof Error ? e.message : "Could not reorder slides");
|
|
16335
|
+
} finally {
|
|
16336
|
+
setRowBusyIndex(null);
|
|
16337
|
+
}
|
|
16338
|
+
};
|
|
16339
|
+
const toggleSlideApproved = async (index) => {
|
|
16340
|
+
if (!outline || !Array.isArray(outline.slides) || rowBusyIndex !== null) return;
|
|
16341
|
+
const slides = outline.slides;
|
|
16342
|
+
const nextApproved = !slides[index]?.approved;
|
|
16343
|
+
const previousOutline = outline;
|
|
16344
|
+
const updated = slides.map((s, i) => i === index ? { ...s, approved: nextApproved } : s);
|
|
16345
|
+
setOutline({ ...outline, slides: updated });
|
|
16346
|
+
setRowBusyIndex(index);
|
|
16347
|
+
setRowError(null);
|
|
16348
|
+
try {
|
|
16349
|
+
const endpoint = approveSlideUrl || `/api/presentations/${_job_id}/outline/approve-slide`;
|
|
16350
|
+
const headers = { "Content-Type": "application/json" };
|
|
16351
|
+
if (authToken) headers.Authorization = `Bearer ${authToken}`;
|
|
16352
|
+
const res = await fetch(endpoint, {
|
|
16353
|
+
method: "POST",
|
|
16354
|
+
headers,
|
|
16355
|
+
body: JSON.stringify({ slide_index: index, approved: nextApproved })
|
|
16356
|
+
});
|
|
16357
|
+
if (!res.ok) {
|
|
16358
|
+
const err = await res.json().catch(() => ({}));
|
|
16359
|
+
throw new Error(err.detail || err.error || `Approve failed (${res.status})`);
|
|
16360
|
+
}
|
|
16361
|
+
} catch (e) {
|
|
16362
|
+
setOutline(previousOutline);
|
|
16363
|
+
setRowError(e instanceof Error ? e.message : "Could not update slide");
|
|
16364
|
+
} finally {
|
|
16365
|
+
setRowBusyIndex(null);
|
|
16366
|
+
}
|
|
16367
|
+
};
|
|
16292
16368
|
const handleApproveOutline = async () => {
|
|
16293
16369
|
if (!_job_id || approvingOutline) return;
|
|
16294
16370
|
const endpoint = approveOutlineUrl || `/api/presentations/${_job_id}/approve-outline`;
|
|
@@ -16526,31 +16602,71 @@ var PresentationJobCard = ({
|
|
|
16526
16602
|
] })
|
|
16527
16603
|
] }),
|
|
16528
16604
|
/* @__PURE__ */ jsxs108("div", { className: "mt-4 space-y-2", children: [
|
|
16529
|
-
slides.map((s, i) =>
|
|
16530
|
-
|
|
16531
|
-
/* @__PURE__ */ jsxs108(
|
|
16532
|
-
"span",
|
|
16533
|
-
|
|
16534
|
-
|
|
16535
|
-
|
|
16536
|
-
|
|
16537
|
-
|
|
16538
|
-
|
|
16539
|
-
|
|
16540
|
-
|
|
16541
|
-
|
|
16542
|
-
|
|
16543
|
-
|
|
16544
|
-
|
|
16545
|
-
|
|
16546
|
-
|
|
16547
|
-
|
|
16548
|
-
|
|
16549
|
-
|
|
16550
|
-
|
|
16551
|
-
|
|
16605
|
+
slides.map((s, i) => {
|
|
16606
|
+
const rowBusy = building || rowBusyIndex === i;
|
|
16607
|
+
return /* @__PURE__ */ jsxs108("div", { className: "flex items-center gap-1.5", children: [
|
|
16608
|
+
/* @__PURE__ */ jsx147("span", { className: "text-xs text-zinc-600 w-5 text-right tabular-nums flex-shrink-0", children: s.n ?? i + 1 }),
|
|
16609
|
+
/* @__PURE__ */ jsxs108(
|
|
16610
|
+
"span",
|
|
16611
|
+
{
|
|
16612
|
+
className: "flex items-center gap-1 text-[10px] uppercase tracking-wide text-zinc-500 w-20 flex-shrink-0 truncate",
|
|
16613
|
+
title: s.type,
|
|
16614
|
+
children: [
|
|
16615
|
+
/* @__PURE__ */ jsx147(SlideTypeIcon, {}),
|
|
16616
|
+
s.type || "slide"
|
|
16617
|
+
]
|
|
16618
|
+
}
|
|
16619
|
+
),
|
|
16620
|
+
/* @__PURE__ */ jsx147(
|
|
16621
|
+
"input",
|
|
16622
|
+
{
|
|
16623
|
+
value: messageEdits[i] ?? s.message ?? "",
|
|
16624
|
+
onChange: (e) => setMessageEdits((prev) => ({ ...prev, [i]: e.target.value })),
|
|
16625
|
+
disabled: building,
|
|
16626
|
+
className: "flex-1 min-w-0 bg-zinc-800/60 border border-zinc-700 rounded-lg px-3 h-8 text-xs text-zinc-200 focus:border-indigo-500 outline-none disabled:opacity-60"
|
|
16627
|
+
}
|
|
16628
|
+
),
|
|
16629
|
+
/* @__PURE__ */ jsx147(
|
|
16630
|
+
"button",
|
|
16631
|
+
{
|
|
16632
|
+
type: "button",
|
|
16633
|
+
onClick: () => moveOutlineSlide(i, -1),
|
|
16634
|
+
disabled: rowBusy || i === 0,
|
|
16635
|
+
title: "Move up",
|
|
16636
|
+
className: "w-7 h-7 flex items-center justify-center rounded-md border border-zinc-700 text-zinc-400 hover:text-zinc-100 hover:border-zinc-500 disabled:opacity-30 disabled:hover:text-zinc-400 disabled:hover:border-zinc-700 flex-shrink-0",
|
|
16637
|
+
children: /* @__PURE__ */ jsx147(ChevronUpIcon, {})
|
|
16638
|
+
}
|
|
16639
|
+
),
|
|
16640
|
+
/* @__PURE__ */ jsx147(
|
|
16641
|
+
"button",
|
|
16642
|
+
{
|
|
16643
|
+
type: "button",
|
|
16644
|
+
onClick: () => moveOutlineSlide(i, 1),
|
|
16645
|
+
disabled: rowBusy || i === slides.length - 1,
|
|
16646
|
+
title: "Move down",
|
|
16647
|
+
className: "w-7 h-7 flex items-center justify-center rounded-md border border-zinc-700 text-zinc-400 hover:text-zinc-100 hover:border-zinc-500 disabled:opacity-30 disabled:hover:text-zinc-400 disabled:hover:border-zinc-700 flex-shrink-0",
|
|
16648
|
+
children: /* @__PURE__ */ jsx147(ChevronDownIcon, {})
|
|
16649
|
+
}
|
|
16650
|
+
),
|
|
16651
|
+
/* @__PURE__ */ jsx147(
|
|
16652
|
+
"button",
|
|
16653
|
+
{
|
|
16654
|
+
type: "button",
|
|
16655
|
+
onClick: () => toggleSlideApproved(i),
|
|
16656
|
+
disabled: rowBusy,
|
|
16657
|
+
title: s.approved ? "Marked reviewed" : "Mark as reviewed",
|
|
16658
|
+
className: cn(
|
|
16659
|
+
"w-7 h-7 flex items-center justify-center rounded-md border flex-shrink-0 disabled:opacity-40",
|
|
16660
|
+
s.approved ? "border-emerald-600/50 bg-emerald-950/40 text-emerald-300" : "border-zinc-700 text-zinc-500 hover:text-zinc-300 hover:border-zinc-500"
|
|
16661
|
+
),
|
|
16662
|
+
children: /* @__PURE__ */ jsx147(CheckIcon, {})
|
|
16663
|
+
}
|
|
16664
|
+
)
|
|
16665
|
+
] }, i);
|
|
16666
|
+
}),
|
|
16552
16667
|
slides.length === 0 && /* @__PURE__ */ jsx147("p", { className: "text-xs text-zinc-500", children: "No outline slides were returned; you can still build the deck." })
|
|
16553
16668
|
] }),
|
|
16669
|
+
rowError && /* @__PURE__ */ jsx147("p", { className: "mt-2 text-xs text-red-400/90", children: rowError }),
|
|
16554
16670
|
approveError && /* @__PURE__ */ jsx147("p", { className: "mt-3 text-xs text-red-400/90", children: approveError }),
|
|
16555
16671
|
/* @__PURE__ */ jsx147("div", { className: "mt-4 flex items-center justify-end", children: /* @__PURE__ */ jsxs108(
|
|
16556
16672
|
"button",
|
|
@@ -16800,6 +16916,8 @@ var ShareIcon2 = () => /* @__PURE__ */ jsxs109("svg", { width: "14", height: "14
|
|
|
16800
16916
|
/* @__PURE__ */ jsx148("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
|
|
16801
16917
|
] });
|
|
16802
16918
|
var CheckIcon2 = () => /* @__PURE__ */ jsx148("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx148("polyline", { points: "20 6 9 17 4 12" }) });
|
|
16919
|
+
var ChevronUpIcon2 = () => /* @__PURE__ */ jsx148("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx148("polyline", { points: "18 15 12 9 6 15" }) });
|
|
16920
|
+
var ChevronDownIcon2 = () => /* @__PURE__ */ jsx148("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx148("polyline", { points: "6 9 12 15 18 9" }) });
|
|
16803
16921
|
var RefreshIcon2 = () => /* @__PURE__ */ jsxs109("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
16804
16922
|
/* @__PURE__ */ jsx148("polyline", { points: "23 4 23 10 17 10" }),
|
|
16805
16923
|
/* @__PURE__ */ jsx148("path", { d: "M20.49 15a9 9 0 1 1-2.12-9.36L23 10" })
|
|
@@ -16868,6 +16986,7 @@ var ResearchReportJobCard = (props) => {
|
|
|
16868
16986
|
executive_summary: initialSummary,
|
|
16869
16987
|
key_findings: _initialFindings,
|
|
16870
16988
|
html_url: initialHtmlUrl,
|
|
16989
|
+
pdf_url: initialPdfUrl,
|
|
16871
16990
|
generation_mode: initialGenerationMode,
|
|
16872
16991
|
template_id: initialTemplateId,
|
|
16873
16992
|
template_version_id: initialTemplateVersionId,
|
|
@@ -16881,6 +17000,8 @@ var ResearchReportJobCard = (props) => {
|
|
|
16881
17000
|
shareUrl,
|
|
16882
17001
|
approveUrl,
|
|
16883
17002
|
approveOutlineUrl,
|
|
17003
|
+
reorderSectionsUrl,
|
|
17004
|
+
approveSectionUrl,
|
|
16884
17005
|
regenerateUrl,
|
|
16885
17006
|
hideApproval = false,
|
|
16886
17007
|
className,
|
|
@@ -16897,6 +17018,7 @@ var ResearchReportJobCard = (props) => {
|
|
|
16897
17018
|
const [wordCount, setWordCount] = useState11(initialWordCount ?? 0);
|
|
16898
17019
|
const [summary, setSummary] = useState11(initialSummary || "");
|
|
16899
17020
|
const [htmlUrl, setHtmlUrl] = useState11(initialHtmlUrl || "");
|
|
17021
|
+
const [pdfUrl, setPdfUrl] = useState11(initialPdfUrl || "");
|
|
16900
17022
|
const [generationMode, setGenerationMode] = useState11(
|
|
16901
17023
|
initialGenerationMode || (initialHtmlUrl ? "template" : "")
|
|
16902
17024
|
);
|
|
@@ -16917,6 +17039,8 @@ var ResearchReportJobCard = (props) => {
|
|
|
16917
17039
|
const [approveError, setApproveError] = useState11(null);
|
|
16918
17040
|
const [headingEdits, setHeadingEdits] = useState11({});
|
|
16919
17041
|
const [approvingOutline, setApprovingOutline] = useState11(false);
|
|
17042
|
+
const [rowBusyIndex, setRowBusyIndex] = useState11(null);
|
|
17043
|
+
const [rowError, setRowError] = useState11(null);
|
|
16920
17044
|
const [outlineWritePollUrl, setOutlineWritePollUrl] = useState11(null);
|
|
16921
17045
|
const [regenPollUrl, setRegenPollUrl] = useState11(null);
|
|
16922
17046
|
const previewRef = useRef7(null);
|
|
@@ -17024,6 +17148,7 @@ var ResearchReportJobCard = (props) => {
|
|
|
17024
17148
|
setWordCount(output.word_count || 0);
|
|
17025
17149
|
setSummary(output.executive_summary || "");
|
|
17026
17150
|
setHtmlUrl(output.html_url || "");
|
|
17151
|
+
setPdfUrl(output.pdf_url || "");
|
|
17027
17152
|
if (output.generation_mode) setGenerationMode(output.generation_mode);
|
|
17028
17153
|
if (output.template_id) setTemplateId(output.template_id);
|
|
17029
17154
|
if (output.template_version_id) setTemplateVersionId(output.template_version_id);
|
|
@@ -17051,6 +17176,7 @@ var ResearchReportJobCard = (props) => {
|
|
|
17051
17176
|
const applyRegeneratedOutput = useCallback5(
|
|
17052
17177
|
(out) => {
|
|
17053
17178
|
if (out.html_url) setHtmlUrl(out.html_url);
|
|
17179
|
+
setPdfUrl(out.pdf_url || "");
|
|
17054
17180
|
if (out.template_id) setTemplateId(out.template_id);
|
|
17055
17181
|
setReviewStatus("pending_review");
|
|
17056
17182
|
setTemplateVersionId("");
|
|
@@ -17067,6 +17193,7 @@ var ResearchReportJobCard = (props) => {
|
|
|
17067
17193
|
word_count: out.word_count ?? wordCount,
|
|
17068
17194
|
executive_summary: out.executive_summary ?? summary,
|
|
17069
17195
|
html_url: out.html_url ?? htmlUrl,
|
|
17196
|
+
pdf_url: out.pdf_url ?? pdfUrl,
|
|
17070
17197
|
generation_mode: "template",
|
|
17071
17198
|
template_id: out.template_id ?? templateId,
|
|
17072
17199
|
template_version_id: void 0,
|
|
@@ -17074,7 +17201,7 @@ var ResearchReportJobCard = (props) => {
|
|
|
17074
17201
|
theme: out.theme ?? theme
|
|
17075
17202
|
});
|
|
17076
17203
|
},
|
|
17077
|
-
[title, depth, sectionCount, sourceCount, wordCount, summary, htmlUrl, templateId, theme]
|
|
17204
|
+
[title, depth, sectionCount, sourceCount, wordCount, summary, htmlUrl, pdfUrl, templateId, theme]
|
|
17078
17205
|
);
|
|
17079
17206
|
useSharedPoll(
|
|
17080
17207
|
{
|
|
@@ -17118,6 +17245,7 @@ var ResearchReportJobCard = (props) => {
|
|
|
17118
17245
|
if (out.word_count !== void 0) setWordCount(out.word_count);
|
|
17119
17246
|
if (out.executive_summary) setSummary(out.executive_summary);
|
|
17120
17247
|
if (out.html_url) setHtmlUrl(out.html_url);
|
|
17248
|
+
setPdfUrl(out.pdf_url || "");
|
|
17121
17249
|
if (out.generation_mode) setGenerationMode(out.generation_mode);
|
|
17122
17250
|
if (out.template_id) setTemplateId(out.template_id);
|
|
17123
17251
|
setTemplateVersionId(out.template_version_id || "");
|
|
@@ -17168,6 +17296,76 @@ var ResearchReportJobCard = (props) => {
|
|
|
17168
17296
|
});
|
|
17169
17297
|
return changed ? { ...outline, sections } : void 0;
|
|
17170
17298
|
};
|
|
17299
|
+
const moveOutlineSection = async (index, delta) => {
|
|
17300
|
+
if (!outline || !Array.isArray(outline.sections) || rowBusyIndex !== null) return;
|
|
17301
|
+
const sections = outline.sections;
|
|
17302
|
+
const target = index + delta;
|
|
17303
|
+
if (target < 0 || target >= sections.length) return;
|
|
17304
|
+
const order = sections.map((_, i) => i);
|
|
17305
|
+
[order[index], order[target]] = [order[target], order[index]];
|
|
17306
|
+
const reordered = order.map((i) => sections[i]);
|
|
17307
|
+
const previousOutline = outline;
|
|
17308
|
+
const previousEdits = headingEdits;
|
|
17309
|
+
setOutline({ ...outline, sections: reordered });
|
|
17310
|
+
setHeadingEdits((prev) => {
|
|
17311
|
+
const remapped = {};
|
|
17312
|
+
order.forEach((originalIndex, newIndex) => {
|
|
17313
|
+
if (prev[originalIndex] !== void 0) remapped[newIndex] = prev[originalIndex];
|
|
17314
|
+
});
|
|
17315
|
+
return remapped;
|
|
17316
|
+
});
|
|
17317
|
+
setRowBusyIndex(index);
|
|
17318
|
+
setRowError(null);
|
|
17319
|
+
try {
|
|
17320
|
+
const endpoint = reorderSectionsUrl || `/api/reports/${job_id}/outline/reorder-sections`;
|
|
17321
|
+
const headers = { "Content-Type": "application/json" };
|
|
17322
|
+
if (authToken) headers.Authorization = `Bearer ${authToken}`;
|
|
17323
|
+
const res = await fetch(endpoint, {
|
|
17324
|
+
method: "POST",
|
|
17325
|
+
headers,
|
|
17326
|
+
body: JSON.stringify({ order })
|
|
17327
|
+
});
|
|
17328
|
+
if (!res.ok) {
|
|
17329
|
+
const err = await res.json().catch(() => ({}));
|
|
17330
|
+
throw new Error(err.detail || err.error || `Reorder failed (${res.status})`);
|
|
17331
|
+
}
|
|
17332
|
+
} catch (e) {
|
|
17333
|
+
setOutline(previousOutline);
|
|
17334
|
+
setHeadingEdits(previousEdits);
|
|
17335
|
+
setRowError(e instanceof Error ? e.message : "Could not reorder sections");
|
|
17336
|
+
} finally {
|
|
17337
|
+
setRowBusyIndex(null);
|
|
17338
|
+
}
|
|
17339
|
+
};
|
|
17340
|
+
const toggleSectionApproved = async (index) => {
|
|
17341
|
+
if (!outline || !Array.isArray(outline.sections) || rowBusyIndex !== null) return;
|
|
17342
|
+
const sections = outline.sections;
|
|
17343
|
+
const nextApproved = !sections[index]?.approved;
|
|
17344
|
+
const previousOutline = outline;
|
|
17345
|
+
const updated = sections.map((s, i) => i === index ? { ...s, approved: nextApproved } : s);
|
|
17346
|
+
setOutline({ ...outline, sections: updated });
|
|
17347
|
+
setRowBusyIndex(index);
|
|
17348
|
+
setRowError(null);
|
|
17349
|
+
try {
|
|
17350
|
+
const endpoint = approveSectionUrl || `/api/reports/${job_id}/outline/approve-section`;
|
|
17351
|
+
const headers = { "Content-Type": "application/json" };
|
|
17352
|
+
if (authToken) headers.Authorization = `Bearer ${authToken}`;
|
|
17353
|
+
const res = await fetch(endpoint, {
|
|
17354
|
+
method: "POST",
|
|
17355
|
+
headers,
|
|
17356
|
+
body: JSON.stringify({ section_index: index, approved: nextApproved })
|
|
17357
|
+
});
|
|
17358
|
+
if (!res.ok) {
|
|
17359
|
+
const err = await res.json().catch(() => ({}));
|
|
17360
|
+
throw new Error(err.detail || err.error || `Approve failed (${res.status})`);
|
|
17361
|
+
}
|
|
17362
|
+
} catch (e) {
|
|
17363
|
+
setOutline(previousOutline);
|
|
17364
|
+
setRowError(e instanceof Error ? e.message : "Could not update section");
|
|
17365
|
+
} finally {
|
|
17366
|
+
setRowBusyIndex(null);
|
|
17367
|
+
}
|
|
17368
|
+
};
|
|
17171
17369
|
const handleApproveOutline = async () => {
|
|
17172
17370
|
if (!job_id || approvingOutline) return;
|
|
17173
17371
|
const endpoint = approveOutlineUrl || `/api/reports/${job_id}/approve-outline`;
|
|
@@ -17327,20 +17525,60 @@ var ResearchReportJobCard = (props) => {
|
|
|
17327
17525
|
] })
|
|
17328
17526
|
] }),
|
|
17329
17527
|
/* @__PURE__ */ jsxs109("div", { className: "mt-4 space-y-2", children: [
|
|
17330
|
-
sections.map((s, i) =>
|
|
17331
|
-
|
|
17332
|
-
/* @__PURE__ */
|
|
17333
|
-
"
|
|
17334
|
-
|
|
17335
|
-
|
|
17336
|
-
|
|
17337
|
-
|
|
17338
|
-
|
|
17339
|
-
|
|
17340
|
-
|
|
17341
|
-
|
|
17528
|
+
sections.map((s, i) => {
|
|
17529
|
+
const rowBusy = building || rowBusyIndex === i;
|
|
17530
|
+
return /* @__PURE__ */ jsxs109("div", { className: "flex items-center gap-1.5", children: [
|
|
17531
|
+
/* @__PURE__ */ jsx148("span", { className: "text-xs text-zinc-600 w-5 text-right tabular-nums flex-shrink-0", children: i + 1 }),
|
|
17532
|
+
/* @__PURE__ */ jsx148(
|
|
17533
|
+
"input",
|
|
17534
|
+
{
|
|
17535
|
+
value: headingEdits[i] ?? s.heading ?? "",
|
|
17536
|
+
onChange: (e) => setHeadingEdits((prev) => ({ ...prev, [i]: e.target.value })),
|
|
17537
|
+
disabled: building,
|
|
17538
|
+
className: "flex-1 min-w-0 bg-zinc-800/60 border border-zinc-700 rounded-lg px-3 h-8 text-xs text-zinc-200 focus:border-violet-500 outline-none disabled:opacity-60"
|
|
17539
|
+
}
|
|
17540
|
+
),
|
|
17541
|
+
/* @__PURE__ */ jsx148(
|
|
17542
|
+
"button",
|
|
17543
|
+
{
|
|
17544
|
+
type: "button",
|
|
17545
|
+
onClick: () => moveOutlineSection(i, -1),
|
|
17546
|
+
disabled: rowBusy || i === 0,
|
|
17547
|
+
title: "Move up",
|
|
17548
|
+
className: "w-7 h-7 flex items-center justify-center rounded-md border border-zinc-700 text-zinc-400 hover:text-zinc-100 hover:border-zinc-500 disabled:opacity-30 disabled:hover:text-zinc-400 disabled:hover:border-zinc-700 flex-shrink-0",
|
|
17549
|
+
children: /* @__PURE__ */ jsx148(ChevronUpIcon2, {})
|
|
17550
|
+
}
|
|
17551
|
+
),
|
|
17552
|
+
/* @__PURE__ */ jsx148(
|
|
17553
|
+
"button",
|
|
17554
|
+
{
|
|
17555
|
+
type: "button",
|
|
17556
|
+
onClick: () => moveOutlineSection(i, 1),
|
|
17557
|
+
disabled: rowBusy || i === sections.length - 1,
|
|
17558
|
+
title: "Move down",
|
|
17559
|
+
className: "w-7 h-7 flex items-center justify-center rounded-md border border-zinc-700 text-zinc-400 hover:text-zinc-100 hover:border-zinc-500 disabled:opacity-30 disabled:hover:text-zinc-400 disabled:hover:border-zinc-700 flex-shrink-0",
|
|
17560
|
+
children: /* @__PURE__ */ jsx148(ChevronDownIcon2, {})
|
|
17561
|
+
}
|
|
17562
|
+
),
|
|
17563
|
+
/* @__PURE__ */ jsx148(
|
|
17564
|
+
"button",
|
|
17565
|
+
{
|
|
17566
|
+
type: "button",
|
|
17567
|
+
onClick: () => toggleSectionApproved(i),
|
|
17568
|
+
disabled: rowBusy,
|
|
17569
|
+
title: s.approved ? "Marked reviewed" : "Mark as reviewed",
|
|
17570
|
+
className: cn(
|
|
17571
|
+
"w-7 h-7 flex items-center justify-center rounded-md border flex-shrink-0 disabled:opacity-40",
|
|
17572
|
+
s.approved ? "border-emerald-600/50 bg-emerald-950/40 text-emerald-300" : "border-zinc-700 text-zinc-500 hover:text-zinc-300 hover:border-zinc-500"
|
|
17573
|
+
),
|
|
17574
|
+
children: /* @__PURE__ */ jsx148(CheckIcon2, {})
|
|
17575
|
+
}
|
|
17576
|
+
)
|
|
17577
|
+
] }, i);
|
|
17578
|
+
}),
|
|
17342
17579
|
sections.length === 0 && /* @__PURE__ */ jsx148("p", { className: "text-xs text-zinc-500", children: "No outline sections were returned; you can still build the report." })
|
|
17343
17580
|
] }),
|
|
17581
|
+
rowError && /* @__PURE__ */ jsx148("p", { className: "mt-2 text-xs text-red-400/90", children: rowError }),
|
|
17344
17582
|
approveError && /* @__PURE__ */ jsx148("p", { className: "mt-3 text-xs text-red-400/90", children: approveError }),
|
|
17345
17583
|
/* @__PURE__ */ jsx148("div", { className: "mt-4 flex items-center justify-end", children: /* @__PURE__ */ jsxs109(
|
|
17346
17584
|
"button",
|
|
@@ -17403,6 +17641,26 @@ var ResearchReportJobCard = (props) => {
|
|
|
17403
17641
|
window.open(htmlUrl, "_blank", "noopener,noreferrer");
|
|
17404
17642
|
}
|
|
17405
17643
|
};
|
|
17644
|
+
const handleDownloadPdf = async () => {
|
|
17645
|
+
if (!pdfUrl) return;
|
|
17646
|
+
const filename = `${(title ?? "").replace(/[^a-z0-9]/gi, "-").toLowerCase()}.pdf`;
|
|
17647
|
+
const href = `/api/download?url=${encodeURIComponent(pdfUrl)}&filename=${encodeURIComponent(filename)}`;
|
|
17648
|
+
try {
|
|
17649
|
+
const response = await fetch(href);
|
|
17650
|
+
if (!response.ok) throw new Error(`status ${response.status}`);
|
|
17651
|
+
const blob = await response.blob();
|
|
17652
|
+
const objectUrl = window.URL.createObjectURL(blob);
|
|
17653
|
+
const anchor = document.createElement("a");
|
|
17654
|
+
anchor.href = objectUrl;
|
|
17655
|
+
anchor.download = filename;
|
|
17656
|
+
document.body.appendChild(anchor);
|
|
17657
|
+
anchor.click();
|
|
17658
|
+
anchor.remove();
|
|
17659
|
+
window.URL.revokeObjectURL(objectUrl);
|
|
17660
|
+
} catch {
|
|
17661
|
+
window.open(pdfUrl, "_blank", "noopener,noreferrer");
|
|
17662
|
+
}
|
|
17663
|
+
};
|
|
17406
17664
|
const resolveShareLink = () => {
|
|
17407
17665
|
if (shareUrl) return shareUrl;
|
|
17408
17666
|
if (typeof window !== "undefined" && job_id) {
|
|
@@ -17455,6 +17713,7 @@ var ResearchReportJobCard = (props) => {
|
|
|
17455
17713
|
word_count: wordCount,
|
|
17456
17714
|
executive_summary: summary,
|
|
17457
17715
|
html_url: htmlUrl,
|
|
17716
|
+
pdf_url: pdfUrl,
|
|
17458
17717
|
generation_mode: generationMode,
|
|
17459
17718
|
template_id: data.template_id || templateId,
|
|
17460
17719
|
template_version_id: data.template_version_id || templateVersionId,
|
|
@@ -17592,6 +17851,18 @@ var ResearchReportJobCard = (props) => {
|
|
|
17592
17851
|
]
|
|
17593
17852
|
}
|
|
17594
17853
|
),
|
|
17854
|
+
pdfUrl && /* @__PURE__ */ jsxs109(
|
|
17855
|
+
"button",
|
|
17856
|
+
{
|
|
17857
|
+
onClick: handleDownloadPdf,
|
|
17858
|
+
title: "Download PDF",
|
|
17859
|
+
className: "flex items-center gap-1.5 px-2.5 h-7 rounded-lg border border-zinc-700 bg-zinc-800 hover:border-zinc-500 text-zinc-400 hover:text-zinc-200 text-xs font-medium transition-colors",
|
|
17860
|
+
children: [
|
|
17861
|
+
/* @__PURE__ */ jsx148(DownloadIcon2, {}),
|
|
17862
|
+
/* @__PURE__ */ jsx148("span", { children: "PDF" })
|
|
17863
|
+
]
|
|
17864
|
+
}
|
|
17865
|
+
),
|
|
17595
17866
|
/* @__PURE__ */ jsxs109(
|
|
17596
17867
|
"button",
|
|
17597
17868
|
{
|