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