Skip to content

Commit 6897222

Browse files
authored
Merge pull request #147 from docusign/feature/webforms-example
Web Forms code example
2 parents 0936c5e + b4760dc commit 6897222

File tree

16 files changed

+353
-8
lines changed

16 files changed

+353
-8
lines changed

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ gem 'docusign_click', '~> 1.4.0'
7373
gem 'docusign_esign', '~> 3.25.0'
7474
gem 'docusign_monitor', '~> 1.2.0'
7575
gem 'docusign_rooms', '~> 1.3.0'
76+
gem 'docusign_webforms', '~> 1.0.0'
7677
gem 'omniauth-oauth2', '~> 1.8.0'
7778
gem 'omniauth-rails_csrf_protection'
7879

Gemfile.lock

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,11 @@ GEM
124124
json (~> 2.1, >= 2.1.0)
125125
jwt (~> 2.2, >= 2.2.1)
126126
typhoeus (~> 1.0, >= 1.0.1)
127+
docusign_webforms (1.0.0)
128+
addressable (~> 2.7, >= 2.7.0)
129+
json (~> 2.1, >= 2.1.0)
130+
jwt (~> 2.2, >= 2.2.1)
131+
typhoeus (~> 1.0, >= 1.0.1)
127132
erubi (1.12.0)
128133
ethon (0.16.0)
129134
ffi (>= 1.15.0)
@@ -133,7 +138,6 @@ GEM
133138
ruby2_keywords (>= 0.0.4)
134139
faraday-net_http (3.0.2)
135140
ffi (1.15.5)
136-
ffi (1.15.5-x64-mingw-ucrt)
137141
globalid (1.1.0)
138142
activesupport (>= 5.0)
139143
hashie (5.0.0)
@@ -173,9 +177,7 @@ GEM
173177
net-smtp (0.3.3)
174178
net-protocol
175179
nio4r (2.5.9)
176-
nokogiri (1.15.4-x64-mingw-ucrt)
177-
racc (~> 1.4)
178-
nokogiri (1.15.4-x86_64-linux)
180+
nokogiri (1.15.4-x86_64-darwin)
179181
racc (~> 1.4)
180182
oauth2 (2.0.9)
181183
faraday (>= 0.17.3, < 3.0)
@@ -293,8 +295,7 @@ GEM
293295
actionpack (>= 5.2)
294296
activesupport (>= 5.2)
295297
sprockets (>= 3.0.0)
296-
sqlite3 (1.6.4-x64-mingw-ucrt)
297-
sqlite3 (1.6.4-x86_64-linux)
298+
sqlite3 (1.6.4-x86_64-darwin)
298299
test-unit (3.6.1)
299300
power_assert
300301
thor (1.2.2)
@@ -327,8 +328,7 @@ GEM
327328
zeitwerk (2.6.11)
328329

329330
PLATFORMS
330-
x64-mingw-ucrt
331-
x86_64-linux
331+
x86_64-darwin-21
332332

333333
DEPENDENCIES
334334
bootsnap (~> 1.7.3)
@@ -341,6 +341,7 @@ DEPENDENCIES
341341
docusign_esign (~> 3.25.0)
342342
docusign_monitor (~> 1.2.0)
343343
docusign_rooms (~> 1.3.0)
344+
docusign_webforms (~> 1.0.0)
344345
jbuilder (~> 2.11.5)
345346
listen (~> 3.8.0)
346347
matrix (~> 0.4.2)

