Skip to content

Commit 7f913d5

Browse files
multi tab support
1 parent b005905 commit 7f913d5

File tree

2 files changed

+101
-88
lines changed

2 files changed

+101
-88
lines changed

lib/connectedFields/controllers/eg001SetConnectedFields.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,13 @@ eg001SetConnectedFields.createController = async (req, res) => {
4040
// Step 2. Call the worker method
4141
const { body } = req;
4242
const selectedAppId = validator.escape(body.appId);
43-
const verificationData = extractVerificationData(selectedAppId, req.session.apps);
43+
const selectedApp = req.session.apps.filter(app => app.appId === selectedAppId)[0];
4444
const envelopeArgs = {
4545
signerEmail: validator.escape(body.signerEmail),
4646
signerName: validator.escape(body.signerName),
4747
docFile: path.resolve(demoDocsPath, pdfFile),
48-
verificationData
48+
appId: selectedAppId,
49+
app: selectedApp,
4950
};
5051
const args = {
5152
accessToken: req.user.accessToken,

lib/connectedFields/examples/setConnectedFields.js

Lines changed: 98 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,15 @@ const getTabGroups = async (args) => {
2626
const response = await axios.get(url, { headers });
2727
const responseData = response.data;
2828

29+
const filteredApps = responseData.filter(app =>
30+
app.tabs?.some(tab =>
31+
(tab.extensionData?.actionContract?.includes('Verify')) ||
32+
(tab.tabLabel?.includes('connecteddata'))
33+
)
34+
);
35+
2936
let uniqueApps = [];
30-
if (responseData && responseData.length > 0) {
37+
if (filteredApps.length > 0) {
3138
uniqueApps = [...new Map(responseData.map(item => [item.appId, item])).values()];
3239
}
3340
//ds-snippet-end:ConnectedFields1Step3
@@ -71,31 +78,27 @@ const sendEnvelope = async (args) => {
7178
/**
7279
* This function gets the verification data for selected extension app
7380
* @param {string} selectedAppId the GUID of selected extension app
74-
* @param {array} apps the list of extension apps
81+
* @param {array} tab the extension tab
7582
* @returns {Object} Verification data
7683
*/
7784
//ds-snippet-start:ConnectedFields1Step4
78-
const extractVerificationData = (selectedAppId, apps) => {
79-
const selectedApp = apps.filter(app => app.appId === selectedAppId)[0];
85+
const extractVerificationData = (selectedAppId, tab) => {
86+
const extensionData = tab.extensionData;
8087

8188
return {
82-
appId: selectedApp.appId,
83-
extensionGroupId: selectedApp.tabs[0].extensionData.extensionGroupId,
84-
publisherName: selectedApp.tabs[0].extensionData.publisherName,
85-
applicationName: selectedApp.tabs[0].extensionData.applicationName,
86-
actionName: selectedApp.tabs[0].extensionData.actionName,
87-
actionInputKey: selectedApp.tabs[0].extensionData.actionInputKey,
88-
actionContract: selectedApp.tabs[0].extensionData.actionContract,
89-
extensionName: selectedApp.tabs[0].extensionData.extensionName,
90-
extensionContract: selectedApp.tabs[0].extensionData.extensionContract,
91-
requiredForExtension: selectedApp.tabs[0].extensionData.requiredForExtension,
92-
tabLabel: selectedApp.tabs.map((tab) => tab.tabLabel).join(', '),
93-
connectionKey: selectedApp.tabs[0].extensionData.connectionInstances
94-
? selectedApp.tabs[0].extensionData.connectionInstances[0].connectionKey
95-
: '',
96-
connectionValue: selectedApp.tabs[0].extensionData.connectionInstances
97-
? selectedApp.tabs[0].extensionData.connectionInstances[0].connectionValue
98-
: '',
89+
appId: selectedAppId,
90+
extensionGroupId: extensionData.extensionGroupId,
91+
publisherName: extensionData.publisherName,
92+
applicationName: extensionData.applicationName,
93+
actionName: extensionData.actionName,
94+
actionInputKey: extensionData.actionInputKey,
95+
actionContract: extensionData.actionContract,
96+
extensionName: extensionData.extensionName,
97+
extensionContract: extensionData.extensionContract,
98+
requiredForExtension: extensionData.requiredForExtension,
99+
tabLabel: tab.tabLabel,
100+
connectionKey: extensionData.connectionInstances ? extensionData.connectionInstances[0].connectionKey : '',
101+
connectionValue: extensionData.connectionInstances ? extensionData.connectionInstances[0].connectionValue : '',
99102
};
100103
};
101104
//ds-snippet-end:ConnectedFields1Step4
@@ -121,15 +124,14 @@ function makeEnvelope(args) {
121124
// The envelope has one recipients.
122125
// recipient 1 - signer
123126

124-
let docPdfBytes;
125-
// read file from a local directory
126-
// The read could raise an exception if the file is not available!
127-
docPdfBytes = fs.readFileSync(args.docFile);
128-
129127
// create the envelope definition
130128
let env = new docusign.EnvelopeDefinition();
131129
env.emailSubject = 'Please sign this document';
132130

131+
// read file from a local directory
132+
// The read could raise an exception if the file is not available!
133+
const docPdfBytes = fs.readFileSync(args.docFile);
134+
133135
// add the documents
134136
let doc = new docusign.Document();
135137
let docb64 = Buffer.from(docPdfBytes).toString('base64');
@@ -142,77 +144,42 @@ function makeEnvelope(args) {
142144
env.documents = [doc];
143145

144146
// Create a signer recipient to sign the document, identified by name and email
145-
let signer = docusign.Signer.constructFromObject({
146-
email: args.signerEmail,
147-
name: args.signerName,
148-
recipientId: 1,
149-
});
147+
let signer = new docusign.Signer();
148+
signer.email = args.signerEmail;
149+
signer.name = args.signerName;
150+
signer.recipientId = '1';
151+
signer.routingOrder = '1';
150152

151153
// Create signHere fields (also known as tabs) on the documents,
152154
// We're using anchor (autoPlace) positioning
153155
//
154156
// The DocuSign platform seaches throughout your envelope's
155157
// documents for matching anchor strings.
156-
let signHere = docusign.SignHere.constructFromObject({
157-
anchorString: '/sn1/',
158-
anchorYOffset: '10',
159-
anchorUnits: 'pixels',
160-
anchorXOffset: '20',
161-
});
158+
let signHere = new docusign.SignHere();
159+
signHere.anchorString = '/sn1/';
160+
signHere.anchorYOffset = '10';
161+
signHere.anchorUnits = 'pixels';
162+
signHere.anchorXOffset = '20';
163+
164+
let textTabs = [];
165+
for (const tab of args.app.tabs.filter(t => !t.tabLabel.includes('SuggestionInput'))) {
166+
const verificationData = extractVerificationData(args.appId, tab);
167+
const textTab = makeTextTab(verificationData, textTabs.length);
168+
169+
textTabs.push(textTab);
170+
}
162171

163-
const extensionData = {
164-
extensionGroupId: args.verificationData.extensionGroupId,
165-
publisherName: args.verificationData.publisherName,
166-
applicationId: args.verificationData.appId,
167-
applicationName: args.verificationData.applicationName,
168-
actionName: args.verificationData.actionName,
169-
actionContract: args.verificationData.actionContract,
170-
extensionName: args.verificationData.extensionName,
171-
extensionContract: args.verificationData.extensionContract,
172-
requiredForExtension: args.verificationData.requiredForExtension,
173-
actionInputKey: args.verificationData.actionInputKey,
174-
extensionPolicy: 'None',
175-
connectionInstances: [
176-
{
177-
connectionKey: args.verificationData.connectionKey,
178-
connectionValue: args.verificationData.connectionValue,
179-
}
180-
]
181-
};
182-
let textTab = docusign.Text.constructFromObject({
183-
requireInitialOnSharedChange: false,
184-
requireAll: false,
185-
name: args.verificationData.applicationName,
186-
required: true,
187-
locked: false,
188-
disableAutoSize: false,
189-
maxLength: 4000,
190-
tabLabel: args.verificationData.tabLabel,
191-
font: 'lucidaconsole',
192-
fontColor: 'black',
193-
fontSize: 'size9',
194-
documentId: '1',
195-
recipientId: '1',
196-
pageNumber: '1',
197-
xPosition: '273',
198-
yPosition: '191',
199-
width: '84',
200-
height: '22',
201-
templateRequired: false,
202-
tabType: 'text',
203-
});
204172
// Tabs are set per recipient / signer
205-
let signerTabs = docusign.Tabs.constructFromObject({
206-
signHereTabs: [signHere],
207-
textTabs: [textTab]
208-
});
173+
let signerTabs = new docusign.Tabs();
174+
signerTabs.signHereTabs = [signHere];
175+
signerTabs.textTabs = textTabs;
176+
209177
signer.tabs = signerTabs;
210178

211179
// Add the recipient to the envelope object
212-
let recipients = docusign.Recipients.constructFromObject({
213-
signers: [signer],
214-
});
215-
recipients.signers[0].tabs.textTabs[0].extensionData = extensionData;
180+
let recipients = new docusign.Recipients();
181+
recipients.signers = [signer];
182+
216183
env.recipients = recipients;
217184

218185
// Request that the envelope be sent by setting |status| to "sent".
@@ -221,6 +188,51 @@ function makeEnvelope(args) {
221188

222189
return env;
223190
}
191+
192+
const getExtensionData = (verificationData) => ({
193+
extensionGroupId: verificationData.extensionGroupId,
194+
publisherName: verificationData.publisherName,
195+
applicationId: verificationData.appId,
196+
applicationName: verificationData.applicationName,
197+
actionName: verificationData.actionName,
198+
actionContract: verificationData.actionContract,
199+
extensionName: verificationData.extensionName,
200+
extensionContract: verificationData.extensionContract,
201+
requiredForExtension: verificationData.requiredForExtension,
202+
actionInputKey: verificationData.actionInputKey,
203+
extensionPolicy: 'MustVerifyToSign',
204+
connectionInstances: [
205+
{
206+
connectionKey: verificationData.connectionKey,
207+
connectionValue: verificationData.connectionValue,
208+
},
209+
],
210+
});
211+
212+
const makeTextTab = (verificationData, textTabsCount) => ({
213+
requireInitialOnSharedChange: false,
214+
requireAll: false,
215+
name: verificationData.applicationName,
216+
required: true,
217+
locked: false,
218+
disableAutoSize: false,
219+
maxLength: 4000,
220+
tabLabel: verificationData.tabLabel,
221+
font: 'lucidaconsole',
222+
fontColor: 'black',
223+
fontSize: 'size9',
224+
documentId: '1',
225+
recipientId: '1',
226+
pageNumber: '1',
227+
xPosition: `${70 + 100 * Math.floor(textTabsCount / 10)}`,
228+
yPosition: `${560 + 20 * (textTabsCount % 10)}`,
229+
width: '84',
230+
height: '22',
231+
templateRequired: false,
232+
tabType: 'text',
233+
tooltip: verificationData.actionInputKey,
234+
extensionData: getExtensionData(verificationData)
235+
});
224236
//ds-snippet-end:ConnectedFields1Step5
225237

226238
module.exports = { getTabGroups, sendEnvelope, extractVerificationData };

0 commit comments

Comments
 (0)