Skip to content
This repository was archived by the owner on Feb 19, 2025. It is now read-only.

Commit d89ea24

Browse files
committed
Added ability to save XFDF
1 parent ad5a88e commit d89ea24

File tree

6 files changed

+82
-9
lines changed

6 files changed

+82
-9
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "webviewer",
33
"widgetName": "WebViewer",
4-
"version": "1.3.0",
4+
"version": "1.2.1",
55
"description": "My widget description",
66
"copyright": "2022 PDFTron",
77
"author": "Andrey Safonov",

src/WebViewer.editorPreview.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,17 @@ export class preview extends Component<WebViewerPreviewProps> {
88
render(): ReactNode {
99
const viewerProps = {
1010
containerHeight: this.props.containerHeight,
11-
file: this.props.fileAttributeUrl || this.props.fileUrl,
11+
fileUrl: this.props.fileAttributeUrl || this.props.fileUrl,
1212
fileId: this.props.fileId,
1313
enableFilePicker: this.props.enableFilePicker,
1414
annotationUser: this.props.annotationUser,
1515
accessibleMode: this.props.accessibleMode,
1616
enableMeasurement: this.props.enableMeasurement,
1717
enableRedaction: this.props.enableRedaction,
1818
enableAnnotations: this.props.enableAnnotations,
19+
xfdfAttribute: this.props.xfdfAttribute,
20+
enableXfdfExportButton: this.props.enableXfdfExportButton,
21+
enableAutoXfdfExport: this.props.enableAutoXfdfExport,
1922
loadAsPDF: this.props.loadAsPDF,
2023
highContrastMode: this.props.highContrastMode,
2124
notesInLeftPanel: this.props.notesInLeftPanel,

src/WebViewer.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,17 @@ export default class WebViewer extends Component<WebViewerContainerProps> {
99
render(): ReactNode {
1010
const viewerProps = {
1111
containerHeight: this.props.containerHeight,
12-
file: this.props.fileAttributeUrl?.value || this.props.fileUrl,
12+
fileUrl: this.props.fileAttributeUrl?.value || this.props.fileUrl,
1313
fileId: this.props.fileId?.value,
1414
enableFilePicker: this.props.enableFilePicker,
1515
annotationUser: this.props.annotationUser?.value,
1616
accessibleMode: this.props.accessibleMode,
1717
enableMeasurement: this.props.enableMeasurement,
1818
enableRedaction: this.props.enableRedaction,
1919
enableAnnotations: this.props.enableAnnotations,
20+
xfdfAttribute: this.props.xfdfAttribute,
21+
enableXfdfExportButton: this.props.enableXfdfExportButton,
22+
enableAutoXfdfExport: this.props.enableAutoXfdfExport,
2023
loadAsPDF: this.props.loadAsPDF,
2124
highContrastMode: this.props.highContrastMode,
2225
notesInLeftPanel: this.props.notesInLeftPanel,

src/WebViewer.xml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,27 @@
7171
<description>Automatically select annotations when they are created.</description>
7272
</property>
7373
</propertyGroup>
74+
<propertyGroup caption="XFDF">
75+
<property key="xfdfAttribute" type="attribute" required="false" onChange="onExportXfdf">
76+
<caption>XFDF Attribute</caption>
77+
<description>The XFDF attribute to import from and export to.</description>
78+
<attributeTypes>
79+
<attributeType name="String"/>
80+
</attributeTypes>
81+
</property>
82+
<property key="onExportXfdf" type="action" required="false">
83+
<caption>On export XFDF</caption>
84+
<description>Trigger an action when exporting annotations to XFDF. This can occur many times when auto-export is enabled.</description>
85+
</property>
86+
<property key="enableXfdfExportButton" type="boolean" defaultValue="false">
87+
<caption>Enable XFDF Export Button</caption>
88+
<description>Enable the button to manually export and save annotations as XFDF.</description>
89+
</property>
90+
<property key="enableAutoXfdfExport" type="boolean" defaultValue="false">
91+
<caption>Enable Auto XFDF Export</caption>
92+
<description>Enable automatic saving of the annotation XFDF when annotations change.</description>
93+
</property>
94+
</propertyGroup>
7495
</propertyGroup>
7596
<propertyGroup caption="UI">
7697
<property key="isVisible" type="attribute" required="false">

src/components/PDFViewer.tsx

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@ import WebViewerModuleClient from "../clients/WebViewerModuleClient";
44

55
export interface InputProps {
66
containerHeight: string;
7-
file?: string;
7+
fileUrl?: string;
88
fileId?: string;
99
enableFilePicker?: boolean;
1010
annotationUser?: string;
1111
accessibleMode?: boolean;
1212
enableMeasurement?: boolean;
1313
enableRedaction?: boolean;
1414
enableAnnotations?: boolean;
15+
xfdfAttribute?: any;
16+
enableXfdfExportButton: boolean;
17+
enableAutoXfdfExport: boolean;
1518
loadAsPDF?: boolean;
1619
highContrastMode?: boolean;
1720
notesInLeftPanel?: boolean;
@@ -90,6 +93,7 @@ const PDFViewer: React.FC<InputProps> = props => {
9093
if (props.enableDocumentUpdates) {
9194
header.push({
9295
type: "actionButton",
96+
title: "Save document",
9397
img: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z"/></svg>',
9498
onClick: async () => {
9599
// Export annotation XFDF
@@ -102,7 +106,9 @@ const PDFViewer: React.FC<InputProps> = props => {
102106
const fileData = await Core.documentViewer.getDocument().getFileData({ xfdfString });
103107

104108
// Send it merged with the document data to REST API to update
105-
const updateTask = currentFileId ? WebViewerModuleClient.updateFile(props.fileId || "", fileData) : WebViewerModuleClient.saveFile(fileData);
109+
const updateTask = currentFileId
110+
? WebViewerModuleClient.updateFile(props.fileId || "", fileData)
111+
: WebViewerModuleClient.saveFile(fileData);
106112

107113
// Add minimum artificial delay to make it look like work is being done
108114
// Otherwise, requests may complete too fast
@@ -128,9 +134,42 @@ const PDFViewer: React.FC<InputProps> = props => {
128134
});
129135
}
130136
});
137+
138+
if (props.xfdfAttribute) {
139+
if (props.xfdfAttribute.readOnly && (props.enableXfdfExportButton || props.enableAutoXfdfExport)) {
140+
console.warn(
141+
"The XFDF attribute is read-only. Please check the user permissions or allow the data source to be editable."
142+
);
143+
} else {
144+
const updateXfdfAttribute = async (): Promise<void> => {
145+
const doc = Core.documentViewer.getDocument();
146+
if (!doc) {
147+
return;
148+
}
149+
150+
const xfdfString = await Core.annotationManager.exportAnnotations();
151+
props.xfdfAttribute.setValue(xfdfString);
152+
};
153+
154+
if (props.enableXfdfExportButton) {
155+
UI.setHeaderItems(header => {
156+
header.push({
157+
type: "actionButton",
158+
title: "Save XFDF",
159+
img: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z"/></svg>',
160+
onClick: updateXfdfAttribute
161+
});
162+
});
163+
}
164+
165+
if (props.enableAutoXfdfExport) {
166+
Core.annotationManager.addEventListener("annotationsChanged", updateXfdfAttribute);
167+
}
168+
}
169+
}
131170
});
132171

133-
Core.documentViewer.addEventListener('documentLoaded', () => {
172+
Core.documentViewer.addEventListener("documentLoaded", () => {
134173
documentLoadCount++;
135174
if (documentLoadCount > 1 && currentFileId) {
136175
currentFileId = null;
@@ -143,10 +182,10 @@ const PDFViewer: React.FC<InputProps> = props => {
143182

144183
// Attributes in Mendix may update later, this will load the file after the update
145184
useEffect(() => {
146-
if (wvInstance && props.file) {
147-
wvInstance.UI.loadDocument(props.file);
185+
if (wvInstance && props.fileUrl) {
186+
wvInstance.UI.loadDocument(props.fileUrl);
148187
}
149-
}, [wvInstance, props.file]);
188+
}, [wvInstance, props.fileUrl]);
150189

151190
// Attributes in Mendix may update later, this will load the file after the update
152191
useEffect(() => {

typings/WebViewerProps.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ export interface WebViewerContainerProps {
4444
enableMeasurement: boolean;
4545
enableRedaction: boolean;
4646
selectAnnotationOnCreation: boolean;
47+
xfdfAttribute?: EditableValue<string>;
48+
enableXfdfExportButton: boolean;
49+
enableAutoXfdfExport: boolean;
4750
isVisible?: EditableValue<boolean>;
4851
containerHeight: string;
4952
enableDarkMode: boolean;
@@ -74,6 +77,10 @@ export interface WebViewerPreviewProps {
7477
enableMeasurement: boolean;
7578
enableRedaction: boolean;
7679
selectAnnotationOnCreation: boolean;
80+
xfdfAttribute: string;
81+
onExportXfdf: {} | null;
82+
enableXfdfExportButton: boolean;
83+
enableAutoXfdfExport: boolean;
7784
isVisible: string;
7885
containerHeight: string;
7986
enableDarkMode: boolean;

0 commit comments

Comments
 (0)