metadata_presenter 0.8.0 → 0.11.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 066133455b4cf94730e5bebe20ac439262cacd2128e3004d988035e822efc818
4
- data.tar.gz: c4513e4dc197c1730ba538b2fc50f1c5302ad70c5a31d3377cb0a23f581fae33
3
+ metadata.gz: f28074c7149c34365903ebb2d3f63f679fe15a9365d9d8d52212bf46781506ae
4
+ data.tar.gz: b5c02391b3978aaadc551076f9b0823c6e73f585d7e401ac5980d976d6e568f2
5
5
  SHA512:
6
- metadata.gz: 6a83357fac7381b7191f9c46edf93f4090be55e40491e06427f108430e5ee4069cc5d797da46d32f289d7785e05a02ae2808059eb7bf470b113bdbf56caf4b91
7
- data.tar.gz: 31760a4dcedb66f45ac8be4bb93882d8278d58fcccf686f734dbf3dc0a762c09608cd54bf20718220ae2b8d0c7e3b47bd546a3f2edb9bf53aa30fe9e19703ca3
6
+ metadata.gz: 2b94a8004d81073a597b09b27844d16d5833a8b68a458423afb330fe1fd880d3a4feea508d7f5ec00e290ce75b7f73e8dc3b5094b5276f75c8477241068ba14a
7
+ data.tar.gz: fb7392086d34f13606a4def4b0347190ec45a90fd2f3ec66271b1ef517a2923496e0ce131323ef8b6084491a93d570282204b33a4bf21d4515c0c1185d05fa3e
@@ -3,7 +3,9 @@ module MetadataPresenter
3
3
  before_action :check_page_exists
4
4
 
5
5
  def create
6
- if page.validate_answers(answers_params)
6
+ @page_answers = PageAnswers.new(page, answers_params)
7
+
8
+ if @page_answers.validate_answers
7
9
  save_user_data # method signature
8
10
  redirect_to_next_page
9
11
  else
@@ -5,6 +5,7 @@ module MetadataPresenter
5
5
  @page ||= service.find_page_by_url(request.env['PATH_INFO'])
6
6
 
7
7
  if @page
8
+ @page_answers = PageAnswers.new(@page, @user_data)
8
9
  render template: @page.template
9
10
  else
10
11
  not_found
@@ -1,5 +1,19 @@
1
1
  module MetadataPresenter
2
2
  module ApplicationHelper
3
+ def main_h1(component)
4
+ if component.legend.present?
5
+ content_tag(:legend, class: 'govuk-fieldset__legend govuk-fieldset__legend--l') do
6
+ content_tag(:h1, class: 'govuk-heading-xl') do
7
+ component.legend
8
+ end
9
+ end
10
+ else
11
+ content_tag(:h1, class: 'govuk-heading-xl') do
12
+ component.label
13
+ end
14
+ end
15
+ end
16
+
3
17
  ## Display user answers on the view
4
18
  ## When the user doesn't answered yet the component will be blank
5
19
  # or with data otherwise, so doing the if in every output is not
@@ -2,4 +2,18 @@ class MetadataPresenter::Component < MetadataPresenter::Metadata
2
2
  def to_partial_path
3
3
  "metadata_presenter/component/#{type}"
4
4
  end
5
+
6
+ def humanised_title
7
+ self.label || self.legend
8
+ end
9
+
10
+ def items
11
+ metadata.items.map do |item|
12
+ OpenStruct.new(
13
+ id: item['label'],
14
+ name: item['label'],
15
+ description: item['hint']
16
+ )
17
+ end
18
+ end
5
19
  end
@@ -24,7 +24,7 @@ class MetadataPresenter::Metadata
24
24
  metadata.respond_to?(method_name)
25
25
  end
26
26
 
27
- def method_missing(method, *args, &block)
28
- metadata.send(method, *args, &block)
27
+ def method_missing(method_name, *args, &block)
28
+ metadata.send(method_name, *args, &block)
29
29
  end
30
30
  end
@@ -2,10 +2,6 @@ module MetadataPresenter
2
2
  class Page < MetadataPresenter::Metadata
3
3
  include ActiveModel::Validations
4
4
 
