ccs-frontend_helpers 0.1.0.rc.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.
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