app/assets/javascripts/search.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const DS_SEARCH = (function () {
66
ROOMS: "rooms",
77
ADMIN: "admin",
88
CONNECT: "connect",
9+
WEBFORMS: "webforms",
910
}
1011

1112
const processJSONData = function () {
@@ -142,6 +143,8 @@ const DS_SEARCH = (function () {
142143
return "eg";
143144
case API_TYPES.CONNECT:
144145
return "cneg";
146+
case API_TYPES.WEBFORMS:
147+
return "weg";
145148
}
146149
}
147150

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# frozen_string_literal: true
2+
3+
class Webforms::Weg001CreateInstanceController < EgController
4+
before_action -> { check_auth('WebForms') }
5+
before_action -> { @example = Utils::ManifestUtils.new.get_example(@manifest, 1, 'WebForms') }
6+
7+
def create_web_form_template
8+
args = {
9+
template_name: 'Web Form Example Template',
10+
account_id: session[:ds_account_id],
11+
base_path: session[:ds_base_path],
12+
access_token: session[:ds_access_token]
13+
}
14+
15+
web_form_template_id = Webforms::Eg001CreateInstanceService.new(args).create_web_form_template
16+
Utils::FileUtils.new.replace_template_id(File.join('data', Rails.application.config.web_form_config_file), web_form_template_id)
17+
session[:web_form_template_id] = web_form_template_id
18+
19+
redirect_to '/weg001webForm'
20+
end
21+
22+
def create_web_form_instance
23+
args = {
24+
form_name: 'Web Form Example Template',
25+
client_user_id: '1234-5678-abcd-ijkl',
26+
account_id: session[:ds_account_id],
27+
base_path: Rails.application.config.webforms_host,
28+
access_token: session[:ds_access_token]
29+
}
30+
create_instance_service = Webforms::Eg001CreateInstanceService.new(args)
31+
web_forms = create_instance_service.list_web_forms
32+
results = create_instance_service.create_web_form_instance web_forms.items.first.id
33+
34+
@integration_key = Rails.application.config.integration_key
35+
@form_url = results.form_url
36+
@instance_token = results.instance_token
37+
render 'webforms/weg001_create_instance/web_form_embed'
38+
end
39+
40+
def get
41+
additional_page = @example['AdditionalPage'].find { |p| p['Name'] == 'create_web_form_template' }
42+
@example['ExampleDescription'] = additional_page['ResultsPageText']
43+
44+
render 'webforms/weg001_create_instance/get'
45+
end
46+
47+
def get_web_form_create_view
48+
redirect_to '/weg001' if session[:web_form_template_id].nil?
49+
50+
additional_page = @example['AdditionalPage'].find { |p| p['Name'] == 'create_web_form' }
51+
@title = @example['ExampleName']
52+
@description = additional_page['ResultsPageText']
53+
54+
render 'webforms/weg001_create_instance/web_form_create'
55+
end
56+
end

app/services/jwt_auth/jwt_creator.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ def self.consent_url(state, api)
1717
scope = 'signature impersonation dtr.rooms.read dtr.rooms.write dtr.documents.read dtr.documents.write dtr.profile.read dtr.profile.write dtr.company.read dtr.company.write room_forms' if api == 'Rooms'
1818
scope = 'signature impersonation click.manage click.send' if api == 'Click'
1919
scope = 'signature impersonation organization_read group_read permission_read user_read user_write account_read domain_read identity_provider_read user_data_redact asset_group_account_read asset_group_account_clone_write asset_group_account_clone_read' if api == 'Admin'
20+
scope = 'signature webforms_read webforms_instance_read webforms_instance_write' if api == 'WebForms'
2021

2122
base_uri = "#{Rails.configuration.authorization_server}/oauth/auth"
2223
response_type = 'code'
@@ -45,6 +46,10 @@ def initialize(session)
4546
scope = 'signature organization_read group_read permission_read user_read user_write account_read domain_read identity_provider_read user_data_redact asset_group_account_read asset_group_account_clone_write asset_group_account_clone_read'
4647
@client_module = DocuSign_Admin
4748
end
49+
if session[:api] == 'WebForms'
50+
scope = 'signature webforms_read webforms_instance_read webforms_instance_write'
51+
@client_module = DocuSign_WebForms
52+
end
4853

4954
@scope = scope
5055
@api_client = create_initial_api_client(host: Rails.configuration.aud, client_module: @client_module, debugging: false)

app/services/utils.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,14 @@ def get_user_id(args)
3030
user_info.sub
3131
end
3232
end
33+
34+
class FileUtils
35+
def replace_template_id(file_path, template_id)
36+
content = File.read(file_path)
37+
38+
content.gsub!('template-id', template_id)
39+
40+
File.write(file_path, content)
41+
end
42+
end
3343
end
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# frozen_string_literal: true
2+
3+
class Webforms::Eg001CreateInstanceService
4+
attr_reader :args
5+
6+
include ApiCreator
7+
8+
def initialize(args)
9+
@args = args
10+
end
11+
12+
def create_web_form_template
13+
templates_api = create_template_api args
14+
15+
options = DocuSign_eSign::ListTemplatesOptions.new
16+
options.search_text = args[:template_name]
17+
web_forms_templates = templates_api.list_templates(args[:account_id], options)
18+
19+
if web_forms_templates.result_set_size.to_i.positive?
20+
template_id = web_forms_templates.envelope_templates[0].template_id
21+
else
22+
template_req_object = make_web_forms_template
23+
template = templates_api.create_template(args[:account_id], template_req_object)
24+
template_id = template.template_id
25+
end
26+
27+
template_id
28+
end
29+
30+
def list_web_forms
31+
configuration = DocuSign_WebForms::Configuration.new
32+
33+
api_client = DocuSign_WebForms::ApiClient.new(configuration)
34+
api_client.set_default_header('Authorization', "Bearer #{args[:access_token]}")
35+
36+
webforms_api = DocuSign_WebForms::FormManagementApi.new(api_client)
37+
38+
options = DocuSign_WebForms::ListFormsOptions.new
39+
options.search = args[:form_name]
40+
41+
webforms_api.list_forms(args[:account_id], options)
42+
end
43+
44+
def create_web_form_instance(form_id)
45+
configuration = DocuSign_WebForms::Configuration.new
46+
47+
api_client = DocuSign_WebForms::ApiClient.new(configuration)
48+
api_client.set_default_header('Authorization', "Bearer #{args[:access_token]}")
49+
50+
webforms_api = DocuSign_WebForms::FormInstanceManagementApi.new(api_client)
51+
52+
web_form_values = {
53+
'PhoneNumber' => '555-555-5555',
54+
'Yes' => ['Yes'],
55+
'Company' => 'Tally',
56+
'JobTitle' => 'Programmer Writer'
57+
}
58+
web_form_req_object = DocuSign_WebForms::CreateInstanceRequestBody.new({
59+
'clientUserId' => args[:client_user_id],
60+
'formValues' => web_form_values,
61+
'expirationOffset' => '3600'
62+
})
63+
webforms_api.create_instance(args[:account_id], form_id, web_form_req_object)
64+
end
65+
66+
private
67+
68+
def make_web_forms_template
69+
template_name = args[:template_name]
70+
doc_file = 'World_Wide_Corp_Web_Form.pdf'
71+
base64_file_content = Base64.encode64(File.binread(File.join('data', doc_file)))
72+
73+
# Create the document model
74+
document = DocuSign_eSign::Document.new({
75+
# Create the DocuSign document object
76+
'documentBase64' => base64_file_content,
77+
'name' => 'World_Wide_Web_Form', # Can be different from actual file name
78+
'fileExtension' => 'pdf', # Many different document types are accepted
79+
'documentId' => '1' # A label used to reference the doc
80+
})
81+
82+
# Create the signer recipient model
83+
# Since these are role definitions, no name/email:
84+
signer = DocuSign_eSign::Signer.new({
85+
'roleName' => 'signer', 'recipientId' => '1', 'routingOrder' => '1'
86+
})
87+
# Create fields using absolute positioning
88+
# Create a sign_here tab (field on the document)
89+
sign_here = DocuSign_eSign::SignHere.new(
90+
'documentId' => '1', 'tabLabel' => 'Signature',
91+
'anchorString' => '/SignHere/', 'anchorUnits' => 'pixel',
92+
'anchorXOffset' => '20', 'anchorYOffset' => '10'
93+
)
94+
check = DocuSign_eSign::Checkbox.new(
95+
'documentId' => '1', 'tabLabel' => 'Yes',
96+
'anchorString' => '/SMS/', 'anchorUnits' => 'pixel',
97+
'anchorXOffset' => '20', 'anchorYOffset' => '10'
98+
)
99+
text1 = DocuSign_eSign::Text.new(
100+
'documentId' => '1', 'tabLabel' => 'FullName',
101+
'anchorString' => '/FullName/', 'anchorUnits' => 'pixel',
102+
'anchorXOffset' => '20', 'anchorYOffset' => '10'
103+
)
104+
text2 = DocuSign_eSign::Text.new(
105+
'documentId' => '1', 'tabLabel' => 'PhoneNumber',
106+
'anchorString' => '/PhoneNumber/', 'anchorUnits' => 'pixel',
107+
'anchorXOffset' => '20', 'anchorYOffset' => '10'
108+
)
109+
text3 = DocuSign_eSign::Text.new(
110+
'documentId' => '1', 'tabLabel' => 'Company',
111+
'anchorString' => '/Company/', 'anchorUnits' => 'pixel',
112+
'anchorXOffset' => '20', 'anchorYOffset' => '10'
113+
)
114+
text4 = DocuSign_eSign::Text.new(
115+
'documentId' => '1', 'tabLabel' => 'JobTitle',
116+
'anchorString' => '/JobTitle/', 'anchorUnits' => 'pixel',
117+
'anchorXOffset' => '20', 'anchorYOffset' => '10'
118+
)
119+
date_signed = DocuSign_eSign::DateSigned.new(
120+
'documentId' => '1', 'tabLabel' => 'DateSigned',
121+
'anchorString' => '/Date/', 'anchorUnits' => 'pixel',
122+
'anchorXOffset' => '20', 'anchorYOffset' => '10'
123+
)
124+
125+
# Add the tabs model to the signer
126+
# The Tabs object takes arrays of the different field/tab types
127+
signer.tabs = DocuSign_eSign::Tabs.new(
128+
'signHereTabs' => [sign_here],
129+
'checkboxTabs' => [check],
130+
'textTabs' => [text1, text2, text3, text4],
131+
'dateSignedTabs' => [date_signed]
132+
)
133+
# Create top two objects
134+
envelope_template_definition = DocuSign_eSign::EnvelopeTemplate.new(
135+
'description' => 'Example template created via the API',
136+
'shared' => 'false'
137+
)
138+
139+
# Top object:
140+
DocuSign_eSign::EnvelopeTemplate.new(
141+
'documents' => [document],
142+
'name' => template_name,
143+
'emailSubject' => 'Please sign this document',
144+
'envelopeTemplateDefinition' => envelope_template_definition,
145+
'recipients' => DocuSign_eSign::Recipients.new(
146+
'signers' => [signer]
147+
),
148+
'status' => 'created'
149+
)
150+
end
151+
end

app/views/ds_common/index.html.erb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@
5353
"m"
5454
elsif api["Name"] == "Connect"
5555
"cn"
56+
elsif api["Name"] == "WebForms"
57+
"w"
5658
else
5759
"e"
5860
end %>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<%= render('partials/example_info') %>
2+
3+
<form class="eg" id="data_form" action="" method="post" data-busy="form">
4+
<%= render('partials/submit_button') %>
5+
</form>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<h4><%= @title %></h4>
2+
<p><%= sanitize @description %></p>
3+
4+
<form class="eg" id="data_form" action="" method="post" data-busy="form">
5+
<%= render('partials/submit_button') %>
6+
</form>

0 commit comments

Comments
 (0)