5
- def validate_answers(answers)
6
- ValidateAnswers.new(page: self, answers: answers).valid?
7
- end
8
-
9
5
  def uuid
10
6
  _uuid
11
7
  end
@@ -0,0 +1,31 @@
1
+ module MetadataPresenter
2
+ class PageAnswers
3
+ include ActiveModel::Model
4
+ include ActiveModel::Validations
5
+
6
+ def initialize(page, answers)
7
+ @page = page
8
+ @answers = answers
9
+ end
10
+
11
+ def validate_answers
12
+ ValidateAnswers.new(self, components: components).valid?
13
+ end
14
+
15
+ def components
16
+ page.components
17
+ end
18
+
19
+ def respond_to_missing?(method_name, include_private = false)
20
+ answers[method_name.to_s].present?
21
+ end
22
+
23
+ def method_missing(method_name, *args, &block)
24
+ answers[method_name.to_s]
25
+ end
26
+
27
+ private
28
+
29
+ attr_reader :page, :answers
30
+ end
31
+ end
@@ -26,28 +26,26 @@ module MetadataPresenter
26
26
  # end
27
27
  #
28
28
  class BaseValidator
29
- # @return [MetadataPresenter::Page] page object from the metadata
30
- attr_reader :page
31
-
32
- # @return [Hash] the user answers
33
- attr_reader :answers
29
+ # @return [MetadataPresenter::PageAnswers] page answers object
30
+ attr_reader :page_answers
34
31
 
35
32
  # @return [MetadataPresenter::Component] component object from the metadata
36
33
  attr_reader :component
37
34
 
38
- def initialize(page:, answers:, component:)
39
- @page = page
40
- @answers = answers
35
+ def initialize(page_answers:, component:)
36
+ @page_answers = page_answers
41
37
  @component = component
42
38
  end
43
39
 
44
40
  def valid?
41
+ return true if user_answer.blank? && allow_blank?
42
+
45
43
  if invalid_answer?
46
44
  error_message = custom_error_message || default_error_message
47
- page.errors.add(component.id, error_message)
45
+ page_answers.errors.add(component.id, error_message)
48
46
  end
49
47
 
50
- page.errors.blank?
48
+ page_answers.errors.blank?
51
49
  end
52
50
 
53
51
  # The custom message will be lookup from the schema key on the metadata.
@@ -65,7 +63,7 @@ module MetadataPresenter
65
63
  # @return [String] user answer for the specific component
66
64
  #
67
65
  def user_answer
68
- answers[component.name]
66
+ page_answers.send(component.name)
69
67
  end
70
68
 
71
69
  # The default error message will be look using the schema key.
@@ -117,9 +115,19 @@ module MetadataPresenter
117
115
  #
118
116
  def error_message_hash
119
117
  {
120
- control: component.label,
118
+ control: component.humanised_title,
121
119
  schema_key.to_sym => component.validation[schema_key]
122
120
  }
123
121
  end
122
+
123
+ # Method signature to be overwrite in the subclass if you do not want to allow
124
+ # blank values. We should not allow blank when performing the required
125
+ # validation.
126
+ #
127
+ # @return [TrueClass]
128
+ #
129
+ def allow_blank?
130
+ true unless self.class.name.demodulize.include?('RequiredValidator')
131
+ end
124
132
  end
125
133
  end
@@ -1,11 +1,10 @@
1
1
  module MetadataPresenter
2
2
  class ValidateAnswers
3
- attr_reader :page, :components, :answers
3
+ attr_reader :page_answers, :components
4
4
 
5
- def initialize(page:, answers:)
6
- @page = page
7
- @answers = answers
8
- @components = Array(page.components)
5
+ def initialize(page_answers, components:)
6
+ @page_answers = page_answers
7
+ @components = Array(components)
9
8
  end
10
9
 
11
10
  def valid?
@@ -16,12 +15,13 @@ module MetadataPresenter
16
15
  !valid?
17
16
  end
18
17
 
18
+ private
19
+
19
20
  def validators
20
21
  components.map do |component|
21
22
  component_validations(component).map do |key|
22
23
  "MetadataPresenter::#{key.classify}Validator".constantize.new(
23
- page: page,
24
- answers: answers,
24
+ page_answers: page_answers,
25
25
  component: component
26
26
  )
27
27
  end
