ccs-frontend_helpers 0.1.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +2 -0
  3. data/.rubocop.yml +127 -0
  4. data/CHANGELOG.md +44 -0
  5. data/Gemfile +10 -0
  6. data/Gemfile.lock +241 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +102 -0
  9. data/Rakefile +10 -0
  10. data/ccs-frontend_helpers.gemspec +47 -0
  11. data/lib/ccs/frontend_helpers/ccs_frontend/dashboard_panels.rb +79 -0
  12. data/lib/ccs/frontend_helpers/ccs_frontend/footer.rb +141 -0
  13. data/lib/ccs/frontend_helpers/ccs_frontend/header.rb +205 -0
  14. data/lib/ccs/frontend_helpers/ccs_frontend/logo.rb +49 -0
  15. data/lib/ccs/frontend_helpers/ccs_frontend.rb +20 -0
  16. data/lib/ccs/frontend_helpers/govuk_frontend/accordion.rb +115 -0
  17. data/lib/ccs/frontend_helpers/govuk_frontend/back_link.rb +39 -0
  18. data/lib/ccs/frontend_helpers/govuk_frontend/breadcrumbs.rb +76 -0
  19. data/lib/ccs/frontend_helpers/govuk_frontend/button.rb +127 -0
  20. data/lib/ccs/frontend_helpers/govuk_frontend/cookie_banner.rb +136 -0
  21. data/lib/ccs/frontend_helpers/govuk_frontend/details.rb +46 -0
  22. data/lib/ccs/frontend_helpers/govuk_frontend/error_message.rb +67 -0
  23. data/lib/ccs/frontend_helpers/govuk_frontend/error_summary.rb +100 -0
  24. data/lib/ccs/frontend_helpers/govuk_frontend/field/character_count.rb +165 -0
  25. data/lib/ccs/frontend_helpers/govuk_frontend/field/checkboxes.rb +200 -0
  26. data/lib/ccs/frontend_helpers/govuk_frontend/field/date_input.rb +153 -0
  27. data/lib/ccs/frontend_helpers/govuk_frontend/field/file_upload.rb +83 -0
  28. data/lib/ccs/frontend_helpers/govuk_frontend/field/input.rb +153 -0
  29. data/lib/ccs/frontend_helpers/govuk_frontend/field/radios.rb +201 -0
  30. data/lib/ccs/frontend_helpers/govuk_frontend/field/select.rb +124 -0
  31. data/lib/ccs/frontend_helpers/govuk_frontend/field/textarea.rb +106 -0
  32. data/lib/ccs/frontend_helpers/govuk_frontend/field.rb +213 -0
  33. data/lib/ccs/frontend_helpers/govuk_frontend/fieldset.rb +71 -0
  34. data/lib/ccs/frontend_helpers/govuk_frontend/footer.rb +183 -0
  35. data/lib/ccs/frontend_helpers/govuk_frontend/form_group.rb +50 -0
  36. data/lib/ccs/frontend_helpers/govuk_frontend/header.rb +161 -0
  37. data/lib/ccs/frontend_helpers/govuk_frontend/hint.rb +38 -0
  38. data/lib/ccs/frontend_helpers/govuk_frontend/inset_text.rb +44 -0
  39. data/lib/ccs/frontend_helpers/govuk_frontend/label.rb +92 -0
  40. data/lib/ccs/frontend_helpers/govuk_frontend/notification_banner.rb +136 -0
  41. data/lib/ccs/frontend_helpers/govuk_frontend/pagination.rb +336 -0
  42. data/lib/ccs/frontend_helpers/govuk_frontend/panel.rb +51 -0
  43. data/lib/ccs/frontend_helpers/govuk_frontend/phase_banner.rb +49 -0
  44. data/lib/ccs/frontend_helpers/govuk_frontend/skip_link.rb +40 -0
  45. data/lib/ccs/frontend_helpers/govuk_frontend/step_by_step_navigation.rb +215 -0
  46. data/lib/ccs/frontend_helpers/govuk_frontend/summary_list.rb +226 -0
  47. data/lib/ccs/frontend_helpers/govuk_frontend/table.rb +124 -0
  48. data/lib/ccs/frontend_helpers/govuk_frontend/tabs.rb +95 -0
  49. data/lib/ccs/frontend_helpers/govuk_frontend/tag.rb +42 -0
  50. data/lib/ccs/frontend_helpers/govuk_frontend/warning_text.rb +53 -0
  51. data/lib/ccs/frontend_helpers/govuk_frontend.rb +82 -0
  52. data/lib/ccs/frontend_helpers/shared_methods.rb +27 -0
  53. data/lib/ccs/frontend_helpers/version.rb +7 -0
  54. data/lib/ccs/frontend_helpers.rb +20 -0
  55. data/sig/ccs/frontend_helpers.rbs +6 -0
  56. metadata +241 -0
