Skip to content

Commit 3f9b6eb

Browse files
Merge pull request #591 from OpenSignLabs/plan
2 parents 6390706 + 2265bee commit 3f9b6eb

File tree

4 files changed

+121
-17
lines changed

4 files changed

+121
-17
lines changed

apps/OpenSign/src/pages/Form.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ const Forms = (props) => {
300300
<div className="flex gap-2 justify-center items-center">
301301
<div className="flex justify-between items-center px-2 py-2 w-full font-bold rounded border-[1px] border-[#ccc] text-gray-500 bg-white text-[13px]">
302302
<div className="break-all">
303-
file selected : {getFileName(fileload)}
303+
file selected : {getFileName(fileupload)}
304304
</div>
305305
<div
306306
onClick={() => setFileUpload([])}

apps/OpenSignServer/Utils.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,3 +150,96 @@ export const updateMailCount = async extUserId => {
150150
console.log('Error updating EmailCount in contracts_users: ' + error.message);
151151
}
152152
};
153+
154+
export function formatWidgetOptions(type, options) {
155+
const status = options?.required === true ? 'required' : 'optional' || 'required';
156+
const defaultValue = options?.default || '';
157+
const values = options?.values || [];
158+
switch (type) {
159+
case 'signature':
160+
return { name: 'signature', status: 'required' };
161+
case 'stamp':
162+
return { status: status, name: 'stamp' };
163+
case 'initials':
164+
return { status: status, name: options.name || 'initials' };
165+
case 'image':
166+
return { status: status, name: options.name || 'image' };
167+
case 'email':
168+
return { status: status, name: options.name || 'email', validation: { type: 'email' } };
169+
case 'name':
170+
return { status: status, name: options.name || 'name' };
171+
case 'job title':
172+
return { status: status, name: options.name || 'job title' };
173+
case 'company':
174+
return { status: status, name: options.name || 'company' };
175+
case 'date': {
176+
let today = new Date();
177+
let dd = String(today.getDate()).padStart(2, '0');
178+
let mm = String(today.getMonth() + 1).padStart(2, '0'); // January is 0!
179+
let yyyy = today.getFullYear();
180+
today = dd + '-' + mm + '-' + yyyy;
181+
let dateFormat = options?.format;
182+
dateFormat = dateFormat.replace(/m/g, 'M');
183+
return {
184+
status: status,
185+
name: options.name || 'date',
186+
response: defaultValue || today,
187+
validation: { format: dateFormat || 'dd-MM-yyyy', type: 'date-format' },
188+
};
189+
}
190+
case 'textbox':
191+
return {
192+
status: status,
193+
name: 'textbox',
194+
defaultValue: defaultValue,
195+
hint: options.hint,
196+
validation: { type: 'regex', pattern: options?.regularexpression || '/^[a-zA-Z0-9s]+$/' },
197+
};
198+
case 'checkbox': {
199+
const arr = options?.values;
200+
let selectedvalues = [];
201+
for (const obj of options.selectedvalues) {
202+
const index = arr.indexOf(obj);
203+
selectedvalues.push(index);
204+
}
205+
return {
206+
status: status,
207+
name: options.name || 'checkbox',
208+
values: values,
209+
isReadOnly: options?.readonly || false,
210+
isHideLabel: options?.hidelabel || false,
211+
validation: {
212+
minRequiredCount: options?.validation?.minselections || 0,
213+
maxRequiredCount: options?.validation?.maxselections || 0,
214+
},
215+
defaultValue: selectedvalues || [],
216+
};
217+
}
218+
case 'radio button': {
219+
return {
220+
status: status,
221+
name: options.name || 'radio',
222+
values: values,
223+
isReadOnly: options?.readonly || false,
224+
isHideLabel: options?.hidelabel || false,
225+
defaultValue: defaultValue,
226+
};
227+
}
228+
case 'dropdown':
229+
return {
230+
status: status,
231+
name: options.name || 'dropdown',
232+
values: values,
233+
defaultValue: defaultValue,
234+
};
235+
default:
236+
break;
237+
}
238+
}
239+
240+
export function sanitizeFileName(fileName) {
241+
// Remove spaces and invalid characters
242+
const file = fileName.replace(/[^a-zA-Z0-9._-]/g, '');
243+
const removedot = file.replace(/\.(?=.*\.)/g, '');
244+
return removedot.replace(/[^a-zA-Z0-9._-]/g, '');
245+
}

