From 2265bee61fff35dc53aaed91fc5108c557f34b44 Mon Sep 17 00:00:00 2001 From: prafull-opensignlabs Date: Fri, 12 Apr 2024 17:13:27 +0530 Subject: [PATCH] feat: add widgets in API --- apps/OpenSign/src/pages/Form.js | 2 +- apps/OpenSignServer/Utils.js | 93 +++++++++++++++++++ .../v1/routes/createDocumentwithCoordinate.js | 22 +++-- .../v1/routes/createTemplatewithCoordinate.js | 21 +++-- 4 files changed, 121 insertions(+), 17 deletions(-) diff --git a/apps/OpenSign/src/pages/Form.js b/apps/OpenSign/src/pages/Form.js index 99177827a..98192793e 100644 --- a/apps/OpenSign/src/pages/Form.js +++ b/apps/OpenSign/src/pages/Form.js @@ -300,7 +300,7 @@ const Forms = (props) => {
- file selected : {getFileName(fileload)} + file selected : {getFileName(fileupload)}
setFileUpload([])} diff --git a/apps/OpenSignServer/Utils.js b/apps/OpenSignServer/Utils.js index d94b46118..18d90138b 100644 --- a/apps/OpenSignServer/Utils.js +++ b/apps/OpenSignServer/Utils.js @@ -150,3 +150,96 @@ export const updateMailCount = async extUserId => { console.log('Error updating EmailCount in contracts_users: ' + error.message); } }; + +export function formatWidgetOptions(type, options) { + const status = options?.required === true ? 'required' : 'optional' || 'required'; + const defaultValue = options?.default || ''; + const values = options?.values || []; + switch (type) { + case 'signature': + return { name: 'signature', status: 'required' }; + case 'stamp': + return { status: status, name: 'stamp' }; + case 'initials': + return { status: status, name: options.name || 'initials' }; + case 'image': + return { status: status, name: options.name || 'image' }; + case 'email': + return { status: status, name: options.name || 'email', validation: { type: 'email' } }; + case 'name': + return { status: status, name: options.name || 'name' }; + case 'job title': + return { status: status, name: options.name || 'job title' }; + case 'company': + return { status: status, name: options.name || 'company' }; + case 'date': { + let today = new Date(); + let dd = String(today.getDate()).padStart(2, '0'); + let mm = String(today.getMonth() + 1).padStart(2, '0'); // January is 0! + let yyyy = today.getFullYear(); + today = dd + '-' + mm + '-' + yyyy; + let dateFormat = options?.format; + dateFormat = dateFormat.replace(/m/g, 'M'); + return { + status: status, + name: options.name || 'date', + response: defaultValue || today, + validation: { format: dateFormat || 'dd-MM-yyyy', type: 'date-format' }, + }; + } + case 'textbox': + return { + status: status, + name: 'textbox', + defaultValue: defaultValue, + hint: options.hint, + validation: { type: 'regex', pattern: options?.regularexpression || '/^[a-zA-Z0-9s]+$/' }, + }; + case 'checkbox': { + const arr = options?.values; + let selectedvalues = []; + for (const obj of options.selectedvalues) { + const index = arr.indexOf(obj); + selectedvalues.push(index); + } + return { + status: status, + name: options.name || 'checkbox', + values: values, + isReadOnly: options?.readonly || false, + isHideLabel: options?.hidelabel || false, + validation: { + minRequiredCount: options?.validation?.minselections || 0, + maxRequiredCount: options?.validation?.maxselections || 0, + }, + defaultValue: selectedvalues || [], + }; + } + case 'radio button': { + return { + status: status, + name: options.name || 'radio', + values: values, + isReadOnly: options?.readonly || false, + isHideLabel: options?.hidelabel || false, + defaultValue: defaultValue, + }; + } + case 'dropdown': + return { + status: status, + name: options.name || 'dropdown', + values: values, + defaultValue: defaultValue, + }; + default: + break; + } +} + +export function sanitizeFileName(fileName) { + // Remove spaces and invalid characters + const file = fileName.replace(/[^a-zA-Z0-9._-]/g, ''); + const removedot = file.replace(/\.(?=.*\.)/g, ''); + return removedot.replace(/[^a-zA-Z0-9._-]/g, ''); +} diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/createDocumentwithCoordinate.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/createDocumentwithCoordinate.js index d3d31b2e4..f6656f6fb 100644 --- a/apps/OpenSignServer/cloud/customRoute/v1/routes/createDocumentwithCoordinate.js +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/createDocumentwithCoordinate.js @@ -1,5 +1,12 @@ import axios from 'axios'; -import { color, customAPIurl, replaceMailVaribles, saveFileUsage } from '../../../../Utils.js'; +import { + color, + customAPIurl, + replaceMailVaribles, + saveFileUsage, + formatWidgetOptions, + sanitizeFileName, +} from '../../../../Utils.js'; // `sendDoctoWebhook` is used to send res data of document on webhook async function sendDoctoWebhook(doc, WebhookUrl, userId) { @@ -92,9 +99,8 @@ export default async function createDocumentwithCoordinate(request, response) { const buffer = Buffer.from(base64, 'base64'); saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId); } else { - const file = new Parse.File(`${name}.pdf`, { - base64: base64File, - }); + const filename = sanitizeFileName(`${name}.pdf`); + const file = new Parse.File(filename, { base64: base64File }, 'application/pdf'); await file.save({ useMasterKey: true }); fileUrl = file.url(); const buffer = Buffer.from(base64File, 'base64'); @@ -177,17 +183,17 @@ export default async function createDocumentwithCoordinate(request, response) { for (const widget of signer.widgets) { const pageNumber = widget.page; + const options = formatWidgetOptions(widget.type, widget.options); const page = placeHolder.find(page => page.pageNumber === pageNumber); - const signOpt = { name: 'signature', status: 'required' }; const widgetData = { - isStamp: widget.type === 'stamp'|| widget.type === 'image', + isStamp: widget.type === 'stamp' || widget.type === 'image', key: randomId(), isDrag: false, scale: 1, isMobile: false, zIndex: 1, - type: widget.type, - options: widget.type === 'signature' ? signOpt : widget.options, + type: widget.type === 'textbox' ? 'text input' : widget.type, + options: options, Width: widget.w, Height: widget.h, xPosition: widget.x, diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/createTemplatewithCoordinate.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/createTemplatewithCoordinate.js index 4a0d3ed59..6bff19bc2 100644 --- a/apps/OpenSignServer/cloud/customRoute/v1/routes/createTemplatewithCoordinate.js +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/createTemplatewithCoordinate.js @@ -1,5 +1,11 @@ import axios from 'axios'; -import { color, customAPIurl, saveFileUsage } from '../../../../Utils.js'; +import { + color, + customAPIurl, + saveFileUsage, + formatWidgetOptions, + sanitizeFileName, +} from '../../../../Utils.js'; const randomId = () => Math.floor(1000 + Math.random() * 9000); export default async function createTemplatewithCoordinate(request, response) { @@ -43,9 +49,8 @@ export default async function createTemplatewithCoordinate(request, response) { const buffer = Buffer.from(base64, 'base64'); saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId); } else { - const file = new Parse.File(`${name}.pdf`, { - base64: base64File, - }); + const filename = sanitizeFileName(`${name}.pdf`); + const file = new Parse.File(filename, { base64: base64File }, 'application/pdf'); await file.save({ useMasterKey: true }); fileUrl = file.url(); const buffer = Buffer.from(base64File, 'base64'); @@ -134,16 +139,16 @@ export default async function createTemplatewithCoordinate(request, response) { for (const widget of signer.widgets) { const pageNumber = widget.page; const page = placeHolder.find(page => page.pageNumber === pageNumber); - const signOpt = { name: 'signature', status: 'required' }; + const options = formatWidgetOptions(widget.type, widget.options); const widgetData = { - isStamp: widget.type === 'stamp'|| widget.type === 'image', + isStamp: widget.type === 'stamp' || widget.type === 'image', key: randomId(), isDrag: false, scale: 1, isMobile: false, zIndex: 1, - type: widget.type, - options: widget.type === 'signature' ? signOpt : widget.options, + type: widget.type === 'textbox' ? 'text input' : widget.type, + options: options, Width: widget.w, Height: widget.h, xPosition: widget.x,