prontoforms 0.2.0 → 2.0.1
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.
- checksums.yaml +4 -4
- data/.github/workflows/checks.yml +66 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +12 -0
- data/.travis.yml +10 -0
- data/CHANGELOG.md +31 -0
- data/Gemfile +6 -0
- data/README.md +17 -1
- data/Rakefile +5 -3
- data/bin/console +4 -10
- data/bin/setup +2 -2
- data/lib/prontoforms.rb +10 -1
- data/lib/prontoforms/client.rb +74 -15
- data/lib/prontoforms/document.rb +31 -0
- data/lib/prontoforms/form.rb +75 -0
- data/lib/prontoforms/form_iteration.rb +40 -0
- data/lib/prontoforms/form_space.rb +55 -0
- data/lib/prontoforms/form_submission.rb +109 -8
- data/lib/prontoforms/resource.rb +19 -7
- data/lib/prontoforms/resource_list.rb +26 -4
- data/lib/prontoforms/user.rb +34 -0
- data/lib/prontoforms/version.rb +3 -1
- data/prontoforms.gemspec +28 -15
- metadata +85 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f254afead3ca132b09b3e4ebf60cd559326bce2e0c858bc718fd1211fc7f4db2
|
4
|
+
data.tar.gz: ff60c3483da8612616398ab4cab00f818e7447746ee6b34c712b612031d1f8f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dee8fa61c40fc5a1ba90e7ca95c9b49d5c8e88df0221e0d27bddff417c1554ac424d4ee2cf388ee58bfc01e6b688174f1b04bb478a84a24a27bfe9677e58f85f
|
7
|
+
data.tar.gz: 3ee0a6c9ca3da3652000194106ae0b6f29d10a617c292ae114a9ccf9e6f9deef591cd9a6e9d16e4220a444900aeffb81555a35eae7bdfa178dc1c5b45168a819
|
@@ -0,0 +1,66 @@
|
|
1
|
+
name: Checks
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [master]
|
6
|
+
|
7
|
+
jobs:
|
8
|
+
test:
|
9
|
+
name: Run automated tests
|
10
|
+
runs-on: ubuntu-latest
|
11
|
+
steps:
|
12
|
+
- name: Checkout repository
|
13
|
+
uses: actions/checkout@v2
|
14
|
+
|
15
|
+
- name: Set up ruby
|
16
|
+
uses: actions/setup-ruby@v1
|
17
|
+
with:
|
18
|
+
ruby-version: 2.6
|
19
|
+
|
20
|
+
- name: Install dependencies
|
21
|
+
run: |
|
22
|
+
gem install bundler -v 2.1.4
|
23
|
+
bundle install
|
24
|
+
|
25
|
+
- name: Test
|
26
|
+
run: bundle exec rake
|
27
|
+
|
28
|
+
- name: Report test coverage
|
29
|
+
uses: paambaati/codeclimate-action@v2.7.4
|
30
|
+
env:
|
31
|
+
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
32
|
+
|
33
|
+
rubocop:
|
34
|
+
name: Rubocop
|
35
|
+
runs-on: ubuntu-latest
|
36
|
+
strategy:
|
37
|
+
fail-fast: false
|
38
|
+
|
39
|
+
steps:
|
40
|
+
- name: Checkout repository
|
41
|
+
uses: actions/checkout@v2
|
42
|
+
|
43
|
+
- name: Set up Ruby
|
44
|
+
uses: ruby/setup-ruby@v1
|
45
|
+
with:
|
46
|
+
ruby-version: 2.6
|
47
|
+
|
48
|
+
- name: Install Code Scanning integration
|
49
|
+
run: bundle add code-scanning-rubocop --version 0.3.0 --skip-install
|
50
|
+
|
51
|
+
- name: Install dependencies
|
52
|
+
run: |
|
53
|
+
gem install bundler -v 2.1.4
|
54
|
+
bundle install
|
55
|
+
|
56
|
+
- name: Rubocop run
|
57
|
+
run: |
|
58
|
+
bash -c "
|
59
|
+
bundle exec rubocop --require code_scanning --format CodeScanning::SarifFormatter -o rubocop.sarif
|
60
|
+
[[ $? -ne 2 ]]
|
61
|
+
"
|
62
|
+
|
63
|
+
- name: Upload Sarif output
|
64
|
+
uses: github/codeql-action/upload-sarif@v1
|
65
|
+
with:
|
66
|
+
sarif_file: rubocop.sarif
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
data/.travis.yml
CHANGED
@@ -1,6 +1,16 @@
|
|
1
1
|
---
|
2
|
+
os: linux
|
3
|
+
dist: xenial
|
2
4
|
language: ruby
|
3
5
|
cache: bundler
|
4
6
|
rvm:
|
5
7
|
- 2.6.0
|
6
8
|
before_install: gem install bundler -v 2.1.4
|
9
|
+
before_script:
|
10
|
+
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
11
|
+
- chmod +x ./cc-test-reporter
|
12
|
+
- ./cc-test-reporter before-build
|
13
|
+
script:
|
14
|
+
- bundle exec rspec
|
15
|
+
after_script:
|
16
|
+
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|
data/CHANGELOG.md
CHANGED
@@ -0,0 +1,31 @@
|
|
1
|
+
# prontoforms changelog
|
2
|
+
|
3
|
+
## [Unreleased]
|
4
|
+
### Added
|
5
|
+
* Added Form resource
|
6
|
+
* Can retrieve forms by form space
|
7
|
+
|
8
|
+
## [v0.3.1] - 15 Sep 2020
|
9
|
+
### Removed
|
10
|
+
* Unused `InvalidHttpVerb` error class
|
11
|
+
|
12
|
+
## [v0.3.0] - 15 Sep 2020
|
13
|
+
### Added
|
14
|
+
* Autogenerated documentation via YARD.
|
15
|
+
|
16
|
+
### Changed
|
17
|
+
* Errors now provide a message describing the issue
|
18
|
+
* `ProntoForms::Client` now raises error on invalid resource definition.
|
19
|
+
|
20
|
+
## [v0.2.0] - 26 Aug 2020
|
21
|
+
### Bugfixes
|
22
|
+
* Corrected pagination of resource lists
|
23
|
+
|
24
|
+
## [v0.1.0] - 25 Aug 2020
|
25
|
+
* Initial release
|
26
|
+
|
27
|
+
[Unreleased]: https://github.com/paulholden2/prontoforms/compare/v0.3.1...HEAD
|
28
|
+
[v0.1.0]: https://github.com/paulholden2/prontoforms/releases/tag/v0.1.0
|
29
|
+
[v0.2.0]: https://github.com/paulholden2/prontoforms/releases/tag/v0.2.0
|
30
|
+
[v0.3.0]: https://github.com/paulholden2/prontoforms/releases/tag/v0.3.0
|
31
|
+
[v0.3.1]: https://github.com/paulholden2/prontoforms/releases/tag/v0.3.1
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
# ProntoForms
|
2
2
|
|
3
|
+
[](https://actions-badge.atrox.dev/paulholden2/prontoforms/goto?ref=master) [](https://badge.fury.io/rb/prontoforms) [](http://inch-ci.org/github/paulholden2/prontoforms) [](https://codeclimate.com/github/paulholden2/prontoforms/maintainability) [](https://codeclimate.com/github/paulholden2/prontoforms/test_coverage)
|
4
|
+
|
3
5
|
A library for interacting with the ProntoForms REST API in Ruby applications.
|
4
6
|
|
7
|
+
Note: version 0.4.0 included a breaking change, and has been yanked from
|
8
|
+
RubyGems. If you are using it, please upgrade to 1.x or revert to 0.3.1.
|
9
|
+
|
5
10
|
## Installation
|
6
11
|
|
7
12
|
Add this line to your application's Gemfile:
|
@@ -20,7 +25,16 @@ Or install it yourself as:
|
|
20
25
|
|
21
26
|
## Usage
|
22
27
|
|
23
|
-
|
28
|
+
To get started, first [create a ProntoForms API key] in your ProntoForms
|
29
|
+
account. Then you can begin using the API client in your Ruby application:
|
30
|
+
|
31
|
+
```rb
|
32
|
+
client = ProntoForms::Client.new(api_key_id, api_key_secret)
|
33
|
+
client.form_spaces # Returns all FormSpaces in your account
|
34
|
+
```
|
35
|
+
|
36
|
+
Review [the documentation](https://rubydoc.info/github/paulholden2/prontoforms)
|
37
|
+
for more information on how to use this library to interact with ProntoForms.
|
24
38
|
|
25
39
|
## Development
|
26
40
|
|
@@ -37,3 +51,5 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/paulho
|
|
37
51
|
## License
|
38
52
|
|
39
53
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
54
|
+
|
55
|
+
[create a ProntoForms API key]: https://support.prontoforms.com/hc/en-us/articles/217496468-Setup-an-API-Application-on-ProntoForms#Create
|
data/Rakefile
CHANGED
data/bin/console
CHANGED
@@ -1,14 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
require
|
4
|
-
require
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'prontoforms'
|
6
|
+
require 'irb'
|
5
7
|
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require "pry"
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require "irb"
|
14
8
|
IRB.start(__FILE__)
|
data/bin/setup
CHANGED
data/lib/prontoforms.rb
CHANGED
@@ -1,6 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'prontoforms/version'
|
2
4
|
require 'prontoforms/client'
|
3
5
|
|
4
6
|
module ProntoForms
|
5
|
-
|
7
|
+
# Base error class.
|
8
|
+
class Error < StandardError
|
9
|
+
attr_reader :message
|
10
|
+
|
11
|
+
def initialize(message)
|
12
|
+
@message = message
|
13
|
+
end
|
14
|
+
end
|
6
15
|
end
|
data/lib/prontoforms/client.rb
CHANGED
@@ -1,43 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'faraday'
|
2
4
|
require 'json'
|
3
5
|
require 'prontoforms/resource_list'
|
4
6
|
require 'prontoforms/form_space'
|
5
7
|
require 'prontoforms/form_submission'
|
8
|
+
require 'prontoforms/user'
|
6
9
|
|
7
10
|
module ProntoForms
|
11
|
+
# Allows you to retrieve resources from ProntoForms and perform other
|
12
|
+
# functions with the API.
|
8
13
|
class Client
|
9
|
-
|
14
|
+
# @return [String] ProntoForms API key ID
|
15
|
+
attr_reader :api_key_id
|
16
|
+
# @return [String] ProntoForms API key secret
|
17
|
+
attr_reader :api_key_secret
|
10
18
|
|
19
|
+
# Create a client and use provided API credentials
|
20
|
+
# @param api_key_id Your ProntoForms REST API key
|
21
|
+
# @param api_key_secret Your ProntoForms REST API secret
|
11
22
|
def initialize(api_key_id, api_key_secret)
|
12
23
|
@api_key_id = api_key_id
|
13
24
|
@api_key_secret = api_key_secret
|
14
25
|
end
|
15
26
|
|
16
|
-
|
17
|
-
|
18
|
-
|
27
|
+
# Defines a resource that can be retrieved in a list
|
28
|
+
# @return [nil]
|
29
|
+
# @api private
|
30
|
+
# @!macro [attach] resource_list
|
31
|
+
# @method $1
|
32
|
+
# Retrieve a list of $2 resources
|
33
|
+
# @return [ResourceList] A ResourceList containing $2 results
|
34
|
+
def self.resource_list(method, resource, url = resource.resource_name)
|
19
35
|
define_method(method) do |query: {}|
|
20
|
-
res = connection.
|
36
|
+
res = connection.get do |req|
|
21
37
|
req.url url
|
22
38
|
query.each { |k, v| req.params[k] = v }
|
23
39
|
end
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
40
|
+
|
41
|
+
data = JSON.parse(res.body)
|
42
|
+
|
43
|
+
return nil if data.fetch('pageData').size.zero?
|
44
|
+
|
45
|
+
ResourceList.new(data, { 'p' => 0, 's' => 100 }.merge(query), method,
|
46
|
+
resource, self)
|
32
47
|
end
|
33
48
|
end
|
34
49
|
|
35
|
-
|
36
|
-
|
50
|
+
resource_list :form_spaces, FormSpace
|
51
|
+
resource_list :form_submissions, FormSubmission
|
52
|
+
|
53
|
+
# Retrieve a user by identifier
|
54
|
+
# @param id [String] The user identifier
|
55
|
+
# @return [User] A User object for the requested user
|
56
|
+
def user(id)
|
57
|
+
raise ArgumentError, 'id must be provided' if id.nil?
|
58
|
+
|
59
|
+
res = connection.get do |req|
|
60
|
+
req.url "users/#{id}"
|
61
|
+
end
|
62
|
+
|
63
|
+
User.new(JSON.parse(res.body), self)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Retrieve a form space by its identifier
|
67
|
+
# @param id [String] The form space identifier
|
68
|
+
# @return [FormSpace] A FormSpace object
|
69
|
+
def form_space(id)
|
70
|
+
raise ArgumentError, 'id must be provided' if id.nil?
|
71
|
+
|
72
|
+
res = connection.get do |req|
|
73
|
+
req.url "formspaces/#{id}"
|
74
|
+
end
|
75
|
+
|
76
|
+
FormSpace.new(JSON.parse(res.body), self)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Retrieve a form submission by identifier
|
80
|
+
# @param id [String] The form submission identifier
|
81
|
+
# @return [FormSubmission] A FormSubmission object
|
82
|
+
def form_submission(id)
|
83
|
+
return nil if id.nil?
|
84
|
+
|
85
|
+
res = connection.get do |req|
|
86
|
+
req.url "data/#{id}"
|
87
|
+
end
|
88
|
+
|
89
|
+
FormSubmission.new(JSON.parse(res.body), self)
|
90
|
+
end
|
37
91
|
|
92
|
+
# Create a connection that can be used to execute a request against the
|
93
|
+
# ProntoForms API.
|
94
|
+
# @return [Faraday::Connection]
|
95
|
+
# @api private
|
38
96
|
def connection
|
39
97
|
Faraday.new(url: 'https://api.prontoforms.com/api/1.1') do |conn|
|
40
98
|
conn.basic_auth(api_key_id, api_key_secret)
|
99
|
+
conn.use Faraday::Response::RaiseError
|
41
100
|
end
|
42
101
|
end
|
43
102
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'prontoforms/resource'
|
4
|
+
|
5
|
+
module ProntoForms
|
6
|
+
# A Document is a configuration that generates output data or files when
|
7
|
+
# attached to a form.
|
8
|
+
class Document < Resource
|
9
|
+
def self.resource_name
|
10
|
+
'documents'
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [String] The Document identifier
|
14
|
+
property :id, key: 'identifier'
|
15
|
+
# @return [String] Document type
|
16
|
+
property :type, key: 'type'
|
17
|
+
# @return [String] Document name
|
18
|
+
property :name, key: 'name'
|
19
|
+
# @return [String] Document descriptiojn
|
20
|
+
property :description, key: 'description'
|
21
|
+
# @return [String] Document form version
|
22
|
+
property :form_document_version, key: 'formDocumentVersion'
|
23
|
+
# @return [Boolean] Whether the document is standard (system generated)
|
24
|
+
property :standard, key: 'standard'
|
25
|
+
# @return [String] Whether the document auto-links to new forms
|
26
|
+
property :auto_link, key: 'autoLink'
|
27
|
+
|
28
|
+
alias standard? standard
|
29
|
+
alias auto_link? auto_link
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'prontoforms/resource'
|
4
|
+
require 'prontoforms/form_iteration'
|
5
|
+
|
6
|
+
module ProntoForms
|
7
|
+
# A form includes inputs, validations, logic, and other configuration that
|
8
|
+
# facilitates data capture for a specific purpose.
|
9
|
+
class Form < Resource
|
10
|
+
def self.resource_name
|
11
|
+
'forms'
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [String] The Form identifier
|
15
|
+
property :id, key: 'identifier'
|
16
|
+
# @return [String] Form name
|
17
|
+
property :name, key: 'name'
|
18
|
+
# @return [String] Form description
|
19
|
+
property :description, key: 'description'
|
20
|
+
# @return [String] Form state
|
21
|
+
property :state, key: 'state'
|
22
|
+
|
23
|
+
# Get the Form's form space ID
|
24
|
+
# @return [String] Form space identifier
|
25
|
+
def form_space_id
|
26
|
+
parent.id
|
27
|
+
end
|
28
|
+
|
29
|
+
def active_version_id
|
30
|
+
full_data.dig('activeVersion', 'identifier')
|
31
|
+
end
|
32
|
+
|
33
|
+
def current_version
|
34
|
+
res = client.connection.get do |req|
|
35
|
+
req.url "#{url}/iterations/#{active_version_id}"
|
36
|
+
end
|
37
|
+
|
38
|
+
FormIteration.new(JSON.parse(res.body), client, self)
|
39
|
+
end
|
40
|
+
|
41
|
+
def iteration(id)
|
42
|
+
raise ArgumentError, 'id must be provided' if id.nil?
|
43
|
+
|
44
|
+
res = client.connection.get do |req|
|
45
|
+
req.url "#{url}/iterations/#{id}"
|
46
|
+
end
|
47
|
+
|
48
|
+
FormIteration.new(JSON.parse(res.body), client, self)
|
49
|
+
end
|
50
|
+
|
51
|
+
def iterations(query: {})
|
52
|
+
res = client.connection.get do |req|
|
53
|
+
req.url "#{url}/iterations"
|
54
|
+
end
|
55
|
+
|
56
|
+
ResourceList.new(JSON.parse(res.body), {
|
57
|
+
'p' => 0,
|
58
|
+
's' => 100
|
59
|
+
}.merge(query), :iterations, FormIteration, client, self)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def full_data
|
65
|
+
return @full_data unless @full_data.nil?
|
66
|
+
|
67
|
+
@full_data = client.form_space(form_space_id).form(id).data
|
68
|
+
@full_data
|
69
|
+
end
|
70
|
+
|
71
|
+
def url
|
72
|
+
"formspaces/#{form_space_id}/forms/#{id}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'prontoforms/resource'
|
4
|
+
|
5
|
+
module ProntoForms
|
6
|
+
# A form iteration is a form configuration, distinct from a form version
|
7
|
+
# in that version numbers increment when a form iteration is deployed.
|
8
|
+
class FormIteration < Resource
|
9
|
+
def self.resource_name
|
10
|
+
'iterations'
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [String] The form iteration identifier
|
14
|
+
property :id, key: 'identifier'
|
15
|
+
# @return [Integer] Version number
|
16
|
+
property :version, key: 'version'
|
17
|
+
# @return [String] Form iteration state
|
18
|
+
property :state, key: 'state'
|
19
|
+
# @return [String] Initiation method for the form iteration
|
20
|
+
property :initiation_method, key: 'initiationMethod'
|
21
|
+
# @return [String] Can dispatched forms of this iteration be declined
|
22
|
+
property :dispatched_declinable, key: 'dispatchDeclinable'
|
23
|
+
|
24
|
+
alias can_decline_dispatch? dispatched_declinable
|
25
|
+
|
26
|
+
# @return [Array] Array of document IDs attached to this iteration
|
27
|
+
def document_ids
|
28
|
+
full_data.fetch('documentIds')
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def full_data
|
34
|
+
return @full_data unless @full_data.nil?
|
35
|
+
|
36
|
+
@full_data = parent.iteration(id).data
|
37
|
+
@full_data
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,10 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'prontoforms/resource'
|
4
|
+
require 'prontoforms/form'
|
5
|
+
require 'prontoforms/document'
|
2
6
|
|
3
7
|
module ProntoForms
|
8
|
+
# Represents a form space resource in ProntoForms. Form spaces are the
|
9
|
+
# primary organizational unit for forms, data sources, destinations, and
|
10
|
+
# other resources.
|
4
11
|
class FormSpace < Resource
|
12
|
+
# @return [String] The FormSpace identifier
|
5
13
|
property :id, key: 'identifier'
|
14
|
+
# @return [String] The FormSpace name
|
6
15
|
property :name, key: 'name'
|
16
|
+
# @return [String] The address that error emails are sent to
|
7
17
|
property :problem_contact_email, key: 'problemContactEmail'
|
18
|
+
# @return [Boolean] Whether updates are automatically pushed to devices
|
8
19
|
property :push_updates_to_device, key: 'pushUpdatesToDevice'
|
20
|
+
|
21
|
+
# Get all documents in the form space
|
22
|
+
# @return [ResourceList] A ResourceList containing Document objects
|
23
|
+
def documents
|
24
|
+
res = client.connection.get do |req|
|
25
|
+
req.url "formspaces/#{id}/documents"
|
26
|
+
end
|
27
|
+
|
28
|
+
ResourceList.new(JSON.parse(res.body), {
|
29
|
+
'p' => 0,
|
30
|
+
's' => 100
|
31
|
+
}, :documents, Document, self)
|
32
|
+
end
|
33
|
+
|
34
|
+
def document(document_id)
|
35
|
+
res = client.connection.get do |req|
|
36
|
+
req.url "formspaces/#{id}/documents/#{document_id}"
|
37
|
+
end
|
38
|
+
|
39
|
+
Document.new(JSON.parse(res.body), client, self)
|
40
|
+
end
|
41
|
+
|
42
|
+
def form(form_id)
|
43
|
+
res = client.connection.get do |req|
|
44
|
+
req.url "formspaces/#{id}/forms/#{form_id}"
|
45
|
+
end
|
46
|
+
|
47
|
+
data = JSON.parse(res.body)
|
48
|
+
Form.new(data, client, self)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Get all forms in the form space
|
52
|
+
# @return [ResourceList] A ResourceList containing Form objects
|
53
|
+
def forms(query: {})
|
54
|
+
res = client.connection.get do |req|
|
55
|
+
req.url "formspaces/#{id}/forms"
|
56
|
+
query.each { |k, v| req.params[k] = v }
|
57
|
+
end
|
58
|
+
|
59
|
+
ResourceList.new(JSON.parse(res.body), {
|
60
|
+
'p' => 0,
|
61
|
+
's' => 100
|
62
|
+
}.merge(query), :forms, Form, client, self)
|
63
|
+
end
|
9
64
|
end
|
10
65
|
end
|
@@ -1,36 +1,137 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'json'
|
2
4
|
require 'prontoforms/resource'
|
3
5
|
|
4
6
|
module ProntoForms
|
7
|
+
# A FormSubmission represents submitted form data in ProntoForms. It
|
8
|
+
# includes various metadata about the submission as well.
|
5
9
|
class FormSubmission < Resource
|
6
|
-
def self.resource_name
|
10
|
+
def self.resource_name
|
11
|
+
'data'
|
12
|
+
end
|
7
13
|
|
14
|
+
# @return [String] The FormSubmission identifier
|
8
15
|
property :id, key: 'identifier'
|
16
|
+
# @return [String] Submission reference number
|
9
17
|
property :reference_number, key: 'referenceNumber'
|
18
|
+
# @return [String] Submission state. One of: Complete, Processing,
|
19
|
+
# Dispatched
|
10
20
|
property :state, key: 'state'
|
21
|
+
# @return [String] Submission data state
|
11
22
|
property :data_state, key: 'dataState'
|
23
|
+
# @return [Boolean] Has the submission data been persisted on the server
|
12
24
|
property :data_persisted, key: 'dataPersisted'
|
25
|
+
# @return [String] The form's version identifier
|
13
26
|
property :form_version_id, key: 'formVersionId'
|
27
|
+
# @return [String] The form's identifier
|
14
28
|
property :form_id, key: 'formId'
|
29
|
+
# @return [String] Submitter's user identifier
|
15
30
|
property :user_id, key: 'userId'
|
31
|
+
# @return [String] Submitter's username
|
16
32
|
property :username, key: 'username'
|
17
|
-
# Aliases
|
18
|
-
property :data_persisted?, key: 'dataPersisted'
|
19
|
-
property :submitter_id, key: 'userId'
|
20
|
-
property :submitter_username, key: 'username'
|
21
33
|
|
34
|
+
alias data_persisted? data_persisted
|
35
|
+
alias submitter_id user_id
|
36
|
+
alias submitter_username username
|
37
|
+
|
38
|
+
# @return [DateTime] Timestamp the submission was received by the server
|
22
39
|
property :server_receive_date do
|
23
40
|
str = data.fetch('serverReceiveDate')
|
24
41
|
str.nil? ? nil : DateTime.strptime(str)
|
25
42
|
end
|
26
43
|
|
44
|
+
# Retrieve the pages containing the form questions and answers
|
45
|
+
# @return [Hash] Hash of questions and answers for the FormSubmission
|
27
46
|
def pages
|
47
|
+
document.fetch('pages')
|
48
|
+
end
|
49
|
+
|
50
|
+
# Retrieve the dispatching User, if the form was dispatched
|
51
|
+
# @return [User] The user that dispatched the form, or nil
|
52
|
+
def dispatcher
|
53
|
+
return nil unless dispatched?
|
54
|
+
|
55
|
+
client.user(document.dig('dispatcher', 'identifier'))
|
56
|
+
end
|
57
|
+
|
58
|
+
# Check if the form was dispatched
|
59
|
+
# @return [Boolean] True if the form was dispatched; false otherwise
|
60
|
+
def dispatched?
|
61
|
+
!document.dig('dispatcher', 'identifier').nil?
|
62
|
+
end
|
63
|
+
|
64
|
+
# Retrieve the form space for the form submission
|
65
|
+
# @return [FormSpace] Form space for the submission's form
|
66
|
+
def form_space
|
67
|
+
client.form_space(full_data.dig('form', 'formSpaceId'))
|
68
|
+
end
|
69
|
+
|
70
|
+
# Retrieve the form for the form submission
|
71
|
+
# @return [Form] Form for the submission
|
72
|
+
def form
|
73
|
+
form_space.form(full_data.dig('form', 'formId'))
|
74
|
+
end
|
75
|
+
|
76
|
+
# Retrieve the current version of the form
|
77
|
+
# @return [FormIteration] The form iteration
|
78
|
+
def form_version
|
79
|
+
form.current_version
|
80
|
+
end
|
81
|
+
|
82
|
+
# Retrieve all documents attached to this form submission
|
83
|
+
# @return [Array] Documents attached to the form submission
|
84
|
+
def documents(populate: false)
|
85
|
+
ids = form_version.document_ids
|
86
|
+
if populate
|
87
|
+
ids.map { |id| form_space.document(id) }
|
88
|
+
else
|
89
|
+
ids
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Download a specific document. The Document must have been attached to
|
94
|
+
# the form's current version at the time of submission.
|
95
|
+
# @return [IO] Data stream for the document
|
96
|
+
def download_document(document)
|
97
|
+
io = StringIO.new
|
98
|
+
client.connection.get do |req|
|
99
|
+
req.url "#{url}/documents/#{document.id}"
|
100
|
+
req.options.on_data = proc { |chunk| io << chunk }
|
101
|
+
end
|
102
|
+
io.rewind
|
103
|
+
io
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def url
|
109
|
+
"#{resource_name}/#{id}"
|
110
|
+
end
|
111
|
+
|
112
|
+
def full_data
|
113
|
+
return @full_data unless @full_data.nil?
|
114
|
+
|
115
|
+
@full_data = client.form_submission(id).data
|
116
|
+
@full_data
|
117
|
+
end
|
118
|
+
|
119
|
+
# Returns additional data about the submission. Uses cached data,
|
120
|
+
# otherwise it loads and returns the data via #document!
|
121
|
+
def document
|
122
|
+
return @document unless @document.nil?
|
123
|
+
|
124
|
+
document!
|
125
|
+
end
|
126
|
+
|
127
|
+
# Force loads the submission document
|
128
|
+
def document!
|
28
129
|
res = client.connection.get do |req|
|
29
130
|
req.url "#{resource_name}/#{id}/document.json"
|
30
131
|
end
|
31
|
-
|
32
|
-
|
33
|
-
|
132
|
+
|
133
|
+
@document = JSON.parse(res.body)
|
134
|
+
@document
|
34
135
|
end
|
35
136
|
end
|
36
137
|
end
|
data/lib/prontoforms/resource.rb
CHANGED
@@ -1,19 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'date'
|
2
4
|
|
3
5
|
module ProntoForms
|
6
|
+
# Base class for resource-related classes.
|
4
7
|
class Resource
|
5
|
-
|
8
|
+
# @return [Hash] Retrieve raw JSON data associated with this resource
|
9
|
+
attr_reader :data
|
10
|
+
# @return [Client] API client
|
11
|
+
attr_reader :client
|
12
|
+
# @return [Resource] Parent object (applicable to child resources)
|
13
|
+
attr_reader :parent
|
6
14
|
|
15
|
+
# Defines a property of the resource
|
16
|
+
# @return [nil]
|
17
|
+
# @api private
|
7
18
|
def self.property(name, key: nil, &block)
|
8
|
-
define_method(name)
|
19
|
+
define_method(name) do
|
9
20
|
if block_given?
|
10
21
|
instance_eval(&block)
|
11
22
|
elsif !key.nil?
|
12
|
-
|
13
|
-
|
14
|
-
nil
|
23
|
+
key = [key] unless key.is_a?(Array)
|
24
|
+
key.inject(data) { |obj, k| obj.fetch(k) }
|
15
25
|
end
|
16
|
-
|
26
|
+
end
|
17
27
|
end
|
18
28
|
|
19
29
|
def initialize(data, client, parent = nil)
|
@@ -22,11 +32,13 @@ module ProntoForms
|
|
22
32
|
@parent = parent
|
23
33
|
end
|
24
34
|
|
35
|
+
# The resource's identifier
|
25
36
|
def self.resource_name
|
26
|
-
name =
|
37
|
+
name = to_s.split('::').last
|
27
38
|
"#{name.downcase}s"
|
28
39
|
end
|
29
40
|
|
41
|
+
# The resource's identifier
|
30
42
|
def resource_name
|
31
43
|
self.class.resource_name
|
32
44
|
end
|
@@ -1,24 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'prontoforms/resource'
|
2
4
|
|
3
5
|
module ProntoForms
|
6
|
+
# A wrapper for retrieving paged resources.
|
4
7
|
class ResourceList < Resource
|
5
|
-
|
8
|
+
# @return [Hash] Query parameters for this resource list for e.g. filters
|
9
|
+
attr_reader :query
|
10
|
+
# @return [Symbol] Method to send to parent object (usually the client)
|
11
|
+
attr_reader :method
|
12
|
+
# @return [Class] Resource class
|
13
|
+
attr_reader :resource
|
14
|
+
# @return [Client] API client
|
15
|
+
attr_reader :client
|
16
|
+
# @return [Resource] Parent object (for child resources)
|
17
|
+
attr_reader :parent
|
6
18
|
|
19
|
+
# Initialize the resource list
|
20
|
+
# TODO: splat
|
21
|
+
# rubocop:disable Metrics/ParameterLists
|
7
22
|
def initialize(data, query, method, resource, client, parent = nil)
|
8
23
|
super(data, client)
|
9
24
|
@query = query
|
10
25
|
@method = method
|
11
26
|
@resource = resource
|
27
|
+
@parent = parent
|
12
28
|
end
|
29
|
+
# rubocop:enable Metrics/ParameterLists
|
13
30
|
|
31
|
+
# Retrieve the next page of results, using the same number of items per
|
32
|
+
# page as the original request.
|
33
|
+
# @return [ResourceList] A ResourceList with the next set of results
|
14
34
|
def next
|
15
|
-
client.send(method, query: query.merge({ 'p' => query['p'] + 1}))
|
35
|
+
client.send(method, query: query.merge({ 'p' => query['p'] + 1 }))
|
16
36
|
end
|
17
37
|
|
38
|
+
# Retrieve the result set
|
39
|
+
# @return [Array] Array of resource objects
|
18
40
|
def items
|
19
|
-
@data.fetch('pageData').map
|
41
|
+
@data.fetch('pageData').map do |item|
|
20
42
|
resource.new(item, client, parent)
|
21
|
-
|
43
|
+
end
|
22
44
|
end
|
23
45
|
end
|
24
46
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'prontoforms/resource'
|
4
|
+
|
5
|
+
module ProntoForms
|
6
|
+
# A ProntoForms user account.
|
7
|
+
class User < Resource
|
8
|
+
def self.resource_name
|
9
|
+
'users'
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [String] The User identifier
|
13
|
+
property :id, key: 'identifier'
|
14
|
+
# @return [String] The user's username
|
15
|
+
property :username, key: 'username'
|
16
|
+
# @return [String] The user's role
|
17
|
+
property :role, key: 'role'
|
18
|
+
# @return [String] The user's email address
|
19
|
+
property :email, key: 'email'
|
20
|
+
# @return [String] The user's first name
|
21
|
+
property :first_name, key: 'firstName'
|
22
|
+
# @return [String] The user's last name
|
23
|
+
property :last_name, key: 'lastName'
|
24
|
+
# @return [String] The user's preferred locale
|
25
|
+
property :locale, key: 'locale'
|
26
|
+
|
27
|
+
# Get a display name consisting of the first name followed by last name
|
28
|
+
# e.g. "John Doe"
|
29
|
+
# @return [String] The display name for the user
|
30
|
+
def display_name
|
31
|
+
"#{first_name} #{last_name}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/prontoforms/version.rb
CHANGED
data/prontoforms.gemspec
CHANGED
@@ -1,16 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'lib/prontoforms/version'
|
2
4
|
|
5
|
+
# rubocop:disable Layout/LineLength
|
3
6
|
Gem::Specification.new do |spec|
|
4
|
-
spec.name
|
5
|
-
spec.version
|
6
|
-
spec.authors
|
7
|
-
spec.email
|
7
|
+
spec.name = 'prontoforms'
|
8
|
+
spec.version = ProntoForms::VERSION
|
9
|
+
spec.authors = ['Paul Holden']
|
10
|
+
spec.email = ['paul@codelunker.com']
|
8
11
|
|
9
|
-
spec.summary
|
10
|
-
spec.description
|
11
|
-
spec.homepage
|
12
|
-
spec.license
|
13
|
-
spec.required_ruby_version = Gem::Requirement.new('>= 2.
|
12
|
+
spec.summary = 'A library for using the ProntoForms REST API in Ruby applications.'
|
13
|
+
spec.description = 'A library for using the ProntoForms REST API in Ruby applications.'
|
14
|
+
spec.homepage = 'https://github.com/paulholden2/prontoforms'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.6.0')
|
14
17
|
|
15
18
|
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
16
19
|
|
@@ -19,17 +22,27 @@ Gem::Specification.new do |spec|
|
|
19
22
|
spec.metadata['changelog_uri'] = 'https://github.com/paulholden2/prontoforms/blog/master/CHANGELOG.md'
|
20
23
|
|
21
24
|
# Specify which files should be added to the gem when it is released.
|
22
|
-
# The `git ls-files -z` loads the files in the RubyGem that have been added
|
23
|
-
|
24
|
-
|
25
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added
|
26
|
+
# into git.
|
27
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
28
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
29
|
+
f.match(%r{^(test|spec|features)/})
|
30
|
+
end
|
25
31
|
end
|
26
|
-
|
27
|
-
spec.
|
32
|
+
|
33
|
+
spec.bindir = 'exe'
|
34
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
35
|
spec.require_paths = ['lib']
|
29
36
|
|
30
37
|
spec.add_dependency 'faraday', '~> 1.0'
|
31
38
|
|
32
39
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
33
|
-
spec.add_development_dependency 'rake', '
|
40
|
+
spec.add_development_dependency 'rake', '>= 12.3.3'
|
34
41
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
42
|
+
spec.add_development_dependency 'rubocop', '~> 0.82.0'
|
43
|
+
spec.add_development_dependency 'sinatra', '~> 2.0'
|
44
|
+
spec.add_development_dependency 'sinatra-contrib', '~> 2.0'
|
45
|
+
spec.add_development_dependency 'webmock', '~> 3.6'
|
46
|
+
spec.add_development_dependency 'yard', '~> 0.9'
|
35
47
|
end
|
48
|
+
# rubocop:enable Layout/LineLength
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prontoforms
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paul Holden
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-12-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -42,16 +42,16 @@ dependencies:
|
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 12.3.3
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 12.3.3
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,15 +66,87 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.82.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.82.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: sinatra
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '2.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: sinatra-contrib
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '2.0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '2.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: webmock
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '3.6'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '3.6'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: yard
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0.9'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0.9'
|
69
139
|
description: A library for using the ProntoForms REST API in Ruby applications.
|
70
140
|
email:
|
71
|
-
- paul@
|
141
|
+
- paul@codelunker.com
|
72
142
|
executables: []
|
73
143
|
extensions: []
|
74
144
|
extra_rdoc_files: []
|
75
145
|
files:
|
146
|
+
- ".github/workflows/checks.yml"
|
76
147
|
- ".gitignore"
|
77
148
|
- ".rspec"
|
149
|
+
- ".rubocop.yml"
|
78
150
|
- ".travis.yml"
|
79
151
|
- CHANGELOG.md
|
80
152
|
- Gemfile
|
@@ -85,10 +157,14 @@ files:
|
|
85
157
|
- bin/setup
|
86
158
|
- lib/prontoforms.rb
|
87
159
|
- lib/prontoforms/client.rb
|
160
|
+
- lib/prontoforms/document.rb
|
161
|
+
- lib/prontoforms/form.rb
|
162
|
+
- lib/prontoforms/form_iteration.rb
|
88
163
|
- lib/prontoforms/form_space.rb
|
89
164
|
- lib/prontoforms/form_submission.rb
|
90
165
|
- lib/prontoforms/resource.rb
|
91
166
|
- lib/prontoforms/resource_list.rb
|
167
|
+
- lib/prontoforms/user.rb
|
92
168
|
- lib/prontoforms/version.rb
|
93
169
|
- prontoforms.gemspec
|
94
170
|
homepage: https://github.com/paulholden2/prontoforms
|
@@ -107,14 +183,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
107
183
|
requirements:
|
108
184
|
- - ">="
|
109
185
|
- !ruby/object:Gem::Version
|
110
|
-
version: 2.
|
186
|
+
version: 2.6.0
|
111
187
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
188
|
requirements:
|
113
189
|
- - ">="
|
114
190
|
- !ruby/object:Gem::Version
|
115
191
|
version: '0'
|
116
192
|
requirements: []
|
117
|
-
rubygems_version: 3.
|
193
|
+
rubygems_version: 3.1.4
|
118
194
|
signing_key:
|
119
195
|
specification_version: 4
|
120
196
|
summary: A library for using the ProntoForms REST API in Ruby applications.
|