@@ -0,0 +1,165 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'textarea'
4
+
5
+ module CCS
6
+ module FrontendHelpers
7
+ module GovUKFrontend
8
+ module Field
9
+ # = GOV.UK Character count
10
+ #
11
+ # This helper is used for generating the character count component from the
12
+ # {https://design-system.service.gov.uk/components/character-count GDS - Components - Character count}
13
+ #
14
+ # This is a wrapper around a Textarea module and so makes use of the methods in {Textarea}
15
+
16
+ module CharacterCount
17
+ include Textarea
18
+
19
+ # Generates the HTML for the GOV.UK character count component.
20
+ # It works by warpping the govuk_textarea in HTML which will trigger the JavaScript to do the character count.
21
+ #
22
+ # @param attribute [String, Symbol] the attribute of the character count text area
23
+ # @param govuk_character_count_options [Hash] options that will be used for the parts of the form group, label, hint, textarea and the character count
24
+ #
25
+ # @option govuk_character_count_options [String] :error_message (nil) the error message to be displayed
26
+ # @option govuk_character_count_options [ActiveModel] :model (nil) optional model that can be used to find an error message
27
+ # @option govuk_character_count_options [ActionView::Helpers::FormBuilder] :form (nil) optional form builder used to create
28
+ # the textarea tag and find the error message
29
+ # @option govuk_character_count_options [Hash] :form_group see {govuk_field}
30
+ # @option govuk_character_count_options [Hash] :label see {govuk_field}
31
+ # @option govuk_character_count_options [Hash] :hint see {govuk_field}
32
+ # @option govuk_character_count_options [Hash] :textarea see {govuk_textarea}
33
+ # @option govuk_character_count_options [Hash] :character_count ({}) the options that will be used when rendering the textarea.
34
+ # See {_govuk_character_count} for more details.
35
+ #
36
+ # @return [ActiveSupport::SafeBuffer] the HTML for the GOV.UK chracter count
37
+ # which can then be rendered on the page
38
+
39
+ def govuk_character_count(attribute, **govuk_character_count_options)
40
+ character_count_attribute = govuk_character_count_options[:form] ? "#{form.object_name}_#{attribute}" : attribute
41
+
42
+ _govuk_character_count(character_count_attribute, **govuk_character_count_options) do |govuk_textarea_options|
43
+ govuk_textarea(
44
+ attribute,
45
+ error_message: govuk_character_count_options[:error_message],
46
+ model: govuk_character_count_options[:model],
47
+ form: govuk_character_count_options[:form],
48
+ **govuk_textarea_options
49
+ )
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ # Wrapper method used by {govuk_character_count} to generate the character count HTML
56
+ #
57
+ # @param attribute [String, Symbol] the attribute of the character count
58
+ # @param govuk_character_count_options [Hash] options that will be used in customising the HTML.
59
+ # This includes everything described in {govuk_character_count}
60
+ # with the addition of the +:character_count+ which are described below
61
+ #
62
+ # @option govuk_character_count_options [String] :maxlength (required) - if +maxwords+ is set, this is not required.
63
+ # The maximum number of characters.
64
+ # If +maxwords+ is provided, the +maxlength+ option will be ignored.
65
+ # @option govuk_character_count_options [String] :maxwords (required) - if maxlength is set, this is not required.
66
+ # The maximum number of words.
67
+ # If +maxwords+ is provided, the +maxlength+ option will be ignored.
68
+ # @option govuk_character_count_options [String] :threshold the percentage value of the limit at which point the count message is displayed.
69
+ # If this attribute is set, the count message will be hidden by default.
70
+ # @option govuk_textarea_options [Hash] :fallback_hint ({}) additional parameters that will be used to create the hint containing the character count text.
71
+ # This includes all the options in {govuk_hint} plus +:count_message+.
72
+ # This will replace the default text for the count message.
73
+ # If you want the count number to appear, put %<count>s in the string and it will be replaced with the number
74
+ #
75
+ # @yield the textarea HTML generated by {govuk_character_count}
76
+ #
77
+ # @yieldparam govuk_textarea_options [Hash] the options used in the textarea called by {govuk_character_count}
78
+ #
79
+ # @return [ActiveSupport::SafeBuffer] the HTML for the chracter count which wrpas arround {govuk_character_count}
80
+
81
+ def _govuk_character_count(attribute, **govuk_character_count_options)
82
+ deep_init_hash(govuk_character_count_options, :textarea, :attributes, :aria)
83
+ govuk_character_count_options[:textarea][:attributes][:aria][:describedby] = [govuk_character_count_options.dig(:textarea, :attributes, :aria, :describedby), "#{attribute}-info"].compact.join(' ')
84
+
85
+ govuk_character_count_options[:textarea][:classes] = "#{govuk_character_count_options[:textarea][:classes]} govuk-js-character-count".lstrip
86
+
87
+ tag.div(**get_character_count_attributes(**govuk_character_count_options)) do
88
+ concat(yield(govuk_character_count_options))
89
+ concat(character_count_hint(attribute, **govuk_character_count_options))
90
+ end
91
+ end
92
+
93
+ # Generates the fallback hint HTML for {_govuk_character_count}
94
+ #
95
+ # @param (see _govuk_character_count)
96
+ #
97
+ # @option (see _govuk_character_count)
98
+ #
99
+ # @return [ActiveSupport::SafeBuffer] the HTML for the fullback hint used in {_govuk_character_count}
100
+
101
+ def character_count_hint(attribute, **govuk_character_count_options)
102
+ fallback_hint_length = govuk_character_count_options[:character_count][:maxwords] || govuk_character_count_options[:character_count][:maxlength]
103
+ fallback_hint_default = "You can enter up to %<count>s #{govuk_character_count_options[:character_count][:maxwords] ? 'words' : 'characters'}"
104
+
105
+ deep_init_hash(govuk_character_count_options, :character_count, :fallback_hint, :attributes)
106
+
107
+ fallback_hint_text = format(govuk_character_count_options[:character_count][:fallback_hint][:count_message] || fallback_hint_default, count: fallback_hint_length)
108
+
109
+ govuk_character_count_options[:character_count][:fallback_hint][:classes] = "#{govuk_character_count_options.dig(:character_count, :fallback_hint, :classes)} govuk-character-count__message".lstrip
110
+ govuk_character_count_options[:character_count][:fallback_hint][:attributes].merge!(id: "#{attribute}-info")
111
+
112
+ govuk_hint(fallback_hint_text, **govuk_character_count_options[:character_count][:fallback_hint])
113
+ end
114
+
115
+ # Generates a hash with the character count attributes used in {_govuk_character_count}
116
+ #
117
+ # @param govuk_character_count_options [Hash] options that will be used in customising the HTML.
118
+ # This includes everything described in {govuk_character_count}
119
+ # with the addition of the +:character_count+ which are described below
120
+ #
121
+ # @option (see _govuk_character_count)
122
+ #
123
+ # @return [Hash] contains the HTMl attributes used in {_govuk_character_count}
124
+
125
+ def get_character_count_attributes(**govuk_character_count_options)
126
+ govuk_character_count_attributes = { class: 'govuk-character-count', data: { module: 'govuk-character-count' } }
127
+
128
+ %i[maxlength threshold maxwords].each do |data_attribute|
129
+ govuk_character_count_attributes[:data][data_attribute] = govuk_character_count_options[:character_count][data_attribute].to_s if govuk_character_count_options[:character_count][data_attribute]
130
+ end
131
+
132
+ govuk_character_count_attributes
133
+ end
134
+
135
+ # Method to initialise hashes within hashes if it is not already initialised
136
+ #
137
+ # @param hash [Hash] the hash that is going to be initialised
138
+ # @param keys [Array] the keys that are going to be initialised in the hash
139
+ #
140
+ # @example When the hash is completely empty
141
+ # hash = { }
142
+ # keys = [:a, :b, :c]
143
+ #
144
+ # deep_init_hash(hash, *keys)
145
+ #
146
+ # hash = { a: { b: { c: { } } } }
147
+ #
148
+ # @example When the hash has already been initialised
149
+ # hash = { a: { b: { d: 'hello' } } }
150
+ # keys = [:a, :b, :c]
151
+ #
152
+ # deep_init_hash(hash, *keys)
153
+ #
154
+ # hash = { a: { b: { d: 'hello', c: { } } } }
155
+
156
+ def deep_init_hash(hash, *keys)
157
+ current_hash = hash
158
+
159
+ keys.each { |key| current_hash = (current_hash[key] ||= {}) }
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,200 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../field'
4
+
5
+ module CCS
6
+ module FrontendHelpers
7
+ module GovUKFrontend
8
+ module Field
9
+ # = GOV.UK Checkboxes
10
+ #
11
+ # This helper is used for generating the checkboxes component from the
12
+ # {https://design-system.service.gov.uk/components/checkboxes GDS - Components - Checkboxes}
13
+ #
14
+ # This is considered a Field module and so makes use of the methods in {CCS::FrontendHelpers::GovUKFrontend::Field}
15
+
16
+ module Checkboxes
17
+ include Field
18
+
19
+ # Generates the HTML for the GOV.UK Checkboxes component
20
+ #
21
+ # @param attribute [String, Symbol] the attribute of the raido buttons
22
+ # @param items [Array] array of checkbox items, see {_govuk_checkboxes_fields}
23
+ # @param govuk_checkboxes_options [Hash] options that will be used for the parts of the fieldset, form group, hint and checkbox buttons
24
+ #
25
+ # @option govuk_checkboxes_options [String] :error_message (nil) the error message to be displayed
26
+ # @option govuk_checkboxes_options [ActiveModel] :model (nil) optional model that can be used to find an error message
27
+ # @option govuk_checkboxes_options [ActionView::Helpers::FormBuilder] :form (nil) optional form builder used to create
28
+ # the checkbox tags and find the error message
29
+ # @option govuk_checkboxes_options [Hash] :form_group see {govuk_fields}
30
+ # @option govuk_checkboxes_options [Hash] :fieldset see {govuk_fields}
31
+ # @option govuk_checkboxes_options [Hash] :hint see {govuk_field}
32
+ # @option govuk_checkboxes_options [Hash] :checkboxes ({}) the options that will be used when rendering the checkbox buttons.
33
+ # See {_govuk_checkboxes_fields} for more details.
34
+ #
35
+ # @return [ActiveSupport::SafeBuffer] the HTML for the GOV.UK Checkboxes
36
+ # which can then be rendered on the page
37
+
38
+ def govuk_checkboxes(attribute, items, **govuk_checkboxes_options)
39
+ govuk_fields(:checkboxes, attribute, **govuk_checkboxes_options) do |govuk_field_options|
40
+ if govuk_checkboxes_options[:model] || govuk_checkboxes_options[:form]
41
+ values = (govuk_checkboxes_options[:model] || govuk_checkboxes_options[:form].object).send(attribute) || []
42
+ items.each { |item| item[:checked] = values.include?(item[:value]) }
43
+ end
44
+
45
+ concat(
46
+ if govuk_checkboxes_options[:form]
47
+ govuk_checkbox_field_form(govuk_checkboxes_options[:form], attribute, items, **govuk_field_options)
48
+ else
49
+ govuk_checkbox_field_tag(attribute, items, **govuk_field_options)
50
+ end
51
+ )
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ # Generates the checkboxes HTML for {govuk_checkboxes}
58
+ #
59
+ # @param attribute [String, Symbol] the attribute of the raido buttons
60
+ # @param items [Array] array of checkbox items, see {_govuk_checkboxes_fields}
61
+ # @param govuk_checkboxes_options [Hash] options that will be used in customising the HTML
62
+ #
63
+ # @option (see _govuk_checkboxes_fields)
64
+ #
65
+ # @return [ActiveSupport::SafeBuffer] the HTML for the checkbox buttons which is used in {govuk_checkboxes}
66
+
67
+ def govuk_checkbox_field_tag(attribute, items, **govuk_checkboxes_options)
68
+ _govuk_checkboxes_fields(items, **govuk_checkboxes_options) do |checkbox_item|
69
+ govuk_checkbox_item_tag(attribute, checkbox_item)
70
+ end
71
+ end
72
+
73
+ # Generates the checkboxes HTML for {govuk_checkboxes} when there is a ActionView::Helpers::FormBuilder
74
+ #
75
+ # @param form [ActionView::Helpers::FormBuilder] the form builder used to create the checkbox buttons
76
+ # @param (see govuk_checkbox_field_tag)
77
+ #
78
+ # @option (see _govuk_checkboxes_fields)
79
+ #
80
+ # @return (see govuk_checkbox_field_tag)
81
+
82
+ def govuk_checkbox_field_form(form, attribute, items, **govuk_checkboxes_options)
83
+ _govuk_checkboxes_fields(items, **govuk_checkboxes_options) do |checkbox_item|
84
+ govuk_checkbox_item_form(form, attribute, checkbox_item)
85
+ end
86
+ end
87
+
88
+ # Wrapper method used by {govuk_checkbox_field_tag} and {govuk_checkbox_field_form} to generate the checkboxes HTML
89
+ #
90
+ # @param items [Array] array of checkbox items.
91
+ # Each item is a hash which can be:
92
+ # - +:divider+ text to separate checkbox items
93
+ # - checkbox item, see {_govuk_checkbox_item}
94
+ # @param govuk_checkboxes_options [Hash] options that will be used in customising the HTML
95
+ #
96
+ # @option govuk_checkboxes_options [String] :classes additional CSS classes for the checkboxes HTML
97
+ # @option govuk_checkboxes_options [Hash] :attributes ({ module: 'govuk-checkboxes' }) any additional attributes that will added as part of the HTML
98
+ #
99
+ # @yield the checkbox item HTML generated by {govuk_checkbox_field_tag} or {govuk_checkbox_field_form}
100
+ #
101
+ # @yieldparam checkbox_item [Hash] the current checkbox item to be rendered
102
+ #
103
+ # @return [ActiveSupport::SafeBuffer] the HTML for the checkbox buttons which is used in {govuk_checkbox_field_tag} or {govuk_checkbox_field_form}
104
+
105
+ def _govuk_checkboxes_fields(items, **govuk_checkboxes_options)
106
+ initialise_attributes_and_set_classes(govuk_checkboxes_options, 'govuk-checkboxes')
107
+ set_data_module(govuk_checkboxes_options, 'govuk-checkboxes')
108
+
109
+ tag.div(**govuk_checkboxes_options[:attributes]) do
110
+ items.each do |checkbox_item|
111
+ concat(
112
+ if checkbox_item[:divider]
113
+ tag.div(checkbox_item[:divider], class: 'govuk-checkboxes__divider')
114
+ else
115
+ tag.div(class: 'govuk-checkboxes__item') do
116
+ yield(checkbox_item)
117
+ end
118
+ end
119
+ )
120
+ end
121
+ end
122
+ end
123
+
124
+ # Generates the HTML for a checkbox button for {govuk_checkbox_field_form}
125
+ #
126
+ # @param (see _govuk_checkbox_item)
127
+ #
128
+ # @option (see _govuk_checkbox_item)
129
+ #
130
+ # @return (see _govuk_checkbox_item)
131
+
132
+ def govuk_checkbox_item_tag(attribute, checkbox_item)
133
+ _govuk_checkbox_item(attribute, checkbox_item) do
134
+ checkbox_item[:attributes][:id] ||= "#{sanitize_to_id(attribute)}_#{sanitize_to_id(checkbox_item[:value])}"
135
+
136
+ concat(check_box_tag("#{attribute}[]", checkbox_item[:value], checkbox_item[:checked], **checkbox_item[:attributes]))
137
+ concat(govuk_label(checkbox_item[:attributes][:id], checkbox_item[:label][:text], **checkbox_item[:label]))
138
+ end
139
+ end
140
+
141
+ # Generates the HTML for a checkbox button for {govuk_checkbox_field_tag}
142
+ #
143
+ # @param (see _govuk_checkbox_item)
144
+ # @param form [ActionView::Helpers::FormBuilder] the form builder used to create the checkbox buttons
145
+ #
146
+ # @option (see _govuk_checkbox_item)
147
+ #
148
+ # @return (see _govuk_checkbox_item)
149
+
150
+ def govuk_checkbox_item_form(form, attribute, checkbox_item)
151
+ _govuk_checkbox_item(attribute, checkbox_item) do
152
+ (checkbox_item[:label][:attributes] ||= {})[:value] = checkbox_item[:value]
153
+ checkbox_item[:label][:attributes][:for] = checkbox_item[:attributes][:id] if checkbox_item[:attributes][:id]
154
+
155
+ concat(form.check_box(attribute, checkbox_item[:attributes].merge({ multiple: true, include_hidden: false }), checkbox_item[:value]))
156
+ concat(govuk_label(attribute, checkbox_item[:label][:text], form: form, **checkbox_item[:label]))
157
+ end
158
+ end
159
+
160
+ # rubocop:disable Metrics/AbcSize
161
+
162
+ # Wrapper method used by {govuk_checkbox_item_tag} and {govuk_checkbox_item_form} to generate the checkboxes HTML
163
+ # including the label and hint, if there is one.
164
+ #
165
+ # @param attribute [String, Symbol] the attribute of the raido buttons
166
+ # @param checkbox_item [Hash] the options for the checkbox item
167
+ #
168
+ # @option checkbox_item [String] :classes additional CSS classes for the checkbox button HTML
169
+ # @option checkbox_item [Hash] :label the parameters that will be used to create the label for the checkbox button, see {govuk_label}
170
+ # @option checkbox_item [Hash] :hint (nil) the parameters that will be used to create the hint for the checkbox button, see {govuk_hint}.
171
+ # If no hint is given then no hint will be rendered
172
+ # @option checkbox_item [Hash] :conditional (nil) content that will appear when the checkbox input is checked.
173
+ # It can have the following options:
174
+ # - +[:content]+ the content that will be shown
175
+ # - +[:attributes][:id]+ the id of the conditional section
176
+ # If no conditional is given then no conditional content will be rendered
177
+ # @option checkbox_item [Hash] :attributes ({}) any additional attributes that will be added as part of the checkbox button HTML
178
+ #
179
+ # @return [ActiveSupport::SafeBuffer] the HTML for the checkbox buttons, label and hint
180
+ # which is used in {govuk_checkbox_item_tag} and {govuk_checkbox_item_form}
181
+
182
+ def _govuk_checkbox_item(attribute, checkbox_item)
183
+ (checkbox_item[:attributes] ||= {})[:class] = 'govuk-checkboxes__input'
184
+ checkbox_item[:label] ||= {}
185
+ checkbox_item[:label][:classes] = "govuk-checkboxes__label #{checkbox_item[:label][:classes]}".rstrip
186
+
187
+ set_item_options_for_hint('checkboxes', attribute, checkbox_item)
188
+ set_conditional_item_options('checkboxes', attribute, checkbox_item)
189
+
190
+ yield
191
+ concat(govuk_hint(checkbox_item[:hint][:text], **checkbox_item[:hint])) if checkbox_item[:hint]
192
+ concat(tag.div(checkbox_item[:conditional][:content], class: checkbox_item[:conditional][:attributes][:class], id: checkbox_item[:conditional][:attributes][:id])) if checkbox_item[:conditional]
193
+ end
194
+
195
+ # rubocop:enable Metrics/AbcSize
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end
@@ -0,0 +1,153 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../field'
4
+ require_relative 'input'
5
+
6
+ module CCS
7
+ module FrontendHelpers
8
+ module GovUKFrontend
9
+ module Field
10
+ # = GOV.UK Date Input
11
+ #
12
+ # This helper is used for generating the date input component from the
13
+ # {https://design-system.service.gov.uk/components/date-input GDS - Components - Date Input}
14
+ #
15
+ # This is considered a Field module and so makes use of the methods in {CCS::FrontendHelpers::GovUKFrontend::Field}
16
+
17
+ module DateInput
18
+ include Field
19
+ include Input
20
+
21
+ # Generates the HTML for the GOV.UK date input component
22
+ #
23
+ # @param attribute [String, Symbol] the attribute of the date input
24
+ # @param govuk_date_input_options [Hash] options that will be used for the parts of the fieldset, form group, hint and date input
25
+ #
26
+ # @option govuk_date_input_options [String] :error_message (nil) the error message to be displayed
27
+ # @option govuk_date_input_options [ActiveModel] :model (nil) optional model that can be used to find an error message
28
+ # @option govuk_date_input_options [ActionView::Helpers::FormBuilder] :form (nil) optional form builder used to create
29
+ # the date tag and find the error message
30
+ # @option govuk_date_input_options [Hash] :form_group see {govuk_fields}
31
+ # @option govuk_date_input_options [Hash] :fieldset see {govuk_fields}
32
+ # @option govuk_date_input_options [Hash] :hint see {govuk_field}
33
+ # @option govuk_date_input_options [Hash] :date_input_options ({}) the options that will be used when rendering the date input.
34
+ # See {_govuk_date_input_fields} for more details.
35
+ #
36
+ # @return [ActiveSupport::SafeBuffer] the HTML for the GOV.UK Date Input
37
+ # which can then be rendered on the page
38
+
39
+ def govuk_date_input(attribute, **govuk_date_input_options)
40
+ set_govuk_date_input_fieldset_options(**govuk_date_input_options)
41
+
42
+ govuk_fields(:date_input, attribute, **govuk_date_input_options) do |govuk_field_options, error_message|
43
+ concat(_govuk_date_input_fields(attribute, error_message, **govuk_field_options) do |date_item_attribute, date_item_input_options|
44
+ govuk_input(
45
+ date_item_attribute,
46
+ model: govuk_date_input_options[:model],
47
+ form: govuk_date_input_options[:form],
48
+ **date_item_input_options
49
+ )
50
+ end)
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ # Sets the role for the fieldset to group
57
+ #
58
+ # @param govuk_date_input_options [Hash] options that will be used for the parts of the fieldset, form group, hint and date input
59
+
60
+ def set_govuk_date_input_fieldset_options(**govuk_date_input_options)
61
+ (govuk_date_input_options[:fieldset][:attributes] ||= {})[:role] = 'group'
62
+ end
63
+
64
+ # Wrapper method used by {govuk_date_input} to generate the date inputs HTML
65
+ #
66
+ # @param attribute [String, Symbol] the attribute of the date input
67
+ # @param any_errors [Boolean] flag to indicate if the inputs need the error class
68
+ # @param govuk_date_input_options [Hash] options that will be used in customising the HTML
69
+ #
70
+ # @option govuk_date_input_options [String] :classes additional CSS classes for the date inputs HTML
71
+ # @option govuk_date_input_options[Array] :date_items an array of the date items that will be rendered.
72
+ # Each date item hash must contain the +:name+ to add as suffix to attribute.
73
+ # Anything else in the hash will be used as options in a {govuk_input}.
74
+ # @option govuk_date_input_options [Hash] :attributes ({}) any additional attributes that will added as part of the HTML
75
+ #
76
+ # @yield the date input item HTML generated by the parent method
77
+ #
78
+ # @yieldparam date_item_attribute [String] the attribute for individual date input
79
+ # @yieldparam date_item_input_options [Hash] the HTML options used for the date input item
80
+ #
81
+ # @return [ActiveSupport::SafeBuffer] the HTML for the date inputs which is used in {govuk_date_input}
82
+
83
+ def _govuk_date_input_fields(attribute, any_errors, **govuk_date_input_options)
84
+ initialise_attributes_and_set_classes(govuk_date_input_options, 'govuk-date-input')
85
+
86
+ date_items = govuk_date_input_options[:date_items] || govuk_default_date_items
87
+
88
+ tag.div(**govuk_date_input_options[:attributes]) do
89
+ enumerate_and_set_date_input_options(date_items, any_errors) do |date_item_input_options|
90
+ concat(tag.div(class: 'govuk-date-input__item') do
91
+ concat(yield("#{attribute}_#{date_item_input_options[:name]}", date_item_input_options))
92
+ end)
93
+ end
94
+ end
95
+ end
96
+
97
+ # rubocop:disable Metrics/CyclomaticComplexity
98
+
99
+ # Enumerates and inititalises the attributes of each date input item and is used by {_govuk_date_input_fields}
100
+ #
101
+ # @param date_items [Array] an array of the date item hashes that will be inititalised
102
+ # @param any_errors [Boolean] flag to indicate if the inputs need the error class
103
+ #
104
+ # @yield the date input item HTML generated by teach date input item
105
+ #
106
+ # @yieldparam date_item_input_options [Hash] the HTML options used for the date input item
107
+
108
+ def enumerate_and_set_date_input_options(date_items, any_errors)
109
+ date_items.each do |date_item_input_options|
110
+ (date_item_input_options[:input] ||= {})[:attributes] ||= {}
111
+
112
+ date_item_input_options[:input][:classes] = "govuk-date-input__input #{date_item_input_options[:input][:classes]} #{'govuk-input--error' if any_errors}".rstrip
113
+
114
+ date_item_input_options[:input][:attributes][:inputmode] ||= 'numeric'
115
+
116
+ date_item_input_options[:label] ||= {}
117
+ date_item_input_options[:label][:text] ||= date_item_input_options[:name].capitalize
118
+ date_item_input_options[:label][:classes] = 'govuk-date-input__label'
119
+
120
+ yield(date_item_input_options)
121
+ end
122
+ end
123
+ # rubocop:enable Metrics/CyclomaticComplexity
124
+
125
+ # The default date items used in {_govuk_date_input_fields} if no date items are provided
126
+
127
+ def govuk_default_date_items
128
+ [
129
+ {
130
+ name: 'day',
131
+ input: {
132
+ classes: 'govuk-input--width-2'
133
+ }
134
+ },
135
+ {
136
+ name: 'month',
137
+ input: {
138
+ classes: 'govuk-input--width-2'
139
+ }
140
+ },
141
+ {
142
+ name: 'year',
143
+ input: {
144
+ classes: 'govuk-input--width-4'
145
+ }
146
+ }
147
+ ]
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../field'
4
+
5
+ module CCS
6
+ module FrontendHelpers
7
+ module GovUKFrontend
8
+ module Field
9
+ # = GOV.UK File Upload
10
+ #
11
+ # This helper is used for generating the file upload component from the
12
+ # {https://design-system.service.gov.uk/components/file-upload GDS - Components - File Upload}
13
+ #
14
+ # This is considered a Field module and so makes use of the methods in {CCS::FrontendHelpers::GovUKFrontend::Field}
15
+
16
+ module FileUpload
17
+ include Field
18
+
19
+ # Generates the HTML for the GOV.UK file upload component
20
+ #
21
+ # @param attribute [String, Symbol] the attribute of the file upload
22
+ # @param govuk_file_upload_options [Hash] options that will be used for the parts of the form group, label, hint and file upload
23
+ #
24
+ # @option govuk_file_upload_options [String] :error_message (nil) the error message to be displayed
25
+ # @option govuk_file_upload_options [ActiveModel] :model (nil) optional model that can be used to find an error message
26
+ # @option govuk_file_upload_options [ActionView::Helpers::FormBuilder] :form (nil) optional form builder used to create
27
+ # the file upload input and find the error message
28
+ # @option govuk_file_upload_options [Hash] :form_group see {govuk_field}
29
+ # @option govuk_file_upload_options [Hash] :label see {govuk_field}
30
+ # @option govuk_file_upload_options [Hash] :hint see {govuk_field}
31
+ # @option govuk_file_upload_options [Hash] :file_upload ({}) the options that will be used when rendering the file upload.
32
+ # See {govuk_file_upload_tag} for more details.
33
+ #
34
+ # @return [ActiveSupport::SafeBuffer] the HTML for the GOV.UK File Upload
35
+ # which can then be rendered on the page
36
+
37
+ def govuk_file_upload(attribute, **govuk_file_upload_options)
38
+ govuk_field(:file_upload, attribute, **govuk_file_upload_options) do |govuk_field_options, error_message|
39
+ initialise_attributes_and_set_classes(govuk_field_options, "govuk-file-upload #{'govuk-file-upload--error' if error_message}".rstrip)
40
+
41
+ concat(
42
+ if govuk_file_upload_options[:form]
43
+ govuk_file_upload_form(govuk_file_upload_options[:form], attribute, **govuk_field_options)
44
+ else
45
+ govuk_file_upload_tag(attribute, **govuk_field_options)
46
+ end
47
+ )
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ # Generates the file upload HTML for {govuk_file_upload}
54
+ #
55
+ # @param attribute [String, Symbol] the attribute of the file upload
56
+ # @param govuk_file_upload_options [Hash] options that will be used in customising the HTML
57
+ #
58
+ # @option govuk_file_upload_options [String] :classes additional CSS classes for the file upload HTML
59
+ # @option govuk_file_upload_options [Hash] :attributes ({}) any additional attributes that will added as part of the HTML
60
+ #
61
+ # @return [ActiveSupport::SafeBuffer] the HTML for the file upload field which is used in {govuk_file_upload}
62
+
63
+ def govuk_file_upload_tag(attribute, **govuk_file_upload_options)
64
+ file_field_tag(attribute, **govuk_file_upload_options[:attributes])
65
+ end
66
+
67
+ # Generates the file upload HTML for {govuk_file_upload} when there is a ActionView::Helpers::FormBuilder
68
+ #
69
+ # @param form [ActionView::Helpers::FormBuilder] the form builder used to create the file upload input
70
+ # @param (see govuk_file_upload_tag)
71
+ #
72
+ # @option (see govuk_file_upload_tag)
73
+ #
74
+ # @return (see govuk_file_upload_tag)
75
+
76
+ def govuk_file_upload_form(form, attribute, **govuk_file_upload_options)
77
+ form.file_field(attribute, **govuk_file_upload_options[:attributes])
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end