Skip to content

Commit 9b9af79

Browse files
committed
2 parents f6131d0 + 65ee017 commit 9b9af79

16 files changed

+439
-13
lines changed

index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const {
3434

3535
const {
3636
eg001click, eg002click, eg003click,
37-
eg004click, eg005click,
37+
eg004click, eg005click, eg006click
3838
} = require("./lib/click/controllers");
3939

4040
const {
@@ -170,6 +170,8 @@ if (examplesApi.examplesApi.isRoomsApi) {
170170
.post('/eg004', eg004click.createController)
171171
.get('/eg005', eg005click.getController)
172172
.post('/eg005', eg005click.createController)
173+
.get('/eg006', eg006click.getController)
174+
.post('/eg006', eg006click.createController)
173175
} else if (examplesApi.examplesApi.isMonitorApi) {
174176
app.get('/eg001', eg001monitor.getController)
175177
.post('/eg001', eg001monitor.createController)
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/**
2+
* @file
3+
* Example 6: Embed a clickwrap
4+
* @author DocuSign
5+
*/
6+
7+
const path = require("path");
8+
const { embedClickwrap, getActiveClickwraps, getInactiveClickwraps } = require("../examples/embedClickwrap");
9+
const validator = require("validator");
10+
const { getExampleByNumber } = require("../../manifestService");
11+
const dsConfig = require("../../../config/index.js").config;
12+
13+
const eg006EmbedClickwrap = exports;
14+
const exampleNumber = 6;
15+
const eg = `eg00${exampleNumber}`; // This example reference.
16+
const mustAuthenticate = "/ds/mustAuthenticate";
17+
const minimumBufferMin = 3;
18+
19+
/**
20+
* Create clickwrap
21+
* @param {Object} req Request obj
22+
* @param {Object} res Response obj
23+
*/
24+
eg006EmbedClickwrap.createController = async (req, res) => {
25+
// Step 1. Check the token
26+
// At this point we should have a good token. But we
27+
// double-check here to enable a better UX to the user
28+
const isTokenOK = req.dsAuth.checkToken(minimumBufferMin);
29+
if (!isTokenOK) {
30+
req.flash("info", "Sorry, you need to re-authenticate.");
31+
// Save the current operation so it will be resumed after authentication
32+
req.dsAuth.setEg(req, eg);
33+
return res.redirect(mustAuthenticate);
34+
}
35+
36+
// Get required arguments
37+
const { body } = req;
38+
let results = null;
39+
40+
const documentArgs = {
41+
fullName: validator.escape(body.fullName),
42+
email: validator.escape(body.email),
43+
company: validator.escape(body.company),
44+
jobTitle: validator.escape(body.title),
45+
date: validator.escape(body.date),
46+
};
47+
48+
const args = {
49+
accessToken: req.user.accessToken,
50+
basePath: dsConfig.clickAPIUrl,
51+
accountId: req.session.accountId,
52+
clickwrapName: req.body.clickwrapName,
53+
clickwrapId: req.body.clickwrapId,
54+
documentArgs: documentArgs
55+
};
56+
const example = getExampleByNumber(res.locals.manifest, exampleNumber);
57+
58+
// Call the worker method
59+
try {
60+
results = await embedClickwrap(args);
61+
console.log(JSON.parse(JSON.stringify(results)));
62+
} catch (error) {
63+
if (embedClickwrap.agreementUrl == null) {
64+
const errorCode = "Error:";
65+
const errorMessage = "The email address was already used to agree to this elastic template. Provide a different email address if you want to view the agreement and agree to it.";
66+
res.render("pages/error", {err: error, errorCode, errorMessage});
67+
} else {
68+
const errorBody = error && error.response && error.response.body;
69+
// We can pull the DocuSign error code and message from the response body
70+
const errorCode = errorBody && errorBody.errorCode;
71+
const errorMessage = errorBody && errorBody.message;
72+
73+
// In production, may want to provide customized error messages and
74+
// remediation advice to the user.
75+
res.render('pages/error', {err: error, errorCode, errorMessage});
76+
}
77+
}
78+
if (results) {
79+
// Save for use by other examples that need an clickwrapId
80+
const example = getExampleByNumber(res.locals.manifest, exampleNumber);
81+
res.render("pages/example_click6_done", {
82+
title: example.ExampleName,
83+
message: example.ResultsPageText,
84+
agreementUrl: JSON.parse(JSON.stringify(results)).agreementUrl
85+
});
86+
}
87+
}
88+
89+
90+
/**
91+
* Render page with our form for the example
92+
* @param {Object} req Request obj
93+
* @param {Object} res Response obj
94+
*/
95+
eg006EmbedClickwrap.getController = async (req, res) => {
96+
// Check that the authentication token is okay with a long buffer time.
97+
// If needed, now is the best time to ask the user to authenticate,
98+
// since they have not yet entered any information into the form
99+
const isTokenOK = req.dsAuth.checkToken();
100+
if (!isTokenOK) {
101+
// Save the current operation so it will be resumed after authentication
102+
req.dsAuth.setEg(req, eg);
103+
return res.redirect(mustAuthenticate);
104+
}
105+
106+
const args = {
107+
accessToken: req.user.accessToken,
108+
basePath: dsConfig.clickAPIUrl,
109+
accountId: req.session.accountId,
110+
};
111+
112+
const example = getExampleByNumber(res.locals.manifest, exampleNumber);
113+
const sourceFile = (path.basename(__filename))[5].toLowerCase() + (path.basename(__filename)).substr(6);
114+
res.render("pages/click-examples/eg006EmbedClickwrap", {
115+
eg: eg, csrfToken: req.csrfToken(),
116+
example: example,
117+
sourceFile: sourceFile,
118+
clickwrapsData: await getActiveClickwraps(args),
119+
clickwrapsExist: await getInactiveClickwraps(args),
120+
sourceUrl: dsConfig.githubExampleUrl + 'click/examples/' + sourceFile,
121+
documentation: dsConfig.documentation + eg,
122+
showDoc: dsConfig.documentation
123+
});
124+
}

lib/click/controllers/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ module.exports.eg002click = require('./eg002ActivateClickwrap');
33
module.exports.eg003click = require('./eg003CreateNewClickwrapVersion');
44
module.exports.eg004click = require('./eg004ListClickwraps');
55
module.exports.eg005click = require('./eg005ClickwrapResponses');
6+
module.exports.eg006click = require('./eg006EmbedClickwrap');

lib/click/examples/embedClickwrap.js

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/**
2+
* @file
3+
* Example 6: Embed a clickwrap
4+
* @author DocuSign
5+
*/
6+
7+
const fs = require("fs-extra");
8+
const docusignClick = require("docusign-click");
9+
10+
/**
11+
* Work with creating of the clickwrap
12+
* @param {Object} args Arguments for embedding a clickwrap
13+
* @param {string} args.accessToken The access token
14+
* @param {string} args.basePath The API base path URL
15+
* @param {string} args.documentArgs.fullName
16+
* @param {string} args.documentArgs.email
17+
* @param {string} args.documentArgs.company
18+
* @param {string} args.documentArgs.jobTitle
19+
* @param {string} args.documentArgs.date
20+
*/
21+
22+
const embedClickwrap = async (args) => {
23+
24+
const documentArgs = {
25+
fullName: args.documentArgs.fullName,
26+
email: args.documentArgs.email,
27+
company: args.documentArgs.company,
28+
jobTitle: args.documentArgs.jobTitle,
29+
date: args.documentArgs.date,
30+
};
31+
32+
const userAgreement = new docusignClick.UserAgreementRequest.constructFromObject({
33+
clientUserId: documentArgs.email,
34+
documentData: {
35+
fullName: documentArgs.fullName,
36+
email: documentArgs.email,
37+
company: documentArgs.company,
38+
title: documentArgs.jobTitle,
39+
date: documentArgs.date,
40+
},
41+
// requireReacceptance: true,
42+
});
43+
44+
45+
// Step 4. Call the Click API
46+
const dsApiClient = new docusignClick.ApiClient();
47+
dsApiClient.setBasePath(args.basePath);
48+
dsApiClient.addDefaultHeader("Authorization", "Bearer " + args.accessToken);
49+
const accountApi = new docusignClick.AccountsApi(dsApiClient);
50+
51+
// Embed the clickwrap
52+
const result = await accountApi.createHasAgreed(
53+
args.accountId, args.clickwrapId, {
54+
userAgreementRequest: userAgreement
55+
});
56+
console.log(`See the embedded clickwrap in the dialog box.`);
57+
return result;
58+
};
59+
60+
const getActiveClickwraps = async (args) => {
61+
// Call the Click API
62+
// Create Click API client
63+
const dsApiClient = new docusignClick.ApiClient();
64+
dsApiClient.setBasePath(args.basePath)
65+
dsApiClient.addDefaultHeader("Authorization", "Bearer " + args.accessToken);
66+
const accountApi = new docusignClick.AccountsApi(dsApiClient);
67+
68+
// Get a list of inactive clickwraps
69+
return await accountApi.getClickwraps(args.accountId, {status: 'active'});
70+
}
71+
72+
const getInactiveClickwraps = async (args) => {
73+
// Call the Click API
74+
// Create Click API client
75+
const dsApiClient = new docusignClick.ApiClient();
76+
dsApiClient.setBasePath(args.basePath)
77+
dsApiClient.addDefaultHeader("Authorization", "Bearer " + args.accessToken);
78+
const accountApi = new docusignClick.AccountsApi(dsApiClient);
79+
80+
// Get a list of inactive clickwraps
81+
return await accountApi.getClickwraps(args.accountId, {status: 'inactive'});
82+
}
83+
84+
module.exports = { getInactiveClickwraps, getActiveClickwraps, embedClickwrap };
85+

package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"cookie-parser": "^1.4.4",
3232
"csurf": "^1.10.0",
3333
"docusign-admin": "^1.1.0",
34-
"docusign-click": "^1.1.0",
34+
"docusign-click": "^1.2.2",
3535
"docusign-esign": "^5.16.0",
3636
"docusign-monitor": "^1.1.0",
3737
"docusign-rooms": "^1.1.0",
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<%- include("../../partials/examplesHead") %>
2+
3+
<%- include("../../partials/exampleInfo") %>
4+
5+
<% include("../../partials/functions") %>
6+
7+
<% if (clickwrapsData.clickwraps.length == 0 && clickwrapsExist.clickwraps.length == 0) { %>
8+
<%- formatString(example.RedirectsToOtherCodeExamples[0].RedirectText, formatString('href="eg00{0}"', example.RedirectsToOtherCodeExamples[0].CodeExampleToRedirectTo)) %>
9+
<form class="eg" action="eg001" method="get">
10+
<%- include("../../partials/continueButton") %>
11+
</form>
12+
<% } else if (clickwrapsData.clickwraps.length == 0) { %>
13+
<%- formatString(example.RedirectsToOtherCodeExamples[1].RedirectText, formatString('href="eg00{0}"', example.RedirectsToOtherCodeExamples[1].CodeExampleToRedirectTo)) %>
14+
<form class="eg" action="eg002" method="get">
15+
<%- include("../../partials/continueButton") %>
16+
</form>
17+
<% } else { %>
18+
<form class="eg" action="" method="post" data-busy="form-download">
19+
<% if(example.Forms && example.Forms[0].FormName) { %>
20+
<%- example.Forms[0].FormName %>
21+
<% } %>
22+
23+
<div class="form-group">
24+
<label for="clickwrapId"><%= example.Forms[0].Inputs[0].InputName %></label>
25+
<select class="custom-select" id="clickwrapId"
26+
name="clickwrapId">
27+
<% for(var i=0; i < clickwrapsData.clickwraps.length; i++) { %>
28+
<option value="<%=clickwrapsData.clickwraps[i].clickwrapId%>"><%= clickwrapsData.clickwraps[i].clickwrapName %></option>
29+
<% } %>
30+
</select>
31+
</div>
32+
33+
<div class="form-group">
34+
<label for="fullName"><%= example.Forms[0].Inputs[1].InputName %></label>
35+
<input type="text" class="form-control" id="fullName" name="fullName"
36+
placeholder="<%= example.Forms[0].Inputs[1].InputPlaceholder %>" required/>
37+
</div>
38+
39+
<div class="form-group">
40+
<label for="email"><%= example.Forms[0].Inputs[2].InputName %></label>
41+
<input type="email" class="form-control" id="email" name="email"
42+
placeholder="<%= example.Forms[0].Inputs[2].InputPlaceholder %>" required/>
43+
</div>
44+
45+
<div class="form-group">
46+
<label for="company"><%= example.Forms[0].Inputs[3].InputName %></label>
47+
<input type="text" class="form-control" id="company" name="company"
48+
placeholder="<%= example.Forms[0].Inputs[2].InputPlaceholder %>" required/>
49+
</div>
50+
51+
<div class="form-group">
52+
<label for="title"><%= example.Forms[0].Inputs[4].InputName %></label>
53+
<input type="text" class="form-control" id="title" name="title"
54+
placeholder="<%= example.Forms[0].Inputs[3].InputPlaceholder %>" required/>
55+
</div>
56+
57+
<div class="form-group">
58+
<label for="date"><%= example.Forms[0].Inputs[5].InputName %></label>
59+
<input type="date" class="form-control" id="date" name="date"
60+
placeholder="<%= example.Forms[0].Inputs[4].InputPlaceholder %>" required/>
61+
</div>
62+
63+
<input type="hidden" name="_csrf" value="<%- csrfToken %>">
64+
<%- include("../../partials/submitButton") %>
65+
</form>
66+
<% } %>
67+
68+
<%- include("../../partials/examplesFoot") %>

views/pages/example_click6_done.ejs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<%- include("../partials/genericHead") %>
2+
3+
<h2><%= title %></h2>
4+
<p><%- message %></p>
5+
6+
<p>Agreement URL received back from the API call: <code><%- agreementUrl %></code></p>
7+
8+
<p id="agreementStatus">
9+
<%- locals.manifest.SupportingTexts.HelpingTexts.NOTAGREED %>
10+
</p>
11+
12+
<div id="ds-terms-of-service"></div>
13+
<script src="https://demo.docusign.net/clickapi/sdk/latest/docusign-click.js"></script>
14+
<script>docuSignClick.Clickwrap.render({
15+
agreementUrl: "<%- agreementUrl %>",
16+
onAgreed: function() {
17+
// Triggered if the user has just agreed
18+
document.getElementById("agreementStatus").innerHTML = "<%- locals.manifest.SupportingTexts.HelpingTexts.AGREED %>";
19+
}
20+
}, "#ds-terms-of-service");
21+
</script>
22+
23+
24+
<p><a href="/">Continue</a></p>
25+
26+
<%- include("../partials/genericFoot") %>

views/pages/index_admin_examples.ejs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
a Node Express application.</p>
88
<% } %>
99

10-
<%- include("index_examples_list") %>
10+
<%- include("index_admin_examples_list") %>
1111

1212
</div>
1313

0 commit comments

Comments
 (0)