Skip to content

Commit 138fc1b

Browse files
authored
Merge pull request #566 from alphagov/CM-683-reorder-telephone-numbers-3
(CM-683) Reorderable telephone numbers
2 parents 14ef339 + c2bd896 commit 138fc1b

12 files changed

Lines changed: 418 additions & 3 deletions

File tree

app/assets/stylesheets/components/_array-component.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,12 @@
4545
@extend .gem-c-button--secondary-quiet; // stylelint-disable-line scss/at-extend-no-missing-placeholder
4646
}
4747
}
48+
49+
&--sortable {
50+
.gem-c-add-another__move-button-wrapper {
51+
top: govuk-spacing(6);
52+
right: govuk-spacing(3);
53+
}
54+
}
4855
// stylelint-enable selector-no-qualifying-type
4956
}

app/components/edition/details/fields/array/item_component.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ def components
2424
fields = field.nested_fields || [field]
2525

2626
fields.map do |item|
27-
helpers.component_for_field(item, context(item))
27+
helpers.component_for_field(item, context_for_field(item))
2828
end
2929
end
3030

31-
def context(field)
31+
def context_for_field(field)
3232
Edition::Details::Fields::Context.new(
3333
edition:,
3434
field:,
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<% components.each do |component| %>
2+
<%= render component %>
3+
<% end %>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
class Edition::Details::Fields::Array::SortableItemComponent < ViewComponent::Base
2+
include ErrorsHelper
3+
4+
def initialize(field:, edition:, schema:, value:, index:, parent_indexes:)
5+
@field = field
6+
@edition = edition
7+
@schema = schema
8+
@value = value
9+
@index = index
10+
@parent_indexes = parent_indexes
11+
end
12+
13+
private
14+
15+
attr_reader :field, :edition, :schema, :value, :index, :parent_indexes
16+
17+
def components
18+
fields = field.nested_fields || [field]
19+
20+
fields.map do |item|
21+
helpers.component_for_field(item, context_for_field(item))
22+
end
23+
end
24+
25+
def context_for_field(field)
26+
Edition::Details::Fields::Context.new(
27+
edition:,
28+
field:,
29+
schema:,
30+
index:,
31+
details: value,
32+
parent_indexes:,
33+
)
34+
end
35+
end
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<%= tag.div class: wrapper_classes, data: { ga4_section: label, module: "array-component" } do %>
2+
<%= render "govuk_publishing_components/components/add_another", {
3+
fieldset_legend: label,
4+
add_button_text: I18n.t("buttons.add_another", item: label.downcase),
5+
sortable: true,
6+
items:,
7+
empty: render(empty_component),
8+
} %>
9+
<% end %>
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
class Edition::Details::Fields::SortableArrayComponent < ViewComponent::Base
2+
def initialize(context)
3+
@context = context
4+
end
5+
6+
private
7+
8+
attr_reader :context
9+
10+
delegate :field, :name, :id, :error_items, :edition, :schema, :subschema, :object_title, :indexes, to: :context
11+
12+
def subschema_block_type
13+
@subschema_block_type ||= subschema&.block_type
14+
end
15+
16+
def label
17+
field.title.singularize
18+
end
19+
20+
def value
21+
context.value || []
22+
end
23+
24+
def number_of_items
25+
if value.count.positive?
26+
value.count
27+
else
28+
field.is_required? ? 1 : 0
29+
end
30+
end
31+
32+
def components
33+
number_of_items.times.map do |index|
34+
component(index)
35+
end
36+
end
37+
38+
def empty_component
39+
component(number_of_items)
40+
end
41+
42+
def component(index)
43+
Edition::Details::Fields::Array::SortableItemComponent.new(
44+
field:,
45+
edition:,
46+
schema:,
47+
value: value[index],
48+
index: index,
49+
parent_indexes: indexes,
50+
)
51+
end
52+
53+
def wrapper_classes
54+
%W[
55+
app-c-content-block-manager-array-component
56+
app-c-content-block-manager-array-component--sortable
57+
app-c-content-block-manager-array-component--#{field.name}
58+
]
59+
end
60+
61+
def order_input(index)
62+
tag.input(
63+
class: "gem-c-input govuk-input govuk-input--width-2",
64+
id: "sortable_#{field.name}_#{index}_order",
65+
name: "#{field.name}[#{index}]order",
66+
value: index,
67+
)
68+
end
69+
70+
def items
71+
components.map.with_index do |component, index|
72+
{
73+
fields: render(component),
74+
order_input: order_input(index),
75+
}
76+
end
77+
end
78+
end

config/content_block_manager.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ schemas:
144144
component: textarea
145145
govspeak_enabled: true
146146
telephone_numbers:
147+
component: sortable_array
147148
field_order:
148149
- type
149150
- label
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
@javascript
2+
Feature: Editor is able to reorder their telephone number fields
3+
- As an editor who has spent time inputting telephone number fields
4+
- So that I don't have to delete items or start again
5+
- I want to be able to reorder my fields into the order I want
6+
7+
Background:
8+
Given I am logged in
9+
And the organisation "Ministry of Example" exists
10+
And I visit the Content Block Manager home page
11+
And I click to create an object
12+
And I click on the "contact" schema
13+
And I complete the form with the following fields:
14+
| title | description | organisation | instructions_to_publishers |
15+
| my basic contact | this is basic | Ministry of Example | this is important |
16+
17+
Scenario: Creating an edition and changing the order of the telephone numbers
18+
When I click on the "telephones" subschema
19+
And I fill in the "telephone" form with the following fields:
20+
| title |
21+
| Many phone numbers |
22+
And I add the following "telephone_numbers" to the form:
23+
| label | telephone_number |
24+
| Telephone 1 | 1 |
25+
| Telephone 2 | 2 |
26+
| Telephone 3 | 3 |
27+
| Telephone 4 | 4 |
28+
And I reorder the 2nd item up
29+
And I reorder the 3rd item down
30+
And I save and continue
31+
Then I should see the items are in the order:
32+
| label | telephone_number |
33+
| Telephone 2 | 2 |
34+
| Telephone 1 | 1 |
35+
| Telephone 4 | 4 |
36+
| Telephone 3 | 3 |
37+
And I save and open the page

features/step_definitions/embedded_object_steps.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
field_prefix = "edition[details][#{@object_type.pluralize}][#{item_type}][]"
3939

4040
row.each do |key, value|
41-
within all(".app-c-content-block-manager-array-item-component").last do
41+
within all(".app-c-content-block-manager-array-component fieldset").last do
4242
field = page.all(:css, "[name='#{field_prefix}[#{key}]']").last
4343
if field.tag_name == "select"
4444
select value, from: field[:id]

features/step_definitions/reorder_steps.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,18 @@
4141
expect(item).to playwright_matchers.have_text(item_title)
4242
end
4343
end
44+
45+
Then(/I reorder the (\d+)(?:st|nd|rd|th) item (up|down)$/) do |cardinality, direction|
46+
rows = page.find_all(".js-add-another__fieldset")
47+
button = rows[cardinality.to_i - 1].find("button[data-action='move-#{direction}']")
48+
button.click
49+
end
50+
51+
Then("I should see the items are in the order:") do |table|
52+
cards = page.find_all(".gem-c-summary__block .govuk-summary-card")
53+
54+
table.hashes.each_with_index do |expected, index|
55+
value_row = cards[index].find_all(".govuk-summary-list__value")[1]
56+
expect(value_row).to have_text(expected["telephone_number"])
57+
end
58+
end

0 commit comments

Comments
 (0)