@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<29bf3465293095c44e826394c602cde1>>
|
||||
* @generated SignedSource<<25880ab79f8b6ae18f3ead4431a90329>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type DocumentOrderField = "CREATED_AT" | "TITLE";
|
||||
export type DocumentOrderField = "CREATED_AT" | "DOCUMENT_TYPE" | "TITLE";
|
||||
export type OrderDirection = "ASC" | "DESC";
|
||||
export type DocumentOrder = {
|
||||
direction: OrderDirection;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<b61f74ae791f86da55afd868c68c85e4>>
|
||||
* @generated SignedSource<<9ea096db73885458f35ae718a00ded47>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type DocumentOrderField = "CREATED_AT" | "TITLE";
|
||||
export type DocumentOrderField = "CREATED_AT" | "DOCUMENT_TYPE" | "TITLE";
|
||||
export type OrderDirection = "ASC" | "DESC";
|
||||
export type DocumentOrder = {
|
||||
direction: OrderDirection;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import {
|
||||
Avatar,
|
||||
Button,
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogTitle,
|
||||
IconArrowInbox,
|
||||
Markdown,
|
||||
} from "@probo/ui";
|
||||
import { graphql } from "relay-runtime";
|
||||
@@ -11,9 +13,11 @@ import { useTranslate } from "@probo/i18n";
|
||||
import { useState, type ReactNode } from "react";
|
||||
import { useFragment } from "react-relay";
|
||||
import type { DocumentVersionHistoryDialogFragment$key } from "./__generated__/DocumentVersionHistoryDialogFragment.graphql";
|
||||
import type { DocumentVersionHistoryDialogExportPDFMutation } from "./__generated__/DocumentVersionHistoryDialogExportPDFMutation.graphql";
|
||||
import clsx from "clsx";
|
||||
import type { NodeOf } from "/types";
|
||||
import type { DocumentDetailPageDocumentFragment$data } from "../__generated__/DocumentDetailPageDocumentFragment.graphql";
|
||||
import { useMutationWithToasts } from "/hooks/useMutationWithToasts";
|
||||
|
||||
const historyFragment = graphql`
|
||||
fragment DocumentVersionHistoryDialogFragment on DocumentVersion {
|
||||
@@ -30,6 +34,16 @@ const historyFragment = graphql`
|
||||
}
|
||||
`;
|
||||
|
||||
const exportPDFMutation = graphql`
|
||||
mutation DocumentVersionHistoryDialogExportPDFMutation(
|
||||
$documentVersionId: ID!
|
||||
) {
|
||||
exportDocumentVersionPDF(input: { documentVersionId: $documentVersionId }) {
|
||||
data
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
type Props = {
|
||||
document: DocumentDetailPageDocumentFragment$data;
|
||||
children?: ReactNode;
|
||||
@@ -41,6 +55,46 @@ export function DocumentVersionHistoryDialog(props: Props) {
|
||||
const { __ } = useTranslate();
|
||||
const versions = props.document.versions.edges.map((edge) => edge.node);
|
||||
const [selectedVersion, setSelectedVersion] = useState<Version>(versions[0]);
|
||||
const [exportPDF, isExporting] =
|
||||
useMutationWithToasts<DocumentVersionHistoryDialogExportPDFMutation>(
|
||||
exportPDFMutation,
|
||||
{
|
||||
errorMessage: __("Failed to export PDF"),
|
||||
successMessage: __("PDF exported successfully"),
|
||||
}
|
||||
);
|
||||
|
||||
const handleDownloadPDF = () => {
|
||||
exportPDF({
|
||||
variables: { documentVersionId: selectedVersion.id },
|
||||
onCompleted: (data) => {
|
||||
if (data.exportDocumentVersionPDF.data) {
|
||||
// Handle data URI format (data:application/pdf;base64,...)
|
||||
const dataUri = data.exportDocumentVersionPDF.data;
|
||||
|
||||
// Extract base64 part from data URI
|
||||
const base64Data = dataUri.split(",")[1];
|
||||
|
||||
// Convert base64 to blob and download
|
||||
const binaryString = atob(base64Data);
|
||||
const bytes = new Uint8Array(binaryString.length);
|
||||
for (let i = 0; i < binaryString.length; i++) {
|
||||
bytes[i] = binaryString.charCodeAt(i);
|
||||
}
|
||||
const blob = new Blob([bytes], { type: "application/pdf" });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const link = document.createElement("a");
|
||||
link.href = url;
|
||||
link.download = `${props.document.title}-v${selectedVersion.version}.pdf`;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog trigger={props.children}>
|
||||
<DialogContent className="flex" scrollableChildren>
|
||||
@@ -59,6 +113,16 @@ export function DocumentVersionHistoryDialog(props: Props) {
|
||||
))}
|
||||
</aside>
|
||||
<main className="flex-1 px-12 py-8">
|
||||
<div className="mb-4">
|
||||
<Button
|
||||
onClick={handleDownloadPDF}
|
||||
icon={IconArrowInbox}
|
||||
variant="secondary"
|
||||
disabled={isExporting}
|
||||
>
|
||||
{isExporting ? __("Exporting...") : __("Download PDF")}
|
||||
</Button>
|
||||
</div>
|
||||
<Markdown content={selectedVersion.content} />
|
||||
</main>
|
||||
</DialogContent>
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* @generated SignedSource<<06126b60bc37d8fbbb9a475af6d5d29d>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type DocumentVersionHistoryDialogExportPDFMutation$variables = {
|
||||
documentVersionId: string;
|
||||
};
|
||||
export type DocumentVersionHistoryDialogExportPDFMutation$data = {
|
||||
readonly exportDocumentVersionPDF: {
|
||||
readonly data: string;
|
||||
};
|
||||
};
|
||||
export type DocumentVersionHistoryDialogExportPDFMutation = {
|
||||
response: DocumentVersionHistoryDialogExportPDFMutation$data;
|
||||
variables: DocumentVersionHistoryDialogExportPDFMutation$variables;
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
var v0 = [
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "documentVersionId"
|
||||
}
|
||||
],
|
||||
v1 = [
|
||||
{
|
||||
"alias": null,
|
||||
"args": [
|
||||
{
|
||||
"fields": [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "documentVersionId",
|
||||
"variableName": "documentVersionId"
|
||||
}
|
||||
],
|
||||
"kind": "ObjectValue",
|
||||
"name": "input"
|
||||
}
|
||||
],
|
||||
"concreteType": "ExportDocumentVersionPDFPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "exportDocumentVersionPDF",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "data",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
];
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "DocumentVersionHistoryDialogExportPDFMutation",
|
||||
"selections": (v1/*: any*/),
|
||||
"type": "Mutation",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Operation",
|
||||
"name": "DocumentVersionHistoryDialogExportPDFMutation",
|
||||
"selections": (v1/*: any*/)
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "45204e42c1018e00dcceaae84eb9a5f7",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "DocumentVersionHistoryDialogExportPDFMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation DocumentVersionHistoryDialogExportPDFMutation(\n $documentVersionId: ID!\n) {\n exportDocumentVersionPDF(input: {documentVersionId: $documentVersionId}) {\n data\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "587bcc8bb6cf72e64a5eca18769ac432";
|
||||
|
||||
export default node;
|
||||
Reference in New Issue
Block a user