@@ -31,18 +31,7 @@ module MetadataPresenter
31
31
  def component_validations(component)
32
32
  return [] if component.validation.blank?
33
33
 
34
- component.validation.reject do |_, value|
35
- value.blank? ||
36
- (optional_question?(component) && question_not_answered?)
37
- end.keys
38
- end
39
-
40
- def optional_question?(component)
41
- component.validation['required'] == false
42
- end
43
-
44
- def question_not_answered?
45
- answers.values.any?(&:blank?)
34
+ component.validation.select { |_,value| value.present? }.keys
46
35
  end
47
36
  end
48
37
  end
@@ -1,8 +1,7 @@
1
1
  <%=
2
2
  f.govuk_text_field component.id.to_sym,
3
- label: { text: component.label },
3
+ label: { text: input_title },
4
4
  hint: { text: component.hint },
5
5
  name: "answers[#{component.name}]",
6
- value: answer(component.name),
7
6
  width: component.width_class_input.to_i
8
7
  %>
@@ -0,0 +1,9 @@
1
+ <%=
2
+ f.govuk_collection_radio_buttons component.id.to_sym,
3
+ component.items,
4
+ :id,
5
+ :name,
6
+ :description,
7
+ legend: { text: input_title },
8
+ hint: { text: component.hint }
9
+ %>
@@ -1,7 +1,6 @@
1
1
  <%=
2
2
  f.govuk_text_field component.id.to_sym,
3
- label: { text: component.label },
3
+ label: { text: input_title },
4
4
  hint: { text: component.hint },
5
- name: "answers[#{component.name}]",
6
- value: answer(component.name)
5
+ name: "answers[#{component.name}]"
7
6
  %>
@@ -1,9 +1,8 @@
1
1
  <%=
2
2
  f.govuk_text_area component.id.to_sym,
3
- label: { text: component.label },
3
+ label: { text: input_title },
4
4
  hint: { text: component.hint },
5
5
  name: "answers[#{component.name}]",
6
- value: answer(component.name),
7
6
  max_chars: component.maxchars,
8
7
  max_words: component.maxwords,
9
8
  threshold: component.threshold,
@@ -31,7 +31,7 @@
31
31
  <% Array(page.components).each do |component| %>
32
32
  <div class="govuk-summary-list__row">
33
33
  <dt class="govuk-summary-list__key">
34
- <%= component.label %>
34
+ <%= component.humanised_title %>
35
35
  </dt>
36
36
 
37
37
  <dd class="govuk-summary-list__value">
@@ -1,14 +1,14 @@
1
1
  <div class="fb-main-grid-wrapper" data-block-id="<%= @page.id %>" data-block-type="page" data-block-pagetype="<%= @page.type %>">
2
2
  <div class="govuk-grid-row">
3
3
  <div class="govuk-grid-column-two-thirds">
4
- <h1 class="<%= @page.heading_class %>" data-block-id="<%= @page.id %>" data-block-property="heading">
5
- <%= @page.heading.html_safe %>
6
- </h1>
7
-
8
- <%= form_for @page, url: @page.url, method: :post do |f| %>
4
+ <%= form_for @page_answers, as: :answers, url: @page.url, method: :post do |f| %>
9
5
  <%= f.govuk_error_summary %>
10
6
  <% @page.components.each do |component| %>
11
- <%= render partial: component, locals: { component: component, f: f } %>
7
+ <%= render partial: component, locals: {
8
+ component: component,
9
+ f: f,
10
+ input_title: main_h1(component) }
11
+ %>
12
12
  <% end %>
13
13
 
14
14
  <%= f.govuk_submit(disabled: editable?) %>
@@ -0,0 +1,9 @@
1
+ {
2
+ "_id": "component.radios",
3
+ "_type": "radios",
4
+ "errors": {},
5
+ "hint": "Component hint",
6
+ "items": [],
7
+ "name": "component-name",
8
+ "legend": "Required legend"
9
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "_id": "definition.radio",
3
+ "_type": "radio",
4
+ "label": "Required label",
5
+ "value": "radio-value"
6
+ }
@@ -58,10 +58,10 @@
58
58
  "_type": "page.singlequestion",