apps/OpenSignServer/cloud/customRoute/v1/routes/createDocumentwithCoordinate.js

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import axios from 'axios';
2-
import { color, customAPIurl, replaceMailVaribles, saveFileUsage } from '../../../../Utils.js';
2+
import {
3+
color,
4+
customAPIurl,
5+
replaceMailVaribles,
6+
saveFileUsage,
7+
formatWidgetOptions,
8+
sanitizeFileName,
9+
} from '../../../../Utils.js';
310

411
// `sendDoctoWebhook` is used to send res data of document on webhook
512
async function sendDoctoWebhook(doc, WebhookUrl, userId) {
@@ -92,9 +99,8 @@ export default async function createDocumentwithCoordinate(request, response) {
9299
const buffer = Buffer.from(base64, 'base64');
93100
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
94101
} else {
95-
const file = new Parse.File(`${name}.pdf`, {
96-
base64: base64File,
97-
});
102+
const filename = sanitizeFileName(`${name}.pdf`);
103+
const file = new Parse.File(filename, { base64: base64File }, 'application/pdf');
98104
await file.save({ useMasterKey: true });
99105
fileUrl = file.url();
100106
const buffer = Buffer.from(base64File, 'base64');
@@ -177,17 +183,17 @@ export default async function createDocumentwithCoordinate(request, response) {
177183

178184
for (const widget of signer.widgets) {
179185
const pageNumber = widget.page;
186+
const options = formatWidgetOptions(widget.type, widget.options);
180187
const page = placeHolder.find(page => page.pageNumber === pageNumber);
181-
const signOpt = { name: 'signature', status: 'required' };
182188
const widgetData = {
183-
isStamp: widget.type === 'stamp'|| widget.type === 'image',
189+
isStamp: widget.type === 'stamp' || widget.type === 'image',
184190
key: randomId(),
185191
isDrag: false,
186192
scale: 1,
187193
isMobile: false,
188194
zIndex: 1,
189-
type: widget.type,
190-
options: widget.type === 'signature' ? signOpt : widget.options,
195+
type: widget.type === 'textbox' ? 'text input' : widget.type,
196+
options: options,
191197
Width: widget.w,
192198
Height: widget.h,
193199
xPosition: widget.x,

apps/OpenSignServer/cloud/customRoute/v1/routes/createTemplatewithCoordinate.js

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import axios from 'axios';
2-
import { color, customAPIurl, saveFileUsage } from '../../../../Utils.js';
2+
import {
3+
color,
4+
customAPIurl,
5+
saveFileUsage,
6+
formatWidgetOptions,
7+
sanitizeFileName,
8+
} from '../../../../Utils.js';
39

410
const randomId = () => Math.floor(1000 + Math.random() * 9000);
511
export default async function createTemplatewithCoordinate(request, response) {
@@ -43,9 +49,8 @@ export default async function createTemplatewithCoordinate(request, response) {
4349
const buffer = Buffer.from(base64, 'base64');
4450
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
4551
} else {
46-
const file = new Parse.File(`${name}.pdf`, {
47-
base64: base64File,
48-
});
52+
const filename = sanitizeFileName(`${name}.pdf`);
53+
const file = new Parse.File(filename, { base64: base64File }, 'application/pdf');
4954
await file.save({ useMasterKey: true });
5055
fileUrl = file.url();
5156
const buffer = Buffer.from(base64File, 'base64');
@@ -134,16 +139,16 @@ export default async function createTemplatewithCoordinate(request, response) {
134139
for (const widget of signer.widgets) {
135140
const pageNumber = widget.page;
136141
const page = placeHolder.find(page => page.pageNumber === pageNumber);
137-
const signOpt = { name: 'signature', status: 'required' };
142+
const options = formatWidgetOptions(widget.type, widget.options);
138143
const widgetData = {
139-
isStamp: widget.type === 'stamp'|| widget.type === 'image',
144+
isStamp: widget.type === 'stamp' || widget.type === 'image',
140145
key: randomId(),
141146
isDrag: false,
142147
scale: 1,
143148
isMobile: false,
144149
zIndex: 1,
145-
type: widget.type,
146-
options: widget.type === 'signature' ? signOpt : widget.options,
150+
type: widget.type === 'textbox' ? 'text input' : widget.type,
151+
options: options,
147152
Width: widget.w,
148153
Height: widget.h,
149154
xPosition: widget.x,

0 commit comments

Comments
 (0)