@verdocs/js-sdk 4.0.4 → 4.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +1891 -1881
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1891 -1882
- package/dist/index.mjs.map +1 -1
- package/dist/package.json +3 -3
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -441,2168 +441,2177 @@ class VerdocsEndpoint {
|
|
|
441
441
|
}
|
|
442
442
|
|
|
443
443
|
/**
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
* ```typescript
|
|
447
|
-
* import {Envelopes, ICreateEnvelopeRole, ICreateEnvelopeRequest} from '@verdocs/js-sdk/Envelopes';
|
|
448
|
-
*
|
|
449
|
-
* const role1: ICreateEnvelopeRole = {
|
|
450
|
-
* type: 'signer',
|
|
451
|
-
* name: 'Seller',
|
|
452
|
-
* full_name: 'Paige Turner',
|
|
453
|
-
* email: 'paige.turner@nomail.com',
|
|
454
|
-
* phone: '',
|
|
455
|
-
* sequence: 1,
|
|
456
|
-
* delegator: false,
|
|
457
|
-
* message: '',
|
|
458
|
-
* };
|
|
459
|
-
*
|
|
460
|
-
* const role2: ICreateEnvelopeRole = {
|
|
461
|
-
* type: 'signer',
|
|
462
|
-
* name: 'Buyer',
|
|
463
|
-
* full_name: 'Will Power',
|
|
464
|
-
* email: 'will.power@nomail.com',
|
|
465
|
-
* phone: '',
|
|
466
|
-
* sequence: 2,
|
|
467
|
-
* delegator: false,
|
|
468
|
-
* message: '',
|
|
469
|
-
* };
|
|
470
|
-
*
|
|
471
|
-
* const request: ICreateEnvelopeRequest = {template_id: 'd2338742-f3a1-465b-8592-806587413cc1', name: 'Bill of Sale', roles: [role1, role2]};
|
|
472
|
-
* const {id, recipients} = await Envelopes.createEnvelope(VerdocsEndpoint.getDefault(), request);
|
|
473
|
-
* ```
|
|
474
|
-
*/
|
|
475
|
-
const createEnvelope = async (endpoint, request) => endpoint.api //
|
|
476
|
-
.post('/envelopes', request)
|
|
477
|
-
.then((r) => r.data);
|
|
478
|
-
/**
|
|
479
|
-
* Get a summary of currently active envelopes.
|
|
480
|
-
*
|
|
481
|
-
* ```typescript
|
|
482
|
-
* import {Envelopes} from '@verdocs/js-sdk/Envelopes';
|
|
483
|
-
*
|
|
484
|
-
* const {action_required, completed, waiting_on_others} = await Envelopes.getSummary(VerdocsEndpoint.getDefault());
|
|
485
|
-
* ```
|
|
486
|
-
*/
|
|
487
|
-
const getEnvelopesSummary = async (endpoint, page) => endpoint.api //
|
|
488
|
-
.post('/envelopes/summary', { page })
|
|
489
|
-
.then((r) => r.data);
|
|
490
|
-
/**
|
|
491
|
-
* Search for envelopes matching various criteria.
|
|
492
|
-
*
|
|
493
|
-
* ```typescript
|
|
494
|
-
* import {Envelopes} from '@verdocs/js-sdk/Envelopes';
|
|
495
|
-
*
|
|
496
|
-
* const {result, page, total} = await Envelopes.search(VerdocsEndpoint.getDefault(), { ... });
|
|
497
|
-
* ```
|
|
498
|
-
*/
|
|
499
|
-
const searchEnvelopes = async (endpoint, params) => endpoint.api //
|
|
500
|
-
.post('/envelopes/search', params)
|
|
501
|
-
.then((r) => r.data);
|
|
502
|
-
/**
|
|
503
|
-
* Get a signing session for an Envelope.
|
|
504
|
-
*/
|
|
505
|
-
const getSigningSession = async (endpoint, params) => {
|
|
506
|
-
window.console.log('[JS_SDK] getSigningSession', params, endpoint.api);
|
|
507
|
-
return endpoint.api //
|
|
508
|
-
.get(`/envelopes/${params.envelopeId}/recipients/${encodeURIComponent(params.roleId)}/invitation/${params.inviteCode}`)
|
|
509
|
-
.then((r) => {
|
|
510
|
-
// Avoiding a jsonwebtoken dependency here - we don't actually need the whole library
|
|
511
|
-
const signerToken = r.headers?.signer_token || '';
|
|
512
|
-
const session = decodeAccessTokenBody(signerToken);
|
|
513
|
-
endpoint.setToken(signerToken);
|
|
514
|
-
return { recipient: r.data, session, signerToken };
|
|
515
|
-
});
|
|
516
|
-
};
|
|
517
|
-
/**
|
|
518
|
-
* Get the list of recipients for an Envelope.
|
|
519
|
-
*/
|
|
520
|
-
const getEnvelopeRecipients = async (endpoint, envelopeId) => endpoint.api //
|
|
521
|
-
.get(`/envelopes/${envelopeId}/recipients`)
|
|
522
|
-
.then((r) => r.data);
|
|
523
|
-
/**
|
|
524
|
-
* Get all metadata for an Envelope.
|
|
525
|
-
*/
|
|
526
|
-
const getEnvelope = async (endpoint, envelopeId) => endpoint.api //
|
|
527
|
-
.get(`/envelopes/${envelopeId}`)
|
|
528
|
-
.then((r) => r.data);
|
|
529
|
-
/**
|
|
530
|
-
* Get an Envelope Document
|
|
531
|
-
*/
|
|
532
|
-
const getEnvelopeDocument = async (endpoint, envelopeId, documentId) => endpoint.api //
|
|
533
|
-
.get(`/envelopes/${envelopeId}/envelope_documents/${documentId}`)
|
|
534
|
-
.then((r) => r.data);
|
|
535
|
-
/**
|
|
536
|
-
* Get a pre-signed download link for an Envelope Document. This link expires quickly, so it should
|
|
537
|
-
* be accessed immediately and never shared. Content-Disposition will be set to "download".
|
|
538
|
-
*/
|
|
539
|
-
const getDocumentDownloadLink = async (endpoint, envelopeId, documentId) => endpoint.api //
|
|
540
|
-
.get(`/envelopes/${envelopeId}/envelope_documents/${documentId}?download=true`)
|
|
541
|
-
.then((r) => r.data);
|
|
542
|
-
/**
|
|
543
|
-
* Get a pre-signed preview link for an Envelope Document. This link expires quickly, so it should
|
|
544
|
-
* be accessed immediately and never shared. Content-Disposition will be set to "inline".
|
|
545
|
-
*/
|
|
546
|
-
const getDocumentPreviewLink = async (endpoint, envelopeId, documentId) => endpoint.api //
|
|
547
|
-
.get(`/envelopes/${envelopeId}/envelope_documents/${documentId}?preview=true`)
|
|
548
|
-
.then((r) => r.data);
|
|
549
|
-
/**
|
|
550
|
-
* Cancel an Envelope.
|
|
551
|
-
*/
|
|
552
|
-
const cancelEnvelope = async (endpoint, envelopeId) => endpoint.api //
|
|
553
|
-
.put(`/envelopes/${envelopeId}`, { action: 'cancel' })
|
|
554
|
-
.then((r) => r.data);
|
|
555
|
-
/**
|
|
556
|
-
* Get (binary download) a file attached to an Envelope. It is important to use this method
|
|
557
|
-
* rather than a direct A HREF or similar link to set the authorization headers for the
|
|
558
|
-
* request.
|
|
559
|
-
*/
|
|
560
|
-
const getEnvelopeFile = async (endpoint, envelopeId, documentId) => endpoint.api //
|
|
561
|
-
.get(`/envelopes/${envelopeId}/envelope_documents/${documentId}?file=true`, { responseType: 'blob' })
|
|
562
|
-
.then((r) => r.data);
|
|
563
|
-
/**
|
|
564
|
-
* Update a Document field. Typically called during the signing process as a Recipient fills in fields.
|
|
565
|
-
*/
|
|
566
|
-
const updateEnvelopeField = async (endpoint, envelopeId, fieldName, value) => endpoint.api //
|
|
567
|
-
.put(`/envelopes/${envelopeId}/fields/${fieldName}`, value)
|
|
568
|
-
.then((r) => r.data);
|
|
569
|
-
/**
|
|
570
|
-
* Update a Document signature field. Signature fields are ID-driven. Call `Document.createSignature()` first to create a
|
|
571
|
-
* signature for a Recipient, then call `Documents.updateDocumentFieldSignature()` to attach it to a field.
|
|
572
|
-
*/
|
|
573
|
-
const updateEnvelopeFieldSignature = async (endpoint, envelopeId, fieldName, signatureId) => endpoint.api //
|
|
574
|
-
.put(`/envelopes/${envelopeId}/fields/${fieldName}/signature/${signatureId}`)
|
|
575
|
-
.then((r) => r.data);
|
|
576
|
-
/**
|
|
577
|
-
* Update a Document signature field. Signature fields are ID-driven. Call `Document.createSignature()` first to create a
|
|
578
|
-
* signature for a Recipient, then call `Documents.updateDocumentFieldSignature()` to attach it to a field.
|
|
444
|
+
* Given a `rgba(r,g,b,a)` string value, returns the hex equivalent, dropping the alpha channel.
|
|
579
445
|
*/
|
|
580
|
-
|
|
581
|
-
.
|
|
582
|
-
|
|
446
|
+
function getRGB(rgba) {
|
|
447
|
+
const rgbNumbers = rgba.replace('rgba(', '').replace(')', '').split(',');
|
|
448
|
+
const rgbObject = {
|
|
449
|
+
red: +rgbNumbers[0],
|
|
450
|
+
green: +rgbNumbers[1],
|
|
451
|
+
blue: +rgbNumbers[2],
|
|
452
|
+
alpha: +rgbNumbers[3],
|
|
453
|
+
};
|
|
454
|
+
const alpha = 1 - rgbObject.alpha;
|
|
455
|
+
const red = Math.round((rgbObject.alpha * (rgbObject.red / 255) + alpha) * 255);
|
|
456
|
+
const green = Math.round((rgbObject.alpha * (rgbObject.green / 255) + alpha) * 255);
|
|
457
|
+
const blue = Math.round((rgbObject.alpha * (rgbObject.blue / 255) + alpha) * 255);
|
|
458
|
+
return '#' + rgbToHex(red) + rgbToHex(green) + rgbToHex(blue);
|
|
459
|
+
}
|
|
583
460
|
/**
|
|
584
|
-
*
|
|
461
|
+
* Given an RGB string value, returns the hex equivalent.
|
|
585
462
|
*/
|
|
586
|
-
|
|
587
|
-
const
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
const total = event.total || 1;
|
|
594
|
-
const loaded = event.loaded || 0;
|
|
595
|
-
onUploadProgress?.(Math.floor((loaded * 100) / (total || 1)), loaded, total || 1);
|
|
596
|
-
},
|
|
597
|
-
})
|
|
598
|
-
.then((r) => r.data);
|
|
599
|
-
};
|
|
463
|
+
function rgbToHex(rgb) {
|
|
464
|
+
const hex = rgb.toString(16);
|
|
465
|
+
if (hex.length < 2) {
|
|
466
|
+
return '0' + hex;
|
|
467
|
+
}
|
|
468
|
+
return hex;
|
|
469
|
+
}
|
|
600
470
|
/**
|
|
601
|
-
*
|
|
471
|
+
* Given a signer role index, return the color code for that signer.
|
|
602
472
|
*/
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
473
|
+
function getRGBA(roleIndex) {
|
|
474
|
+
switch (roleIndex % 10) {
|
|
475
|
+
case 0:
|
|
476
|
+
return roleIndex === 0 ? 'rgba(255, 193, 7, 0.4)' : 'rgba(134, 134, 134, 0.3)'; // #FFE69C
|
|
477
|
+
case 1:
|
|
478
|
+
return 'rgba(156, 39, 176, .4)'; // '#E3C3E9'
|
|
479
|
+
case 2:
|
|
480
|
+
return 'rgba(33, 150, 243, .4)'; // '#C1E1FB'
|
|
481
|
+
case 3:
|
|
482
|
+
return 'rgba(220, 231, 117, 0.3)';
|
|
483
|
+
case 4:
|
|
484
|
+
return 'rgba(121, 134, 203, 0.3)';
|
|
485
|
+
case 5:
|
|
486
|
+
return 'rgba(77, 182, 172, 0.3)';
|
|
487
|
+
case 6:
|
|
488
|
+
return 'rgba(255, 202, 165, 0.3)';
|
|
489
|
+
case 7:
|
|
490
|
+
return 'rgba(2, 247, 190, 0.3)';
|
|
491
|
+
case 8:
|
|
492
|
+
return 'rgba(255, 138, 101, 0.3)';
|
|
493
|
+
case 9:
|
|
494
|
+
return 'rgba(82, 255, 79, 0.3)';
|
|
495
|
+
default:
|
|
496
|
+
return 'rgba(229, 115, 155, 0.3)';
|
|
497
|
+
}
|
|
498
|
+
}
|
|
617
499
|
/**
|
|
618
|
-
*
|
|
500
|
+
* Given a role name, return a color code for it. This works by computing a hash code so the specific color returned
|
|
501
|
+
* is not specified explicitly, but will be the same for every call with the same input value.
|
|
619
502
|
*/
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
503
|
+
function nameToRGBA(str) {
|
|
504
|
+
if (!!str) {
|
|
505
|
+
const validNum = parseInt(str.slice(-1), 10);
|
|
506
|
+
if (!isNaN(validNum)) {
|
|
507
|
+
str += (validNum * 99).toString();
|
|
508
|
+
}
|
|
509
|
+
let hash = 0;
|
|
510
|
+
for (let i = 0; i < str.length; i++) {
|
|
511
|
+
// tslint:disable-next-line:no-bitwise
|
|
512
|
+
hash = str.charCodeAt(i) + ((hash << 5) - hash);
|
|
513
|
+
}
|
|
514
|
+
hash = Math.round(hash / 1.3);
|
|
515
|
+
// tslint:disable-next-line:no-bitwise
|
|
516
|
+
const c = (hash & 0x00ffff08).toString(16).toUpperCase();
|
|
517
|
+
const hex = '#' + '00000'.substring(0, 6 - c.length) + c;
|
|
518
|
+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
519
|
+
const color = {
|
|
520
|
+
r: parseInt(result[1], 16),
|
|
521
|
+
g: parseInt(result[2], 16),
|
|
522
|
+
b: parseInt(result[3], 16),
|
|
523
|
+
};
|
|
524
|
+
return `rgba(${color.r}, ${color.g}, ${color.b}, 0.2)`;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
623
527
|
/**
|
|
624
|
-
*
|
|
625
|
-
* into PNG resources suitable for display in IMG tags although they may be used elsewhere. Note that these are intended
|
|
626
|
-
* for DISPLAY ONLY, are not legally binding documents, and do not contain any encoded metadata from participants.
|
|
528
|
+
* Helper function to obtain a color code given a role name given various possible inputs.
|
|
627
529
|
*/
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
const cachedEnvelopes = {};
|
|
632
|
-
/**
|
|
633
|
-
* Wrapper for `getEnvelope()` that limits queries to one every 2 seconds per template ID.
|
|
634
|
-
* This is intended for use in component hierarchies that all rely on the same template
|
|
635
|
-
* to avoid unnecessary repeat server calls.
|
|
636
|
-
*/
|
|
637
|
-
const throttledGetEnvelope = (endpoint, envelopeId) => {
|
|
638
|
-
if (cachedEnvelopes[envelopeId] && cachedEnvelopes[envelopeId].loaded + 2000 < new Date().getTime()) {
|
|
639
|
-
return cachedEnvelopes[envelopeId].envelope;
|
|
530
|
+
function getRoleColor(name, roles, index) {
|
|
531
|
+
if (index) {
|
|
532
|
+
return getRGBA(index);
|
|
640
533
|
}
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
*/
|
|
655
|
-
const listEnvelopes = (endpoint, params) => endpoint.api //
|
|
656
|
-
.post('/envelopes/list', params)
|
|
657
|
-
.then((r) => r.data);
|
|
534
|
+
else if (roles && roles.length > 0) {
|
|
535
|
+
const roleIndex = roles.findIndex((role) => role === name);
|
|
536
|
+
if (roleIndex > -1) {
|
|
537
|
+
return getRGBA(roleIndex);
|
|
538
|
+
}
|
|
539
|
+
else {
|
|
540
|
+
return nameToRGBA(name);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
else {
|
|
544
|
+
return nameToRGBA(name);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
658
547
|
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
const
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
548
|
+
const YEAR = 365 * 24 * 60 * 60;
|
|
549
|
+
// const MONTH = 30 * 24 * 60 * 60;
|
|
550
|
+
const WEEK = 7 * 24 * 60 * 60;
|
|
551
|
+
const DAY = 24 * 60 * 60;
|
|
552
|
+
const HOUR = 60 * 60;
|
|
553
|
+
const MINUTE = 60;
|
|
554
|
+
const formatShortTimeAgo = (val) => {
|
|
555
|
+
if (val === undefined || val === null) {
|
|
556
|
+
return '';
|
|
557
|
+
}
|
|
558
|
+
let dateInput;
|
|
559
|
+
if (typeof val === 'string' || typeof val === 'number') {
|
|
560
|
+
dateInput = new Date(val);
|
|
561
|
+
}
|
|
562
|
+
else if (typeof val === 'object') {
|
|
563
|
+
dateInput = val;
|
|
564
|
+
}
|
|
565
|
+
else {
|
|
566
|
+
return '';
|
|
567
|
+
}
|
|
568
|
+
const timeDiff = Math.floor((new Date().getTime() - dateInput.getTime()) / 1000);
|
|
569
|
+
if (timeDiff >= YEAR) {
|
|
570
|
+
return Math.floor(timeDiff / YEAR) + 'Y';
|
|
571
|
+
}
|
|
572
|
+
// if (timeDiff >= MONTH) {
|
|
573
|
+
// return Math.floor(timeDiff / MONTH) + 'M';
|
|
574
|
+
// }
|
|
575
|
+
if (timeDiff >= WEEK) {
|
|
576
|
+
return Math.floor(timeDiff / WEEK) + 'W';
|
|
577
|
+
}
|
|
578
|
+
if (timeDiff >= DAY) {
|
|
579
|
+
return Math.floor(timeDiff / DAY) + 'D';
|
|
580
|
+
}
|
|
581
|
+
if (timeDiff >= HOUR) {
|
|
582
|
+
return Math.floor(timeDiff / HOUR) + 'H';
|
|
583
|
+
}
|
|
584
|
+
if (timeDiff >= MINUTE) {
|
|
585
|
+
return Math.floor(timeDiff / MINUTE) + 'M';
|
|
586
|
+
}
|
|
587
|
+
return `${timeDiff}S`;
|
|
671
588
|
};
|
|
589
|
+
function timePeriod(type) {
|
|
590
|
+
let endDate = new Date().getTime();
|
|
591
|
+
const today = new Date();
|
|
592
|
+
const month = today.getMonth();
|
|
593
|
+
const year = today.getFullYear();
|
|
594
|
+
let startDate = null;
|
|
595
|
+
switch (type) {
|
|
596
|
+
case '30d':
|
|
597
|
+
startDate = endDate - 60 * 60 * 24 * 30 * 1000;
|
|
598
|
+
break;
|
|
599
|
+
case '60d':
|
|
600
|
+
startDate = endDate - 60 * 60 * 24 * 60 * 1000;
|
|
601
|
+
break;
|
|
602
|
+
case '6m':
|
|
603
|
+
startDate = endDate - 60 * 60 * 24 * 30 * 6 * 1000;
|
|
604
|
+
break;
|
|
605
|
+
case 'this_month':
|
|
606
|
+
startDate = new Date(year, month, 1).getTime();
|
|
607
|
+
break;
|
|
608
|
+
case 'last_month':
|
|
609
|
+
startDate = new Date(year, month - 1, 1).getTime();
|
|
610
|
+
endDate = new Date(year, month, 0).getTime();
|
|
611
|
+
break;
|
|
612
|
+
case 'this_year':
|
|
613
|
+
startDate = new Date(year, 0, 1);
|
|
614
|
+
break;
|
|
615
|
+
case 'all_time':
|
|
616
|
+
default:
|
|
617
|
+
return null;
|
|
618
|
+
}
|
|
619
|
+
if (startDate === null && endDate === null) {
|
|
620
|
+
return null;
|
|
621
|
+
}
|
|
622
|
+
return {
|
|
623
|
+
start_time: new Date(startDate).toISOString(),
|
|
624
|
+
end_time: new Date(endDate).toISOString(),
|
|
625
|
+
};
|
|
626
|
+
}
|
|
672
627
|
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
*
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
*/
|
|
698
|
-
const envelopeRecipientUpdateName = (endpoint, envelopeId, roleName, fullName) => updateRecipient(endpoint, envelopeId, roleName, { action: 'update', new_full_name: fullName });
|
|
699
|
-
/**
|
|
700
|
-
* Change a recipient's name.
|
|
701
|
-
*/
|
|
702
|
-
const envelopeRecipientPrepare = (endpoint, envelopeId, roleName, recipients) => updateRecipient(endpoint, envelopeId, roleName, { action: 'prepare', recipients });
|
|
703
|
-
/**
|
|
704
|
-
* Get a signing token.
|
|
705
|
-
*/
|
|
706
|
-
const getSignerToken = (endpoint, envelopeId, roleName) => endpoint.api //
|
|
707
|
-
.get(`/envelopes/${envelopeId}/recipients/${encodeURIComponent(roleName)}/signer-token`)
|
|
708
|
-
.then((r) => r.data);
|
|
709
|
-
/**
|
|
710
|
-
* Get an in-person signing link.
|
|
711
|
-
*/
|
|
712
|
-
const getInPersonLink = (endpoint, envelopeId, roleName) => endpoint.api //
|
|
713
|
-
.get(`/envelopes/${envelopeId}/recipients/${encodeURIComponent(roleName)}?in_person_link=true`)
|
|
714
|
-
.then((r) => r.data);
|
|
715
|
-
/**
|
|
716
|
-
* Send a delegation request.
|
|
717
|
-
*/
|
|
718
|
-
const sendDelegate = (endpoint, envelopeId, roleName) => endpoint.api //
|
|
719
|
-
.post(`/envelopes/${envelopeId}/recipients/${encodeURIComponent(roleName)}/delegate`)
|
|
720
|
-
.then((r) => r.data);
|
|
721
|
-
/**
|
|
722
|
-
* Resend a recipient's invitation.
|
|
723
|
-
*/
|
|
724
|
-
const resendInvitation = (endpoint, envelopeId, roleName) => endpoint.api //
|
|
725
|
-
.post(`/envelopes/${envelopeId}/recipients/${encodeURIComponent(roleName)}/resend_invitation`)
|
|
726
|
-
.then((r) => r.data);
|
|
628
|
+
function getRTop(y, fieldHeight, iTextHeight, yRatio) {
|
|
629
|
+
return iTextHeight - (y + fieldHeight) * yRatio;
|
|
630
|
+
}
|
|
631
|
+
function getRLeft(x, ratio) {
|
|
632
|
+
return x * ratio;
|
|
633
|
+
}
|
|
634
|
+
function getRValue(y, ratio) {
|
|
635
|
+
return y * ratio;
|
|
636
|
+
}
|
|
637
|
+
function blobToBase64(image) {
|
|
638
|
+
const fileReader = new FileReader();
|
|
639
|
+
return new Promise((resolve, reject) => {
|
|
640
|
+
fileReader.onerror = () => {
|
|
641
|
+
reject(new DOMException('Problem reading blob.'));
|
|
642
|
+
};
|
|
643
|
+
fileReader.onload = () => {
|
|
644
|
+
resolve(fileReader.result);
|
|
645
|
+
};
|
|
646
|
+
fileReader.readAsDataURL(image);
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
function rescale(r, n) {
|
|
650
|
+
return r * n;
|
|
651
|
+
}
|
|
727
652
|
|
|
728
653
|
/**
|
|
729
|
-
*
|
|
730
|
-
*
|
|
731
|
-
*/
|
|
732
|
-
const createEnvelopeReminder = (endpoint, envelopeId, params) => endpoint.api //
|
|
733
|
-
.post(`/envelopes/${envelopeId}/reminder/`, params)
|
|
734
|
-
.then((r) => r.data);
|
|
735
|
-
/**
|
|
736
|
-
* Get the reminder configuration for an envelope.
|
|
737
|
-
*/
|
|
738
|
-
const getEnvelopeReminder = (endpoint, envelopeId, reminderId) => endpoint.api //
|
|
739
|
-
.get(`/envelopes/${envelopeId}/reminder/${reminderId}`)
|
|
740
|
-
.then((r) => r.data);
|
|
741
|
-
/**
|
|
742
|
-
* Update the reminder configuration for an envelope.
|
|
743
|
-
*/
|
|
744
|
-
const updateEnvelopeReminder = (endpoint, envelopeId, reminderId, params) => endpoint.api //
|
|
745
|
-
.put(`/envelopes/${envelopeId}/reminder/${reminderId}`, params)
|
|
746
|
-
.then((r) => r.data);
|
|
747
|
-
/**
|
|
748
|
-
* Delete the reminder configuration for an envelope.
|
|
654
|
+
* Given a File, extract the file's content as a base64 encoded data URL. The response will have a prefix that
|
|
655
|
+
* includes the MIME type of the file, e.g. "data:image/jpeg;base64,iVBORw0K......"
|
|
749
656
|
*/
|
|
750
|
-
const
|
|
751
|
-
|
|
752
|
-
.
|
|
753
|
-
|
|
657
|
+
const fileToDataUrl = (file) => new Promise((resolve, reject) => {
|
|
658
|
+
const reader = new FileReader();
|
|
659
|
+
reader.onload = () => resolve({
|
|
660
|
+
lastModified: file.lastModified,
|
|
661
|
+
size: file.size,
|
|
662
|
+
type: file.type,
|
|
663
|
+
name: file.name,
|
|
664
|
+
data: reader.result,
|
|
665
|
+
});
|
|
666
|
+
reader.onerror = reject;
|
|
667
|
+
if (file) {
|
|
668
|
+
reader.readAsDataURL(file);
|
|
669
|
+
}
|
|
670
|
+
else {
|
|
671
|
+
reject(new Error('Invalid file'));
|
|
672
|
+
}
|
|
673
|
+
});
|
|
754
674
|
/**
|
|
755
|
-
*
|
|
756
|
-
*
|
|
757
|
-
* @module
|
|
675
|
+
* Trigger a download dialog to save a blob as a file on disk.
|
|
758
676
|
*/
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
/**
|
|
772
|
-
* Check to see if the envelope has been completed.
|
|
773
|
-
*/
|
|
774
|
-
const envelopeIsComplete = (envelope) => envelope.status !== 'complete';
|
|
775
|
-
/**
|
|
776
|
-
* Check to see if the user owns the envelope.
|
|
777
|
-
*/
|
|
778
|
-
const userCanCancelEnvelope = (session, envelope) => userIsEnvelopeOwner(session, envelope) &&
|
|
779
|
-
envelope.status !== 'complete' &&
|
|
780
|
-
envelope.status !== 'declined' &&
|
|
781
|
-
envelope.status !== 'canceled';
|
|
782
|
-
/**
|
|
783
|
-
* Check to see if the user owns the envelope.
|
|
784
|
-
*/
|
|
785
|
-
const userCanFinishEnvelope = (session, envelope) => userIsEnvelopeOwner(session, envelope) &&
|
|
786
|
-
envelope.status !== 'complete' &&
|
|
787
|
-
envelope.status !== 'declined' &&
|
|
788
|
-
envelope.status !== 'canceled';
|
|
789
|
-
/**
|
|
790
|
-
* Returns true if the recipient has a pending action. Note that this does not necessarily mean the recipient can act (yet).
|
|
791
|
-
*/
|
|
792
|
-
const recipientHasAction = (recipient) => !['submitted', 'canceled', 'declined'].includes(recipient.status);
|
|
793
|
-
/**
|
|
794
|
-
* Returns the recipients who still have a pending action. Note that not all of these recipients may be able to act (yet).
|
|
795
|
-
*/
|
|
796
|
-
const getRecipientsWithActions = (envelope) => (envelope?.recipients || []).filter(recipientHasAction);
|
|
797
|
-
/**
|
|
798
|
-
* Returns true if the recipient can act.
|
|
799
|
-
*/
|
|
800
|
-
const recipientCanAct = (recipient, recipientsWithActions) => recipient.sequence === recipientsWithActions?.[0]?.sequence;
|
|
801
|
-
/**
|
|
802
|
-
* Returns true if the user can act.
|
|
803
|
-
*/
|
|
804
|
-
const userCanAct = (email, recipientsWithActions) => {
|
|
805
|
-
const recipient = recipientsWithActions.find((r) => r.email === email);
|
|
806
|
-
return recipient && recipient.sequence === recipientsWithActions?.[0]?.sequence;
|
|
807
|
-
};
|
|
808
|
-
/**
|
|
809
|
-
* Returns true if the user can act.
|
|
810
|
-
*/
|
|
811
|
-
const userCanSignNow = (session, envelope) => {
|
|
812
|
-
if (!session) {
|
|
813
|
-
return false;
|
|
814
|
-
}
|
|
815
|
-
const recipientsWithActions = getRecipientsWithActions(envelope);
|
|
816
|
-
const myRecipient = recipientsWithActions.find((r) => r.profile_id === session?.profile_id || r.email === session?.email);
|
|
817
|
-
return (myRecipient &&
|
|
818
|
-
envelopeIsActive(envelope) &&
|
|
819
|
-
userIsEnvelopeRecipient(session, envelope) &&
|
|
820
|
-
recipientCanAct(myRecipient, recipientsWithActions));
|
|
821
|
-
};
|
|
822
|
-
const getNextRecipient = (envelope) => {
|
|
823
|
-
const recipientsWithActions = getRecipientsWithActions(envelope);
|
|
824
|
-
return recipientsWithActions?.[0];
|
|
825
|
-
};
|
|
826
|
-
|
|
827
|
-
/**
|
|
828
|
-
* Create a signature block. In a typical signing workflow, the user is asked at the beginning of the process to "adopt"
|
|
829
|
-
* a signature block to be used for all signature fields in the document. Thus, this is typically called one time to
|
|
830
|
-
* create and store a signature block. Thereafter, the ID of the signature block may be re-used for each signature field
|
|
831
|
-
* to be "stamped" by the user.
|
|
832
|
-
*/
|
|
833
|
-
const createSignature = (endpoint, name, signature) => {
|
|
834
|
-
const data = new FormData();
|
|
835
|
-
data.append('signature', signature, name);
|
|
836
|
-
return endpoint.api //
|
|
837
|
-
.post(`/signatures`, data)
|
|
838
|
-
.then((r) => r.data);
|
|
677
|
+
const downloadBlob = (blob, name = 'file.pdf') => {
|
|
678
|
+
const blobUrl = URL.createObjectURL(blob);
|
|
679
|
+
const link = document.createElement('a');
|
|
680
|
+
link.href = blobUrl;
|
|
681
|
+
link.download = name;
|
|
682
|
+
document.body.appendChild(link);
|
|
683
|
+
link.dispatchEvent(new MouseEvent('click', {
|
|
684
|
+
bubbles: true,
|
|
685
|
+
cancelable: true,
|
|
686
|
+
view: window,
|
|
687
|
+
}));
|
|
688
|
+
document.body.removeChild(link);
|
|
839
689
|
};
|
|
840
|
-
/**
|
|
841
|
-
* Get the availbable signatures for a user.
|
|
842
|
-
*/
|
|
843
|
-
const getSignatures = (endpoint) => endpoint.api //
|
|
844
|
-
.get('/signatures')
|
|
845
|
-
.then((r) => r.data);
|
|
846
|
-
/**
|
|
847
|
-
* Get a user's signature by ID.
|
|
848
|
-
*/
|
|
849
|
-
const getSignature = (endpoint, signatureId) => endpoint.api //
|
|
850
|
-
.get(`/signatures/${signatureId}`)
|
|
851
|
-
.then((r) => r.data);
|
|
852
|
-
/**
|
|
853
|
-
* Delete a user's signature.
|
|
854
|
-
*/
|
|
855
|
-
const deleteSignature = (endpoint, signatureId) => endpoint.api //
|
|
856
|
-
.delete(`/signatures/${signatureId}`)
|
|
857
|
-
.then((r) => r.data);
|
|
858
|
-
|
|
859
|
-
/**
|
|
860
|
-
* API keys are used to authenticate server-to-server calls. (API keys should **never** be used for client-to-server operations!)
|
|
861
|
-
* To generate a key, either use the Verdocs admin interface and make note of the client_id and client_secret generated, or call
|
|
862
|
-
* createKey as shown below. Then call {@link Users.Auth.authenticateApp} to obtain an access token using the provided ID and
|
|
863
|
-
* secret. Note that server-to-server authentication requests return shorter-lived tokens, so it is important to check the `exp`
|
|
864
|
-
* field and re-authenticate as needed for subsequent calls.
|
|
865
|
-
*
|
|
866
|
-
* API keys may be updated or rotated at any time. Regular rotation is recommended. Rotation will not expire or invalidate
|
|
867
|
-
* existing server-to-server sessions, so it may be done at any time without disrupting your application.
|
|
868
|
-
*
|
|
869
|
-
* @module
|
|
870
|
-
*/
|
|
871
|
-
/**
|
|
872
|
-
* Get a list of keys for a given organization. The caller must have admin access to the organization.
|
|
873
|
-
*
|
|
874
|
-
* ```typescript
|
|
875
|
-
* import {ApiKeys} from '@verdocs/js-sdk/Organizations';
|
|
876
|
-
*
|
|
877
|
-
* const keys = await ApiKeys.getKeys(ORGID);
|
|
878
|
-
* ```
|
|
879
|
-
*/
|
|
880
|
-
const getApiKeys = (endpoint, organizationId) => endpoint.api //
|
|
881
|
-
.get(`/organizations/${organizationId}/api_key`)
|
|
882
|
-
.then((r) => r.data);
|
|
883
|
-
/**
|
|
884
|
-
* Create an API key.
|
|
885
|
-
*
|
|
886
|
-
* ```typescript
|
|
887
|
-
* import {ApiKeys} from '@verdocs/js-sdk/Organizations';
|
|
888
|
-
*
|
|
889
|
-
* await ApiKeys.createKey(ORGID, {name: NEWNAME});
|
|
890
|
-
* ```
|
|
891
|
-
*/
|
|
892
|
-
const createApiKey = (endpoint, organizationId, params) => endpoint.api //
|
|
893
|
-
.post(`/organizations/${organizationId}/api_key`, params)
|
|
894
|
-
.then((r) => r.data);
|
|
895
|
-
/**
|
|
896
|
-
* Rotate the secret for an API key. The caller must have admin access to the organization.
|
|
897
|
-
*
|
|
898
|
-
* ```typescript
|
|
899
|
-
* import {ApiKeys} from '@verdocs/js-sdk/Organizations';
|
|
900
|
-
*
|
|
901
|
-
* const {client_secret: newSecret} = await ApiKeys.rotateKey(ORGID, CLIENTID);
|
|
902
|
-
* ```
|
|
903
|
-
*/
|
|
904
|
-
const rotateApiKey = (endpoint, organizationId, clientId) => endpoint.api //
|
|
905
|
-
.put(`/organizations/${organizationId}/api_key/${clientId}/rotate`)
|
|
906
|
-
.then((r) => r.data);
|
|
907
|
-
/**
|
|
908
|
-
* Update an API key to change its assigned Profile ID or Name.
|
|
909
|
-
*
|
|
910
|
-
* ```typescript
|
|
911
|
-
* import {ApiKeys} from '@verdocs/js-sdk/Organizations';
|
|
912
|
-
*
|
|
913
|
-
* await ApiKeys.updateKey(ORGID, CLIENTID, {name: NEWNAME});
|
|
914
|
-
* ```
|
|
915
|
-
*/
|
|
916
|
-
const updateApiKey = (endpoint, organizationId, clientId, params) => endpoint.api //
|
|
917
|
-
.patch(`/organizations/${organizationId}/api_key/${clientId}`, params)
|
|
918
|
-
.then((r) => r.data);
|
|
919
|
-
/**
|
|
920
|
-
* Delete an API key.
|
|
921
|
-
*
|
|
922
|
-
* ```typescript
|
|
923
|
-
* import {ApiKeys} from '@verdocs/js-sdk/Organizations';
|
|
924
|
-
*
|
|
925
|
-
* await ApiKeys.deleteKey(ORGID, CLIENTID);
|
|
926
|
-
* ```
|
|
927
|
-
*/
|
|
928
|
-
const deleteApiKey = (endpoint, organizationId, clientId) => endpoint.api //
|
|
929
|
-
.delete(`/organizations/${organizationId}/api_key/${clientId}`)
|
|
930
|
-
.then((r) => r.data);
|
|
931
|
-
|
|
932
|
-
/**
|
|
933
|
-
* Organizations may contain "Groups" of user profiles, called Members. Groups may have permissions assigned that
|
|
934
|
-
* apply to all Members, making it easy to configure role-based access control (RBAC) within an Organization. Note
|
|
935
|
-
* that permissions are **additive**. A user may be a member of more than one group, and may also have permissions
|
|
936
|
-
* assigned directly. In that case, the user will have the combined set of all permissions inherited from all
|
|
937
|
-
* sources.
|
|
938
|
-
*
|
|
939
|
-
* @module
|
|
940
|
-
*/
|
|
941
|
-
/**
|
|
942
|
-
* Get a list of groups for a given organization. The caller must have admin access to the organization.
|
|
943
|
-
*
|
|
944
|
-
* ```typescript
|
|
945
|
-
* import {Groups} from '@verdocs/js-sdk/Organizations';
|
|
946
|
-
*
|
|
947
|
-
* const groups = await Groups.getGroups(ORGID);
|
|
948
|
-
* ```
|
|
949
|
-
*/
|
|
950
|
-
const getGroups = (endpoint, organizationId) => endpoint.api //
|
|
951
|
-
.get(`/organizations/${organizationId}/groups`)
|
|
952
|
-
.then((r) => r.data);
|
|
953
|
-
/**
|
|
954
|
-
* Get a single group by name. Returns a detail record.
|
|
955
|
-
*
|
|
956
|
-
* ```typescript
|
|
957
|
-
* import {Groups} from '@verdocs/js-sdk/Organizations';
|
|
958
|
-
*
|
|
959
|
-
* const groups = await Groups.getGroups(ORGID);
|
|
960
|
-
* ```
|
|
961
|
-
*/
|
|
962
|
-
const getGroupByName = (endpoint, organizationId, name) => endpoint.api //
|
|
963
|
-
.get(`/organizations/${organizationId}/groups`, { params: { name } })
|
|
964
|
-
.then((r) => r.data);
|
|
965
|
-
/**
|
|
966
|
-
* Get the details for a group.
|
|
967
|
-
*
|
|
968
|
-
* ```typescript
|
|
969
|
-
* import {Groups} from '@verdocs/js-sdk/Organizations';
|
|
970
|
-
*
|
|
971
|
-
* const groups = await Groups.getGroups(ORGID);
|
|
972
|
-
* ```
|
|
973
|
-
*/
|
|
974
|
-
const getGroup = (endpoint, organizationId, groupId) => endpoint.api //
|
|
975
|
-
.get(`/organizations/${organizationId}/groups/${groupId}`)
|
|
976
|
-
.then((r) => r.data);
|
|
977
|
-
const getGroupMembers = (endpoint, organizationId, groupId) => endpoint.api //
|
|
978
|
-
.get(`/organizations/${organizationId}/groups/${groupId}/members`)
|
|
979
|
-
.then((r) => r.data);
|
|
980
|
-
const addGroupMembers = (endpoint, organizationId, groupId, params) => endpoint.api //
|
|
981
|
-
.post(`/organizations/${organizationId}/groups/${groupId}/members`, params)
|
|
982
|
-
.then((r) => r.data);
|
|
983
|
-
const deleteGroupMembers = (endpoint, organizationId, groupId, params) => endpoint.api //
|
|
984
|
-
.put(`/organizations/${organizationId}/groups/${groupId}/delete_members`, params)
|
|
985
|
-
.then((r) => r.data);
|
|
986
|
-
const addGroupPermission = (endpoint, organizationId, groupId, permission) => endpoint.api //
|
|
987
|
-
.post(`/organizations/${organizationId}/groups/${groupId}/permissions/${permission}`, {})
|
|
988
|
-
.then((r) => r.data);
|
|
989
|
-
const deleteGroupPermission = (endpoint, organizationId, groupId, permission) => endpoint.api //
|
|
990
|
-
.delete(`/organizations/${organizationId}/groups/${groupId}/permissions/${permission}`)
|
|
991
|
-
.then((r) => r.data);
|
|
992
690
|
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
691
|
+
const Countries = [
|
|
692
|
+
{ code: '+7 840', name: 'Abkhazia', value: '+7' },
|
|
693
|
+
{ code: '+93', name: 'Afghanistan', value: '+93' },
|
|
694
|
+
{ code: '+355', name: 'Albania', value: '+355' },
|
|
695
|
+
{ code: '+213', name: 'Algeria', value: '+213' },
|
|
696
|
+
{ code: '+1', name: 'American Samoa', value: '+1' },
|
|
697
|
+
{ code: '+376', name: 'Andorra', value: '+376' },
|
|
698
|
+
{ code: '+244', name: 'Angola', value: '+244' },
|
|
699
|
+
{ code: '+1', name: 'Anguilla', value: '+1' },
|
|
700
|
+
{ code: '+1', name: 'Antigua and Barbuda', value: '+1' },
|
|
701
|
+
{ code: '+54', name: 'Argentina', value: '+54' },
|
|
702
|
+
{ code: '+374', name: 'Armenia', value: '+374' },
|
|
703
|
+
{ code: '+297', name: 'Aruba', value: '+297' },
|
|
704
|
+
{ code: '+247', name: 'Ascension', value: '+247' },
|
|
705
|
+
{ code: '+61', name: 'Australia', value: '+61' },
|
|
706
|
+
{ code: '+672', name: 'Australian External Territories', value: '+672' },
|
|
707
|
+
{ code: '+43', name: 'Austria', value: '+43' },
|
|
708
|
+
{ code: '+994', name: 'Azerbaijan', value: '+994' },
|
|
709
|
+
{ code: '+1', name: 'Bahamas', value: '+1' },
|
|
710
|
+
{ code: '+973', name: 'Bahrain', value: '+973' },
|
|
711
|
+
{ code: '+880', name: 'Bangladesh', value: '+880' },
|
|
712
|
+
{ code: '+1', name: 'Barbados', value: '+1' },
|
|
713
|
+
{ code: '+1', name: 'Barbuda', value: '+1' },
|
|
714
|
+
{ code: '+375', name: 'Belarus', value: '+375' },
|
|
715
|
+
{ code: '+32', name: 'Belgium', value: '+32' },
|
|
716
|
+
{ code: '+501', name: 'Belize', value: '+501' },
|
|
717
|
+
{ code: '+229', name: 'Benin', value: '+229' },
|
|
718
|
+
{ code: '+1', name: 'Bermuda', value: '+1' },
|
|
719
|
+
{ code: '+975', name: 'Bhutan', value: '+975' },
|
|
720
|
+
{ code: '+591', name: 'Bolivia', value: '+591' },
|
|
721
|
+
{ code: '+387', name: 'Bosnia and Herzegovina', value: '+387' },
|
|
722
|
+
{ code: '+267', name: 'Botswana', value: '+267' },
|
|
723
|
+
{ code: '+55', name: 'Brazil', value: '+55' },
|
|
724
|
+
{ code: '+246', name: 'British Indian Ocean Territory', value: '+246' },
|
|
725
|
+
{ code: '+1', name: 'British Virgin Islands', value: '+1' },
|
|
726
|
+
{ code: '+673', name: 'Brunei', value: '+673' },
|
|
727
|
+
{ code: '+359', name: 'Bulgaria', value: '+359' },
|
|
728
|
+
{ code: '+226', name: 'Burkina Faso', value: '+226' },
|
|
729
|
+
{ code: '+257', name: 'Burundi', value: '+257' },
|
|
730
|
+
{ code: '+855', name: 'Cambodia', value: '+855' },
|
|
731
|
+
{ code: '+237', name: 'Cameroon', value: '+237' },
|
|
732
|
+
{ code: '+1', name: 'Canada', value: '+1' },
|
|
733
|
+
{ code: '+238', name: 'Cape Verde', value: '+238' },
|
|
734
|
+
{ code: '+1', name: 'Cayman Islands', value: '+1' },
|
|
735
|
+
{ code: '+236', name: 'Central African Republic', value: '+236' },
|
|
736
|
+
{ code: '+235', name: 'Chad', value: '+235' },
|
|
737
|
+
{ code: '+56', name: 'Chile', value: '+56' },
|
|
738
|
+
{ code: '+86', name: 'China', value: '+86' },
|
|
739
|
+
{ code: '+61', name: 'Christmas Island', value: '+61' },
|
|
740
|
+
{ code: '+61', name: 'Cocos-Keeling Islands', value: '+61' },
|
|
741
|
+
{ code: '+57', name: 'Colombia', value: '+57' },
|
|
742
|
+
{ code: '+269', name: 'Comoros', value: '+269' },
|
|
743
|
+
{ code: '+242', name: 'Congo', value: '+242' },
|
|
744
|
+
{ code: '+243', name: 'Congo, Dem. Rep. of (Zaire)', value: '+243' },
|
|
745
|
+
{ code: '+682', name: 'Cook Islands', value: '+682' },
|
|
746
|
+
{ code: '+506', name: 'Costa Rica', value: '+506' },
|
|
747
|
+
{ code: '+385', name: 'Croatia', value: '+385' },
|
|
748
|
+
{ code: '+53', name: 'Cuba', value: '+53' },
|
|
749
|
+
{ code: '+599', name: 'Curacao', value: '+599' },
|
|
750
|
+
{ code: '+537', name: 'Cyprus', value: '+537' },
|
|
751
|
+
{ code: '+420', name: 'Czech Republic', value: '+420' },
|
|
752
|
+
{ code: '+45', name: 'Denmark', value: '+45' },
|
|
753
|
+
{ code: '+246', name: 'Diego Garcia', value: '+246' },
|
|
754
|
+
{ code: '+253', name: 'Djibouti', value: '+253' },
|
|
755
|
+
{ code: '+1', name: 'Dominica', value: '+1' },
|
|
756
|
+
{ code: '+1', name: 'Dominican Republic', value: '+1' },
|
|
757
|
+
{ code: '+670', name: 'East Timor', value: '+670' },
|
|
758
|
+
{ code: '+56', name: 'Easter Island', value: '+56' },
|
|
759
|
+
{ code: '+593', name: 'Ecuador', value: '+593' },
|
|
760
|
+
{ code: '+20', name: 'Egypt', value: '+20' },
|
|
761
|
+
{ code: '+503', name: 'El Salvador', value: '+503' },
|
|
762
|
+
{ code: '+240', name: 'Equatorial Guinea', value: '+240' },
|
|
763
|
+
{ code: '+291', name: 'Eritrea', value: '+291' },
|
|
764
|
+
{ code: '+372', name: 'Estonia', value: '+372' },
|
|
765
|
+
{ code: '+251', name: 'Ethiopia', value: '+251' },
|
|
766
|
+
{ code: '+500', name: 'Falkland Islands', value: '+500' },
|
|
767
|
+
{ code: '+298', name: 'Faroe Islands', value: '+298' },
|
|
768
|
+
{ code: '+679', name: 'Fiji', value: '+679' },
|
|
769
|
+
{ code: '+358', name: 'Finland', value: '+358' },
|
|
770
|
+
{ code: '+33', name: 'France', value: '+33' },
|
|
771
|
+
{ code: '+596', name: 'Martinique', value: '+596' },
|
|
772
|
+
{ code: '+594', name: 'French Guiana', value: '+594' },
|
|
773
|
+
{ code: '+689', name: 'French Polynesia', value: '+689' },
|
|
774
|
+
{ code: '+241', name: 'Gabon', value: '+241' },
|
|
775
|
+
{ code: '+220', name: 'Gambia', value: '+220' },
|
|
776
|
+
{ code: '+995', name: 'Georgia', value: '+995' },
|
|
777
|
+
{ code: '+49', name: 'Germany', value: '+49' },
|
|
778
|
+
{ code: '+233', name: 'Ghana', value: '+233' },
|
|
779
|
+
{ code: '+350', name: 'Gibraltar', value: '+350' },
|
|
780
|
+
{ code: '+30', name: 'Greece', value: '+30' },
|
|
781
|
+
{ code: '+299', name: 'Greenland', value: '+299' },
|
|
782
|
+
{ code: '+1', name: 'Grenada', value: '+1' },
|
|
783
|
+
{ code: '+590', name: 'Guadeloupe', value: '+590' },
|
|
784
|
+
{ code: '+1', name: 'Guam', value: '+1' },
|
|
785
|
+
{ code: '+502', name: 'Guatemala', value: '+502' },
|
|
786
|
+
{ code: '+224', name: 'Guinea', value: '+224' },
|
|
787
|
+
{ code: '+245', name: 'Guinea-Bissau', value: '+245' },
|
|
788
|
+
{ code: '+595', name: 'Guyana', value: '+595' },
|
|
789
|
+
{ code: '+509', name: 'Haiti', value: '+509' },
|
|
790
|
+
{ code: '+504', name: 'Honduras', value: '+504' },
|
|
791
|
+
{ code: '+852', name: 'Hong Kong SAR China', value: '+852' },
|
|
792
|
+
{ code: '+36', name: 'Hungary', value: '+36' },
|
|
793
|
+
{ code: '+354', name: 'Iceland', value: '+354' },
|
|
794
|
+
{ code: '+91', name: 'India', value: '+91' },
|
|
795
|
+
{ code: '+62', name: 'Indonesia', value: '+62' },
|
|
796
|
+
{ code: '+98', name: 'Iran', value: '+98' },
|
|
797
|
+
{ code: '+964', name: 'Iraq', value: '+964' },
|
|
798
|
+
{ code: '+353', name: 'Ireland', value: '+353' },
|
|
799
|
+
{ code: '+972', name: 'Israel', value: '+972' },
|
|
800
|
+
{ code: '+39', name: 'Italy', value: '+39' },
|
|
801
|
+
{ code: '+225', name: 'Ivory Coast', value: '+225' },
|
|
802
|
+
{ code: '+1', name: 'Jamaica', value: '+1' },
|
|
803
|
+
{ code: '+81', name: 'Japan', value: '+81' },
|
|
804
|
+
{ code: '+962', name: 'Jordan', value: '+962' },
|
|
805
|
+
{ code: '+77', name: 'Kazakhstan', value: '+7' },
|
|
806
|
+
{ code: '+254', name: 'Kenya', value: '+254' },
|
|
807
|
+
{ code: '+686', name: 'Kiribati', value: '+686' },
|
|
808
|
+
{ code: '+965', name: 'Kuwait', value: '+965' },
|
|
809
|
+
{ code: '+996', name: 'Kyrgyzstan', value: '+996' },
|
|
810
|
+
{ code: '+856', name: 'Laos', value: '+856' },
|
|
811
|
+
{ code: '+371', name: 'Latvia', value: '+371' },
|
|
812
|
+
{ code: '+961', name: 'Lebanon', value: '+961' },
|
|
813
|
+
{ code: '+266', name: 'Lesotho', value: '+266' },
|
|
814
|
+
{ code: '+231', name: 'Liberia', value: '+231' },
|
|
815
|
+
{ code: '+218', name: 'Libya', value: '+218' },
|
|
816
|
+
{ code: '+423', name: 'Liechtenstein', value: '+423' },
|
|
817
|
+
{ code: '+370', name: 'Lithuania', value: '+370' },
|
|
818
|
+
{ code: '+352', name: 'Luxembourg', value: '+352' },
|
|
819
|
+
{ code: '+853', name: 'Macau SAR China', value: '+853' },
|
|
820
|
+
{ code: '+389', name: 'Macedonia', value: '+389' },
|
|
821
|
+
{ code: '+261', name: 'Madagascar', value: '+261' },
|
|
822
|
+
{ code: '+265', name: 'Malawi', value: '+265' },
|
|
823
|
+
{ code: '+60', name: 'Malaysia', value: '+60' },
|
|
824
|
+
{ code: '+960', name: 'Maldives', value: '+960' },
|
|
825
|
+
{ code: '+223', name: 'Mali', value: '+223' },
|
|
826
|
+
{ code: '+356', name: 'Malta', value: '+356' },
|
|
827
|
+
{ code: '+692', name: 'Marshall Islands', value: '+692' },
|
|
828
|
+
{ code: '+596', name: 'Martinique', value: '+596' },
|
|
829
|
+
{ code: '+222', name: 'Mauritania', value: '+222' },
|
|
830
|
+
{ code: '+230', name: 'Mauritius', value: '+230' },
|
|
831
|
+
{ code: '+262', name: 'Mayotte or Réunion', value: '+262' },
|
|
832
|
+
{ code: '+52', name: 'Mexico', value: '+52' },
|
|
833
|
+
{ code: '+691', name: 'Micronesia', value: '+691' },
|
|
834
|
+
{ code: '+1', name: 'Midway Island', value: '+1' },
|
|
835
|
+
{ code: '+373', name: 'Moldova', value: '+373' },
|
|
836
|
+
{ code: '+377', name: 'Monaco', value: '+377' },
|
|
837
|
+
{ code: '+976', name: 'Mongolia', value: '+976' },
|
|
838
|
+
{ code: '+382', name: 'Montenegro', value: '+382' },
|
|
839
|
+
{ code: '+1', name: 'Montserrat', value: '+1' },
|
|
840
|
+
{ code: '+212', name: 'Morocco', value: '+212' },
|
|
841
|
+
{ code: '+95', name: 'Myanmar', value: '+95' },
|
|
842
|
+
{ code: '+264', name: 'Namibia', value: '+264' },
|
|
843
|
+
{ code: '+674', name: 'Nauru', value: '+674' },
|
|
844
|
+
{ code: '+977', name: 'Nepal', value: '+977' },
|
|
845
|
+
{ code: '+31', name: 'Netherlands', value: '+31' },
|
|
846
|
+
{ code: '+599', name: 'Netherlands Antilles', value: '+599' },
|
|
847
|
+
{ code: '+1', name: 'Nevis', value: '+1' },
|
|
848
|
+
{ code: '+687', name: 'New Caledonia', value: '+687' },
|
|
849
|
+
{ code: '+64', name: 'New Zealand', value: '+64' },
|
|
850
|
+
{ code: '+505', name: 'Nicaragua', value: '+505' },
|
|
851
|
+
{ code: '+227', name: 'Niger', value: '+227' },
|
|
852
|
+
{ code: '+234', name: 'Nigeria', value: '+234' },
|
|
853
|
+
{ code: '+683', name: 'Niue', value: '+683' },
|
|
854
|
+
{ code: '+672', name: 'Norfolk Island', value: '+672' },
|
|
855
|
+
{ code: '+850', name: 'North Korea', value: '+850' },
|
|
856
|
+
{ code: '+1', name: 'Northern Mariana Islands', value: '+1' },
|
|
857
|
+
{ code: '+47', name: 'Norway', value: '+47' },
|
|
858
|
+
{ code: '+968', name: 'Oman', value: '+968' },
|
|
859
|
+
{ code: '+92', name: 'Pakistan', value: '+92' },
|
|
860
|
+
{ code: '+680', name: 'Palau', value: '+680' },
|
|
861
|
+
{ code: '+970', name: 'Palestinian Territory', value: '+970' },
|
|
862
|
+
{ code: '+507', name: 'Panama', value: '+507' },
|
|
863
|
+
{ code: '+675', name: 'Papua New Guinea', value: '+675' },
|
|
864
|
+
{ code: '+595', name: 'Paraguay', value: '+595' },
|
|
865
|
+
{ code: '+51', name: 'Peru', value: '+51' },
|
|
866
|
+
{ code: '+63', name: 'Philippines', value: '+63' },
|
|
867
|
+
{ code: '+48', name: 'Poland', value: '+48' },
|
|
868
|
+
{ code: '+351', name: 'Portugal', value: '+351' },
|
|
869
|
+
{ code: '+1', name: 'Puerto Rico', value: '+1' },
|
|
870
|
+
{ code: '+974', name: 'Qatar', value: '+974' },
|
|
871
|
+
{ code: '+40', name: 'Romania', value: '+40' },
|
|
872
|
+
{ code: '+7', name: 'Russia', value: '+7' },
|
|
873
|
+
{ code: '+250', name: 'Rwanda', value: '+250' },
|
|
874
|
+
{ code: '508', name: 'Saint Pierre and Miquelon', value: '508' },
|
|
875
|
+
{ code: '+685', name: 'Samoa', value: '+685' },
|
|
876
|
+
{ code: '+378', name: 'San Marino', value: '+378' },
|
|
877
|
+
{ code: '+966', name: 'Saudi Arabia', value: '+966' },
|
|
878
|
+
{ code: '+221', name: 'Senegal', value: '+221' },
|
|
879
|
+
{ code: '+381', name: 'Serbia', value: '+381' },
|
|
880
|
+
{ code: '+248', name: 'Seychelles', value: '+248' },
|
|
881
|
+
{ code: '+232', name: 'Sierra Leone', value: '+232' },
|
|
882
|
+
{ code: '+65', name: 'Singapore', value: '+65' },
|
|
883
|
+
{ code: '+421', name: 'Slovakia', value: '+421' },
|
|
884
|
+
{ code: '+386', name: 'Slovenia', value: '+386' },
|
|
885
|
+
{ code: '+677', name: 'Solomon Islands', value: '+677' },
|
|
886
|
+
{ code: '+27', name: 'South Africa', value: '+27' },
|
|
887
|
+
{ code: '+500', name: 'South Georgia and the South Sandwich Islands', value: '+500' },
|
|
888
|
+
{ code: '+82', name: 'South Korea', value: '+82' },
|
|
889
|
+
{ code: '+34', name: 'Spain', value: '+34' },
|
|
890
|
+
{ code: '+94', name: 'Sri Lanka', value: '+94' },
|
|
891
|
+
{ code: '+249', name: 'Sudan', value: '+249' },
|
|
892
|
+
{ code: '+597', name: 'Suriname', value: '+597' },
|
|
893
|
+
{ code: '+268', name: 'Swaziland', value: '+268' },
|
|
894
|
+
{ code: '+46', name: 'Sweden', value: '+46' },
|
|
895
|
+
{ code: '+41', name: 'Switzerland', value: '+41' },
|
|
896
|
+
{ code: '+963', name: 'Syria', value: '+963' },
|
|
897
|
+
{ code: '+886', name: 'Taiwan', value: '+886' },
|
|
898
|
+
{ code: '+992', name: 'Tajikistan', value: '+992' },
|
|
899
|
+
{ code: '+255', name: 'Tanzania', value: '+255' },
|
|
900
|
+
{ code: '+66', name: 'Thailand', value: '+66' },
|
|
901
|
+
{ code: '+670', name: 'Timor Leste', value: '+670' },
|
|
902
|
+
{ code: '+228', name: 'Togo', value: '+228' },
|
|
903
|
+
{ code: '+690', name: 'Tokelau', value: '+690' },
|
|
904
|
+
{ code: '+676', name: 'Tonga', value: '+676' },
|
|
905
|
+
{ code: '+1', name: 'Trinidad and Tobago', value: '+1' },
|
|
906
|
+
{ code: '+216', name: 'Tunisia', value: '+216' },
|
|
907
|
+
{ code: '+90', name: 'Turkey', value: '+90' },
|
|
908
|
+
{ code: '+993', name: 'Turkmenistan', value: '+993' },
|
|
909
|
+
{ code: '+1', name: 'Turks and Caicos Islands', value: '+1' },
|
|
910
|
+
{ code: '+688', name: 'Tuvalu', value: '+688' },
|
|
911
|
+
{ code: '+1', name: 'U.S. Virgin Islands', value: '+1' },
|
|
912
|
+
{ code: '+256', name: 'Uganda', value: '+256' },
|
|
913
|
+
{ code: '+380', name: 'Ukraine', value: '+380' },
|
|
914
|
+
{ code: '+971', name: 'United Arab Emirates', value: '+971' },
|
|
915
|
+
{ code: '+44', name: 'United Kingdom', value: '+44' },
|
|
916
|
+
{ code: '+1', name: 'United States', value: '+1' },
|
|
917
|
+
{ code: '+598', name: 'Uruguay', value: '+598' },
|
|
918
|
+
{ code: '+998', name: 'Uzbekistan', value: '+998' },
|
|
919
|
+
{ code: '+678', name: 'Vanuatu', value: '+678' },
|
|
920
|
+
{ code: '+58', name: 'Venezuela', value: '+58' },
|
|
921
|
+
{ code: '+84', name: 'Vietnam', value: '+84' },
|
|
922
|
+
{ code: '+1', name: 'Wake Island', value: '+1' },
|
|
923
|
+
{ code: '+681', name: 'Wallis and Futuna', value: '+681' },
|
|
924
|
+
{ code: '+967', name: 'Yemen', value: '+967' },
|
|
925
|
+
{ code: '+260', name: 'Zambia', value: '+260' },
|
|
926
|
+
{ code: '+255', name: 'Zanzibar', value: '+255' },
|
|
927
|
+
{ code: '+263', name: 'Zimbabwe', value: '+263' },
|
|
928
|
+
];
|
|
929
|
+
function getCountryByCode(code) {
|
|
930
|
+
const found = Countries.find((country) => country.code === code);
|
|
931
|
+
if (found)
|
|
932
|
+
return found;
|
|
933
|
+
if (isFrenchGuiana(code)) {
|
|
934
|
+
return { code: '+594', name: 'French Guiana', value: '+594' };
|
|
1098
935
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
const profile_id = session?.profile_id || 'BOGUS';
|
|
1102
|
-
const organization_id = session?.organization_id || 'BOGUS';
|
|
1103
|
-
if (!profile_id) {
|
|
1104
|
-
return { canPerform: false, message: 'Active session required' };
|
|
936
|
+
else if (isGuadeloupe(code)) {
|
|
937
|
+
return { code: '+590', name: 'Guadeloupe', value: '+590' };
|
|
1105
938
|
}
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
939
|
+
else if (isMartinique(code)) {
|
|
940
|
+
return { code: '+596', name: 'Martinique', value: '+596' };
|
|
941
|
+
}
|
|
942
|
+
else if (isMayotte(code)) {
|
|
943
|
+
return { code: '+262', name: 'Mayotte or Réunion', value: '+262' };
|
|
944
|
+
}
|
|
945
|
+
return null;
|
|
946
|
+
}
|
|
947
|
+
function isFrenchGuiana(code) {
|
|
948
|
+
return '+594' === code.substring(0, 4);
|
|
949
|
+
}
|
|
950
|
+
function isGuadeloupe(code) {
|
|
951
|
+
return '+590' === code.substring(0, 4);
|
|
952
|
+
}
|
|
953
|
+
function isMartinique(code) {
|
|
954
|
+
return '+596' === code.substring(0, 4);
|
|
955
|
+
}
|
|
956
|
+
function isMayotte(code) {
|
|
957
|
+
return '+262' === code.substring(0, 4);
|
|
958
|
+
}
|
|
959
|
+
function getPlusOneCountry(code) {
|
|
960
|
+
let info = null;
|
|
961
|
+
switch (code.substring(0, 5)) {
|
|
962
|
+
case '+1684':
|
|
963
|
+
info = { code: '+1', name: 'American Samoa', value: '+1' };
|
|
1117
964
|
break;
|
|
1118
|
-
case '
|
|
1119
|
-
|
|
965
|
+
case '+1264':
|
|
966
|
+
info = { code: '+1', name: 'Anguilla', value: '+1' };
|
|
1120
967
|
break;
|
|
1121
|
-
case '
|
|
1122
|
-
|
|
1123
|
-
if ((!isPersonal && isSameOrg) || !isPublic) {
|
|
1124
|
-
permissionsRequired.push('template:member:read');
|
|
1125
|
-
}
|
|
1126
|
-
}
|
|
968
|
+
case '+1268':
|
|
969
|
+
info = { code: '+1', name: 'Antigua and Barbuda', value: '+1' };
|
|
1127
970
|
break;
|
|
1128
|
-
case '
|
|
1129
|
-
|
|
1130
|
-
permissionsRequired.push('template:member:read');
|
|
1131
|
-
permissionsRequired.push('template:member:write');
|
|
1132
|
-
}
|
|
971
|
+
case '+1242':
|
|
972
|
+
info = { code: '+1', name: 'Bahamas', value: '+1' };
|
|
1133
973
|
break;
|
|
1134
|
-
case '
|
|
1135
|
-
|
|
1136
|
-
permissionsRequired.push('template:creator:create:personal');
|
|
1137
|
-
}
|
|
1138
|
-
else {
|
|
1139
|
-
permissionsRequired.push('template:member:visibility');
|
|
1140
|
-
}
|
|
974
|
+
case '+1246':
|
|
975
|
+
info = { code: '+1', name: 'Barbados', value: '+1' };
|
|
1141
976
|
break;
|
|
1142
|
-
case '
|
|
1143
|
-
|
|
1144
|
-
permissionsRequired.push('template:creator:create:org');
|
|
1145
|
-
}
|
|
1146
|
-
else {
|
|
1147
|
-
permissionsRequired.push('template:member:visibility');
|
|
1148
|
-
}
|
|
977
|
+
case '+1441':
|
|
978
|
+
info = { code: '+1', name: 'Bermuda', value: '+1' };
|
|
1149
979
|
break;
|
|
1150
|
-
case '
|
|
1151
|
-
|
|
1152
|
-
permissionsRequired.push('template:creator:create:public');
|
|
1153
|
-
permissionsRequired.push('template:creator:visibility');
|
|
1154
|
-
}
|
|
1155
|
-
else {
|
|
1156
|
-
permissionsRequired.push('template:member:visibility');
|
|
1157
|
-
}
|
|
980
|
+
case '+1284':
|
|
981
|
+
info = { code: '+1', name: 'British Virgin Islands', value: '+1' };
|
|
1158
982
|
break;
|
|
1159
|
-
case '
|
|
1160
|
-
|
|
1161
|
-
permissionsRequired.push('template:creator:delete');
|
|
1162
|
-
}
|
|
1163
|
-
else {
|
|
1164
|
-
permissionsRequired.push('template:member:delete');
|
|
1165
|
-
}
|
|
983
|
+
case '+1':
|
|
984
|
+
info = { code: '+1', name: '', value: '+1' };
|
|
1166
985
|
break;
|
|
1167
|
-
default:
|
|
1168
|
-
return { canPerform: false, message: 'Action is not defined' };
|
|
1169
|
-
}
|
|
1170
|
-
if (hasRequiredPermissions(session, permissionsRequired)) {
|
|
1171
|
-
return { canPerform: true, message: '' };
|
|
1172
986
|
}
|
|
1173
|
-
return
|
|
1174
|
-
}
|
|
1175
|
-
|
|
987
|
+
return info;
|
|
988
|
+
}
|
|
989
|
+
function isCanada(code) {
|
|
990
|
+
const canadianAreaCodes = [
|
|
991
|
+
'403',
|
|
992
|
+
'587',
|
|
993
|
+
'780',
|
|
994
|
+
'825',
|
|
995
|
+
'604',
|
|
996
|
+
'250',
|
|
997
|
+
'778',
|
|
998
|
+
'236',
|
|
999
|
+
'204',
|
|
1000
|
+
'431',
|
|
1001
|
+
'506',
|
|
1002
|
+
'709',
|
|
1003
|
+
'867',
|
|
1004
|
+
'782',
|
|
1005
|
+
'902',
|
|
1006
|
+
'867',
|
|
1007
|
+
'548',
|
|
1008
|
+
'705',
|
|
1009
|
+
'365',
|
|
1010
|
+
'613',
|
|
1011
|
+
'807',
|
|
1012
|
+
'226',
|
|
1013
|
+
'289',
|
|
1014
|
+
'437',
|
|
1015
|
+
'519',
|
|
1016
|
+
'647',
|
|
1017
|
+
'905',
|
|
1018
|
+
'249',
|
|
1019
|
+
'343',
|
|
1020
|
+
'416',
|
|
1021
|
+
'902',
|
|
1022
|
+
'782',
|
|
1023
|
+
'450',
|
|
1024
|
+
'418',
|
|
1025
|
+
'579',
|
|
1026
|
+
'873',
|
|
1027
|
+
'367',
|
|
1028
|
+
'514',
|
|
1029
|
+
'581',
|
|
1030
|
+
'819',
|
|
1031
|
+
'438',
|
|
1032
|
+
'639',
|
|
1033
|
+
'306',
|
|
1034
|
+
'867',
|
|
1035
|
+
];
|
|
1036
|
+
const areaCode = code.substring(0, 5);
|
|
1037
|
+
return canadianAreaCodes.findIndex((x) => '+1' + x === areaCode) > -1;
|
|
1038
|
+
}
|
|
1039
|
+
function isAmericanSamoa(code) {
|
|
1040
|
+
return code.substring(0, 5) === '+1684';
|
|
1041
|
+
}
|
|
1042
|
+
function isDominicanRepublic(code) {
|
|
1043
|
+
return '+1809' === code.substring(0, 5) || '+1829' === code.substring(0, 5) || '+1849' === code.substring(0, 5);
|
|
1044
|
+
}
|
|
1045
|
+
function isPuertoRico(code) {
|
|
1046
|
+
return code.substring(0, 5) === '+' || code.substring(0, 5) === '+';
|
|
1047
|
+
}
|
|
1048
|
+
// need to finish
|
|
1049
|
+
function getMatchingCountry(code, substrings) {
|
|
1050
|
+
const toMatch = code.substring(0, substrings);
|
|
1051
|
+
return Countries.filter((c) => c.code === toMatch).length;
|
|
1052
|
+
}
|
|
1053
|
+
// const e164Regex = new RegExp(/\+[1-9]\d{6,14}/g);
|
|
1054
|
+
// export function simpleE164Validator(code: string) {
|
|
1055
|
+
// return (code !== null && code.length < 16 && code.length > 6 && e164Regex.test(code)) || code === '' || code === null;
|
|
1056
|
+
// }
|
|
1176
1057
|
|
|
1177
1058
|
/**
|
|
1178
|
-
*
|
|
1179
|
-
*/
|
|
1180
|
-
const createField = (endpoint, templateId, params) => endpoint.api //
|
|
1181
|
-
.post(`/templates/${templateId}/fields`, params)
|
|
1182
|
-
.then((r) => r.data);
|
|
1183
|
-
/**
|
|
1184
|
-
* Update a template field.
|
|
1059
|
+
* Capitalize the first letter of a string.
|
|
1185
1060
|
*/
|
|
1186
|
-
const
|
|
1187
|
-
.put(`/templates/${templateId}/fields/${fieldName}`, params)
|
|
1188
|
-
.then((r) => r.data);
|
|
1061
|
+
const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
1189
1062
|
/**
|
|
1190
|
-
*
|
|
1063
|
+
* Convert a phone-number-like string to E164 format.
|
|
1064
|
+
* @see https://46elks.com/kb/e164
|
|
1191
1065
|
*/
|
|
1192
|
-
const
|
|
1193
|
-
|
|
1194
|
-
|
|
1066
|
+
const convertToE164 = (input) => {
|
|
1067
|
+
// "(212) 555-1212" => +12125551212
|
|
1068
|
+
// "+46766861004" => "+46766861004"
|
|
1069
|
+
// "212-555-1212" => +12125551212
|
|
1070
|
+
// "212.555.1212" => +12125551212
|
|
1071
|
+
// "212 555 1212" => +12125551212
|
|
1072
|
+
let temp = (input || '').trim();
|
|
1073
|
+
// If we are already prefixed, assume the user did it deliberately and attempt to use what they entered. We also short-circuit blanks.
|
|
1074
|
+
if (!temp || temp.startsWith('+')) {
|
|
1075
|
+
return temp;
|
|
1076
|
+
}
|
|
1077
|
+
// Remove any spaces, parenthesis or other punctuation.
|
|
1078
|
+
temp = temp.replace(/[^0-9]/g, '');
|
|
1079
|
+
// If the number begins with a zero, remove the leading zero. Do not combine this with the previous step because it needs to be removed
|
|
1080
|
+
// whether it's the actual first character e.g. `0(5)` or just the first digit e.g. `(05`.
|
|
1081
|
+
temp = temp.replace(/^0/g, '');
|
|
1082
|
+
// Prepend the country code and +. We're assuming US in this case given the target demographic. Users in other countries would/should be
|
|
1083
|
+
// already entering a prefix so they'd shortcut out of this routine via the + prefix check.
|
|
1084
|
+
return `+1${temp}`;
|
|
1085
|
+
};
|
|
1195
1086
|
|
|
1196
1087
|
/**
|
|
1197
|
-
*
|
|
1198
|
-
*
|
|
1088
|
+
* Create an array containing a sequence of integers, e.g. [START, START+1, START+2, ...] This is frequently useful
|
|
1089
|
+
* in rendering operations when there is no source array to .map() across.
|
|
1199
1090
|
*/
|
|
1200
|
-
const
|
|
1201
|
-
.
|
|
1202
|
-
.
|
|
1091
|
+
const integerSequence = (start, count) => Array(count)
|
|
1092
|
+
.fill(1)
|
|
1093
|
+
.map((_, index) => index + start);
|
|
1203
1094
|
/**
|
|
1204
|
-
*
|
|
1095
|
+
* Format a profile's full name
|
|
1205
1096
|
*/
|
|
1206
|
-
const
|
|
1207
|
-
.get(`/templates/${templateId}/reminder/${reminderId}`)
|
|
1208
|
-
.then((r) => r.data);
|
|
1097
|
+
const formatFullName = (profile) => profile ? `${capitalize(profile.first_name)} ${capitalize(profile.last_name)}` : 'Invalid User';
|
|
1209
1098
|
/**
|
|
1210
|
-
*
|
|
1099
|
+
* Format a profile's initials
|
|
1211
1100
|
*/
|
|
1212
|
-
const
|
|
1213
|
-
.put(`/templates/${templateId}/reminder/${reminderId}`, params)
|
|
1214
|
-
.then((r) => r.data);
|
|
1101
|
+
const formatInitials = (profile) => profile ? `${capitalize(profile.first_name).charAt(0)} ${capitalize(profile.last_name).charAt(0)}` : '--';
|
|
1215
1102
|
/**
|
|
1216
|
-
*
|
|
1103
|
+
* Generate suggested initials for a full name, e.g. "John Doe" will yield "JD".
|
|
1217
1104
|
*/
|
|
1218
|
-
const
|
|
1219
|
-
.
|
|
1220
|
-
.
|
|
1105
|
+
const fullNameToInitials = (name) => name
|
|
1106
|
+
.split(' ')
|
|
1107
|
+
.map((word) => word[0])
|
|
1108
|
+
.join('');
|
|
1221
1109
|
|
|
1222
1110
|
/**
|
|
1223
|
-
*
|
|
1224
|
-
* their names, which must be unique (e.g. 'Recipient 1'). Template fields are assigned to roles for signing operations,
|
|
1225
|
-
* so you may have 'Recipient 1 Signature 1' and so forth.
|
|
1111
|
+
* Create an envelope
|
|
1226
1112
|
*
|
|
1227
|
-
*
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
*
|
|
1113
|
+
* ```typescript
|
|
1114
|
+
* import {Envelopes, ICreateEnvelopeRole, ICreateEnvelopeRequest} from '@verdocs/js-sdk/Envelopes';
|
|
1115
|
+
*
|
|
1116
|
+
* const role1: ICreateEnvelopeRole = {
|
|
1117
|
+
* type: 'signer',
|
|
1118
|
+
* name: 'Seller',
|
|
1119
|
+
* full_name: 'Paige Turner',
|
|
1120
|
+
* email: 'paige.turner@nomail.com',
|
|
1121
|
+
* phone: '',
|
|
1122
|
+
* sequence: 1,
|
|
1123
|
+
* delegator: false,
|
|
1124
|
+
* message: '',
|
|
1125
|
+
* };
|
|
1126
|
+
*
|
|
1127
|
+
* const role2: ICreateEnvelopeRole = {
|
|
1128
|
+
* type: 'signer',
|
|
1129
|
+
* name: 'Buyer',
|
|
1130
|
+
* full_name: 'Will Power',
|
|
1131
|
+
* email: 'will.power@nomail.com',
|
|
1132
|
+
* phone: '',
|
|
1133
|
+
* sequence: 2,
|
|
1134
|
+
* delegator: false,
|
|
1135
|
+
* message: '',
|
|
1136
|
+
* };
|
|
1137
|
+
*
|
|
1138
|
+
* const request: ICreateEnvelopeRequest = {template_id: 'd2338742-f3a1-465b-8592-806587413cc1', name: 'Bill of Sale', roles: [role1, role2]};
|
|
1139
|
+
* const {id, recipients} = await Envelopes.createEnvelope(VerdocsEndpoint.getDefault(), request);
|
|
1140
|
+
* ```
|
|
1250
1141
|
*/
|
|
1251
|
-
const
|
|
1252
|
-
.
|
|
1142
|
+
const createEnvelope = async (endpoint, request) => endpoint.api //
|
|
1143
|
+
.post('/envelopes', request)
|
|
1253
1144
|
.then((r) => r.data);
|
|
1254
1145
|
/**
|
|
1255
|
-
*
|
|
1146
|
+
* Get a summary of currently active envelopes.
|
|
1147
|
+
*
|
|
1148
|
+
* ```typescript
|
|
1149
|
+
* import {Envelopes} from '@verdocs/js-sdk/Envelopes';
|
|
1150
|
+
*
|
|
1151
|
+
* const {action_required, completed, waiting_on_others} = await Envelopes.getSummary(VerdocsEndpoint.getDefault());
|
|
1152
|
+
* ```
|
|
1256
1153
|
*/
|
|
1257
|
-
const
|
|
1258
|
-
.post(
|
|
1154
|
+
const getEnvelopesSummary = async (endpoint, page) => endpoint.api //
|
|
1155
|
+
.post('/envelopes/summary', { page })
|
|
1259
1156
|
.then((r) => r.data);
|
|
1260
|
-
|
|
1261
1157
|
/**
|
|
1262
|
-
*
|
|
1263
|
-
* recipients. Every Organization has a set of tags "owned" by that Organization and only visible inside it.
|
|
1264
|
-
* Verdocs also provides a set of system-wide "featured" tags available to all Organizations.
|
|
1158
|
+
* Search for envelopes matching various criteria.
|
|
1265
1159
|
*
|
|
1266
|
-
*
|
|
1160
|
+
* ```typescript
|
|
1161
|
+
* import {Envelopes} from '@verdocs/js-sdk/Envelopes';
|
|
1162
|
+
*
|
|
1163
|
+
* const {result, page, total} = await Envelopes.search(VerdocsEndpoint.getDefault(), { ... });
|
|
1164
|
+
* ```
|
|
1267
1165
|
*/
|
|
1166
|
+
const searchEnvelopes = async (endpoint, params) => endpoint.api //
|
|
1167
|
+
.post('/envelopes/search', params)
|
|
1168
|
+
.then((r) => r.data);
|
|
1268
1169
|
/**
|
|
1269
|
-
*
|
|
1170
|
+
* Get a signing session for an Envelope.
|
|
1270
1171
|
*/
|
|
1271
|
-
const
|
|
1272
|
-
.
|
|
1273
|
-
.
|
|
1172
|
+
const getSigningSession = async (endpoint, params) => {
|
|
1173
|
+
window.console.log('[JS_SDK] getSigningSession', params, endpoint.api);
|
|
1174
|
+
return endpoint.api //
|
|
1175
|
+
.get(`/envelopes/${params.envelopeId}/recipients/${encodeURIComponent(params.roleId)}/invitation/${params.inviteCode}`)
|
|
1176
|
+
.then((r) => {
|
|
1177
|
+
// Avoiding a jsonwebtoken dependency here - we don't actually need the whole library
|
|
1178
|
+
const signerToken = r.headers?.signer_token || '';
|
|
1179
|
+
const session = decodeAccessTokenBody(signerToken);
|
|
1180
|
+
endpoint.setToken(signerToken);
|
|
1181
|
+
return { recipient: r.data, session, signerToken };
|
|
1182
|
+
});
|
|
1183
|
+
};
|
|
1274
1184
|
/**
|
|
1275
|
-
* Get
|
|
1185
|
+
* Get the list of recipients for an Envelope.
|
|
1276
1186
|
*/
|
|
1277
|
-
const
|
|
1278
|
-
.get(`/
|
|
1187
|
+
const getEnvelopeRecipients = async (endpoint, envelopeId) => endpoint.api //
|
|
1188
|
+
.get(`/envelopes/${envelopeId}/recipients`)
|
|
1279
1189
|
.then((r) => r.data);
|
|
1280
1190
|
/**
|
|
1281
|
-
*
|
|
1191
|
+
* Get all metadata for an Envelope.
|
|
1282
1192
|
*/
|
|
1283
|
-
const
|
|
1284
|
-
.
|
|
1193
|
+
const getEnvelope = async (endpoint, envelopeId) => endpoint.api //
|
|
1194
|
+
.get(`/envelopes/${envelopeId}`)
|
|
1285
1195
|
.then((r) => r.data);
|
|
1286
1196
|
/**
|
|
1287
|
-
*
|
|
1197
|
+
* Get an Envelope Document
|
|
1288
1198
|
*/
|
|
1289
|
-
const
|
|
1290
|
-
.
|
|
1199
|
+
const getEnvelopeDocument = async (endpoint, envelopeId, documentId) => endpoint.api //
|
|
1200
|
+
.get(`/envelopes/${envelopeId}/envelope_documents/${documentId}`)
|
|
1291
1201
|
.then((r) => r.data);
|
|
1292
1202
|
/**
|
|
1293
|
-
* Get
|
|
1203
|
+
* Get a pre-signed download link for an Envelope Document. This link expires quickly, so it should
|
|
1204
|
+
* be accessed immediately and never shared. Content-Disposition will be set to "download".
|
|
1294
1205
|
*/
|
|
1295
|
-
const
|
|
1296
|
-
.get(`/
|
|
1206
|
+
const getDocumentDownloadLink = async (endpoint, envelopeId, documentId) => endpoint.api //
|
|
1207
|
+
.get(`/envelopes/${envelopeId}/envelope_documents/${documentId}?download=true`)
|
|
1297
1208
|
.then((r) => r.data);
|
|
1298
1209
|
/**
|
|
1299
|
-
* Get
|
|
1210
|
+
* Get a pre-signed preview link for an Envelope Document. This link expires quickly, so it should
|
|
1211
|
+
* be accessed immediately and never shared. Content-Disposition will be set to "inline".
|
|
1300
1212
|
*/
|
|
1301
|
-
const
|
|
1302
|
-
.get(
|
|
1213
|
+
const getDocumentPreviewLink = async (endpoint, envelopeId, documentId) => endpoint.api //
|
|
1214
|
+
.get(`/envelopes/${envelopeId}/envelope_documents/${documentId}?preview=true`)
|
|
1303
1215
|
.then((r) => r.data);
|
|
1304
|
-
|
|
1305
1216
|
/**
|
|
1306
|
-
*
|
|
1307
|
-
* recipients.
|
|
1308
|
-
*
|
|
1309
|
-
* @module
|
|
1217
|
+
* Cancel an Envelope.
|
|
1310
1218
|
*/
|
|
1219
|
+
const cancelEnvelope = async (endpoint, envelopeId) => endpoint.api //
|
|
1220
|
+
.put(`/envelopes/${envelopeId}`, { action: 'cancel' })
|
|
1221
|
+
.then((r) => r.data);
|
|
1311
1222
|
/**
|
|
1312
|
-
* Get
|
|
1313
|
-
*
|
|
1314
|
-
*
|
|
1315
|
-
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
1316
|
-
*
|
|
1317
|
-
* await Templates.getTemplates((VerdocsEndpoint.getDefault());
|
|
1318
|
-
* await Templates.getTemplates((VerdocsEndpoint.getDefault(), { is_starred: true });
|
|
1319
|
-
* await Templates.getTemplates((VerdocsEndpoint.getDefault(), { is_creator: true });
|
|
1320
|
-
* await Templates.getTemplates((VerdocsEndpoint.getDefault(), { is_organization: true });
|
|
1321
|
-
* ```
|
|
1223
|
+
* Get (binary download) a file attached to an Envelope. It is important to use this method
|
|
1224
|
+
* rather than a direct A HREF or similar link to set the authorization headers for the
|
|
1225
|
+
* request.
|
|
1322
1226
|
*/
|
|
1323
|
-
const
|
|
1324
|
-
.
|
|
1227
|
+
const getEnvelopeFile = async (endpoint, envelopeId, documentId) => endpoint.api //
|
|
1228
|
+
.get(`/envelopes/${envelopeId}/envelope_documents/${documentId}?file=true`, { responseType: 'blob' })
|
|
1325
1229
|
.then((r) => r.data);
|
|
1326
|
-
// export interface IListTemplatesParams {
|
|
1327
|
-
// name?: string;
|
|
1328
|
-
// sharing?: 'all' | 'personal' | 'shared' | 'public';
|
|
1329
|
-
// starred?: 'all' | 'starred' | 'unstarred';
|
|
1330
|
-
// sort?: 'name' | 'created_at' | 'updated_at' | 'last_used_at' | 'counter' | 'star_counter';
|
|
1331
|
-
// direction?: 'asc' | 'desc';
|
|
1332
|
-
// page?: number;
|
|
1333
|
-
// rows?: number;
|
|
1334
|
-
// }
|
|
1335
1230
|
/**
|
|
1336
|
-
*
|
|
1337
|
-
*
|
|
1338
|
-
* ```typescript
|
|
1339
|
-
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
1340
|
-
*
|
|
1341
|
-
* await Templates.listTemplates((VerdocsEndpoint.getDefault(), { sharing: 'personal', sort: 'last_used_at' });
|
|
1342
|
-
* ```
|
|
1231
|
+
* Update a Document field. Typically called during the signing process as a Recipient fills in fields.
|
|
1343
1232
|
*/
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
// .then((r) => r.data);
|
|
1233
|
+
const updateEnvelopeField = async (endpoint, envelopeId, fieldName, value) => endpoint.api //
|
|
1234
|
+
.put(`/envelopes/${envelopeId}/fields/${fieldName}`, value)
|
|
1235
|
+
.then((r) => r.data);
|
|
1348
1236
|
/**
|
|
1349
|
-
*
|
|
1350
|
-
*
|
|
1351
|
-
* ```typescript
|
|
1352
|
-
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
1353
|
-
*
|
|
1354
|
-
* const template = await Templates.getTemplate((VerdocsEndpoint.getDefault(), '83da3d70-7857-4392-b876-c4592a304bc9');
|
|
1355
|
-
* ```
|
|
1237
|
+
* Update a Document signature field. Signature fields are ID-driven. Call `Document.createSignature()` first to create a
|
|
1238
|
+
* signature for a Recipient, then call `Documents.updateDocumentFieldSignature()` to attach it to a field.
|
|
1356
1239
|
*/
|
|
1357
|
-
const
|
|
1358
|
-
.
|
|
1240
|
+
const updateEnvelopeFieldSignature = async (endpoint, envelopeId, fieldName, signatureId) => endpoint.api //
|
|
1241
|
+
.put(`/envelopes/${envelopeId}/fields/${fieldName}/signature/${signatureId}`)
|
|
1359
1242
|
.then((r) => r.data);
|
|
1360
1243
|
/**
|
|
1361
|
-
*
|
|
1362
|
-
*
|
|
1363
|
-
* ```typescript
|
|
1364
|
-
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
1365
|
-
*
|
|
1366
|
-
* const template = await Templates.getTemplateOwnerInfo((VerdocsEndpoint.getDefault(), '83da3d70-7857-4392-b876-c4592a304bc9');
|
|
1367
|
-
* ```
|
|
1244
|
+
* Update a Document signature field. Signature fields are ID-driven. Call `Document.createSignature()` first to create a
|
|
1245
|
+
* signature for a Recipient, then call `Documents.updateDocumentFieldSignature()` to attach it to a field.
|
|
1368
1246
|
*/
|
|
1369
|
-
const
|
|
1370
|
-
.
|
|
1247
|
+
const updateEnvelopeFieldInitials = async (endpoint, envelopeId, fieldName, initialId) => endpoint.api //
|
|
1248
|
+
.put(`/envelopes/${envelopeId}/fields/${fieldName}/initial/${initialId}`)
|
|
1371
1249
|
.then((r) => r.data);
|
|
1372
|
-
const ALLOWED_CREATE_FIELDS = [
|
|
1373
|
-
'name',
|
|
1374
|
-
'is_personal',
|
|
1375
|
-
'is_public',
|
|
1376
|
-
'sender',
|
|
1377
|
-
'description',
|
|
1378
|
-
'roles',
|
|
1379
|
-
'fields',
|
|
1380
|
-
];
|
|
1381
1250
|
/**
|
|
1382
|
-
*
|
|
1383
|
-
*
|
|
1384
|
-
* ```typescript
|
|
1385
|
-
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
1386
|
-
*
|
|
1387
|
-
* const newTemplate = await Templates.createTemplate((VerdocsEndpoint.getDefault(), {...});
|
|
1388
|
-
* ```
|
|
1251
|
+
* Upload an attachment.
|
|
1389
1252
|
*/
|
|
1390
|
-
const
|
|
1391
|
-
const
|
|
1253
|
+
const uploadEnvelopeFieldAttachment = async (endpoint, envelopeId, fieldName, file, onUploadProgress) => {
|
|
1254
|
+
const formData = new FormData();
|
|
1255
|
+
formData.append('document', file, file.name);
|
|
1256
|
+
return endpoint.api //
|
|
1257
|
+
.put(`/envelopes/${envelopeId}/fields/${fieldName}`, formData, {
|
|
1392
1258
|
timeout: 120000,
|
|
1393
1259
|
onUploadProgress: (event) => {
|
|
1394
1260
|
const total = event.total || 1;
|
|
1395
1261
|
const loaded = event.loaded || 0;
|
|
1396
1262
|
onUploadProgress?.(Math.floor((loaded * 100) / (total || 1)), loaded, total || 1);
|
|
1397
1263
|
},
|
|
1398
|
-
}
|
|
1399
|
-
|
|
1400
|
-
if (params.documents.length > 10) {
|
|
1401
|
-
throw new Error('createTemplate() has a maximum of 10 documents that can be attached.');
|
|
1402
|
-
}
|
|
1403
|
-
const formData = new FormData();
|
|
1404
|
-
ALLOWED_CREATE_FIELDS.forEach((allowedKey) => {
|
|
1405
|
-
if (params[allowedKey] !== undefined) {
|
|
1406
|
-
formData.append(allowedKey, params[allowedKey]);
|
|
1407
|
-
}
|
|
1408
|
-
});
|
|
1409
|
-
params.documents.forEach((file) => {
|
|
1410
|
-
formData.append('documents', file, file.name);
|
|
1411
|
-
});
|
|
1412
|
-
return endpoint.api.post('/templates', formData, options).then((r) => r.data);
|
|
1413
|
-
}
|
|
1414
|
-
else {
|
|
1415
|
-
return endpoint.api.post('/templates', params, options).then((r) => r.data);
|
|
1416
|
-
}
|
|
1264
|
+
})
|
|
1265
|
+
.then((r) => r.data);
|
|
1417
1266
|
};
|
|
1418
1267
|
/**
|
|
1419
|
-
*
|
|
1420
|
-
*
|
|
1421
|
-
* ```typescript
|
|
1422
|
-
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
1423
|
-
*
|
|
1424
|
-
* const newTemplate = await Templates.createTemplatev2((VerdocsEndpoint.getDefault(), {...});
|
|
1425
|
-
* ```
|
|
1268
|
+
* Delete an attachment.
|
|
1426
1269
|
*/
|
|
1427
|
-
const
|
|
1428
|
-
const
|
|
1270
|
+
const deleteEnvelopeFieldAttachment = async (endpoint, envelopeId, fieldName, file, onUploadProgress) => {
|
|
1271
|
+
const formData = new FormData();
|
|
1272
|
+
// Omitting file is the trigger here
|
|
1273
|
+
return endpoint.api //
|
|
1274
|
+
.put(`/envelopes/${envelopeId}/fields/${fieldName}`, formData, {
|
|
1429
1275
|
timeout: 120000,
|
|
1430
1276
|
onUploadProgress: (event) => {
|
|
1431
1277
|
const total = event.total || 1;
|
|
1432
1278
|
const loaded = event.loaded || 0;
|
|
1433
1279
|
onUploadProgress?.(Math.floor((loaded * 100) / (total || 1)), loaded, total || 1);
|
|
1434
1280
|
},
|
|
1435
|
-
}
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1281
|
+
})
|
|
1282
|
+
.then((r) => r.data);
|
|
1283
|
+
};
|
|
1284
|
+
/**
|
|
1285
|
+
* Get the attached file for an attachment field (if any)
|
|
1286
|
+
*/
|
|
1287
|
+
const getFieldAttachment = async (endpoint, envelopeId, fieldName) => endpoint.api //
|
|
1288
|
+
.get(`/envelopes/${envelopeId}/fields/${fieldName}/document`, { responseType: 'blob' })
|
|
1289
|
+
.then((r) => r.data);
|
|
1290
|
+
/**
|
|
1291
|
+
* Get a display URI for a given page in a file attached to an envelope document. These pages are rendered server-side
|
|
1292
|
+
* into PNG resources suitable for display in IMG tags although they may be used elsewhere. Note that these are intended
|
|
1293
|
+
* for DISPLAY ONLY, are not legally binding documents, and do not contain any encoded metadata from participants.
|
|
1294
|
+
*/
|
|
1295
|
+
const getEnvelopeDocumentPageDisplayUri = async (endpoint, envelopeId, documentId, page, type = 'original') => endpoint.api
|
|
1296
|
+
.get(`/envelopes/${envelopeId}/envelope_documents/${documentId}/pages/${page}/image?type=${type}`, { timeout: 20000 })
|
|
1297
|
+
.then((r) => r.data);
|
|
1298
|
+
const cachedEnvelopes = {};
|
|
1299
|
+
/**
|
|
1300
|
+
* Wrapper for `getEnvelope()` that limits queries to one every 2 seconds per template ID.
|
|
1301
|
+
* This is intended for use in component hierarchies that all rely on the same template
|
|
1302
|
+
* to avoid unnecessary repeat server calls.
|
|
1303
|
+
*/
|
|
1304
|
+
const throttledGetEnvelope = (endpoint, envelopeId) => {
|
|
1305
|
+
if (cachedEnvelopes[envelopeId] && cachedEnvelopes[envelopeId].loaded + 2000 < new Date().getTime()) {
|
|
1306
|
+
return cachedEnvelopes[envelopeId].envelope;
|
|
1450
1307
|
}
|
|
1308
|
+
return getEnvelope(endpoint, envelopeId).then((envelope) => {
|
|
1309
|
+
cachedEnvelopes[envelopeId] = { loaded: new Date().getTime(), envelope };
|
|
1310
|
+
return envelope;
|
|
1311
|
+
});
|
|
1312
|
+
};
|
|
1313
|
+
/**a
|
|
1314
|
+
* Lists all envelopes accessible by the caller, with optional filters.
|
|
1315
|
+
*
|
|
1316
|
+
* ```typescript
|
|
1317
|
+
* import {Envelopes} from '@verdocs/js-sdk/Envelopes';
|
|
1318
|
+
*
|
|
1319
|
+
* const {totals, envelopes} = await Envelopes.listEnvelopes((VerdocsEndpoint.getDefault(), { q: 'test', sort: 'created_at' });
|
|
1320
|
+
* ```
|
|
1321
|
+
*/
|
|
1322
|
+
const listEnvelopes = (endpoint, params) => endpoint.api //
|
|
1323
|
+
.post('/envelopes/list', params)
|
|
1324
|
+
.then((r) => r.data);
|
|
1325
|
+
/**
|
|
1326
|
+
* Get all of the envelopes that were sent using a given template.
|
|
1327
|
+
* NOTE: This endpoint will be retired soon. Its response is not paginated and it is typically used only to retrieve
|
|
1328
|
+
* "submitted data" for a template. A new endpoint will be introduced to provide this function more directly.
|
|
1329
|
+
* @deprecated
|
|
1330
|
+
*/
|
|
1331
|
+
const getEnvelopesByTemplateId = async (endpoint, templateId) => endpoint.api //
|
|
1332
|
+
.get(`/envelopes?template_id=${templateId}`)
|
|
1333
|
+
.then((r) => r.data);
|
|
1334
|
+
|
|
1335
|
+
/**
|
|
1336
|
+
* Create an initials block. In a typical signing workflow, the user is asked at the beginning of the process to "adopt"
|
|
1337
|
+
* an initials block to be used for all initials fields in the document. Thus, this is typically called one time to
|
|
1338
|
+
* create and store an initials block. Thereafter, the ID of the initials block may be re-used for each initials field
|
|
1339
|
+
* to be "stamped" by the user.
|
|
1340
|
+
*/
|
|
1341
|
+
const createInitials = (endpoint, name, initials) => {
|
|
1342
|
+
const data = new FormData();
|
|
1343
|
+
data.append('initial', initials, name);
|
|
1344
|
+
return endpoint.api //
|
|
1345
|
+
.post(`/initials`, data)
|
|
1346
|
+
.then((r) => r.data);
|
|
1451
1347
|
};
|
|
1348
|
+
|
|
1349
|
+
/**
|
|
1350
|
+
* Update a recipient's status block
|
|
1351
|
+
*/
|
|
1352
|
+
const updateRecipient = async (endpoint, envelopeId, roleName, params) => endpoint.api //
|
|
1353
|
+
.put(`/envelopes/${envelopeId}/recipients/${roleName}`, params)
|
|
1354
|
+
.then((r) => r.data);
|
|
1355
|
+
/**
|
|
1356
|
+
* Submit an envelope (signing is finished). Note that all fields must be valid/completed for this to succeed.
|
|
1357
|
+
*/
|
|
1358
|
+
const envelopeRecipientSubmit = (endpoint, envelopeId, roleName) => updateRecipient(endpoint, envelopeId, roleName, { action: 'submit' });
|
|
1359
|
+
/**
|
|
1360
|
+
* Decline to complete an envelope (signing will not terminated).
|
|
1361
|
+
*/
|
|
1362
|
+
const envelopeRecipientDecline = (endpoint, envelopeId, roleName) => updateRecipient(endpoint, envelopeId, roleName, { action: 'decline' });
|
|
1363
|
+
/**
|
|
1364
|
+
* Claim / change ownership of an envelope. This is a special-case operation only available in certain workflows.
|
|
1365
|
+
*/
|
|
1366
|
+
const envelopeRecipientChangeOwner = (endpoint, envelopeId, roleName, email, fullName) => updateRecipient(endpoint, envelopeId, roleName, { action: 'owner_update', email, full_name: fullName });
|
|
1367
|
+
/**
|
|
1368
|
+
* Agree to electronic signing.
|
|
1369
|
+
*/
|
|
1370
|
+
const envelopeRecipientAgree = (endpoint, envelopeId, roleName, agreed) => updateRecipient(endpoint, envelopeId, roleName, { action: 'update', agreed });
|
|
1452
1371
|
/**
|
|
1453
|
-
*
|
|
1454
|
-
*
|
|
1455
|
-
* ```typescript
|
|
1456
|
-
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
1457
|
-
*
|
|
1458
|
-
* const newTemplate = await Templates.createTemplateFromSharepoint((VerdocsEndpoint.getDefault(), {...});
|
|
1459
|
-
* ```
|
|
1372
|
+
* Change a recipient's name.
|
|
1460
1373
|
*/
|
|
1461
|
-
const
|
|
1462
|
-
const options = {
|
|
1463
|
-
timeout: 120000,
|
|
1464
|
-
};
|
|
1465
|
-
return endpoint.api.post('/templates/from-sharepoint', params, options).then((r) => r.data);
|
|
1466
|
-
};
|
|
1374
|
+
const envelopeRecipientUpdateName = (endpoint, envelopeId, roleName, fullName) => updateRecipient(endpoint, envelopeId, roleName, { action: 'update', new_full_name: fullName });
|
|
1467
1375
|
/**
|
|
1468
|
-
*
|
|
1469
|
-
*
|
|
1470
|
-
* ```typescript
|
|
1471
|
-
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
1472
|
-
*
|
|
1473
|
-
* const updatedTemplate = await Templates.updateTemplate((VerdocsEndpoint.getDefault(), '83da3d70-7857-4392-b876-c4592a304bc9', { name: 'New Name' });
|
|
1474
|
-
* ```
|
|
1376
|
+
* Change a recipient's name.
|
|
1475
1377
|
*/
|
|
1476
|
-
const
|
|
1477
|
-
|
|
1378
|
+
const envelopeRecipientPrepare = (endpoint, envelopeId, roleName, recipients) => updateRecipient(endpoint, envelopeId, roleName, { action: 'prepare', recipients });
|
|
1379
|
+
/**
|
|
1380
|
+
* Get a signing token.
|
|
1381
|
+
*/
|
|
1382
|
+
const getSignerToken = (endpoint, envelopeId, roleName) => endpoint.api //
|
|
1383
|
+
.get(`/envelopes/${envelopeId}/recipients/${encodeURIComponent(roleName)}/signer-token`)
|
|
1478
1384
|
.then((r) => r.data);
|
|
1479
1385
|
/**
|
|
1480
|
-
*
|
|
1481
|
-
*
|
|
1482
|
-
* ```typescript
|
|
1483
|
-
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
1484
|
-
*
|
|
1485
|
-
* await Templates.deleteTemplate((VerdocsEndpoint.getDefault(), '83da3d70-7857-4392-b876-c4592a304bc9');
|
|
1486
|
-
* ```
|
|
1386
|
+
* Get an in-person signing link.
|
|
1487
1387
|
*/
|
|
1488
|
-
const
|
|
1489
|
-
.
|
|
1388
|
+
const getInPersonLink = (endpoint, envelopeId, roleName) => endpoint.api //
|
|
1389
|
+
.get(`/envelopes/${envelopeId}/recipients/${encodeURIComponent(roleName)}?in_person_link=true`)
|
|
1490
1390
|
.then((r) => r.data);
|
|
1491
1391
|
/**
|
|
1492
|
-
*
|
|
1493
|
-
*
|
|
1494
|
-
* ```typescript
|
|
1495
|
-
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
1496
|
-
*
|
|
1497
|
-
* const {result, page, total} = await Templates.search((VerdocsEndpoint.getDefault(), { ... });
|
|
1498
|
-
* ```
|
|
1392
|
+
* Send a delegation request.
|
|
1499
1393
|
*/
|
|
1500
|
-
const
|
|
1501
|
-
.post(
|
|
1394
|
+
const sendDelegate = (endpoint, envelopeId, roleName) => endpoint.api //
|
|
1395
|
+
.post(`/envelopes/${envelopeId}/recipients/${encodeURIComponent(roleName)}/delegate`)
|
|
1502
1396
|
.then((r) => r.data);
|
|
1503
1397
|
/**
|
|
1504
|
-
*
|
|
1505
|
-
*
|
|
1506
|
-
* ```typescript
|
|
1507
|
-
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
1508
|
-
*
|
|
1509
|
-
* const summary = await Templates.getSummary((VerdocsEndpoint.getDefault(), 0);
|
|
1510
|
-
* ```
|
|
1398
|
+
* Resend a recipient's invitation.
|
|
1511
1399
|
*/
|
|
1512
|
-
const
|
|
1513
|
-
.post(
|
|
1400
|
+
const resendInvitation = (endpoint, envelopeId, roleName) => endpoint.api //
|
|
1401
|
+
.post(`/envelopes/${envelopeId}/recipients/${encodeURIComponent(roleName)}/resend_invitation`)
|
|
1514
1402
|
.then((r) => r.data);
|
|
1515
|
-
|
|
1403
|
+
|
|
1516
1404
|
/**
|
|
1517
|
-
*
|
|
1518
|
-
*
|
|
1519
|
-
* to avoid unnecessary repeat server calls.
|
|
1405
|
+
* Enable automatic reminders. setup_time is the number of days after the envelope is sent that the first reminder
|
|
1406
|
+
* should be sent. interval_time is the number of days between reminders.
|
|
1520
1407
|
*/
|
|
1521
|
-
const
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
}
|
|
1525
|
-
return getTemplate(endpoint, templateId).then((template) => {
|
|
1526
|
-
cachedTemplates[templateId] = { loaded: new Date().getTime(), template };
|
|
1527
|
-
return template;
|
|
1528
|
-
});
|
|
1529
|
-
};
|
|
1408
|
+
const createEnvelopeReminder = (endpoint, envelopeId, params) => endpoint.api //
|
|
1409
|
+
.post(`/envelopes/${envelopeId}/reminder/`, params)
|
|
1410
|
+
.then((r) => r.data);
|
|
1530
1411
|
/**
|
|
1531
|
-
*
|
|
1532
|
-
*
|
|
1533
|
-
* ```typescript
|
|
1534
|
-
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
1535
|
-
*
|
|
1536
|
-
* const {totals, templates} = await Templates.listTemplates((VerdocsEndpoint.getDefault(), { q: 'test', sort: 'created_at' }); * ```
|
|
1412
|
+
* Get the reminder configuration for an envelope.
|
|
1537
1413
|
*/
|
|
1538
|
-
const
|
|
1539
|
-
.
|
|
1414
|
+
const getEnvelopeReminder = (endpoint, envelopeId, reminderId) => endpoint.api //
|
|
1415
|
+
.get(`/envelopes/${envelopeId}/reminder/${reminderId}`)
|
|
1416
|
+
.then((r) => r.data);
|
|
1417
|
+
/**
|
|
1418
|
+
* Update the reminder configuration for an envelope.
|
|
1419
|
+
*/
|
|
1420
|
+
const updateEnvelopeReminder = (endpoint, envelopeId, reminderId, params) => endpoint.api //
|
|
1421
|
+
.put(`/envelopes/${envelopeId}/reminder/${reminderId}`, params)
|
|
1422
|
+
.then((r) => r.data);
|
|
1423
|
+
/**
|
|
1424
|
+
* Delete the reminder configuration for an envelope.
|
|
1425
|
+
*/
|
|
1426
|
+
const deleteEnvelopeReminder = (endpoint, envelopeId, reminderId) => endpoint.api //
|
|
1427
|
+
.delete(`/envelopes/${envelopeId}/reminder/${reminderId}`)
|
|
1540
1428
|
.then((r) => r.data);
|
|
1541
1429
|
|
|
1542
1430
|
/**
|
|
1543
|
-
*
|
|
1431
|
+
* Various helpers to identify available operations for an envelope by a user.
|
|
1544
1432
|
*
|
|
1545
1433
|
* @module
|
|
1546
1434
|
*/
|
|
1547
1435
|
/**
|
|
1548
|
-
*
|
|
1549
|
-
*
|
|
1550
|
-
* ```typescript
|
|
1551
|
-
* import {TemplateDocument} from '@verdocs/js-sdk/Templates';
|
|
1552
|
-
*
|
|
1553
|
-
* await TemplateDocument.geTemplateDocuments((VerdocsEndpoint.getDefault(), templateId);
|
|
1554
|
-
* ```
|
|
1436
|
+
* Check to see if the user owns the envelope.
|
|
1555
1437
|
*/
|
|
1556
|
-
const
|
|
1557
|
-
.get(`/templates/${templateId}/documents/`)
|
|
1558
|
-
.then((r) => r.data);
|
|
1438
|
+
const userIsEnvelopeOwner = (session, envelope) => envelope.profile_id === session?.profile_id;
|
|
1559
1439
|
/**
|
|
1560
|
-
*
|
|
1561
|
-
*
|
|
1562
|
-
* ```typescript
|
|
1563
|
-
* import {TemplateDocument} from '@verdocs/js-sdk/Templates';
|
|
1564
|
-
*
|
|
1565
|
-
* await TemplateDocument.geTemplateDocument((VerdocsEndpoint.getDefault(), templateId,documentId);
|
|
1566
|
-
* ```
|
|
1440
|
+
* Check to see if the user owns the envelope.
|
|
1567
1441
|
*/
|
|
1568
|
-
const
|
|
1569
|
-
.get(`/templates/${templateId}/documents/${documentId}`)
|
|
1570
|
-
.then((r) => r.data);
|
|
1442
|
+
const userIsEnvelopeRecipient = (session, envelope) => envelope.profile_id === session?.profile_id;
|
|
1571
1443
|
/**
|
|
1572
|
-
*
|
|
1573
|
-
*
|
|
1574
|
-
* ```typescript
|
|
1575
|
-
* import {TemplateDocument} from '@verdocs/js-sdk/Templates';
|
|
1576
|
-
*
|
|
1577
|
-
* await TemplateDocument.createDocument((VerdocsEndpoint.getDefault(), templateID, params);
|
|
1578
|
-
* ```
|
|
1444
|
+
* Check to see if the envelope has pending actions.
|
|
1579
1445
|
*/
|
|
1580
|
-
const
|
|
1581
|
-
const formData = new FormData();
|
|
1582
|
-
formData.append('document', file, file.name);
|
|
1583
|
-
return endpoint.api //
|
|
1584
|
-
.post(`/templates/${templateId}/documents`, formData, {
|
|
1585
|
-
timeout: 120000,
|
|
1586
|
-
onUploadProgress: (event) => {
|
|
1587
|
-
const total = event.total || 1;
|
|
1588
|
-
const loaded = event.loaded || 0;
|
|
1589
|
-
onUploadProgress?.(Math.floor((loaded * 100) / (total || 1)), loaded, total || 1);
|
|
1590
|
-
},
|
|
1591
|
-
})
|
|
1592
|
-
.then((r) => r.data);
|
|
1593
|
-
};
|
|
1446
|
+
const envelopeIsActive = (envelope) => envelope.status !== 'complete' && envelope.status !== 'declined' && envelope.status !== 'canceled';
|
|
1594
1447
|
/**
|
|
1595
|
-
*
|
|
1596
|
-
*
|
|
1597
|
-
* ```typescript
|
|
1598
|
-
* import {TemplateDocument} from '@verdocs/js-sdk/Templates';
|
|
1599
|
-
*
|
|
1600
|
-
* await TemplateDocument.deleteDocument((VerdocsEndpoint.getDefault(), templateID, documentID);
|
|
1601
|
-
* ```
|
|
1448
|
+
* Check to see if the envelope has been completed.
|
|
1602
1449
|
*/
|
|
1603
|
-
const
|
|
1604
|
-
.delete(`/templates/${templateId}/documents/${documentId}`)
|
|
1605
|
-
.then((r) => r.data);
|
|
1450
|
+
const envelopeIsComplete = (envelope) => envelope.status !== 'complete';
|
|
1606
1451
|
/**
|
|
1607
|
-
*
|
|
1608
|
-
* rather than a direct A HREF or similar link to set the authorization headers for the
|
|
1609
|
-
* request.
|
|
1452
|
+
* Check to see if the user owns the envelope.
|
|
1610
1453
|
*/
|
|
1611
|
-
const
|
|
1612
|
-
.
|
|
1613
|
-
.
|
|
1454
|
+
const userCanCancelEnvelope = (session, envelope) => userIsEnvelopeOwner(session, envelope) &&
|
|
1455
|
+
envelope.status !== 'complete' &&
|
|
1456
|
+
envelope.status !== 'declined' &&
|
|
1457
|
+
envelope.status !== 'canceled';
|
|
1614
1458
|
/**
|
|
1615
|
-
*
|
|
1616
|
-
* rather than a direct A HREF or similar link to set the authorization headers for the
|
|
1617
|
-
* request.
|
|
1459
|
+
* Check to see if the user owns the envelope.
|
|
1618
1460
|
*/
|
|
1619
|
-
const
|
|
1620
|
-
.
|
|
1621
|
-
.
|
|
1461
|
+
const userCanFinishEnvelope = (session, envelope) => userIsEnvelopeOwner(session, envelope) &&
|
|
1462
|
+
envelope.status !== 'complete' &&
|
|
1463
|
+
envelope.status !== 'declined' &&
|
|
1464
|
+
envelope.status !== 'canceled';
|
|
1622
1465
|
/**
|
|
1623
|
-
*
|
|
1624
|
-
* into PNG resources suitable for display in IMG tags although they may be used elsewhere. Note that these are intended
|
|
1625
|
-
* for DISPLAY ONLY, are not legally binding documents, and do not contain any encoded metadata from participants. The
|
|
1626
|
-
* original asset may be obtained by calling `getTemplateDocumentFile()` or similar.
|
|
1466
|
+
* Returns true if the recipient has a pending action. Note that this does not necessarily mean the recipient can act (yet).
|
|
1627
1467
|
*/
|
|
1628
|
-
const
|
|
1468
|
+
const recipientHasAction = (recipient) => !['submitted', 'canceled', 'declined'].includes(recipient.status);
|
|
1469
|
+
/**
|
|
1470
|
+
* Returns the recipients who still have a pending action. Note that not all of these recipients may be able to act (yet).
|
|
1471
|
+
*/
|
|
1472
|
+
const getRecipientsWithActions = (envelope) => (envelope?.recipients || []).filter(recipientHasAction);
|
|
1473
|
+
/**
|
|
1474
|
+
* Returns true if the recipient can act.
|
|
1475
|
+
*/
|
|
1476
|
+
const recipientCanAct = (recipient, recipientsWithActions) => recipient.sequence === recipientsWithActions?.[0]?.sequence;
|
|
1477
|
+
/**
|
|
1478
|
+
* Returns true if the user can act.
|
|
1479
|
+
*/
|
|
1480
|
+
const userCanAct = (email, recipientsWithActions) => {
|
|
1481
|
+
const recipient = recipientsWithActions.find((r) => r.email === email);
|
|
1482
|
+
return recipient && recipient.sequence === recipientsWithActions?.[0]?.sequence;
|
|
1483
|
+
};
|
|
1484
|
+
/**
|
|
1485
|
+
* Returns true if the user can act.
|
|
1486
|
+
*/
|
|
1487
|
+
const userCanSignNow = (session, envelope) => {
|
|
1488
|
+
if (!session) {
|
|
1489
|
+
return false;
|
|
1490
|
+
}
|
|
1491
|
+
const recipientsWithActions = getRecipientsWithActions(envelope);
|
|
1492
|
+
const myRecipient = recipientsWithActions.find((r) => r.profile_id === session?.profile_id || r.email === session?.email);
|
|
1493
|
+
return (myRecipient &&
|
|
1494
|
+
envelopeIsActive(envelope) &&
|
|
1495
|
+
userIsEnvelopeRecipient(session, envelope) &&
|
|
1496
|
+
recipientCanAct(myRecipient, recipientsWithActions));
|
|
1497
|
+
};
|
|
1498
|
+
const getNextRecipient = (envelope) => {
|
|
1499
|
+
const recipientsWithActions = getRecipientsWithActions(envelope);
|
|
1500
|
+
return recipientsWithActions?.[0];
|
|
1501
|
+
};
|
|
1629
1502
|
|
|
1630
1503
|
/**
|
|
1631
|
-
*
|
|
1632
|
-
*
|
|
1633
|
-
*
|
|
1634
|
-
*
|
|
1635
|
-
*
|
|
1636
|
-
* await Documents.getDocuments(templateID);
|
|
1637
|
-
* ```
|
|
1504
|
+
* Create a signature block. In a typical signing workflow, the user is asked at the beginning of the process to "adopt"
|
|
1505
|
+
* a signature block to be used for all signature fields in the document. Thus, this is typically called one time to
|
|
1506
|
+
* create and store a signature block. Thereafter, the ID of the signature block may be re-used for each signature field
|
|
1507
|
+
* to be "stamped" by the user.
|
|
1638
1508
|
*/
|
|
1639
|
-
const
|
|
1640
|
-
|
|
1641
|
-
.
|
|
1642
|
-
|
|
1643
|
-
|
|
1509
|
+
const createSignature = (endpoint, name, signature) => {
|
|
1510
|
+
const data = new FormData();
|
|
1511
|
+
data.append('signature', signature, name);
|
|
1512
|
+
return endpoint.api //
|
|
1513
|
+
.post(`/signatures`, data)
|
|
1514
|
+
.then((r) => r.data);
|
|
1515
|
+
};
|
|
1516
|
+
/**
|
|
1517
|
+
* Get the availbable signatures for a user.
|
|
1518
|
+
*/
|
|
1519
|
+
const getSignatures = (endpoint) => endpoint.api //
|
|
1520
|
+
.get('/signatures')
|
|
1644
1521
|
.then((r) => r.data);
|
|
1645
|
-
const EMAIL_REGEX = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
|
1646
|
-
const isValidEmail = (email) => !!email && EMAIL_REGEX.test(email);
|
|
1647
|
-
// @see https://www.regextester.com/1978
|
|
1648
|
-
const PHONE_REGEX = /((?:\+|00)[17](?: |\-)?|(?:\+|00)[1-9]\d{0,2}(?: |\-)?|(?:\+|00)1\-\d{3}(?: |\-)?)?(0\d|\([0-9]{3}\)|[1-9]{0,3})(?:((?: |\-)[0-9]{2}){4}|((?:[0-9]{2}){4})|((?: |\-)[0-9]{3}(?: |\-)[0-9]{4})|([0-9]{7}))/;
|
|
1649
|
-
const isValidPhone = (phone) => !!phone && PHONE_REGEX.test(phone);
|
|
1650
|
-
const isValidRoleName = (value, roles) => roles.findIndex((role) => role.name === value) !== -1;
|
|
1651
|
-
const TagRegEx = /^[a-zA-Z0-9-]{0,32}$/;
|
|
1652
|
-
const isValidTag = (value, tags) => TagRegEx.test(value) || tags.findIndex((tag) => tag === value) !== -1;
|
|
1653
|
-
|
|
1654
1522
|
/**
|
|
1655
|
-
*
|
|
1656
|
-
*
|
|
1657
|
-
* ```typescript
|
|
1658
|
-
* import {Auth} from '@verdocs/js-sdk/Auth';
|
|
1659
|
-
* import {Transport} from '@verdocs/js-sdk/HTTP';
|
|
1660
|
-
*
|
|
1661
|
-
* const {accessToken} = await Auth.authenticateUser({ username: 'test@test.com', password: 'PASSWORD' });
|
|
1662
|
-
* Transport.setAuthToken(accessToken);
|
|
1663
|
-
* ```
|
|
1523
|
+
* Get a user's signature by ID.
|
|
1664
1524
|
*/
|
|
1665
|
-
const
|
|
1666
|
-
.
|
|
1525
|
+
const getSignature = (endpoint, signatureId) => endpoint.api //
|
|
1526
|
+
.get(`/signatures/${signatureId}`)
|
|
1667
1527
|
.then((r) => r.data);
|
|
1668
1528
|
/**
|
|
1669
|
-
*
|
|
1670
|
-
* NodeJS server-side applications. Never expose your Client Secret in a Web or Mobile app!** Also note
|
|
1671
|
-
* that access tokens may be cached by server-side apps (and this is recommended) but do expire after 2
|
|
1672
|
-
* hours. This expiration may change based on future security needs. Application developers are encouraged
|
|
1673
|
-
* to check the `exp` expiration field in the response accessToken and renew tokens after they expire.
|
|
1674
|
-
*
|
|
1675
|
-
* ```typescript
|
|
1676
|
-
* import {Auth} from '@verdocs/js-sdk/Auth';
|
|
1677
|
-
* import {Transport} from '@verdocs/js-sdk/HTTP';
|
|
1678
|
-
*
|
|
1679
|
-
* const {accessToken} = await Auth.authenticateApp({ client_id: 'CLIENTID', client_secret: 'SECRET' });
|
|
1680
|
-
* Transport.setAuthToken(accessToken);
|
|
1681
|
-
* ```
|
|
1529
|
+
* Delete a user's signature.
|
|
1682
1530
|
*/
|
|
1683
|
-
const
|
|
1684
|
-
.
|
|
1531
|
+
const deleteSignature = (endpoint, signatureId) => endpoint.api //
|
|
1532
|
+
.delete(`/signatures/${signatureId}`)
|
|
1685
1533
|
.then((r) => r.data);
|
|
1534
|
+
|
|
1686
1535
|
/**
|
|
1687
|
-
*
|
|
1688
|
-
*
|
|
1689
|
-
*
|
|
1536
|
+
* API keys are used to authenticate server-to-server calls. (API keys should **never** be used for client-to-server operations!)
|
|
1537
|
+
* To generate a key, either use the Verdocs admin interface and make note of the client_id and client_secret generated, or call
|
|
1538
|
+
* createKey as shown below. Then call {@link Users.Auth.authenticateApp} to obtain an access token using the provided ID and
|
|
1539
|
+
* secret. Note that server-to-server authentication requests return shorter-lived tokens, so it is important to check the `exp`
|
|
1540
|
+
* field and re-authenticate as needed for subsequent calls.
|
|
1690
1541
|
*
|
|
1691
|
-
*
|
|
1692
|
-
*
|
|
1542
|
+
* API keys may be updated or rotated at any time. Regular rotation is recommended. Rotation will not expire or invalidate
|
|
1543
|
+
* existing server-to-server sessions, so it may be done at any time without disrupting your application.
|
|
1693
1544
|
*
|
|
1694
|
-
*
|
|
1695
|
-
* if (!valid) {
|
|
1696
|
-
* window.alert('Session invalid or expired. Please re-authenticate.');
|
|
1697
|
-
* }
|
|
1698
|
-
* ```
|
|
1545
|
+
* @module
|
|
1699
1546
|
*/
|
|
1700
|
-
const validateToken = (endpoint, params) => endpoint.api //
|
|
1701
|
-
.post('/token/isValid', params)
|
|
1702
|
-
.then((r) => r.data);
|
|
1703
1547
|
/**
|
|
1704
|
-
*
|
|
1548
|
+
* Get a list of keys for a given organization. The caller must have admin access to the organization.
|
|
1705
1549
|
*
|
|
1706
1550
|
* ```typescript
|
|
1707
|
-
* import {
|
|
1708
|
-
* import {Transport} from '@verdocs/js-sdk/HTTP';
|
|
1551
|
+
* import {ApiKeys} from '@verdocs/js-sdk/Organizations';
|
|
1709
1552
|
*
|
|
1710
|
-
* const
|
|
1711
|
-
* Transport.setAuthToken(accessToken);
|
|
1553
|
+
* const keys = await ApiKeys.getKeys(ORGID);
|
|
1712
1554
|
* ```
|
|
1713
1555
|
*/
|
|
1714
|
-
const
|
|
1715
|
-
.get(
|
|
1556
|
+
const getApiKeys = (endpoint, organizationId) => endpoint.api //
|
|
1557
|
+
.get(`/organizations/${organizationId}/api_key`)
|
|
1716
1558
|
.then((r) => r.data);
|
|
1717
1559
|
/**
|
|
1718
|
-
*
|
|
1560
|
+
* Create an API key.
|
|
1719
1561
|
*
|
|
1720
1562
|
* ```typescript
|
|
1721
|
-
* import {
|
|
1563
|
+
* import {ApiKeys} from '@verdocs/js-sdk/Organizations';
|
|
1722
1564
|
*
|
|
1723
|
-
*
|
|
1724
|
-
* if (status !== 'OK') {
|
|
1725
|
-
* window.alert(`Password reset error: ${message}`);
|
|
1726
|
-
* }
|
|
1565
|
+
* await ApiKeys.createKey(ORGID, {name: NEWNAME});
|
|
1727
1566
|
* ```
|
|
1728
1567
|
*/
|
|
1729
|
-
const
|
|
1730
|
-
.
|
|
1568
|
+
const createApiKey = (endpoint, organizationId, params) => endpoint.api //
|
|
1569
|
+
.post(`/organizations/${organizationId}/api_key`, params)
|
|
1731
1570
|
.then((r) => r.data);
|
|
1732
1571
|
/**
|
|
1733
|
-
*
|
|
1572
|
+
* Rotate the secret for an API key. The caller must have admin access to the organization.
|
|
1734
1573
|
*
|
|
1735
1574
|
* ```typescript
|
|
1736
|
-
* import {
|
|
1575
|
+
* import {ApiKeys} from '@verdocs/js-sdk/Organizations';
|
|
1737
1576
|
*
|
|
1738
|
-
* const {
|
|
1739
|
-
* if (status !== 'OK') {
|
|
1740
|
-
* window.alert(`Please check your email for instructions on how to reset your password.`);
|
|
1741
|
-
* }
|
|
1577
|
+
* const {client_secret: newSecret} = await ApiKeys.rotateKey(ORGID, CLIENTID);
|
|
1742
1578
|
* ```
|
|
1743
1579
|
*/
|
|
1744
|
-
const
|
|
1745
|
-
.
|
|
1580
|
+
const rotateApiKey = (endpoint, organizationId, clientId) => endpoint.api //
|
|
1581
|
+
.put(`/organizations/${organizationId}/api_key/${clientId}/rotate`)
|
|
1746
1582
|
.then((r) => r.data);
|
|
1747
1583
|
/**
|
|
1748
|
-
* Update
|
|
1584
|
+
* Update an API key to change its assigned Profile ID or Name.
|
|
1749
1585
|
*
|
|
1750
1586
|
* ```typescript
|
|
1751
|
-
* import {
|
|
1587
|
+
* import {ApiKeys} from '@verdocs/js-sdk/Organizations';
|
|
1752
1588
|
*
|
|
1753
|
-
*
|
|
1589
|
+
* await ApiKeys.updateKey(ORGID, CLIENTID, {name: NEWNAME});
|
|
1754
1590
|
* ```
|
|
1755
1591
|
*/
|
|
1756
|
-
const
|
|
1757
|
-
.
|
|
1592
|
+
const updateApiKey = (endpoint, organizationId, clientId, params) => endpoint.api //
|
|
1593
|
+
.patch(`/organizations/${organizationId}/api_key/${clientId}`, params)
|
|
1758
1594
|
.then((r) => r.data);
|
|
1759
1595
|
/**
|
|
1760
|
-
*
|
|
1761
|
-
* a parameter here. Instead, the caller must be authenticated as the (unverified) user. To simplify this process,
|
|
1762
|
-
* the access token to be used may be passed directly as a parameter here. This avoids the need to set it as the
|
|
1763
|
-
* active token on an endpoint, which may be inconvenient in workflows where it is preferable to keep the user in
|
|
1764
|
-
* "anonymous" mode while verification is being performed.
|
|
1596
|
+
* Delete an API key.
|
|
1765
1597
|
*
|
|
1766
1598
|
* ```typescript
|
|
1767
|
-
* import {
|
|
1599
|
+
* import {ApiKeys} from '@verdocs/js-sdk/Organizations';
|
|
1768
1600
|
*
|
|
1769
|
-
*
|
|
1601
|
+
* await ApiKeys.deleteKey(ORGID, CLIENTID);
|
|
1770
1602
|
* ```
|
|
1771
1603
|
*/
|
|
1772
|
-
const
|
|
1773
|
-
.
|
|
1774
|
-
.then((r) => r.data);
|
|
1775
|
-
const createUser = (endpoint, params) => endpoint.api //
|
|
1776
|
-
.post('/user', params)
|
|
1777
|
-
.then((r) => r.data);
|
|
1778
|
-
|
|
1779
|
-
// TODO
|
|
1780
|
-
const billingPlaceholder = {};
|
|
1781
|
-
|
|
1782
|
-
const getNotifications = async (endpoint) => endpoint.api //
|
|
1783
|
-
.get('/notifications')
|
|
1604
|
+
const deleteApiKey = (endpoint, organizationId, clientId) => endpoint.api //
|
|
1605
|
+
.delete(`/organizations/${organizationId}/api_key/${clientId}`)
|
|
1784
1606
|
.then((r) => r.data);
|
|
1785
1607
|
|
|
1786
1608
|
/**
|
|
1787
|
-
*
|
|
1788
|
-
*
|
|
1789
|
-
*
|
|
1790
|
-
*
|
|
1609
|
+
* Organizations may contain "Groups" of user profiles, called Members. Groups may have permissions assigned that
|
|
1610
|
+
* apply to all Members, making it easy to configure role-based access control (RBAC) within an Organization. Note
|
|
1611
|
+
* that permissions are **additive**. A user may be a member of more than one group, and may also have permissions
|
|
1612
|
+
* assigned directly. In that case, the user will have the combined set of all permissions inherited from all
|
|
1613
|
+
* sources.
|
|
1791
1614
|
*
|
|
1792
|
-
*
|
|
1793
|
-
* ```
|
|
1615
|
+
* @module
|
|
1794
1616
|
*/
|
|
1795
|
-
const getProfiles = (endpoint) => endpoint.api //
|
|
1796
|
-
.get('/profiles')
|
|
1797
|
-
.then((r) => r.data);
|
|
1798
1617
|
/**
|
|
1799
|
-
* Get
|
|
1618
|
+
* Get a list of groups for a given organization. The caller must have admin access to the organization.
|
|
1800
1619
|
*
|
|
1801
1620
|
* ```typescript
|
|
1802
|
-
* import {
|
|
1621
|
+
* import {Groups} from '@verdocs/js-sdk/Organizations';
|
|
1803
1622
|
*
|
|
1804
|
-
* const
|
|
1623
|
+
* const groups = await Groups.getGroups(ORGID);
|
|
1805
1624
|
* ```
|
|
1806
1625
|
*/
|
|
1807
|
-
const
|
|
1808
|
-
.get(
|
|
1809
|
-
.then((r) =>
|
|
1626
|
+
const getGroups = (endpoint, organizationId) => endpoint.api //
|
|
1627
|
+
.get(`/organizations/${organizationId}/groups`)
|
|
1628
|
+
.then((r) => r.data);
|
|
1810
1629
|
/**
|
|
1811
|
-
* Get a
|
|
1630
|
+
* Get a single group by name. Returns a detail record.
|
|
1812
1631
|
*
|
|
1813
1632
|
* ```typescript
|
|
1814
|
-
* import {
|
|
1633
|
+
* import {Groups} from '@verdocs/js-sdk/Organizations';
|
|
1815
1634
|
*
|
|
1816
|
-
* const
|
|
1635
|
+
* const groups = await Groups.getGroups(ORGID);
|
|
1817
1636
|
* ```
|
|
1818
1637
|
*/
|
|
1819
|
-
const
|
|
1820
|
-
.get(
|
|
1638
|
+
const getGroupByName = (endpoint, organizationId, name) => endpoint.api //
|
|
1639
|
+
.get(`/organizations/${organizationId}/groups`, { params: { name } })
|
|
1821
1640
|
.then((r) => r.data);
|
|
1822
1641
|
/**
|
|
1823
|
-
* Get
|
|
1642
|
+
* Get the details for a group.
|
|
1824
1643
|
*
|
|
1825
1644
|
* ```typescript
|
|
1826
|
-
* import {
|
|
1645
|
+
* import {Groups} from '@verdocs/js-sdk/Organizations';
|
|
1827
1646
|
*
|
|
1828
|
-
* const
|
|
1647
|
+
* const groups = await Groups.getGroups(ORGID);
|
|
1829
1648
|
* ```
|
|
1830
1649
|
*/
|
|
1831
|
-
const
|
|
1832
|
-
.get(
|
|
1650
|
+
const getGroup = (endpoint, organizationId, groupId) => endpoint.api //
|
|
1651
|
+
.get(`/organizations/${organizationId}/groups/${groupId}`)
|
|
1652
|
+
.then((r) => r.data);
|
|
1653
|
+
const getGroupMembers = (endpoint, organizationId, groupId) => endpoint.api //
|
|
1654
|
+
.get(`/organizations/${organizationId}/groups/${groupId}/members`)
|
|
1655
|
+
.then((r) => r.data);
|
|
1656
|
+
const addGroupMembers = (endpoint, organizationId, groupId, params) => endpoint.api //
|
|
1657
|
+
.post(`/organizations/${organizationId}/groups/${groupId}/members`, params)
|
|
1658
|
+
.then((r) => r.data);
|
|
1659
|
+
const deleteGroupMembers = (endpoint, organizationId, groupId, params) => endpoint.api //
|
|
1660
|
+
.put(`/organizations/${organizationId}/groups/${groupId}/delete_members`, params)
|
|
1661
|
+
.then((r) => r.data);
|
|
1662
|
+
const addGroupPermission = (endpoint, organizationId, groupId, permission) => endpoint.api //
|
|
1663
|
+
.post(`/organizations/${organizationId}/groups/${groupId}/permissions/${permission}`, {})
|
|
1833
1664
|
.then((r) => r.data);
|
|
1665
|
+
const deleteGroupPermission = (endpoint, organizationId, groupId, permission) => endpoint.api //
|
|
1666
|
+
.delete(`/organizations/${organizationId}/groups/${groupId}/permissions/${permission}`)
|
|
1667
|
+
.then((r) => r.data);
|
|
1668
|
+
|
|
1834
1669
|
/**
|
|
1835
|
-
*
|
|
1670
|
+
* An invitation represents an opportunity for a Member to join an Organization.
|
|
1836
1671
|
*
|
|
1837
|
-
*
|
|
1838
|
-
|
|
1672
|
+
* @module
|
|
1673
|
+
*/
|
|
1674
|
+
const getOrganizationInvitations = (endpoint, organizationId) => endpoint.api //
|
|
1675
|
+
.get(`/organizations/${organizationId}/invitation`)
|
|
1676
|
+
.then((r) => r.data);
|
|
1677
|
+
const createOrganizationInvitation = (endpoint, organizationId, params) => endpoint.api //
|
|
1678
|
+
.post(`/organizations/${organizationId}/invitation`, params)
|
|
1679
|
+
.then((r) => r.data);
|
|
1680
|
+
const deleteOrganizationInvitation = (endpoint, organizationId, email) => endpoint.api //
|
|
1681
|
+
.delete(`/organizations/${organizationId}/invitation/${email}`)
|
|
1682
|
+
.then((r) => r.data);
|
|
1683
|
+
const updateOrganizationInvitation = (endpoint, organizationId, email, params) => endpoint.api //
|
|
1684
|
+
.patch(`/organizations/${organizationId}/invitation/${email}`, params)
|
|
1685
|
+
.then((r) => r.data);
|
|
1686
|
+
const resendOrganizationInvitation = (endpoint, organizationId, email) => endpoint.api //
|
|
1687
|
+
.post(`/organizations/${organizationId}/invitation/${email}/resend`)
|
|
1688
|
+
.then((r) => r.data);
|
|
1689
|
+
const getOrganizationInvitation = (endpoint, organizationId, email, token) => endpoint.api //
|
|
1690
|
+
.get(`/organizations/${organizationId}/invitation/${email}/accept/${token}`)
|
|
1691
|
+
.then((r) => r.data);
|
|
1692
|
+
const acceptOrganizationInvitation = (endpoint, organizationId, email, token) => endpoint.api //
|
|
1693
|
+
.post(`/organizations/${organizationId}/invitation/${email}/accept/${token}`)
|
|
1694
|
+
.then((r) => r.data);
|
|
1695
|
+
const declineOrganizationInvitation = (endpoint, organizationId, email, token) => endpoint.api //
|
|
1696
|
+
.post(`/organizations/${organizationId}/invitation/${email}/decline/${token}`)
|
|
1697
|
+
.then((r) => r.data);
|
|
1698
|
+
const claimNewUser = (endpoint, organizationId, email, token) => endpoint.api //
|
|
1699
|
+
.put(`/organizations/${organizationId}/invitation/${email}/token/${token}/new_user`)
|
|
1700
|
+
.then((r) => r.data);
|
|
1701
|
+
|
|
1702
|
+
/**
|
|
1703
|
+
* An Organization Member (aka Profile) is an individual user with access to an organization.
|
|
1839
1704
|
*
|
|
1840
|
-
*
|
|
1841
|
-
* ```
|
|
1705
|
+
* @module
|
|
1842
1706
|
*/
|
|
1843
|
-
const
|
|
1844
|
-
.
|
|
1707
|
+
const getOrganizationMembers = (endpoint, organizationId) => endpoint.api //
|
|
1708
|
+
.get(`/organizations/${organizationId}/profiles`)
|
|
1709
|
+
.then((r) => r.data);
|
|
1710
|
+
const deleteOrganizationMember = (endpoint, organizationId, profileId) => endpoint.api //
|
|
1711
|
+
.delete(`/organizations/${organizationId}/profiles/${profileId}`)
|
|
1712
|
+
.then((r) => r.data);
|
|
1713
|
+
const addOrganizationMemberRole = (endpoint, organizationId, profileId, roleId) => endpoint.api //
|
|
1714
|
+
.post(`/organizations/${organizationId}/profiles/${profileId}/role/${roleId}`)
|
|
1715
|
+
.then((r) => r.data);
|
|
1716
|
+
const deleteOrganizationMemberRole = (endpoint, organizationId, profileId, roleId) => endpoint.api //
|
|
1717
|
+
.delete(`/organizations/${organizationId}/profiles/${profileId}/role/${roleId}`)
|
|
1845
1718
|
.then((r) => r.data);
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
* TODO: Add a "public" profile endpoint for public pages
|
|
1849
|
-
*
|
|
1850
|
-
* ```typescript
|
|
1851
|
-
* import {Profiles} from '@verdocs/js-sdk/Users';
|
|
1852
|
-
*
|
|
1853
|
-
* const profile = await Profiles.getProfile('PROFILEID');
|
|
1854
|
-
* ```
|
|
1855
|
-
*/
|
|
1856
|
-
const getProfile = (endpoint, profileId) => endpoint.api //
|
|
1857
|
-
.get(`/profiles/${profileId}`)
|
|
1719
|
+
const getOrganizationMemberPlans = (endpoint, organizationId, profileId) => endpoint.api //
|
|
1720
|
+
.get(`/organizations/${organizationId}/profiles/${profileId}/plans`)
|
|
1858
1721
|
.then((r) => r.data);
|
|
1722
|
+
|
|
1859
1723
|
/**
|
|
1860
|
-
*
|
|
1861
|
-
*
|
|
1862
|
-
* ```typescript
|
|
1863
|
-
* import {Profiles} from '@verdocs/js-sdk/Users';
|
|
1724
|
+
* An Organization is the top level object for ownership for Members, Documents, and Templates.
|
|
1864
1725
|
*
|
|
1865
|
-
*
|
|
1866
|
-
* ```
|
|
1726
|
+
* @module
|
|
1867
1727
|
*/
|
|
1868
|
-
const getProfilePermissions = (endpoint, profileId) => endpoint.api //
|
|
1869
|
-
.get(`/profiles/${profileId}/permissions`)
|
|
1870
|
-
.then((r) => r.data);
|
|
1871
1728
|
/**
|
|
1872
|
-
* Get a
|
|
1873
|
-
*
|
|
1874
|
-
* ```typescript
|
|
1875
|
-
* import {Profiles} from '@verdocs/js-sdk/Users';
|
|
1876
|
-
*
|
|
1877
|
-
* const groups = await Profiles.getProfileGroups('PROFILEID');
|
|
1878
|
-
* ```
|
|
1729
|
+
* Get a list of organizations the user has access to.
|
|
1879
1730
|
*/
|
|
1880
|
-
const
|
|
1881
|
-
.get(
|
|
1731
|
+
const getOrganizations = (endpoint) => endpoint.api //
|
|
1732
|
+
.get('/organizations')
|
|
1882
1733
|
.then((r) => r.data);
|
|
1883
1734
|
/**
|
|
1884
|
-
*
|
|
1885
|
-
* for most operations in Verdocs. It is important to select the appropropriate profile before calling other API functions.
|
|
1886
|
-
*
|
|
1887
|
-
* ```typescript
|
|
1888
|
-
* import {Profiles} from '@verdocs/js-sdk/Users';
|
|
1889
|
-
*
|
|
1890
|
-
* const newProfile = await Profiles.switchProfile('PROFILEID');
|
|
1891
|
-
* ```
|
|
1735
|
+
* Create an organization.
|
|
1892
1736
|
*/
|
|
1893
|
-
const
|
|
1894
|
-
.post(
|
|
1737
|
+
const createOrganization = (endpoint) => endpoint.api //
|
|
1738
|
+
.post('/organizations')
|
|
1895
1739
|
.then((r) => r.data);
|
|
1896
1740
|
/**
|
|
1897
|
-
*
|
|
1898
|
-
* "current" profile for the caller.
|
|
1899
|
-
*
|
|
1900
|
-
* ```typescript
|
|
1901
|
-
* import {Profiles} from '@verdocs/js-sdk/Users';
|
|
1902
|
-
*
|
|
1903
|
-
* const newProfile = await Profiles.updateProfile('PROFILEID');
|
|
1904
|
-
* ```
|
|
1741
|
+
* Delete an organization.
|
|
1905
1742
|
*/
|
|
1906
|
-
const
|
|
1907
|
-
.
|
|
1743
|
+
const deleteOrganization = (endpoint, organizationId) => endpoint.api //
|
|
1744
|
+
.delete(`/organizations/${organizationId}`)
|
|
1908
1745
|
.then((r) => r.data);
|
|
1909
1746
|
/**
|
|
1910
|
-
*
|
|
1911
|
-
*
|
|
1912
|
-
* ```typescript
|
|
1913
|
-
* import {Profiles} from '@verdocs/js-sdk/Users';
|
|
1914
|
-
*
|
|
1915
|
-
* await Profiles.deleteProfile('PROFILEID');
|
|
1916
|
-
* ```
|
|
1747
|
+
* Get an organization by ID.
|
|
1917
1748
|
*/
|
|
1918
|
-
const
|
|
1919
|
-
.
|
|
1749
|
+
const getOrganization = (endpoint, organizationId) => endpoint.api //
|
|
1750
|
+
.get(`/organizations/${organizationId}`)
|
|
1920
1751
|
.then((r) => r.data);
|
|
1921
1752
|
/**
|
|
1922
|
-
*
|
|
1923
|
-
* existing organization should be invited, and follow their invitation links/instructions to create their accounts.
|
|
1924
|
-
*
|
|
1925
|
-
* ```typescript
|
|
1926
|
-
* import {Profiles} from '@verdocs/js-sdk/Users';
|
|
1927
|
-
*
|
|
1928
|
-
* const newAccount = await Profiles.createBusinessAccount({
|
|
1929
|
-
* orgName: 'ORG', email: 'a@b.com', password: '12345678', firstName: 'FIRST', lastName: 'LAST'
|
|
1930
|
-
* });
|
|
1931
|
-
* ```
|
|
1753
|
+
* Update an organization.
|
|
1932
1754
|
*/
|
|
1933
|
-
const
|
|
1934
|
-
.
|
|
1755
|
+
const updateOrganization = (endpoint, organizationId, params) => endpoint.api //
|
|
1756
|
+
.patch(`/organizations/${organizationId}`, params)
|
|
1935
1757
|
.then((r) => r.data);
|
|
1936
|
-
|
|
1937
|
-
|
|
1758
|
+
|
|
1759
|
+
const getWebhooks = (endpoint) => endpoint.api //
|
|
1760
|
+
.get(`/v2/webhooks/organization`)
|
|
1761
|
+
.then((r) => r.data);
|
|
1762
|
+
const setWebhooks = (endpoint, params) => endpoint.api //
|
|
1763
|
+
.post(`/v2/webhooks/organization`, params)
|
|
1938
1764
|
.then((r) => r.data);
|
|
1939
1765
|
|
|
1940
1766
|
/**
|
|
1941
|
-
*
|
|
1942
|
-
*/
|
|
1943
|
-
function getRGB(rgba) {
|
|
1944
|
-
const rgbNumbers = rgba.replace('rgba(', '').replace(')', '').split(',');
|
|
1945
|
-
const rgbObject = {
|
|
1946
|
-
red: +rgbNumbers[0],
|
|
1947
|
-
green: +rgbNumbers[1],
|
|
1948
|
-
blue: +rgbNumbers[2],
|
|
1949
|
-
alpha: +rgbNumbers[3],
|
|
1950
|
-
};
|
|
1951
|
-
const alpha = 1 - rgbObject.alpha;
|
|
1952
|
-
const red = Math.round((rgbObject.alpha * (rgbObject.red / 255) + alpha) * 255);
|
|
1953
|
-
const green = Math.round((rgbObject.alpha * (rgbObject.green / 255) + alpha) * 255);
|
|
1954
|
-
const blue = Math.round((rgbObject.alpha * (rgbObject.blue / 255) + alpha) * 255);
|
|
1955
|
-
return '#' + rgbToHex(red) + rgbToHex(green) + rgbToHex(blue);
|
|
1956
|
-
}
|
|
1957
|
-
/**
|
|
1958
|
-
* Given an RGB string value, returns the hex equivalent.
|
|
1959
|
-
*/
|
|
1960
|
-
function rgbToHex(rgb) {
|
|
1961
|
-
const hex = rgb.toString(16);
|
|
1962
|
-
if (hex.length < 2) {
|
|
1963
|
-
return '0' + hex;
|
|
1964
|
-
}
|
|
1965
|
-
return hex;
|
|
1966
|
-
}
|
|
1967
|
-
/**
|
|
1968
|
-
* Given a signer role index, return the color code for that signer.
|
|
1969
|
-
*/
|
|
1970
|
-
function getRGBA(roleIndex) {
|
|
1971
|
-
switch (roleIndex % 10) {
|
|
1972
|
-
case 0:
|
|
1973
|
-
return roleIndex === 0 ? 'rgba(255, 193, 7, 0.4)' : 'rgba(134, 134, 134, 0.3)'; // #FFE69C
|
|
1974
|
-
case 1:
|
|
1975
|
-
return 'rgba(156, 39, 176, .4)'; // '#E3C3E9'
|
|
1976
|
-
case 2:
|
|
1977
|
-
return 'rgba(33, 150, 243, .4)'; // '#C1E1FB'
|
|
1978
|
-
case 3:
|
|
1979
|
-
return 'rgba(220, 231, 117, 0.3)';
|
|
1980
|
-
case 4:
|
|
1981
|
-
return 'rgba(121, 134, 203, 0.3)';
|
|
1982
|
-
case 5:
|
|
1983
|
-
return 'rgba(77, 182, 172, 0.3)';
|
|
1984
|
-
case 6:
|
|
1985
|
-
return 'rgba(255, 202, 165, 0.3)';
|
|
1986
|
-
case 7:
|
|
1987
|
-
return 'rgba(2, 247, 190, 0.3)';
|
|
1988
|
-
case 8:
|
|
1989
|
-
return 'rgba(255, 138, 101, 0.3)';
|
|
1990
|
-
case 9:
|
|
1991
|
-
return 'rgba(82, 255, 79, 0.3)';
|
|
1992
|
-
default:
|
|
1993
|
-
return 'rgba(229, 115, 155, 0.3)';
|
|
1994
|
-
}
|
|
1995
|
-
}
|
|
1996
|
-
/**
|
|
1997
|
-
* Given a role name, return a color code for it. This works by computing a hash code so the specific color returned
|
|
1998
|
-
* is not specified explicitly, but will be the same for every call with the same input value.
|
|
1999
|
-
*/
|
|
2000
|
-
function nameToRGBA(str) {
|
|
2001
|
-
if (!!str) {
|
|
2002
|
-
const validNum = parseInt(str.slice(-1), 10);
|
|
2003
|
-
if (!isNaN(validNum)) {
|
|
2004
|
-
str += (validNum * 99).toString();
|
|
2005
|
-
}
|
|
2006
|
-
let hash = 0;
|
|
2007
|
-
for (let i = 0; i < str.length; i++) {
|
|
2008
|
-
// tslint:disable-next-line:no-bitwise
|
|
2009
|
-
hash = str.charCodeAt(i) + ((hash << 5) - hash);
|
|
2010
|
-
}
|
|
2011
|
-
hash = Math.round(hash / 1.3);
|
|
2012
|
-
// tslint:disable-next-line:no-bitwise
|
|
2013
|
-
const c = (hash & 0x00ffff08).toString(16).toUpperCase();
|
|
2014
|
-
const hex = '#' + '00000'.substring(0, 6 - c.length) + c;
|
|
2015
|
-
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
2016
|
-
const color = {
|
|
2017
|
-
r: parseInt(result[1], 16),
|
|
2018
|
-
g: parseInt(result[2], 16),
|
|
2019
|
-
b: parseInt(result[3], 16),
|
|
2020
|
-
};
|
|
2021
|
-
return `rgba(${color.r}, ${color.g}, ${color.b}, 0.2)`;
|
|
2022
|
-
}
|
|
2023
|
-
}
|
|
2024
|
-
/**
|
|
2025
|
-
* Helper function to obtain a color code given a role name given various possible inputs.
|
|
1767
|
+
* Confirm whether the user has all of the specified permissions.
|
|
2026
1768
|
*/
|
|
2027
|
-
|
|
2028
|
-
if (index) {
|
|
2029
|
-
return getRGBA(index);
|
|
2030
|
-
}
|
|
2031
|
-
else if (roles && roles.length > 0) {
|
|
2032
|
-
const roleIndex = roles.findIndex((role) => role === name);
|
|
2033
|
-
if (roleIndex > -1) {
|
|
2034
|
-
return getRGBA(roleIndex);
|
|
2035
|
-
}
|
|
2036
|
-
else {
|
|
2037
|
-
return nameToRGBA(name);
|
|
2038
|
-
}
|
|
2039
|
-
}
|
|
2040
|
-
else {
|
|
2041
|
-
return nameToRGBA(name);
|
|
2042
|
-
}
|
|
2043
|
-
}
|
|
1769
|
+
const userHasPermissions = (session, permissions) => permissions.every((perm) => (session?.permissions || []).includes(perm));
|
|
2044
1770
|
|
|
2045
|
-
const
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
const
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
}
|
|
2065
|
-
const timeDiff = Math.floor((new Date().getTime() - dateInput.getTime()) / 1000);
|
|
2066
|
-
if (timeDiff >= YEAR) {
|
|
2067
|
-
return Math.floor(timeDiff / YEAR) + 'Y';
|
|
2068
|
-
}
|
|
2069
|
-
// if (timeDiff >= MONTH) {
|
|
2070
|
-
// return Math.floor(timeDiff / MONTH) + 'M';
|
|
2071
|
-
// }
|
|
2072
|
-
if (timeDiff >= WEEK) {
|
|
2073
|
-
return Math.floor(timeDiff / WEEK) + 'W';
|
|
2074
|
-
}
|
|
2075
|
-
if (timeDiff >= DAY) {
|
|
2076
|
-
return Math.floor(timeDiff / DAY) + 'D';
|
|
2077
|
-
}
|
|
2078
|
-
if (timeDiff >= HOUR) {
|
|
2079
|
-
return Math.floor(timeDiff / HOUR) + 'H';
|
|
2080
|
-
}
|
|
2081
|
-
if (timeDiff >= MINUTE) {
|
|
2082
|
-
return Math.floor(timeDiff / MINUTE) + 'M';
|
|
2083
|
-
}
|
|
2084
|
-
return `${timeDiff}S`;
|
|
2085
|
-
};
|
|
2086
|
-
function timePeriod(type) {
|
|
2087
|
-
let endDate = new Date().getTime();
|
|
2088
|
-
const today = new Date();
|
|
2089
|
-
const month = today.getMonth();
|
|
2090
|
-
const year = today.getFullYear();
|
|
2091
|
-
let startDate = null;
|
|
2092
|
-
switch (type) {
|
|
2093
|
-
case '30d':
|
|
2094
|
-
startDate = endDate - 60 * 60 * 24 * 30 * 1000;
|
|
1771
|
+
const canPerformTemplateAction = (session, action, template) => {
|
|
1772
|
+
if (!template && !action.includes('create')) {
|
|
1773
|
+
return { canPerform: false, message: 'Missing required template object' };
|
|
1774
|
+
}
|
|
1775
|
+
// We use BOGUS here to force the option-chain in things like template?.profile_id to NOT match profile?.profile_id because if both
|
|
1776
|
+
// were undefined, they would actually match.
|
|
1777
|
+
const profile_id = session?.profile_id || 'BOGUS';
|
|
1778
|
+
const organization_id = session?.organization_id || 'BOGUS';
|
|
1779
|
+
if (!profile_id) {
|
|
1780
|
+
return { canPerform: false, message: 'Active session required' };
|
|
1781
|
+
}
|
|
1782
|
+
const isCreator = template?.profile_id === profile_id;
|
|
1783
|
+
const isSameOrg = template?.organization_id === organization_id;
|
|
1784
|
+
const isPersonal = template?.is_personal ?? false;
|
|
1785
|
+
const isPublic = template?.is_public ?? false;
|
|
1786
|
+
const permissionsRequired = [];
|
|
1787
|
+
switch (action) {
|
|
1788
|
+
case 'create_personal':
|
|
1789
|
+
permissionsRequired.push('template:creator:create:personal');
|
|
2095
1790
|
break;
|
|
2096
|
-
case '
|
|
2097
|
-
|
|
1791
|
+
case 'create_org':
|
|
1792
|
+
permissionsRequired.push('template:creator:create:org');
|
|
2098
1793
|
break;
|
|
2099
|
-
case '
|
|
2100
|
-
|
|
1794
|
+
case 'create_public':
|
|
1795
|
+
permissionsRequired.push('template:creator:create:public');
|
|
2101
1796
|
break;
|
|
2102
|
-
case '
|
|
2103
|
-
|
|
1797
|
+
case 'read':
|
|
1798
|
+
if (!isCreator) {
|
|
1799
|
+
if ((!isPersonal && isSameOrg) || !isPublic) {
|
|
1800
|
+
permissionsRequired.push('template:member:read');
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
2104
1803
|
break;
|
|
2105
|
-
case '
|
|
2106
|
-
|
|
2107
|
-
|
|
1804
|
+
case 'write':
|
|
1805
|
+
if (!isCreator) {
|
|
1806
|
+
permissionsRequired.push('template:member:read');
|
|
1807
|
+
permissionsRequired.push('template:member:write');
|
|
1808
|
+
}
|
|
2108
1809
|
break;
|
|
2109
|
-
case '
|
|
2110
|
-
|
|
1810
|
+
case 'change_visibility_personal':
|
|
1811
|
+
if (isCreator) {
|
|
1812
|
+
permissionsRequired.push('template:creator:create:personal');
|
|
1813
|
+
}
|
|
1814
|
+
else {
|
|
1815
|
+
permissionsRequired.push('template:member:visibility');
|
|
1816
|
+
}
|
|
1817
|
+
break;
|
|
1818
|
+
case 'change_visibility_org':
|
|
1819
|
+
if (isCreator) {
|
|
1820
|
+
permissionsRequired.push('template:creator:create:org');
|
|
1821
|
+
}
|
|
1822
|
+
else {
|
|
1823
|
+
permissionsRequired.push('template:member:visibility');
|
|
1824
|
+
}
|
|
1825
|
+
break;
|
|
1826
|
+
case 'change_visibility_public':
|
|
1827
|
+
if (isCreator) {
|
|
1828
|
+
permissionsRequired.push('template:creator:create:public');
|
|
1829
|
+
permissionsRequired.push('template:creator:visibility');
|
|
1830
|
+
}
|
|
1831
|
+
else {
|
|
1832
|
+
permissionsRequired.push('template:member:visibility');
|
|
1833
|
+
}
|
|
1834
|
+
break;
|
|
1835
|
+
case 'delete':
|
|
1836
|
+
if (isCreator) {
|
|
1837
|
+
permissionsRequired.push('template:creator:delete');
|
|
1838
|
+
}
|
|
1839
|
+
else {
|
|
1840
|
+
permissionsRequired.push('template:member:delete');
|
|
1841
|
+
}
|
|
2111
1842
|
break;
|
|
2112
|
-
case 'all_time':
|
|
2113
1843
|
default:
|
|
2114
|
-
return
|
|
1844
|
+
return { canPerform: false, message: 'Action is not defined' };
|
|
2115
1845
|
}
|
|
2116
|
-
if (
|
|
2117
|
-
return
|
|
1846
|
+
if (hasRequiredPermissions(session, permissionsRequired)) {
|
|
1847
|
+
return { canPerform: true, message: '' };
|
|
2118
1848
|
}
|
|
2119
|
-
return {
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
};
|
|
2123
|
-
}
|
|
1849
|
+
return { canPerform: false, message: `Insufficient access to perform '${action}'. Needed permissions: ${permissionsRequired.toString()}` };
|
|
1850
|
+
};
|
|
1851
|
+
const hasRequiredPermissions = (session, permissions) => permissions.every((perm) => (session?.permissions || []).includes(perm));
|
|
2124
1852
|
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
fileReader.readAsDataURL(image);
|
|
2144
|
-
});
|
|
2145
|
-
}
|
|
2146
|
-
function rescale(r, n) {
|
|
2147
|
-
return r * n;
|
|
2148
|
-
}
|
|
1853
|
+
/**
|
|
1854
|
+
* Add a field to a template.
|
|
1855
|
+
*/
|
|
1856
|
+
const createField = (endpoint, templateId, params) => endpoint.api //
|
|
1857
|
+
.post(`/templates/${templateId}/fields`, params)
|
|
1858
|
+
.then((r) => r.data);
|
|
1859
|
+
/**
|
|
1860
|
+
* Update a template field.
|
|
1861
|
+
*/
|
|
1862
|
+
const updateField = (endpoint, templateId, fieldName, params) => endpoint.api //
|
|
1863
|
+
.put(`/templates/${templateId}/fields/${fieldName}`, params)
|
|
1864
|
+
.then((r) => r.data);
|
|
1865
|
+
/**
|
|
1866
|
+
* REmove a field from a template.
|
|
1867
|
+
*/
|
|
1868
|
+
const deleteField = (endpoint, templateId, fieldName) => endpoint.api //
|
|
1869
|
+
.delete(`/templates/${templateId}/fields/${fieldName}`)
|
|
1870
|
+
.then((r) => r.data);
|
|
2149
1871
|
|
|
2150
1872
|
/**
|
|
2151
|
-
*
|
|
2152
|
-
*
|
|
1873
|
+
* Enable automatic reminders. setup_time is the number of days after the envelope is sent that the first reminder
|
|
1874
|
+
* should be sent. interval_time is the number of days between reminders.
|
|
2153
1875
|
*/
|
|
2154
|
-
const
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
lastModified: file.lastModified,
|
|
2158
|
-
size: file.size,
|
|
2159
|
-
type: file.type,
|
|
2160
|
-
name: file.name,
|
|
2161
|
-
data: reader.result,
|
|
2162
|
-
});
|
|
2163
|
-
reader.onerror = reject;
|
|
2164
|
-
if (file) {
|
|
2165
|
-
reader.readAsDataURL(file);
|
|
2166
|
-
}
|
|
2167
|
-
else {
|
|
2168
|
-
reject(new Error('Invalid file'));
|
|
2169
|
-
}
|
|
2170
|
-
});
|
|
1876
|
+
const createTemplateReminder = (endpoint, templateId, params) => endpoint.api //
|
|
1877
|
+
.post(`/templates/${templateId}/reminder/`, params)
|
|
1878
|
+
.then((r) => r.data);
|
|
2171
1879
|
/**
|
|
2172
|
-
*
|
|
1880
|
+
* Get the reminder configuration for a template.
|
|
2173
1881
|
*/
|
|
2174
|
-
const
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
1882
|
+
const getTemplateReminder = (endpoint, templateId, reminderId) => endpoint.api //
|
|
1883
|
+
.get(`/templates/${templateId}/reminder/${reminderId}`)
|
|
1884
|
+
.then((r) => r.data);
|
|
1885
|
+
/**
|
|
1886
|
+
* Update the reminder configuration for a template.
|
|
1887
|
+
*/
|
|
1888
|
+
const updateTemplateReminder = (endpoint, templateId, reminderId, params) => endpoint.api //
|
|
1889
|
+
.put(`/templates/${templateId}/reminder/${reminderId}`, params)
|
|
1890
|
+
.then((r) => r.data);
|
|
1891
|
+
/**
|
|
1892
|
+
* Delete the reminder configuration for a template.
|
|
1893
|
+
*/
|
|
1894
|
+
const deleteTemplateReminder = (endpoint, templateId, reminderId) => endpoint.api //
|
|
1895
|
+
.delete(`/templates/${templateId}/reminder/${reminderId}`)
|
|
1896
|
+
.then((r) => r.data);
|
|
1897
|
+
|
|
1898
|
+
/**
|
|
1899
|
+
* A "role" is an individual participant in a signing flow, such as a signer or CC contact. Roles are identified by
|
|
1900
|
+
* their names, which must be unique (e.g. 'Recipient 1'). Template fields are assigned to roles for signing operations,
|
|
1901
|
+
* so you may have 'Recipient 1 Signature 1' and so forth.
|
|
1902
|
+
*
|
|
1903
|
+
* @module
|
|
1904
|
+
*/
|
|
1905
|
+
const createTemplateRole = (endpoint, templateId, params) => endpoint.api //
|
|
1906
|
+
.post(`/templates/${templateId}/roles`, params)
|
|
1907
|
+
.then((r) => r.data);
|
|
1908
|
+
const getTemplateRoles = (endpoint, templateId) => endpoint.api //
|
|
1909
|
+
.get(`/templates/${templateId}/roles`)
|
|
1910
|
+
.then((r) => r.data);
|
|
1911
|
+
const getTemplateRole = (endpoint, templateId, roleName) => endpoint.api //
|
|
1912
|
+
.get(`/templates/${templateId}/roles/${roleName}`)
|
|
1913
|
+
.then((r) => r.data);
|
|
1914
|
+
const updateTemplateRole = (endpoint, templateId, roleName, params) => endpoint.api //
|
|
1915
|
+
.put(`/templates/${templateId}/roles/${roleName}`, params)
|
|
1916
|
+
.then((r) => r.data);
|
|
1917
|
+
const deleteTemplateRole = (endpoint, templateId, roleName) => endpoint.api //
|
|
1918
|
+
.delete(`/templates/${templateId}/roles/${roleName}`)
|
|
1919
|
+
.then((r) => r.data);
|
|
1920
|
+
const getTemplateRoleFields = (endpoint, templateId, roleName) => endpoint.api //
|
|
1921
|
+
.get(`/templates/${templateId}/roles/${roleName}/fields`)
|
|
1922
|
+
.then((r) => r.data);
|
|
1923
|
+
|
|
1924
|
+
/**
|
|
1925
|
+
* Get the template stars for a template.
|
|
1926
|
+
*/
|
|
1927
|
+
const getStars = (endpoint, templateId) => endpoint.api //
|
|
1928
|
+
.get(`/templates/${templateId}/stars`)
|
|
1929
|
+
.then((r) => r.data);
|
|
1930
|
+
/**
|
|
1931
|
+
* Toggle the template star for a template.
|
|
1932
|
+
*/
|
|
1933
|
+
const toggleStar = (endpoint, templateId) => endpoint.api //
|
|
1934
|
+
.post(`/templates/${templateId}/stars/toggle`)
|
|
1935
|
+
.then((r) => r.data);
|
|
1936
|
+
|
|
1937
|
+
/**
|
|
1938
|
+
* A Tag is a user-specified label applied to a template. Tags help users organize and find Templates.
|
|
1939
|
+
* recipients. Every Organization has a set of tags "owned" by that Organization and only visible inside it.
|
|
1940
|
+
* Verdocs also provides a set of system-wide "featured" tags available to all Organizations.
|
|
1941
|
+
*
|
|
1942
|
+
* @module
|
|
1943
|
+
*/
|
|
1944
|
+
/**
|
|
1945
|
+
* Apply a tag to a template.
|
|
1946
|
+
*/
|
|
1947
|
+
const addTemplateTag = (endpoint, templateId, params) => endpoint.api //
|
|
1948
|
+
.post(`/templates/${templateId}/tags/`, params)
|
|
1949
|
+
.then((r) => r.data);
|
|
1950
|
+
/**
|
|
1951
|
+
* Get all tags for a template.
|
|
1952
|
+
*/
|
|
1953
|
+
const getTemplateTags = (endpoint, templateId) => endpoint.api //
|
|
1954
|
+
.get(`/templates/${templateId}/tags/`)
|
|
1955
|
+
.then((r) => r.data);
|
|
1956
|
+
/**
|
|
1957
|
+
* Remove a tag from a template.
|
|
1958
|
+
*/
|
|
1959
|
+
const deleteTemplateTag = (endpoint, templateId, tagName) => endpoint.api //
|
|
1960
|
+
.post(`/templates/${templateId}/tags/${tagName}`)
|
|
1961
|
+
.then((r) => r.data);
|
|
1962
|
+
/**
|
|
1963
|
+
* Create an Organization-wide tag.
|
|
1964
|
+
*/
|
|
1965
|
+
const createTag = (endpoint, name) => endpoint.api //
|
|
1966
|
+
.post('/tags', { tag_name: name })
|
|
1967
|
+
.then((r) => r.data);
|
|
1968
|
+
/**
|
|
1969
|
+
* Get an Organization-wide tag.
|
|
1970
|
+
*/
|
|
1971
|
+
const getTag = (endpoint, name) => endpoint.api //
|
|
1972
|
+
.get(`/tags/${name}`)
|
|
1973
|
+
.then((r) => r.data);
|
|
1974
|
+
/**
|
|
1975
|
+
* Get all tags available for use by an Organization.
|
|
1976
|
+
*/
|
|
1977
|
+
const getAllTags = (endpoint) => endpoint.api //
|
|
1978
|
+
.get('/tags')
|
|
1979
|
+
.then((r) => r.data);
|
|
2187
1980
|
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
{
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
{ code: '+500', name: 'Falkland Islands', value: '+500' },
|
|
2264
|
-
{ code: '+298', name: 'Faroe Islands', value: '+298' },
|
|
2265
|
-
{ code: '+679', name: 'Fiji', value: '+679' },
|
|
2266
|
-
{ code: '+358', name: 'Finland', value: '+358' },
|
|
2267
|
-
{ code: '+33', name: 'France', value: '+33' },
|
|
2268
|
-
{ code: '+596', name: 'Martinique', value: '+596' },
|
|
2269
|
-
{ code: '+594', name: 'French Guiana', value: '+594' },
|
|
2270
|
-
{ code: '+689', name: 'French Polynesia', value: '+689' },
|
|
2271
|
-
{ code: '+241', name: 'Gabon', value: '+241' },
|
|
2272
|
-
{ code: '+220', name: 'Gambia', value: '+220' },
|
|
2273
|
-
{ code: '+995', name: 'Georgia', value: '+995' },
|
|
2274
|
-
{ code: '+49', name: 'Germany', value: '+49' },
|
|
2275
|
-
{ code: '+233', name: 'Ghana', value: '+233' },
|
|
2276
|
-
{ code: '+350', name: 'Gibraltar', value: '+350' },
|
|
2277
|
-
{ code: '+30', name: 'Greece', value: '+30' },
|
|
2278
|
-
{ code: '+299', name: 'Greenland', value: '+299' },
|
|
2279
|
-
{ code: '+1', name: 'Grenada', value: '+1' },
|
|
2280
|
-
{ code: '+590', name: 'Guadeloupe', value: '+590' },
|
|
2281
|
-
{ code: '+1', name: 'Guam', value: '+1' },
|
|
2282
|
-
{ code: '+502', name: 'Guatemala', value: '+502' },
|
|
2283
|
-
{ code: '+224', name: 'Guinea', value: '+224' },
|
|
2284
|
-
{ code: '+245', name: 'Guinea-Bissau', value: '+245' },
|
|
2285
|
-
{ code: '+595', name: 'Guyana', value: '+595' },
|
|
2286
|
-
{ code: '+509', name: 'Haiti', value: '+509' },
|
|
2287
|
-
{ code: '+504', name: 'Honduras', value: '+504' },
|
|
2288
|
-
{ code: '+852', name: 'Hong Kong SAR China', value: '+852' },
|
|
2289
|
-
{ code: '+36', name: 'Hungary', value: '+36' },
|
|
2290
|
-
{ code: '+354', name: 'Iceland', value: '+354' },
|
|
2291
|
-
{ code: '+91', name: 'India', value: '+91' },
|
|
2292
|
-
{ code: '+62', name: 'Indonesia', value: '+62' },
|
|
2293
|
-
{ code: '+98', name: 'Iran', value: '+98' },
|
|
2294
|
-
{ code: '+964', name: 'Iraq', value: '+964' },
|
|
2295
|
-
{ code: '+353', name: 'Ireland', value: '+353' },
|
|
2296
|
-
{ code: '+972', name: 'Israel', value: '+972' },
|
|
2297
|
-
{ code: '+39', name: 'Italy', value: '+39' },
|
|
2298
|
-
{ code: '+225', name: 'Ivory Coast', value: '+225' },
|
|
2299
|
-
{ code: '+1', name: 'Jamaica', value: '+1' },
|
|
2300
|
-
{ code: '+81', name: 'Japan', value: '+81' },
|
|
2301
|
-
{ code: '+962', name: 'Jordan', value: '+962' },
|
|
2302
|
-
{ code: '+77', name: 'Kazakhstan', value: '+7' },
|
|
2303
|
-
{ code: '+254', name: 'Kenya', value: '+254' },
|
|
2304
|
-
{ code: '+686', name: 'Kiribati', value: '+686' },
|
|
2305
|
-
{ code: '+965', name: 'Kuwait', value: '+965' },
|
|
2306
|
-
{ code: '+996', name: 'Kyrgyzstan', value: '+996' },
|
|
2307
|
-
{ code: '+856', name: 'Laos', value: '+856' },
|
|
2308
|
-
{ code: '+371', name: 'Latvia', value: '+371' },
|
|
2309
|
-
{ code: '+961', name: 'Lebanon', value: '+961' },
|
|
2310
|
-
{ code: '+266', name: 'Lesotho', value: '+266' },
|
|
2311
|
-
{ code: '+231', name: 'Liberia', value: '+231' },
|
|
2312
|
-
{ code: '+218', name: 'Libya', value: '+218' },
|
|
2313
|
-
{ code: '+423', name: 'Liechtenstein', value: '+423' },
|
|
2314
|
-
{ code: '+370', name: 'Lithuania', value: '+370' },
|
|
2315
|
-
{ code: '+352', name: 'Luxembourg', value: '+352' },
|
|
2316
|
-
{ code: '+853', name: 'Macau SAR China', value: '+853' },
|
|
2317
|
-
{ code: '+389', name: 'Macedonia', value: '+389' },
|
|
2318
|
-
{ code: '+261', name: 'Madagascar', value: '+261' },
|
|
2319
|
-
{ code: '+265', name: 'Malawi', value: '+265' },
|
|
2320
|
-
{ code: '+60', name: 'Malaysia', value: '+60' },
|
|
2321
|
-
{ code: '+960', name: 'Maldives', value: '+960' },
|
|
2322
|
-
{ code: '+223', name: 'Mali', value: '+223' },
|
|
2323
|
-
{ code: '+356', name: 'Malta', value: '+356' },
|
|
2324
|
-
{ code: '+692', name: 'Marshall Islands', value: '+692' },
|
|
2325
|
-
{ code: '+596', name: 'Martinique', value: '+596' },
|
|
2326
|
-
{ code: '+222', name: 'Mauritania', value: '+222' },
|
|
2327
|
-
{ code: '+230', name: 'Mauritius', value: '+230' },
|
|
2328
|
-
{ code: '+262', name: 'Mayotte or Réunion', value: '+262' },
|
|
2329
|
-
{ code: '+52', name: 'Mexico', value: '+52' },
|
|
2330
|
-
{ code: '+691', name: 'Micronesia', value: '+691' },
|
|
2331
|
-
{ code: '+1', name: 'Midway Island', value: '+1' },
|
|
2332
|
-
{ code: '+373', name: 'Moldova', value: '+373' },
|
|
2333
|
-
{ code: '+377', name: 'Monaco', value: '+377' },
|
|
2334
|
-
{ code: '+976', name: 'Mongolia', value: '+976' },
|
|
2335
|
-
{ code: '+382', name: 'Montenegro', value: '+382' },
|
|
2336
|
-
{ code: '+1', name: 'Montserrat', value: '+1' },
|
|
2337
|
-
{ code: '+212', name: 'Morocco', value: '+212' },
|
|
2338
|
-
{ code: '+95', name: 'Myanmar', value: '+95' },
|
|
2339
|
-
{ code: '+264', name: 'Namibia', value: '+264' },
|
|
2340
|
-
{ code: '+674', name: 'Nauru', value: '+674' },
|
|
2341
|
-
{ code: '+977', name: 'Nepal', value: '+977' },
|
|
2342
|
-
{ code: '+31', name: 'Netherlands', value: '+31' },
|
|
2343
|
-
{ code: '+599', name: 'Netherlands Antilles', value: '+599' },
|
|
2344
|
-
{ code: '+1', name: 'Nevis', value: '+1' },
|
|
2345
|
-
{ code: '+687', name: 'New Caledonia', value: '+687' },
|
|
2346
|
-
{ code: '+64', name: 'New Zealand', value: '+64' },
|
|
2347
|
-
{ code: '+505', name: 'Nicaragua', value: '+505' },
|
|
2348
|
-
{ code: '+227', name: 'Niger', value: '+227' },
|
|
2349
|
-
{ code: '+234', name: 'Nigeria', value: '+234' },
|
|
2350
|
-
{ code: '+683', name: 'Niue', value: '+683' },
|
|
2351
|
-
{ code: '+672', name: 'Norfolk Island', value: '+672' },
|
|
2352
|
-
{ code: '+850', name: 'North Korea', value: '+850' },
|
|
2353
|
-
{ code: '+1', name: 'Northern Mariana Islands', value: '+1' },
|
|
2354
|
-
{ code: '+47', name: 'Norway', value: '+47' },
|
|
2355
|
-
{ code: '+968', name: 'Oman', value: '+968' },
|
|
2356
|
-
{ code: '+92', name: 'Pakistan', value: '+92' },
|
|
2357
|
-
{ code: '+680', name: 'Palau', value: '+680' },
|
|
2358
|
-
{ code: '+970', name: 'Palestinian Territory', value: '+970' },
|
|
2359
|
-
{ code: '+507', name: 'Panama', value: '+507' },
|
|
2360
|
-
{ code: '+675', name: 'Papua New Guinea', value: '+675' },
|
|
2361
|
-
{ code: '+595', name: 'Paraguay', value: '+595' },
|
|
2362
|
-
{ code: '+51', name: 'Peru', value: '+51' },
|
|
2363
|
-
{ code: '+63', name: 'Philippines', value: '+63' },
|
|
2364
|
-
{ code: '+48', name: 'Poland', value: '+48' },
|
|
2365
|
-
{ code: '+351', name: 'Portugal', value: '+351' },
|
|
2366
|
-
{ code: '+1', name: 'Puerto Rico', value: '+1' },
|
|
2367
|
-
{ code: '+974', name: 'Qatar', value: '+974' },
|
|
2368
|
-
{ code: '+40', name: 'Romania', value: '+40' },
|
|
2369
|
-
{ code: '+7', name: 'Russia', value: '+7' },
|
|
2370
|
-
{ code: '+250', name: 'Rwanda', value: '+250' },
|
|
2371
|
-
{ code: '508', name: 'Saint Pierre and Miquelon', value: '508' },
|
|
2372
|
-
{ code: '+685', name: 'Samoa', value: '+685' },
|
|
2373
|
-
{ code: '+378', name: 'San Marino', value: '+378' },
|
|
2374
|
-
{ code: '+966', name: 'Saudi Arabia', value: '+966' },
|
|
2375
|
-
{ code: '+221', name: 'Senegal', value: '+221' },
|
|
2376
|
-
{ code: '+381', name: 'Serbia', value: '+381' },
|
|
2377
|
-
{ code: '+248', name: 'Seychelles', value: '+248' },
|
|
2378
|
-
{ code: '+232', name: 'Sierra Leone', value: '+232' },
|
|
2379
|
-
{ code: '+65', name: 'Singapore', value: '+65' },
|
|
2380
|
-
{ code: '+421', name: 'Slovakia', value: '+421' },
|
|
2381
|
-
{ code: '+386', name: 'Slovenia', value: '+386' },
|
|
2382
|
-
{ code: '+677', name: 'Solomon Islands', value: '+677' },
|
|
2383
|
-
{ code: '+27', name: 'South Africa', value: '+27' },
|
|
2384
|
-
{ code: '+500', name: 'South Georgia and the South Sandwich Islands', value: '+500' },
|
|
2385
|
-
{ code: '+82', name: 'South Korea', value: '+82' },
|
|
2386
|
-
{ code: '+34', name: 'Spain', value: '+34' },
|
|
2387
|
-
{ code: '+94', name: 'Sri Lanka', value: '+94' },
|
|
2388
|
-
{ code: '+249', name: 'Sudan', value: '+249' },
|
|
2389
|
-
{ code: '+597', name: 'Suriname', value: '+597' },
|
|
2390
|
-
{ code: '+268', name: 'Swaziland', value: '+268' },
|
|
2391
|
-
{ code: '+46', name: 'Sweden', value: '+46' },
|
|
2392
|
-
{ code: '+41', name: 'Switzerland', value: '+41' },
|
|
2393
|
-
{ code: '+963', name: 'Syria', value: '+963' },
|
|
2394
|
-
{ code: '+886', name: 'Taiwan', value: '+886' },
|
|
2395
|
-
{ code: '+992', name: 'Tajikistan', value: '+992' },
|
|
2396
|
-
{ code: '+255', name: 'Tanzania', value: '+255' },
|
|
2397
|
-
{ code: '+66', name: 'Thailand', value: '+66' },
|
|
2398
|
-
{ code: '+670', name: 'Timor Leste', value: '+670' },
|
|
2399
|
-
{ code: '+228', name: 'Togo', value: '+228' },
|
|
2400
|
-
{ code: '+690', name: 'Tokelau', value: '+690' },
|
|
2401
|
-
{ code: '+676', name: 'Tonga', value: '+676' },
|
|
2402
|
-
{ code: '+1', name: 'Trinidad and Tobago', value: '+1' },
|
|
2403
|
-
{ code: '+216', name: 'Tunisia', value: '+216' },
|
|
2404
|
-
{ code: '+90', name: 'Turkey', value: '+90' },
|
|
2405
|
-
{ code: '+993', name: 'Turkmenistan', value: '+993' },
|
|
2406
|
-
{ code: '+1', name: 'Turks and Caicos Islands', value: '+1' },
|
|
2407
|
-
{ code: '+688', name: 'Tuvalu', value: '+688' },
|
|
2408
|
-
{ code: '+1', name: 'U.S. Virgin Islands', value: '+1' },
|
|
2409
|
-
{ code: '+256', name: 'Uganda', value: '+256' },
|
|
2410
|
-
{ code: '+380', name: 'Ukraine', value: '+380' },
|
|
2411
|
-
{ code: '+971', name: 'United Arab Emirates', value: '+971' },
|
|
2412
|
-
{ code: '+44', name: 'United Kingdom', value: '+44' },
|
|
2413
|
-
{ code: '+1', name: 'United States', value: '+1' },
|
|
2414
|
-
{ code: '+598', name: 'Uruguay', value: '+598' },
|
|
2415
|
-
{ code: '+998', name: 'Uzbekistan', value: '+998' },
|
|
2416
|
-
{ code: '+678', name: 'Vanuatu', value: '+678' },
|
|
2417
|
-
{ code: '+58', name: 'Venezuela', value: '+58' },
|
|
2418
|
-
{ code: '+84', name: 'Vietnam', value: '+84' },
|
|
2419
|
-
{ code: '+1', name: 'Wake Island', value: '+1' },
|
|
2420
|
-
{ code: '+681', name: 'Wallis and Futuna', value: '+681' },
|
|
2421
|
-
{ code: '+967', name: 'Yemen', value: '+967' },
|
|
2422
|
-
{ code: '+260', name: 'Zambia', value: '+260' },
|
|
2423
|
-
{ code: '+255', name: 'Zanzibar', value: '+255' },
|
|
2424
|
-
{ code: '+263', name: 'Zimbabwe', value: '+263' },
|
|
1981
|
+
/**
|
|
1982
|
+
* A Template defines how a Verdocs signing flow will be performed, including attachments, signing fields, and
|
|
1983
|
+
* recipients.
|
|
1984
|
+
*
|
|
1985
|
+
* @module
|
|
1986
|
+
*/
|
|
1987
|
+
/**
|
|
1988
|
+
* Get all templates accessible by the caller, with optional filters.
|
|
1989
|
+
*
|
|
1990
|
+
* ```typescript
|
|
1991
|
+
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
1992
|
+
*
|
|
1993
|
+
* await Templates.getTemplates((VerdocsEndpoint.getDefault());
|
|
1994
|
+
* await Templates.getTemplates((VerdocsEndpoint.getDefault(), { is_starred: true });
|
|
1995
|
+
* await Templates.getTemplates((VerdocsEndpoint.getDefault(), { is_creator: true });
|
|
1996
|
+
* await Templates.getTemplates((VerdocsEndpoint.getDefault(), { is_organization: true });
|
|
1997
|
+
* ```
|
|
1998
|
+
*/
|
|
1999
|
+
const getTemplates = (endpoint, params) => endpoint.api //
|
|
2000
|
+
.post('/templates', { params })
|
|
2001
|
+
.then((r) => r.data);
|
|
2002
|
+
// export interface IListTemplatesParams {
|
|
2003
|
+
// name?: string;
|
|
2004
|
+
// sharing?: 'all' | 'personal' | 'shared' | 'public';
|
|
2005
|
+
// starred?: 'all' | 'starred' | 'unstarred';
|
|
2006
|
+
// sort?: 'name' | 'created_at' | 'updated_at' | 'last_used_at' | 'counter' | 'star_counter';
|
|
2007
|
+
// direction?: 'asc' | 'desc';
|
|
2008
|
+
// page?: number;
|
|
2009
|
+
// rows?: number;
|
|
2010
|
+
// }
|
|
2011
|
+
/**
|
|
2012
|
+
* Lists all templates accessible by the caller, with optional filters.
|
|
2013
|
+
*
|
|
2014
|
+
* ```typescript
|
|
2015
|
+
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
2016
|
+
*
|
|
2017
|
+
* await Templates.listTemplates((VerdocsEndpoint.getDefault(), { sharing: 'personal', sort: 'last_used_at' });
|
|
2018
|
+
* ```
|
|
2019
|
+
*/
|
|
2020
|
+
// export const listTemplates = (endpoint: VerdocsEndpoint, params?: IListTemplatesParams) =>
|
|
2021
|
+
// endpoint.api //
|
|
2022
|
+
// .post<ITemplateSummaries>('/templates/list', params, {baseURL: endpoint.getBaseURLv2()})
|
|
2023
|
+
// .then((r) => r.data);
|
|
2024
|
+
/**
|
|
2025
|
+
* Get one template by its ID.
|
|
2026
|
+
*
|
|
2027
|
+
* ```typescript
|
|
2028
|
+
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
2029
|
+
*
|
|
2030
|
+
* const template = await Templates.getTemplate((VerdocsEndpoint.getDefault(), '83da3d70-7857-4392-b876-c4592a304bc9');
|
|
2031
|
+
* ```
|
|
2032
|
+
*/
|
|
2033
|
+
const getTemplate = (endpoint, templateId) => endpoint.api //
|
|
2034
|
+
.get(`/templates/${templateId}`)
|
|
2035
|
+
.then((r) => r.data);
|
|
2036
|
+
/**
|
|
2037
|
+
* Get owner information for a template.
|
|
2038
|
+
*
|
|
2039
|
+
* ```typescript
|
|
2040
|
+
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
2041
|
+
*
|
|
2042
|
+
* const template = await Templates.getTemplateOwnerInfo((VerdocsEndpoint.getDefault(), '83da3d70-7857-4392-b876-c4592a304bc9');
|
|
2043
|
+
* ```
|
|
2044
|
+
*/
|
|
2045
|
+
const getTemplateOwnerInfo = (endpoint, templateId) => endpoint.api //
|
|
2046
|
+
.get(`/templates/${templateId}`)
|
|
2047
|
+
.then((r) => r.data);
|
|
2048
|
+
const ALLOWED_CREATE_FIELDS = [
|
|
2049
|
+
'name',
|
|
2050
|
+
'is_personal',
|
|
2051
|
+
'is_public',
|
|
2052
|
+
'sender',
|
|
2053
|
+
'description',
|
|
2054
|
+
'roles',
|
|
2055
|
+
'fields',
|
|
2425
2056
|
];
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2057
|
+
/**
|
|
2058
|
+
* Create a template.
|
|
2059
|
+
*
|
|
2060
|
+
* ```typescript
|
|
2061
|
+
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
2062
|
+
*
|
|
2063
|
+
* const newTemplate = await Templates.createTemplate((VerdocsEndpoint.getDefault(), {...});
|
|
2064
|
+
* ```
|
|
2065
|
+
*/
|
|
2066
|
+
const createTemplate = (endpoint, params, onUploadProgress) => {
|
|
2067
|
+
const options = {
|
|
2068
|
+
timeout: 120000,
|
|
2069
|
+
onUploadProgress: (event) => {
|
|
2070
|
+
const total = event.total || 1;
|
|
2071
|
+
const loaded = event.loaded || 0;
|
|
2072
|
+
onUploadProgress?.(Math.floor((loaded * 100) / (total || 1)), loaded, total || 1);
|
|
2073
|
+
},
|
|
2074
|
+
};
|
|
2075
|
+
if (params.documents && params.documents[0] instanceof File) {
|
|
2076
|
+
if (params.documents.length > 10) {
|
|
2077
|
+
throw new Error('createTemplate() has a maximum of 10 documents that can be attached.');
|
|
2078
|
+
}
|
|
2079
|
+
const formData = new FormData();
|
|
2080
|
+
ALLOWED_CREATE_FIELDS.forEach((allowedKey) => {
|
|
2081
|
+
if (params[allowedKey] !== undefined) {
|
|
2082
|
+
formData.append(allowedKey, params[allowedKey]);
|
|
2083
|
+
}
|
|
2084
|
+
});
|
|
2085
|
+
params.documents.forEach((file) => {
|
|
2086
|
+
formData.append('documents', file, file.name);
|
|
2087
|
+
});
|
|
2088
|
+
return endpoint.api.post('/templates', formData, options).then((r) => r.data);
|
|
2432
2089
|
}
|
|
2433
|
-
else
|
|
2434
|
-
return
|
|
2090
|
+
else {
|
|
2091
|
+
return endpoint.api.post('/templates', params, options).then((r) => r.data);
|
|
2435
2092
|
}
|
|
2436
|
-
|
|
2437
|
-
|
|
2093
|
+
};
|
|
2094
|
+
/**
|
|
2095
|
+
* Create a template.
|
|
2096
|
+
*
|
|
2097
|
+
* ```typescript
|
|
2098
|
+
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
2099
|
+
*
|
|
2100
|
+
* const newTemplate = await Templates.createTemplatev2((VerdocsEndpoint.getDefault(), {...});
|
|
2101
|
+
* ```
|
|
2102
|
+
*/
|
|
2103
|
+
const createTemplatev2 = (endpoint, params, onUploadProgress) => {
|
|
2104
|
+
const options = {
|
|
2105
|
+
timeout: 120000,
|
|
2106
|
+
onUploadProgress: (event) => {
|
|
2107
|
+
const total = event.total || 1;
|
|
2108
|
+
const loaded = event.loaded || 0;
|
|
2109
|
+
onUploadProgress?.(Math.floor((loaded * 100) / (total || 1)), loaded, total || 1);
|
|
2110
|
+
},
|
|
2111
|
+
};
|
|
2112
|
+
if (params.documents && params.documents[0] instanceof File) {
|
|
2113
|
+
const formData = new FormData();
|
|
2114
|
+
ALLOWED_CREATE_FIELDS.forEach((allowedKey) => {
|
|
2115
|
+
if (params[allowedKey] !== undefined) {
|
|
2116
|
+
formData.append(allowedKey, params[allowedKey]);
|
|
2117
|
+
}
|
|
2118
|
+
});
|
|
2119
|
+
params.documents.forEach((file) => {
|
|
2120
|
+
formData.append('documents', file, file.name);
|
|
2121
|
+
});
|
|
2122
|
+
return endpoint.api.post('/v2/templates', formData, options).then((r) => r.data);
|
|
2438
2123
|
}
|
|
2439
|
-
else
|
|
2440
|
-
return
|
|
2124
|
+
else {
|
|
2125
|
+
return endpoint.api.post('/v2/templates', params, options).then((r) => r.data);
|
|
2441
2126
|
}
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
}
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
}
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2127
|
+
};
|
|
2128
|
+
/**
|
|
2129
|
+
* Create a template from a Sharepoint asset.
|
|
2130
|
+
*
|
|
2131
|
+
* ```typescript
|
|
2132
|
+
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
2133
|
+
*
|
|
2134
|
+
* const newTemplate = await Templates.createTemplateFromSharepoint((VerdocsEndpoint.getDefault(), {...});
|
|
2135
|
+
* ```
|
|
2136
|
+
*/
|
|
2137
|
+
const createTemplateFromSharepoint = (endpoint, params) => {
|
|
2138
|
+
const options = {
|
|
2139
|
+
timeout: 120000,
|
|
2140
|
+
};
|
|
2141
|
+
return endpoint.api.post('/templates/from-sharepoint', params, options).then((r) => r.data);
|
|
2142
|
+
};
|
|
2143
|
+
/**
|
|
2144
|
+
* Update a template.
|
|
2145
|
+
*
|
|
2146
|
+
* ```typescript
|
|
2147
|
+
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
2148
|
+
*
|
|
2149
|
+
* const updatedTemplate = await Templates.updateTemplate((VerdocsEndpoint.getDefault(), '83da3d70-7857-4392-b876-c4592a304bc9', { name: 'New Name' });
|
|
2150
|
+
* ```
|
|
2151
|
+
*/
|
|
2152
|
+
const updateTemplate = (endpoint, templateId, params) => endpoint.api //
|
|
2153
|
+
.put(`/templates/${templateId}`, params)
|
|
2154
|
+
.then((r) => r.data);
|
|
2155
|
+
/**
|
|
2156
|
+
* Delete a template.
|
|
2157
|
+
*
|
|
2158
|
+
* ```typescript
|
|
2159
|
+
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
2160
|
+
*
|
|
2161
|
+
* await Templates.deleteTemplate((VerdocsEndpoint.getDefault(), '83da3d70-7857-4392-b876-c4592a304bc9');
|
|
2162
|
+
* ```
|
|
2163
|
+
*/
|
|
2164
|
+
const deleteTemplate = (endpoint, templateId) => endpoint.api //
|
|
2165
|
+
.delete(`/templates/${templateId}`)
|
|
2166
|
+
.then((r) => r.data);
|
|
2167
|
+
/**
|
|
2168
|
+
* Search for templates matching various criteria.
|
|
2169
|
+
*
|
|
2170
|
+
* ```typescript
|
|
2171
|
+
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
2172
|
+
*
|
|
2173
|
+
* const {result, page, total} = await Templates.search((VerdocsEndpoint.getDefault(), { ... });
|
|
2174
|
+
* ```
|
|
2175
|
+
*/
|
|
2176
|
+
const searchTemplates = async (endpoint, params) => endpoint.api //
|
|
2177
|
+
.post('/templates/search', params)
|
|
2178
|
+
.then((r) => r.data);
|
|
2179
|
+
/**
|
|
2180
|
+
* Get a summary of template data, typically used to populate admin panel dashboard pages.
|
|
2181
|
+
*
|
|
2182
|
+
* ```typescript
|
|
2183
|
+
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
2184
|
+
*
|
|
2185
|
+
* const summary = await Templates.getSummary((VerdocsEndpoint.getDefault(), 0);
|
|
2186
|
+
* ```
|
|
2187
|
+
*/
|
|
2188
|
+
const getTemplatesSummary = async (endpoint, params = {}) => endpoint.api //
|
|
2189
|
+
.post('/templates/summary', params)
|
|
2190
|
+
.then((r) => r.data);
|
|
2191
|
+
const cachedTemplates = {};
|
|
2192
|
+
/**
|
|
2193
|
+
* Wrapper for `getTemplate()` that limits queries to one every 2 seconds per template ID.
|
|
2194
|
+
* This is intended for use in component hierarchies that all rely on the same template
|
|
2195
|
+
* to avoid unnecessary repeat server calls.
|
|
2196
|
+
*/
|
|
2197
|
+
const throttledGetTemplate = (endpoint, templateId) => {
|
|
2198
|
+
if (cachedTemplates[templateId] && cachedTemplates[templateId].loaded + 2000 < new Date().getTime()) {
|
|
2199
|
+
return cachedTemplates[templateId].template;
|
|
2483
2200
|
}
|
|
2484
|
-
return
|
|
2485
|
-
}
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
}
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2201
|
+
return getTemplate(endpoint, templateId).then((template) => {
|
|
2202
|
+
cachedTemplates[templateId] = { loaded: new Date().getTime(), template };
|
|
2203
|
+
return template;
|
|
2204
|
+
});
|
|
2205
|
+
};
|
|
2206
|
+
/**
|
|
2207
|
+
* List templates.
|
|
2208
|
+
*
|
|
2209
|
+
* ```typescript
|
|
2210
|
+
* import {Templates} from '@verdocs/js-sdk/Templates';
|
|
2211
|
+
*
|
|
2212
|
+
* const {totals, templates} = await Templates.listTemplates((VerdocsEndpoint.getDefault(), { q: 'test', sort: 'created_at' }); * ```
|
|
2213
|
+
*/
|
|
2214
|
+
const listTemplates = async (endpoint, params = {}) => endpoint.api //
|
|
2215
|
+
.post('/templates/list', params)
|
|
2216
|
+
.then((r) => r.data);
|
|
2217
|
+
|
|
2218
|
+
/**
|
|
2219
|
+
* A TemplateDocument represents a PDF or other attachment in a Template.
|
|
2220
|
+
*
|
|
2221
|
+
* @module
|
|
2222
|
+
*/
|
|
2223
|
+
/**
|
|
2224
|
+
* Get all the Template Documents associated to a particular Template.
|
|
2225
|
+
*
|
|
2226
|
+
* ```typescript
|
|
2227
|
+
* import {TemplateDocument} from '@verdocs/js-sdk/Templates';
|
|
2228
|
+
*
|
|
2229
|
+
* await TemplateDocument.geTemplateDocuments((VerdocsEndpoint.getDefault(), templateId);
|
|
2230
|
+
* ```
|
|
2231
|
+
*/
|
|
2232
|
+
const getTemplateDocuments = (endpoint, templateId) => endpoint.api //
|
|
2233
|
+
.get(`/templates/${templateId}/documents/`)
|
|
2234
|
+
.then((r) => r.data);
|
|
2235
|
+
/**
|
|
2236
|
+
* Get a specific Document.
|
|
2237
|
+
*
|
|
2238
|
+
* ```typescript
|
|
2239
|
+
* import {TemplateDocument} from '@verdocs/js-sdk/Templates';
|
|
2240
|
+
*
|
|
2241
|
+
* await TemplateDocument.geTemplateDocument((VerdocsEndpoint.getDefault(), templateId,documentId);
|
|
2242
|
+
* ```
|
|
2243
|
+
*/
|
|
2244
|
+
const getTemplateDocument = (endpoint, templateId, documentId) => endpoint.api //
|
|
2245
|
+
.get(`/templates/${templateId}/documents/${documentId}`)
|
|
2246
|
+
.then((r) => r.data);
|
|
2247
|
+
/**
|
|
2248
|
+
* Create a Document for a particular Template.
|
|
2249
|
+
*
|
|
2250
|
+
* ```typescript
|
|
2251
|
+
* import {TemplateDocument} from '@verdocs/js-sdk/Templates';
|
|
2252
|
+
*
|
|
2253
|
+
* await TemplateDocument.createDocument((VerdocsEndpoint.getDefault(), templateID, params);
|
|
2254
|
+
* ```
|
|
2255
|
+
*/
|
|
2256
|
+
const createTemplateDocument = (endpoint, templateId, file, onUploadProgress) => {
|
|
2257
|
+
const formData = new FormData();
|
|
2258
|
+
formData.append('document', file, file.name);
|
|
2259
|
+
return endpoint.api //
|
|
2260
|
+
.post(`/templates/${templateId}/documents`, formData, {
|
|
2261
|
+
timeout: 120000,
|
|
2262
|
+
onUploadProgress: (event) => {
|
|
2263
|
+
const total = event.total || 1;
|
|
2264
|
+
const loaded = event.loaded || 0;
|
|
2265
|
+
onUploadProgress?.(Math.floor((loaded * 100) / (total || 1)), loaded, total || 1);
|
|
2266
|
+
},
|
|
2267
|
+
})
|
|
2268
|
+
.then((r) => r.data);
|
|
2269
|
+
};
|
|
2270
|
+
/**
|
|
2271
|
+
* Delete a specific Document.
|
|
2272
|
+
*
|
|
2273
|
+
* ```typescript
|
|
2274
|
+
* import {TemplateDocument} from '@verdocs/js-sdk/Templates';
|
|
2275
|
+
*
|
|
2276
|
+
* await TemplateDocument.deleteDocument((VerdocsEndpoint.getDefault(), templateID, documentID);
|
|
2277
|
+
* ```
|
|
2278
|
+
*/
|
|
2279
|
+
const deleteTemplateDocument = (endpoint, templateId, documentId) => endpoint.api //
|
|
2280
|
+
.delete(`/templates/${templateId}/documents/${documentId}`)
|
|
2281
|
+
.then((r) => r.data);
|
|
2282
|
+
/**
|
|
2283
|
+
* Get (binary download) a file attached to a Template. It is important to use this method
|
|
2284
|
+
* rather than a direct A HREF or similar link to set the authorization headers for the
|
|
2285
|
+
* request.
|
|
2286
|
+
*/
|
|
2287
|
+
const getTemplateDocumentFile = async (endpoint, templateId, documentId) => endpoint.api //
|
|
2288
|
+
.get(`/templates/${templateId}/documents/${documentId}?file=true`, { responseType: 'blob' })
|
|
2289
|
+
.then((r) => r.data);
|
|
2290
|
+
/**
|
|
2291
|
+
* Get (binary download) a file attached to a Template. It is important to use this method
|
|
2292
|
+
* rather than a direct A HREF or similar link to set the authorization headers for the
|
|
2293
|
+
* request.
|
|
2294
|
+
*/
|
|
2295
|
+
const getTemplateDocumentThumbnail = async (endpoint, templateId, documentId) => endpoint.api //
|
|
2296
|
+
.get(`/templates/${templateId}/documents/${documentId}?thumbnail=true`, { responseType: 'blob' })
|
|
2297
|
+
.then((r) => r.data);
|
|
2298
|
+
/**
|
|
2299
|
+
* Get a display URI for a given page in a file attached to a template document. These pages are rendered server-side
|
|
2300
|
+
* into PNG resources suitable for display in IMG tags although they may be used elsewhere. Note that these are intended
|
|
2301
|
+
* for DISPLAY ONLY, are not legally binding documents, and do not contain any encoded metadata from participants. The
|
|
2302
|
+
* original asset may be obtained by calling `getTemplateDocumentFile()` or similar.
|
|
2303
|
+
*/
|
|
2304
|
+
const getTemplateDocumentPageDisplayUri = async (endpoint, templateId, documentId, page) => endpoint.api.get(`/templates/${templateId}/documents/${documentId}/pages/${page}/image`).then((r) => r.data);
|
|
2305
|
+
|
|
2306
|
+
/**
|
|
2307
|
+
* Get all defined validators
|
|
2308
|
+
*
|
|
2309
|
+
* ```typescript
|
|
2310
|
+
* import {Documents} from '@verdocs/js-sdk/Templates';
|
|
2311
|
+
*
|
|
2312
|
+
* await Documents.getDocuments(templateID);
|
|
2313
|
+
* ```
|
|
2314
|
+
*/
|
|
2315
|
+
const getValidators = (endpoint) => endpoint.api //
|
|
2316
|
+
.get('/validators')
|
|
2317
|
+
.then((r) => r.data);
|
|
2318
|
+
const getValidator = (endpoint, validatorName) => endpoint.api //
|
|
2319
|
+
.get(`/validators/${validatorName}`)
|
|
2320
|
+
.then((r) => r.data);
|
|
2321
|
+
const EMAIL_REGEX = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
|
2322
|
+
const isValidEmail = (email) => !!email && EMAIL_REGEX.test(email);
|
|
2323
|
+
// @see https://www.regextester.com/1978
|
|
2324
|
+
const PHONE_REGEX = /((?:\+|00)[17](?: |\-)?|(?:\+|00)[1-9]\d{0,2}(?: |\-)?|(?:\+|00)1\-\d{3}(?: |\-)?)?(0\d|\([0-9]{3}\)|[1-9]{0,3})(?:((?: |\-)[0-9]{2}){4}|((?:[0-9]{2}){4})|((?: |\-)[0-9]{3}(?: |\-)[0-9]{4})|([0-9]{7}))/;
|
|
2325
|
+
const isValidPhone = (phone) => !!phone && PHONE_REGEX.test(phone);
|
|
2326
|
+
const isValidRoleName = (value, roles) => roles.findIndex((role) => role.name === value) !== -1;
|
|
2327
|
+
const TagRegEx = /^[a-zA-Z0-9-]{0,32}$/;
|
|
2328
|
+
const isValidTag = (value, tags) => TagRegEx.test(value) || tags.findIndex((tag) => tag === value) !== -1;
|
|
2554
2329
|
|
|
2555
2330
|
/**
|
|
2556
|
-
*
|
|
2331
|
+
* Authenticate to Verdocs via user/password authentication
|
|
2332
|
+
*
|
|
2333
|
+
* ```typescript
|
|
2334
|
+
* import {Auth} from '@verdocs/js-sdk/Auth';
|
|
2335
|
+
* import {Transport} from '@verdocs/js-sdk/HTTP';
|
|
2336
|
+
*
|
|
2337
|
+
* const {accessToken} = await Auth.authenticateUser({ username: 'test@test.com', password: 'PASSWORD' });
|
|
2338
|
+
* Transport.setAuthToken(accessToken);
|
|
2339
|
+
* ```
|
|
2340
|
+
*/
|
|
2341
|
+
const authenticateUser = (endpoint, params) => endpoint.api //
|
|
2342
|
+
.post('/authentication/login', params)
|
|
2343
|
+
.then((r) => r.data);
|
|
2344
|
+
/**
|
|
2345
|
+
* Authenticate to Verdocs via client ID / Secret authentication. **NOTE: This is only suitable for
|
|
2346
|
+
* NodeJS server-side applications. Never expose your Client Secret in a Web or Mobile app!** Also note
|
|
2347
|
+
* that access tokens may be cached by server-side apps (and this is recommended) but do expire after 2
|
|
2348
|
+
* hours. This expiration may change based on future security needs. Application developers are encouraged
|
|
2349
|
+
* to check the `exp` expiration field in the response accessToken and renew tokens after they expire.
|
|
2350
|
+
*
|
|
2351
|
+
* ```typescript
|
|
2352
|
+
* import {Auth} from '@verdocs/js-sdk/Auth';
|
|
2353
|
+
* import {Transport} from '@verdocs/js-sdk/HTTP';
|
|
2354
|
+
*
|
|
2355
|
+
* const {accessToken} = await Auth.authenticateApp({ client_id: 'CLIENTID', client_secret: 'SECRET' });
|
|
2356
|
+
* Transport.setAuthToken(accessToken);
|
|
2357
|
+
* ```
|
|
2358
|
+
*/
|
|
2359
|
+
const authenticateApp = (endpoint, params) => endpoint.api //
|
|
2360
|
+
.post('/authentication/login_client', {}, { headers: params })
|
|
2361
|
+
.then((r) => r.data);
|
|
2362
|
+
/**
|
|
2363
|
+
* Validate a token. Only Verdocs tokens will be accepted. Most applications can decode tokens locally,
|
|
2364
|
+
* because tokens will be validated when API calls are made anyway. However, high-security applications
|
|
2365
|
+
* may use this endpoint to check if a token has been revoked.
|
|
2366
|
+
*
|
|
2367
|
+
* ```typescript
|
|
2368
|
+
* import {Auth} from '@verdocs/js-sdk/Auth';
|
|
2369
|
+
*
|
|
2370
|
+
* const {valid} = await Auth.validateToken({ token });
|
|
2371
|
+
* if (!valid) {
|
|
2372
|
+
* window.alert('Session invalid or expired. Please re-authenticate.');
|
|
2373
|
+
* }
|
|
2374
|
+
* ```
|
|
2375
|
+
*/
|
|
2376
|
+
const validateToken = (endpoint, params) => endpoint.api //
|
|
2377
|
+
.post('/token/isValid', params)
|
|
2378
|
+
.then((r) => r.data);
|
|
2379
|
+
/**
|
|
2380
|
+
* If called before the session expires, this will refresh the caller's session and tokens.
|
|
2381
|
+
*
|
|
2382
|
+
* ```typescript
|
|
2383
|
+
* import {Auth} from '@verdocs/js-sdk/Auth';
|
|
2384
|
+
* import {Transport} from '@verdocs/js-sdk/HTTP';
|
|
2385
|
+
*
|
|
2386
|
+
* const {accessToken} = await Auth.refreshTokens();
|
|
2387
|
+
* Transport.setAuthToken(accessToken);
|
|
2388
|
+
* ```
|
|
2389
|
+
*/
|
|
2390
|
+
const refreshTokens = (endpoint) => endpoint.api //
|
|
2391
|
+
.get('/token')
|
|
2392
|
+
.then((r) => r.data);
|
|
2393
|
+
/**
|
|
2394
|
+
* Update the caller's password. To help prevent CSRF attack vectors, the user's old password and email address are required.
|
|
2395
|
+
*
|
|
2396
|
+
* ```typescript
|
|
2397
|
+
* import {Auth} from '@verdocs/js-sdk/Auth';
|
|
2398
|
+
*
|
|
2399
|
+
* const {status, message} = await Auth.updatePassword({ email, oldPassword, newPassword });
|
|
2400
|
+
* if (status !== 'OK') {
|
|
2401
|
+
* window.alert(`Password reset error: ${message}`);
|
|
2402
|
+
* }
|
|
2403
|
+
* ```
|
|
2557
2404
|
*/
|
|
2558
|
-
const
|
|
2405
|
+
const updatePassword = (endpoint, params) => endpoint.api //
|
|
2406
|
+
.put('/user/update_password', params)
|
|
2407
|
+
.then((r) => r.data);
|
|
2559
2408
|
/**
|
|
2560
|
-
*
|
|
2561
|
-
*
|
|
2409
|
+
* Reset the caller's password.
|
|
2410
|
+
*
|
|
2411
|
+
* ```typescript
|
|
2412
|
+
* import {Auth} from '@verdocs/js-sdk/Auth';
|
|
2413
|
+
*
|
|
2414
|
+
* const {success} = await Auth.resetPassword({ email });
|
|
2415
|
+
* if (status !== 'OK') {
|
|
2416
|
+
* window.alert(`Please check your email for instructions on how to reset your password.`);
|
|
2417
|
+
* }
|
|
2418
|
+
* ```
|
|
2562
2419
|
*/
|
|
2563
|
-
const
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2420
|
+
const resetPassword = (endpoint, params) => endpoint.api //
|
|
2421
|
+
.post('/user/reset_password', params)
|
|
2422
|
+
.then((r) => r.data);
|
|
2423
|
+
/**
|
|
2424
|
+
* Update the caller's email address.
|
|
2425
|
+
*
|
|
2426
|
+
* ```typescript
|
|
2427
|
+
* import {Auth} from '@verdocs/js-sdk/Auth';
|
|
2428
|
+
*
|
|
2429
|
+
* const {profiles} = await Auth.updateEmail({ email: newEmail });
|
|
2430
|
+
* ```
|
|
2431
|
+
*/
|
|
2432
|
+
const updateEmail = (endpoint, params) => endpoint.api //
|
|
2433
|
+
.put('/user/update_email', params)
|
|
2434
|
+
.then((r) => r.data);
|
|
2435
|
+
/**
|
|
2436
|
+
* Resend the email verification request. Note that to prevent certain forms of abuse, the email address is not
|
|
2437
|
+
* a parameter here. Instead, the caller must be authenticated as the (unverified) user. To simplify this process,
|
|
2438
|
+
* the access token to be used may be passed directly as a parameter here. This avoids the need to set it as the
|
|
2439
|
+
* active token on an endpoint, which may be inconvenient in workflows where it is preferable to keep the user in
|
|
2440
|
+
* "anonymous" mode while verification is being performed.
|
|
2441
|
+
*
|
|
2442
|
+
* ```typescript
|
|
2443
|
+
* import {Auth} from '@verdocs/js-sdk/Auth';
|
|
2444
|
+
*
|
|
2445
|
+
* const result = await Auth.resendVerification();
|
|
2446
|
+
* ```
|
|
2447
|
+
*/
|
|
2448
|
+
const resendVerification = (endpoint, accessToken) => endpoint.api //
|
|
2449
|
+
.post('/user/email_verification', {}, accessToken ? { headers: { Authorization: `Bearer ${accessToken}` } } : {})
|
|
2450
|
+
.then((r) => r.data);
|
|
2451
|
+
const createUser = (endpoint, params) => endpoint.api //
|
|
2452
|
+
.post('/user', params)
|
|
2453
|
+
.then((r) => r.data);
|
|
2454
|
+
|
|
2455
|
+
// TODO
|
|
2456
|
+
const billingPlaceholder = {};
|
|
2457
|
+
|
|
2458
|
+
const getNotifications = async (endpoint) => endpoint.api //
|
|
2459
|
+
.get('/notifications')
|
|
2460
|
+
.then((r) => r.data);
|
|
2583
2461
|
|
|
2584
2462
|
/**
|
|
2585
|
-
*
|
|
2586
|
-
*
|
|
2463
|
+
* Get the user's available profiles. The current profile will be marked with `current: true`.
|
|
2464
|
+
*
|
|
2465
|
+
* ```typescript
|
|
2466
|
+
* import {Profiles} from '@verdocs/js-sdk/Users';
|
|
2467
|
+
*
|
|
2468
|
+
* const profiles = await Profiles.getProfiles()
|
|
2469
|
+
* ```
|
|
2587
2470
|
*/
|
|
2588
|
-
const
|
|
2589
|
-
.
|
|
2590
|
-
.
|
|
2471
|
+
const getProfiles = (endpoint) => endpoint.api //
|
|
2472
|
+
.get('/profiles')
|
|
2473
|
+
.then((r) => r.data);
|
|
2591
2474
|
/**
|
|
2592
|
-
*
|
|
2475
|
+
* Get the user's available profiles. The current profile will be marked with `current: true`.
|
|
2476
|
+
*
|
|
2477
|
+
* ```typescript
|
|
2478
|
+
* import {Profiles} from '@verdocs/js-sdk/Users';
|
|
2479
|
+
*
|
|
2480
|
+
* const profiles = await Profiles.getCurrentProfile()
|
|
2481
|
+
* ```
|
|
2593
2482
|
*/
|
|
2594
|
-
const
|
|
2483
|
+
const getCurrentProfile = (endpoint) => endpoint.api //
|
|
2484
|
+
.get('/profiles')
|
|
2485
|
+
.then((r) => (r.data || []).find((profile) => profile.current));
|
|
2595
2486
|
/**
|
|
2596
|
-
*
|
|
2487
|
+
* Get a list of system roles.
|
|
2488
|
+
*
|
|
2489
|
+
* ```typescript
|
|
2490
|
+
* import {Profiles} from '@verdocs/js-sdk/Users';
|
|
2491
|
+
*
|
|
2492
|
+
* const roles = await Profiles.getRoles();
|
|
2493
|
+
* ```
|
|
2597
2494
|
*/
|
|
2598
|
-
const
|
|
2495
|
+
const getRoles = (endpoint) => endpoint.api //
|
|
2496
|
+
.get('/roles')
|
|
2497
|
+
.then((r) => r.data);
|
|
2599
2498
|
/**
|
|
2600
|
-
*
|
|
2499
|
+
* Get a list of system roles.
|
|
2500
|
+
*
|
|
2501
|
+
* ```typescript
|
|
2502
|
+
* import {Profiles} from '@verdocs/js-sdk/Users';
|
|
2503
|
+
*
|
|
2504
|
+
* const permissions = await Profiles.getPermissions();
|
|
2505
|
+
* ```
|
|
2601
2506
|
*/
|
|
2602
|
-
const
|
|
2603
|
-
.
|
|
2604
|
-
.
|
|
2605
|
-
|
|
2507
|
+
const getPermissions = (endpoint) => endpoint.api //
|
|
2508
|
+
.get('/permissions')
|
|
2509
|
+
.then((r) => r.data);
|
|
2510
|
+
/**
|
|
2511
|
+
* Create a profile. If the caller does not have a "current" profile set, the new profile will be made current.
|
|
2512
|
+
*
|
|
2513
|
+
* ```typescript
|
|
2514
|
+
* import {Profiles} from '@verdocs/js-sdk/Users';
|
|
2515
|
+
*
|
|
2516
|
+
* const newProfile = await Profiles.createProfile({ first_name: 'FIRST', last_name: 'LAST', email: 'EMAIL' });
|
|
2517
|
+
* ```
|
|
2518
|
+
*/
|
|
2519
|
+
const createProfile = (endpoint, params) => endpoint.api //
|
|
2520
|
+
.post('/profiles', params)
|
|
2521
|
+
.then((r) => r.data);
|
|
2522
|
+
/**
|
|
2523
|
+
* Get a profile. The caller must have admin access to the given profile.
|
|
2524
|
+
* TODO: Add a "public" profile endpoint for public pages
|
|
2525
|
+
*
|
|
2526
|
+
* ```typescript
|
|
2527
|
+
* import {Profiles} from '@verdocs/js-sdk/Users';
|
|
2528
|
+
*
|
|
2529
|
+
* const profile = await Profiles.getProfile('PROFILEID');
|
|
2530
|
+
* ```
|
|
2531
|
+
*/
|
|
2532
|
+
const getProfile = (endpoint, profileId) => endpoint.api //
|
|
2533
|
+
.get(`/profiles/${profileId}`)
|
|
2534
|
+
.then((r) => r.data);
|
|
2535
|
+
/**
|
|
2536
|
+
* Get a profile's permissions. The caller must have admin access to the given profile.
|
|
2537
|
+
*
|
|
2538
|
+
* ```typescript
|
|
2539
|
+
* import {Profiles} from '@verdocs/js-sdk/Users';
|
|
2540
|
+
*
|
|
2541
|
+
* const permissions = await Profiles.getProfilePermissions('PROFILEID');
|
|
2542
|
+
* ```
|
|
2543
|
+
*/
|
|
2544
|
+
const getProfilePermissions = (endpoint, profileId) => endpoint.api //
|
|
2545
|
+
.get(`/profiles/${profileId}/permissions`)
|
|
2546
|
+
.then((r) => r.data);
|
|
2547
|
+
/**
|
|
2548
|
+
* Get a profile's groups.
|
|
2549
|
+
*
|
|
2550
|
+
* ```typescript
|
|
2551
|
+
* import {Profiles} from '@verdocs/js-sdk/Users';
|
|
2552
|
+
*
|
|
2553
|
+
* const groups = await Profiles.getProfileGroups('PROFILEID');
|
|
2554
|
+
* ```
|
|
2555
|
+
*/
|
|
2556
|
+
const getProfileGroups = (endpoint, profileId) => endpoint.api //
|
|
2557
|
+
.get(`/profiles/${profileId}/groups`)
|
|
2558
|
+
.then((r) => r.data);
|
|
2559
|
+
/**
|
|
2560
|
+
* Switch the caller's "current" profile. The current profile is used for permissions checking and profile_id field settings
|
|
2561
|
+
* for most operations in Verdocs. It is important to select the appropropriate profile before calling other API functions.
|
|
2562
|
+
*
|
|
2563
|
+
* ```typescript
|
|
2564
|
+
* import {Profiles} from '@verdocs/js-sdk/Users';
|
|
2565
|
+
*
|
|
2566
|
+
* const newProfile = await Profiles.switchProfile('PROFILEID');
|
|
2567
|
+
* ```
|
|
2568
|
+
*/
|
|
2569
|
+
const switchProfile = (endpoint, profileId) => endpoint.api //
|
|
2570
|
+
.post(`/profiles/${profileId}/switch`)
|
|
2571
|
+
.then((r) => r.data);
|
|
2572
|
+
/**
|
|
2573
|
+
* Update a profile. For future expansion, the profile ID to update is required, but currently this must also be the
|
|
2574
|
+
* "current" profile for the caller.
|
|
2575
|
+
*
|
|
2576
|
+
* ```typescript
|
|
2577
|
+
* import {Profiles} from '@verdocs/js-sdk/Users';
|
|
2578
|
+
*
|
|
2579
|
+
* const newProfile = await Profiles.updateProfile('PROFILEID');
|
|
2580
|
+
* ```
|
|
2581
|
+
*/
|
|
2582
|
+
const updateProfile = (endpoint, profileId, params) => endpoint.api //
|
|
2583
|
+
.put(`/profiles/${profileId}`, params)
|
|
2584
|
+
.then((r) => r.data);
|
|
2585
|
+
/**
|
|
2586
|
+
* Delete a profile. If the requested profile is the caller's curent profile, the next available profile will be selected.
|
|
2587
|
+
*
|
|
2588
|
+
* ```typescript
|
|
2589
|
+
* import {Profiles} from '@verdocs/js-sdk/Users';
|
|
2590
|
+
*
|
|
2591
|
+
* await Profiles.deleteProfile('PROFILEID');
|
|
2592
|
+
* ```
|
|
2593
|
+
*/
|
|
2594
|
+
const deleteProfile = (endpoint, profileId) => endpoint.api //
|
|
2595
|
+
.delete(`/profiles/${profileId}`)
|
|
2596
|
+
.then((r) => r.data);
|
|
2597
|
+
/**
|
|
2598
|
+
* Create a user account and parent organization. This endpoint is for creating a new organization. Users joining an
|
|
2599
|
+
* existing organization should be invited, and follow their invitation links/instructions to create their accounts.
|
|
2600
|
+
*
|
|
2601
|
+
* ```typescript
|
|
2602
|
+
* import {Profiles} from '@verdocs/js-sdk/Users';
|
|
2603
|
+
*
|
|
2604
|
+
* const newAccount = await Profiles.createBusinessAccount({
|
|
2605
|
+
* orgName: 'ORG', email: 'a@b.com', password: '12345678', firstName: 'FIRST', lastName: 'LAST'
|
|
2606
|
+
* });
|
|
2607
|
+
* ```
|
|
2608
|
+
*/
|
|
2609
|
+
const createBusinessAccount = (endpoint, params) => endpoint.api //
|
|
2610
|
+
.post('/user/business', params)
|
|
2611
|
+
.then((r) => r.data);
|
|
2612
|
+
const recordSignupSurvey = (endpoint, params) => endpoint.api //
|
|
2613
|
+
.post('/user/signup', params)
|
|
2614
|
+
.then((r) => r.data);
|
|
2606
2615
|
|
|
2607
|
-
export { AtoB, Countries, VerdocsEndpoint, acceptOrganizationInvitation, addGroupMembers, addGroupPermission, addOrganizationMemberRole, addTemplateTag, authenticateApp, authenticateUser, billingPlaceholder, blobToBase64, canPerformTemplateAction, cancelEnvelope, capitalize, claimNewUser, convertToE164, createApiKey, createBusinessAccount, createEnvelope, createEnvelopeReminder, createField, createInitials, createOrganization, createOrganizationInvitation, createProfile, createSignature, createTag, createTemplate, createTemplateDocument, createTemplateFromSharepoint, createTemplateReminder, createTemplateRole, createTemplatev2, createUser, declineOrganizationInvitation, decodeAccessTokenBody, decodeJWTBody, deleteApiKey, deleteEnvelopeFieldAttachment, deleteEnvelopeReminder, deleteField, deleteGroupMembers, deleteGroupPermission, deleteOrganization, deleteOrganizationInvitation, deleteOrganizationMember, deleteOrganizationMemberRole, deleteProfile, deleteSignature, deleteTemplate, deleteTemplateDocument, deleteTemplateReminder, deleteTemplateRole, deleteTemplateTag, downloadBlob, envelopeIsActive, envelopeIsComplete, envelopeRecipientAgree, envelopeRecipientChangeOwner, envelopeRecipientDecline, envelopeRecipientPrepare, envelopeRecipientSubmit, envelopeRecipientUpdateName, fileToDataUrl, formatFullName, formatInitials, formatShortTimeAgo, fullNameToInitials, getAllTags, getApiKeys, getCountryByCode, getCurrentProfile, getDocumentDownloadLink, getDocumentPreviewLink, getEnvelope, getEnvelopeDocument, getEnvelopeDocumentPageDisplayUri, getEnvelopeFile, getEnvelopeRecipients, getEnvelopeReminder, getEnvelopesSummary, getFieldAttachment, getGroup, getGroupByName, getGroupMembers, getGroups, getInPersonLink, getMatchingCountry, getNextRecipient, getNotifications, getOrganization, getOrganizationInvitation, getOrganizationInvitations, getOrganizationMemberPlans, getOrganizationMembers, getOrganizations, getPermissions, getPlusOneCountry, getProfile, getProfileGroups, getProfilePermissions, getProfiles, getRGB, getRGBA, getRLeft, getRTop, getRValue, getRecipientsWithActions, getRoleColor, getRoles, getSignature, getSignatures, getSignerToken, getSigningSession, getStars, getTag, getTemplate, getTemplateDocument, getTemplateDocumentFile, getTemplateDocumentPageDisplayUri, getTemplateDocumentThumbnail, getTemplateDocuments, getTemplateOwnerInfo, getTemplateReminder, getTemplateRole, getTemplateRoleFields, getTemplateRoles, getTemplateTags, getTemplates, getTemplatesSummary, getValidator, getValidators, getWebhooks, hasRequiredPermissions, integerSequence, isAmericanSamoa, isCanada, isDominicanRepublic, isFrenchGuiana, isGuadeloupe, isMartinique, isMayotte, isPuertoRico, isValidEmail, isValidPhone, isValidRoleName, isValidTag, listEnvelopes, listTemplates, nameToRGBA, recipientCanAct, recipientHasAction, recordSignupSurvey, refreshTokens, rescale, resendInvitation, resendOrganizationInvitation, resendVerification, resetPassword, rotateApiKey, searchEnvelopes, searchTemplates, sendDelegate, setWebhooks, switchProfile, throttledGetEnvelope, throttledGetTemplate, timePeriod, toggleStar, updateApiKey, updateEmail, updateEnvelopeField, updateEnvelopeFieldInitials, updateEnvelopeFieldSignature, updateEnvelopeReminder, updateField, updateOrganization, updateOrganizationInvitation, updatePassword, updateProfile, updateRecipient, updateTemplate, updateTemplateReminder, updateTemplateRole, uploadEnvelopeFieldAttachment, userCanAct, userCanCancelEnvelope, userCanFinishEnvelope, userCanSignNow, userHasPermissions, userIsEnvelopeOwner, userIsEnvelopeRecipient, validateToken };
|
|
2616
|
+
export { AtoB, Countries, VerdocsEndpoint, acceptOrganizationInvitation, addGroupMembers, addGroupPermission, addOrganizationMemberRole, addTemplateTag, authenticateApp, authenticateUser, billingPlaceholder, blobToBase64, canPerformTemplateAction, cancelEnvelope, capitalize, claimNewUser, convertToE164, createApiKey, createBusinessAccount, createEnvelope, createEnvelopeReminder, createField, createInitials, createOrganization, createOrganizationInvitation, createProfile, createSignature, createTag, createTemplate, createTemplateDocument, createTemplateFromSharepoint, createTemplateReminder, createTemplateRole, createTemplatev2, createUser, declineOrganizationInvitation, decodeAccessTokenBody, decodeJWTBody, deleteApiKey, deleteEnvelopeFieldAttachment, deleteEnvelopeReminder, deleteField, deleteGroupMembers, deleteGroupPermission, deleteOrganization, deleteOrganizationInvitation, deleteOrganizationMember, deleteOrganizationMemberRole, deleteProfile, deleteSignature, deleteTemplate, deleteTemplateDocument, deleteTemplateReminder, deleteTemplateRole, deleteTemplateTag, downloadBlob, envelopeIsActive, envelopeIsComplete, envelopeRecipientAgree, envelopeRecipientChangeOwner, envelopeRecipientDecline, envelopeRecipientPrepare, envelopeRecipientSubmit, envelopeRecipientUpdateName, fileToDataUrl, formatFullName, formatInitials, formatShortTimeAgo, fullNameToInitials, getAllTags, getApiKeys, getCountryByCode, getCurrentProfile, getDocumentDownloadLink, getDocumentPreviewLink, getEnvelope, getEnvelopeDocument, getEnvelopeDocumentPageDisplayUri, getEnvelopeFile, getEnvelopeRecipients, getEnvelopeReminder, getEnvelopesByTemplateId, getEnvelopesSummary, getFieldAttachment, getGroup, getGroupByName, getGroupMembers, getGroups, getInPersonLink, getMatchingCountry, getNextRecipient, getNotifications, getOrganization, getOrganizationInvitation, getOrganizationInvitations, getOrganizationMemberPlans, getOrganizationMembers, getOrganizations, getPermissions, getPlusOneCountry, getProfile, getProfileGroups, getProfilePermissions, getProfiles, getRGB, getRGBA, getRLeft, getRTop, getRValue, getRecipientsWithActions, getRoleColor, getRoles, getSignature, getSignatures, getSignerToken, getSigningSession, getStars, getTag, getTemplate, getTemplateDocument, getTemplateDocumentFile, getTemplateDocumentPageDisplayUri, getTemplateDocumentThumbnail, getTemplateDocuments, getTemplateOwnerInfo, getTemplateReminder, getTemplateRole, getTemplateRoleFields, getTemplateRoles, getTemplateTags, getTemplates, getTemplatesSummary, getValidator, getValidators, getWebhooks, hasRequiredPermissions, integerSequence, isAmericanSamoa, isCanada, isDominicanRepublic, isFrenchGuiana, isGuadeloupe, isMartinique, isMayotte, isPuertoRico, isValidEmail, isValidPhone, isValidRoleName, isValidTag, listEnvelopes, listTemplates, nameToRGBA, recipientCanAct, recipientHasAction, recordSignupSurvey, refreshTokens, rescale, resendInvitation, resendOrganizationInvitation, resendVerification, resetPassword, rotateApiKey, searchEnvelopes, searchTemplates, sendDelegate, setWebhooks, switchProfile, throttledGetEnvelope, throttledGetTemplate, timePeriod, toggleStar, updateApiKey, updateEmail, updateEnvelopeField, updateEnvelopeFieldInitials, updateEnvelopeFieldSignature, updateEnvelopeReminder, updateField, updateOrganization, updateOrganizationInvitation, updatePassword, updateProfile, updateRecipient, updateTemplate, updateTemplateReminder, updateTemplateRole, uploadEnvelopeFieldAttachment, userCanAct, userCanCancelEnvelope, userCanFinishEnvelope, userCanSignNow, userHasPermissions, userIsEnvelopeOwner, userIsEnvelopeRecipient, validateToken };
|
|
2608
2617
|
//# sourceMappingURL=index.mjs.map
|