59
59
  "components": [
60
60
  {
61
- "_id": "page.name--text.auto_name__1",
61
+ "_id": "name_text_1",
62
62
  "_type": "text",
63
63
  "label": "Full name",
64
- "name": "full_name",
64
+ "name": "name_text_1",
65
65
  "validation": {
66
66
  "required": true,
67
67
  "max_length": 10,
@@ -79,7 +79,7 @@
79
79
  "heading": "Email address",
80
80
  "components": [
81
81
  {
82
- "_id": "page.email-address--email.auto_name__2",
82
+ "_id": "email-address_email_1",
83
83
  "_type": "text",
84
84
  "errors": {
85
85
  "format": {},
@@ -94,7 +94,7 @@
94
94
  }
95
95
  },
96
96
  "label": "Your email address",
97
- "name": "email_address",
97
+ "name": "email-address_email_1",
98
98
  "validation": {
99
99
  "required": true,
100
100
  "max_length": 30,
@@ -110,10 +110,10 @@
110
110
  "_type": "page.singlequestion",
111
111
  "components": [
112
112
  {
113
- "_id": "page.parent-name--text.auto_name__3",
113
+ "_id": "parent-name_text_1",
114
114
  "_type": "text",
115
115
  "label": "Parent name",
116
- "name": "parent_name",
116
+ "name": "parent-name_text_1",
117
117
  "validation": {
118
118
  "required": false,
119
119
  "max_length": 10,
@@ -132,15 +132,15 @@
132
132
  "heading":"Your age",
133
133
  "components": [
134
134
  {
135
- "_id": "your_age_number_1",
135
+ "_id": "your-age_number_1",
136
136
  "hint": "Component hint",
137
- "name": "your_age_number_1",
137
+ "name": "your-age_number_1",
138
138
  "_type": "number",
139
139
  "label": "Your age",
140
140
  "errors": {},
141
141
  "validation": {
142
- "required": true,
143
- "number": true
142
+ "number": true,
143
+ "required": true
144
144
  },
145
145
  "width_class_input": "10"
146
146
  }
@@ -152,10 +152,10 @@
152
152
  "_type": "page.singlequestion",
153
153
  "components": [
154
154
  {
155
- "_id": "page.family-hobbies--text.auto_name__3",
155
+ "_id": "family-hobbies_text_1",
156
156
  "_type": "textarea",
157
157
  "label": "Your family hobbies",
158
- "name": "family_hobbies",
158
+ "name": "family-hobbies_text_1",
159
159
  "rows": 5,
160
160
  "validation": {
161
161
  "required": true
@@ -165,6 +165,42 @@
165
165
  "heading": "Family Hobbies",
166
166
  "url": "/family-hobbies"
167
167
  },
168
+ {
169
+ "_uuid": "4251b25e-08de-4dcb-8f2f-dd9848dcdca6",
170
+ "_id": "page.do-you-like-star-wars",
171
+ "_type": "page.singlequestion",
172
+ "components": [
173
+ {
174
+ "_id": "do-you-like-star-wars_radios_1",
175
+ "_type": "radios",
176
+ "errors": {},
177
+ "hint": "Component hint",
178
+ "legend": "Do you like Star Wars?",
179
+ "items": [
180
+ {
181
+ "_id": "do-you-like-star-wars_radio_1",
182
+ "_type": "radio",
183
+ "label": "Only on weekends",
184
+ "hint": "Optional item hint",
185
+ "value": "only-on-weekends"
186
+ },
187
+ {
188
+ "_id": "do-you-like-star-wars_radio_2",
189
+ "_type": "radio",
190
+ "label": "Hell no!",
191
+ "hint": "Optional item hint",
192
+ "value": "hell-no"
193
+ }
194
+ ],
195
+ "name": "do-you-like-star-wars_radios_1",
196
+ "validation": {
197
+ "required": true
198
+ }
199
+ }
200
+ ],
201
+ "heading": "Radio buttons",
202
+ "url": "/do-you-like-star-wars"
203
+ },
168
204
  {
169
205
  "_uuid": "e819d0c2-7062-4997-89cf-44d26d098404",
170
206
  "_id": "page._check-answers",
@@ -1,3 +1,3 @@
1
1
  module MetadataPresenter
2
- VERSION = '0.8.0'
2
+ VERSION = '0.11.0'
3
3
  end
@@ -0,0 +1,37 @@
1
+ {
2
+ "$id": "http://gov.uk/schema/v1.0.0/radios",
3
+ "_name": "component.radios",
4
+ "title": "Radios",
5
+ "description": "Let users select one option from a list",
6
+ "type": "object",
7
+ "properties": {
8
+ "_type": {
9
+ "const": "radios"
10
+ },
11
+ "items": {
12
+ "title": "Options",
13
+ "description": "Items that users can select",
14
+ "type": "array",
15
+ "items": {
16
+ "$ref": "definition.radio"
17
+ }
18
+ }
19
+ },
20
+ "allOf": [
21
+ {
22
+ "$ref": "definition.fieldset"
23
+ },
24
+ {
25
+ "$ref": "definition.name"
26
+ }
27
+ ],
28
+ "transforms": {
29
+ "namespace": {
30
+ "propagation": "items[*].conditional_component"
31
+ }
32
+ },
33
+ "required": [
34
+ "name",
35
+ "items"
36
+ ]
37
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "$id": "http://gov.uk/schema/v1.0.0/definition/conditionalcomponent",
3
+ "_name": "definition.conditionalcomponent",
4
+ "nestable": true,
5
+ "title": "Conditional component",
6
+ "description": "Component revealed when user chooses option",
7
+ "allOf": [
8
+ {
9
+ "$ref": "definition.component"
10
+ }
11
+ ]
12
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "$id": "http://gov.uk/schema/v1.0.0/definition/fieldset",
3
+ "_name": "definition.fieldset",
4
+ "title": "Fieldset",
5
+ "description": "Group related form inputs",
6
+ "type": "object",
7
+ "category": [
8
+ "control",
9
+ "fieldset"
10
+ ],
11
+ "properties": {
12
+ "_type": {
13
+ "const": "fieldset"
14
+ },
15
+ "legend": {
16
+ "title": "Legend",
17
+ "description": "Text to use in fieldset legend",
18
+ "type": "string"
19
+ },
20
+ "hint": {
21
+ "title": "Hint",
22
+ "description": "Text to help users answer a question - appears in grey under the legend",
23
+ "type": "string"
24
+ }
25
+ },
26
+ "allOf": [
27
+ {
28
+ "$ref": "definition.repeatable"
29
+ },
30
+ {
31
+ "$ref": "definition.grouping"
32
+ }
33
+ ],
34
+ "required": [
35
+ "legend"
36
+ ]
37
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "$id": "http://gov.uk/schema/v1.0.0/definition/grouping",
3
+ "_name": "definition.grouping",
4
+ "title": "Grouping definition",
5
+ "allOf": [
6
+ {
7
+ "$ref": "definition.component"
8
+ },
9
+ {
10
+ "$ref": "definition.components"
11
+ },
12
+ {
13
+ "$ref": "definition.namespace"
14
+ },
15
+ {
16
+ "$ref": "definition.html_attributes"
17
+ }
18
+ ],
19
+ "category": [
20
+ "grouping"
21
+ ],
22
+ "transforms": {
23
+ "namespace": {
24
+ "propagation": "components[?(@.$control || @.$grouping)]"
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "$id": "http://gov.uk/schema/v1.0.0/definition/option",
3
+ "_name": "definition.option",
4
+ "title": "Option definition",
5
+ "properties": {
6
+ "value": {
7
+ "title": "Option value",
8
+ "description": "Value captured by system when users choose this option",
9
+ "type": "string"
10
+ },
11
+ "hasDivider": {
12
+ "title": "Option divider",
13
+ "description": "Whether to display a textual divider before the option - defaults to ‘or’",
14
+ "type": "boolean"
15
+ }
16
+ },
17
+ "allOf": [
18
+ {
19
+ "$ref": "definition.block"
20
+ },
21
+ {
22
+ "$ref": "definition.label"
23
+ },
24
+ {
25
+ "$ref": "definition.namespace"
26
+ }
27
+ ],
28
+ "required": [
29
+ "value"
30
+ ],
31
+ "category": [
32
+ "component",
33
+ "option"
34
+ ]
35
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "$id": "http://gov.uk/schema/v1.0.0/definition/radio",
3
+ "_name": "definition.radio",
4
+ "idSeed": "value",
5
+ "title": "Radio option",
6
+ "description": "Component that provides a radio option",
7
+ "type": "object",
8
+ "properties": {
9
+ "_type": {
10
+ "const": "radio"
11
+ },
12
+ "hint": {
13
+ "title": "Hint text",
14
+ "description": "Text to help users understand an option - appears in grey under the label",
15
+ "type": "string",
16
+ "content": true
17
+ },
18
+ "conditional_component": {
19
+ "$ref": "definition.conditionalcomponent"
20
+ }
21
+ },
22
+ "allOf": [
23
+ {
24
+ "$ref": "definition.option"
25
+ }
26
+ ],
27
+ "required": [
28
+ "label"
29
+ ]
30
+ }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metadata_presenter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - MoJ Online
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-10 00:00:00.000000000 Z
11
+ date: 2021-02-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -236,6 +236,7 @@ files:
236
236
  - app/models/metadata_presenter/metadata.rb
237
237
  - app/models/metadata_presenter/next_page.rb
238
238
  - app/models/metadata_presenter/page.rb
239
+ - app/models/metadata_presenter/page_answers.rb
239
240
  - app/models/metadata_presenter/service.rb
240
241
  - app/validators/metadata_presenter/base_validator.rb
241
242
  - app/validators/metadata_presenter/max_length_validator.rb
@@ -247,6 +248,7 @@ files:
247
248
  - app/views/errors/404.html
248
249
  - app/views/layouts/metadata_presenter/application.html.erb
249
250
  - app/views/metadata_presenter/component/_number.html.erb
251
+ - app/views/metadata_presenter/component/_radios.html.erb
250
252
  - app/views/metadata_presenter/component/_text.html.erb
251
253
  - app/views/metadata_presenter/component/_textarea.html.erb
252
254
  - app/views/metadata_presenter/header/show.html.erb
@@ -259,10 +261,12 @@ files:
259
261
  - config/initializers/schemas.rb
260
262
  - config/routes.rb
261
263
  - default_metadata/component/number.json
264
+ - default_metadata/component/radios.json
262
265
  - default_metadata/component/text.json
263
266
  - default_metadata/component/textarea.json
264
267
  - default_metadata/config/meta.json
265
268
  - default_metadata/config/service.json
269
+ - default_metadata/definition/radio.json
266
270
  - default_metadata/page/checkanswers.json
267
271
  - default_metadata/page/confirmation.json
268
272
  - default_metadata/page/singlequestion.json
@@ -281,6 +285,7 @@ files:
281
285
  - lib/metadata_presenter/version.rb
282
286
  - lib/tasks/metadata_presenter_tasks.rake
283
287
  - schemas/component/number.json
288
+ - schemas/component/radios.json
284
289
  - schemas/component/text.json
285
290
  - schemas/component/textarea.json
286
291
  - schemas/condition/condition.json
@@ -297,21 +302,26 @@ files:
297
302
  - schemas/definition/condition.text.json
298
303
  - schemas/definition/condition.value_type.json
299
304
  - schemas/definition/conditional.boolean.json
305
+ - schemas/definition/conditionalcomponent.json
300
306
  - schemas/definition/conditions.all.json
301
307
  - schemas/definition/conditions.any.json
302
308
  - schemas/definition/conditions.exactly.json
303
309
  - schemas/definition/control.json
304
310
  - schemas/definition/data.json
305
311
  - schemas/definition/field.json
312
+ - schemas/definition/fieldset.json
313
+ - schemas/definition/grouping.json
306
314
  - schemas/definition/html_attributes.json
307
315
  - schemas/definition/label.json
308
316
  - schemas/definition/link_list.json
309
317
  - schemas/definition/name.json
310
318
  - schemas/definition/namespace.json
311
319
  - schemas/definition/next_page.json
320
+ - schemas/definition/option.json
312
321
  - schemas/definition/page.content.json
313
322
  - schemas/definition/page.form.json
314
323
  - schemas/definition/page.json
324
+ - schemas/definition/radio.json
315
325
  - schemas/definition/repeatable.json
316
326
  - schemas/definition/width_class.input.json
317
327
  - schemas/definition/width_class.json