Skip to content

Commit 329b062

Browse files
committed
feat: add timestamp to electronic signatures example
1 parent 9a9cd90 commit 329b062

File tree

2 files changed

+195
-0
lines changed

2 files changed

+195
-0
lines changed
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
import type {
2+
ImageAnnotation,
3+
InkAnnotation,
4+
Instance,
5+
} from "@nutrient-sdk/viewer";
6+
import { baseOptions } from "../../shared/base-options";
7+
8+
// Signature type is InkAnnotation | ImageAnnotation
9+
type Signature = InkAnnotation | ImageAnnotation;
10+
11+
let signatureWidgetId: string | null = null; // Store the widget ID for deletion
12+
const signatureFieldName = "Sig1"; // Signature field name
13+
let left1 = 380;
14+
let top2 = 150;
15+
let width3 = 180;
16+
let height4 = 30;
17+
18+
window.NutrientViewer.load({
19+
...baseOptions,
20+
theme: window.NutrientViewer.Theme.DARK,
21+
isEditableAnnotation: (annotation) => {
22+
// Check if annotation has isSignature property (InkAnnotation or ImageAnnotation)
23+
if ("isSignature" in annotation) {
24+
return !(annotation as InkAnnotation | ImageAnnotation).isSignature;
25+
}
26+
return true;
27+
},
28+
electronicSignatures: {},
29+
}).then(async (instance: Instance) => {
30+
// Create a widget annotation for the signature
31+
const widget = new window.NutrientViewer.Annotations.WidgetAnnotation({
32+
pageIndex: 0,
33+
boundingBox: new window.NutrientViewer.Geometry.Rect({
34+
left: left1,
35+
top: top2,
36+
width: width3, // Fixed width
37+
height: height4, // Fixed height
38+
}),
39+
opacity: 0.5, // Make it slightly transparent
40+
formFieldName: signatureFieldName,
41+
id: window.NutrientViewer.generateInstantId(),
42+
});
43+
44+
// Store the widget ID for later deletion
45+
signatureWidgetId = widget.id;
46+
47+
// Create the signature form field
48+
const formField = new window.NutrientViewer.FormFields.SignatureFormField({
49+
name: signatureFieldName,
50+
annotationIds: window.NutrientViewer.Immutable.List([widget.id]),
51+
});
52+
await instance.create([widget, formField]);
53+
54+
instance.addEventListener(
55+
"inkSignatures.create",
56+
async (annotation: Signature) => {
57+
if (signatureWidgetId) {
58+
await instance.delete(signatureWidgetId);
59+
}
60+
61+
// Check if annotation is an ImageAnnotation (has contentType property)
62+
const isImageAnnotation = "contentType" in annotation;
63+
const contentType = isImageAnnotation
64+
? (annotation as ImageAnnotation).contentType
65+
: null;
66+
const fileName = isImageAnnotation
67+
? (annotation as ImageAnnotation).fileName
68+
: null;
69+
70+
if (
71+
// creationModes: [window.NutrientViewer.ElectronicSignatureCreationMode.DRAW]
72+
// InkAnnotation (drawn signature) - no contentType
73+
!isImageAnnotation
74+
) {
75+
left1 = left1 + 10;
76+
top2 = top2 - 12;
77+
width3 = width3 - 50;
78+
height4 = height4 + 25;
79+
}
80+
if (
81+
// creationModes: [window.NutrientViewer.ElectronicSignatureCreationMode.TYPE]
82+
contentType === "image/png" &&
83+
fileName === null
84+
) {
85+
left1 = left1 - 30;
86+
top2 = top2 - 12;
87+
width3 = width3 + 200;
88+
height4 = height4 + 25;
89+
}
90+
if (
91+
// creationModes: [window.NutrientViewer.ElectronicSignatureCreationMode.IMAGE],
92+
(contentType === "image/png" || contentType === "image/jpeg") &&
93+
fileName != null
94+
) {
95+
left1 = left1 + 10;
96+
top2 = top2 - 12;
97+
width3 = width3 - 50;
98+
height4 = height4 + 25;
99+
}
100+
101+
const Loggedinuser = "Nutrient";
102+
const signedBy = new window.NutrientViewer.Annotations.TextAnnotation({
103+
pageIndex: 0,
104+
text: {
105+
format: "plain",
106+
value: `powered by ${Loggedinuser}`,
107+
},
108+
boundingBox: new window.NutrientViewer.Geometry.Rect({
109+
left: left1 + 30,
110+
top: top2 - 5,
111+
width: width3 + 100,
112+
height: 13,
113+
}),
114+
font: "Verdana",
115+
fontSize: 9,
116+
fontColor: window.NutrientViewer.Color.BLUE,
117+
horizontalAlign: "left",
118+
//readOnly: true,
119+
locked: true,
120+
lockedContents: true,
121+
note: "Authenticated user",
122+
isFitting: false,
123+
});
124+
125+
instance.create(signedBy);
126+
127+
const currentdate = new Date();
128+
const dateOptions: Intl.DateTimeFormatOptions = {
129+
day: "2-digit",
130+
month: "short",
131+
year: "numeric",
132+
};
133+
const formattedDate = currentdate
134+
.toLocaleDateString("en-GB", dateOptions)
135+
.replace(",", ""); // Example: "04 Dec 2024"
136+
const timeOptions: Intl.DateTimeFormatOptions = {
137+
hour: "2-digit",
138+
minute: "2-digit",
139+
second: "2-digit",
140+
hour12: false,
141+
};
142+
const formattedTime = currentdate.toLocaleTimeString(
143+
"en-GB",
144+
timeOptions,
145+
); // Example: "13:45:30"
146+
const datetime = `${formattedDate} Time: ${formattedTime}`;
147+
const signedAt = new window.NutrientViewer.Annotations.TextAnnotation({
148+
pageIndex: 0,
149+
text: {
150+
format: "plain",
151+
value: `Signed @ ${datetime}`,
152+
},
153+
boundingBox: new window.NutrientViewer.Geometry.Rect({
154+
left: left1 + 30,
155+
top: top2 + 50,
156+
width: width3 + 100,
157+
height: 13,
158+
}),
159+
font: "Verdana",
160+
fontSize: 9,
161+
fontColor: window.NutrientViewer.Color.BLUE,
162+
horizontalAlign: "left",
163+
readOnly: true,
164+
});
165+
instance.create(signedAt);
166+
167+
const lineAnno = new window.NutrientViewer.Annotations.LineAnnotation({
168+
pageIndex: 0,
169+
startPoint: new window.NutrientViewer.Geometry.Point({
170+
x: left1 + 20,
171+
y: top2 - 2,
172+
}),
173+
endPoint: new window.NutrientViewer.Geometry.Point({
174+
x: left1 + 20,
175+
y: top2 + height4 + 5,
176+
}),
177+
boundingBox: new window.NutrientViewer.Geometry.Rect({
178+
left: left1,
179+
top: top2,
180+
width: 20,
181+
height: 60,
182+
}),
183+
locked: true,
184+
lockedContents: true,
185+
});
186+
instance.create(lineAnno);
187+
},
188+
);
189+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
category: signatures
3+
title: Add Timestamp to Electronic Signatures
4+
description: Automatically adds a timestamp, signer name, and decorative line annotation when a user creates an electronic signature, supporting draw, type, and image-based signatures.
5+
keywords: [signature, timestamp, electronic-signature, ink-signature, form-field, widget-annotation, text-annotation, line-annotation]
6+
---

0 commit comments

Comments
 (0)