WebViewer Version:
I want to handle the annotation role based lock like if i assigned two different signature fields for two different people and i want only person can edit or make change in the annotation to whom it was assigned otherwise all other annotations will on readOnly mode so that my functionality will work properly I have also attached my code for referrence
Do you have an issue with a specific file(s)?
Can you reproduce using one of our samples or online demos?
Are you using the WebViewer server?
Does the issue only happen on certain browsers?
Is your issue related to a front-end framework?
Is your issue related to annotations?
Please give a brief summary of your issue:
(Think of this as an email subject)
Please describe your issue and provide steps to reproduce it:
(The more descriptive your answer, the faster we are able to help you)
Please provide a link to a minimal sample where the issue is reproducible:
const applyFields = async () => {
console.log(“@@@@@@@@@@@@@@@@@@@@@@@@”);
const { Annotations, documentViewer } = instance.Core;
const annotationManager = documentViewer.getAnnotationManager();
const fieldManager = annotationManager.getFieldManager();
const annotationsList = annotationManager.getAnnotationsList();
const annotsToDelete = ;
const annotsToDraw = ;
const fieldArr = ; // Array to store field names
// Get current user
const currentUser = annotationManager.getCurrentUser();
await Promise.all(
annotationsList.map(async (annot, index) => {
let inputAnnot;
let field;
// Add this check here - right at the start of processing each annotation
if (!annot || !annot.custom) {
return; // Skip invalid annotations
}
// Skip fields the current user doesn't have access to
if (!canAccessField(annot)) {
return;
}
// Extract fieldName values
const fieldNames = annotationsList
.filter((annot) => annot.custom && annot.custom.name) // Ensure the annotation has a custom name
.map((annot) => annot.custom.name);
// Update the state with the collected field names
setSavedFieldNames(fieldNames);
// Log the field names for debugging
console.log("Saved Field Names:", fieldNames);
// Get the user data from the annotation with proper fallbacks
const fieldData = {
creator: annot.custom.creator || currentUser || "",
assignee: annot.custom.assignee || "",
type: annot.custom.type || "",
value: annot.custom.value || "",
};
// Create a unique field name that includes user information
const fieldName = `${fieldData.assignee}_${
fieldData.type
}_${Date.now()}_${index}`;
console.log("fieldName", fieldName);
fieldArr.push(fieldName);
console.log("fieldArr", fieldArr);
// Proceed with the existing save logic
const annotations = annotationManager.exportAnnotations({ link: true });
const body = { annotationData: annotations };
const val = JSON.stringify(body);
// create a form field based on the type of annotation
if (fieldData.type === "TEXT") {
field = new Annotations.Forms.Field(fieldName, {
type: "Tx",
value: fieldData.value,
userData: fieldData,
});
inputAnnot = new Annotations.TextWidgetAnnotation(field);
inputAnnot.setFieldIndicator(true, "Insert text here");
} else if (fieldData.type === "SIGNATURE") {
field = new Annotations.Forms.Field(fieldName, {
type: "Sig",
userData: fieldData,
});
inputAnnot = new Annotations.SignatureWidgetAnnotation(field, {
appearance: "_DEFAULT",
appearances: {
_DEFAULT: {
Normal: {
data: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuMWMqnEsAAAANSURBVBhXY/j//z8DAAj8Av6IXwbgAAAAAElFTkSuQmCC",
offset: {
x: 100,
y: 100,
},
},
},
},
});
inputAnnot.setFieldIndicator(true, "Sign Here");
} else if (fieldData.type === "DATE") {
field = new Annotations.Forms.Field(fieldName, {
type: "Tx",
value: "mm-dd-yyyy",
userData: fieldData,
actions: {
F: [
{
name: "JavaScript",
javascript: 'AFDate_FormatEx("mmm d, yyyy");',
},
],
K: [
{
name: "JavaScript",
javascript: 'AFDate_FormatEx("mmm d, yyyy");',
},
],
},
});
inputAnnot = new Annotations.DatePickerWidgetAnnotation(field);
} else {
// exit early for other annotations
annotationManager.deleteAnnotation(annot, false, true);
return;
}
// set position
inputAnnot.PageNumber = annot.getPageNumber();
inputAnnot.X = annot.getX();
inputAnnot.Y = annot.getY();
inputAnnot.rotation = annot.Rotation;
if (annot.Rotation === 0 || annot.Rotation === 180) {
inputAnnot.Width = annot.getWidth();
inputAnnot.Height = annot.getHeight();
} else {
inputAnnot.Width = annot.getHeight();
inputAnnot.Height = annot.getWidth();
}
// Set the author of the annotation
inputAnnot.Author = fieldData.creator;
// delete original annotation
annotsToDelete.push(annot);
// customize styles of the form field
Annotations.WidgetAnnotation.getCustomStyles = function (widget) {
if (widget instanceof Annotations.SignatureWidgetAnnotation) {
return {
border: "1px solid #a5c7ff",
};
}
if (widget instanceof Annotations.TextWidgetAnnotation) {
return {
border: "1px dashed #ff9800",
backgroundColor: "#fff3cd",
};
}
if (widget instanceof Annotations.DatePickerWidgetAnnotation) {
return {
border: "1px dashedrgb(255, 51, 0)",
backgroundColor: "#fff3cd",
};
}
};
Annotations.WidgetAnnotation.getCustomStyles(inputAnnot);
// draw the annotation the viewer
annotationManager.addAnnotation(inputAnnot);
fieldManager.addField(field);
annotsToDraw.push(inputAnnot);
})
// setFieldsApplied(true)
);
// Step 2: Group fields by email ID
const groupedFields = fieldArr.reduce((acc, field) => {
// Extract the email ID from the field name
const email = field.split("_")[0]; // Get the part before the first underscore
// Initialize the array for the email if it doesn't exist
if (!acc[email]) {
acc[email] = [];
}
// Add the field to the corresponding email group
acc[email].push(field);
return acc;
}, {});
// Step 3: Convert the grouped object into an array of objects
const finalArray = Object.keys(groupedFields).map((email) => {
const modifiedEmail = email.replace(/\.([^.]*)$/, "<>$1");
return { [modifiedEmail]: groupedFields[email] };
});
setUserAnnotations(finalArray); // Update the state with the final array
// Step 3: Log the final array for debugging
console.log("Final Array of Categorized Fields:", finalArray);
// delete old annotations
annotationManager.deleteAnnotations(annotsToDelete, null, true);
// refresh viewer
await annotationManager.drawAnnotationsFromList(annotsToDraw);
// Save the annotations with user data
const annotations = await annotationManager.exportAnnotations({
link: true,
});
// console.log("annotations", annotations);
const body = {
annotationData: annotations,
userAnnotations: finalArray,
};
const val = JSON.stringify(body);
try {
await props.saveDmsAnnotation(val, props.fileId);
dispatch(setSnackbar(true, "success", "Fields saved successfully"));
} catch (error) {
console.error("Error saving annotations:", error);
dispatch(setSnackbar(true, "error", "Failed to save fields"));
}
};
const addField = (type, point = {}, name = “”, value = “”, flag = {}) => {
if (instance) {
const { documentViewer, Annotations } = instance.Core;
// const annotationManager = documentViewer.getAnnotationManager();
const doc = documentViewer.getDocument();
const displayMode = documentViewer
.getDisplayModeManager()
.getDisplayMode();
const page = displayMode.getSelectedPages(point, point);
if (!!point?.x && page.first == null) {
return; //don't add field to an invalid page location
}
const page_idx =
page.first !== null ? page.first : documentViewer.getCurrentPage();
const page_info = doc.getPageInfo(page_idx);
const page_point = displayMode.windowToPage(point, page_idx);
const zoom = documentViewer.getZoomLevel();
var textAnnot = new Annotations.FreeTextAnnotation();
console.log("textAnnnnnnnnot", textAnnot);
textAnnot.PageNumber = page_idx;
const rotation = documentViewer.getCompleteRotation(page_idx) * 90;
textAnnot.Rotation = rotation;
if (rotation === 270 || rotation === 90) {
textAnnot.Width = 50.0 / zoom;
textAnnot.Height = 250.0 / zoom;
} else {
textAnnot.Width = 250.0 / zoom;
textAnnot.Height = 50.0 / zoom;
}
textAnnot.X =
(page_point?.x || page_info.width / 2) - textAnnot.Width / 2;
textAnnot.Y =
(page_point.y || page_info.height / 2) - textAnnot.Height / 2;
textAnnot.setPadding(new Annotations.Rect(0, 0, 0, 0));
textAnnot.setCustomData("assignee", assignedValues);
textAnnot.custom = {
type,
value,
flag,
name: `${assignedValues}_${type}_`,
// name: `${type}`,
assignee: assignedValues, // Add this to track who the field belongs to
creator: annotationManager.getCurrentUser() || "", // Track who created the field
};
// set the type of annot
textAnnot.setContents(textAnnot.custom.name);
textAnnot.FontSize = "" + 20.0 / zoom + "px";
textAnnot.FillColor = new Annotations.Color(211, 211, 211, 0.5);
textAnnot.TextColor = new Annotations.Color(0, 165, 228);
textAnnot.StrokeThickness = 1;
textAnnot.StrokeColor = new Annotations.Color(0, 165, 228);
textAnnot.TextAlign = "center";
textAnnot.Author = annotationManager.getCurrentUser();
annotationManager.deselectAllAnnotations();
annotationManager.addAnnotation(textAnnot, true);
annotationManager.redrawAnnotation(textAnnot);
annotationManager.selectAnnotation(textAnnot);
// Update the field count for the selected user
setFieldCounts((prevCounts) => ({
...prevCounts,
[assignedValues]: prevCounts[assignedValues] + 1, // Increment the count for the selected user
}));
// Create an array of objects with email and count
const userFieldCounts = Object.keys(fieldCounts).map((email) => ({
email,
count: fieldCounts[email],
}));
// Console log the array
console.log("User Field Counts:", userFieldCounts);
// âś… Increment field count when added
setFieldCount((prevCount) => prevCount + 1);
// âś… Add a unique ID to the annotation for tracking
textAnnot.Id = `field_${Date.now()}`;
// âś… Store reference to track the added field
if (!window.fieldMap) {
window.fieldMap = new Map();
}
window.fieldMap.set(textAnnot.Id, textAnnot);
// âś… Add listener to detect annotation deletions
annotationManager.addEventListener(
"annotationChanged",
(annotations, action) => {
if (action === "delete") {
annotations.forEach((annot) => {
if (window.fieldMap.has(annot.Id)) {
setFieldCount((prevCount) => Math.max(prevCount - 1, 0));
window.fieldMap.delete(annot.Id);
}
});
}
}
);
// âś… Add listener to detect annotation filled
annotationManager.addEventListener(
"annotationChanged",
(annotations, action) => {
if (action === "modify") {
annotations.forEach((annot) => {
if (
annot instanceof Annotations.WidgetAnnotation &&
annot.getField().type === "Sign"
) {
const fieldName = annot.getField().name;
const value = annot.getField().value;
if (value && !window.filledSignatureSet.has(annot.Id)) {
// Signature was just filled
window.filledSignatureSet.add(annot.Id);
setFilledSignatureCount((prevCount) => prevCount + 1);
}
if (!value && window.filledSignatureSet.has(annot.Id)) {
// Signature was cleared (optional support)
window.filledSignatureSet.delete(annot.Id);
setFilledSignatureCount((prevCount) =>
Math.max(prevCount - 1, 0)
);
}
}
});
}
}
);
}
};