From 9885eb88eae6bac0c1f786a1cfa5a343414f8a02 Mon Sep 17 00:00:00 2001
From: pezholio
Date: Fri, 21 Feb 2025 14:32:08 +0000
Subject: [PATCH 1/6] Ensure change notes are not copied when cloning
---
.../content_block_manager/content_block/edition.rb | 11 +++++++----
.../unit/app/models/content_block_edition_test.rb | 6 +++++-
2 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/lib/engines/content_block_manager/app/models/content_block_manager/content_block/edition.rb b/lib/engines/content_block_manager/app/models/content_block_manager/content_block/edition.rb
index d492a6c82eb..566edf5dd54 100644
--- a/lib/engines/content_block_manager/app/models/content_block_manager/content_block/edition.rb
+++ b/lib/engines/content_block_manager/app/models/content_block_manager/content_block/edition.rb
@@ -38,10 +38,13 @@ def first_class_details
def clone_edition(creator:)
new_edition = dup
- new_edition.state = "draft"
- new_edition.organisation = lead_organisation
- new_edition.creator = creator
-
+ new_edition.assign_attributes(
+ state: "draft",
+ organisation: lead_organisation,
+ creator: creator,
+ change_note: nil,
+ internal_change_note: nil,
+ )
new_edition
end
diff --git a/lib/engines/content_block_manager/test/unit/app/models/content_block_edition_test.rb b/lib/engines/content_block_manager/test/unit/app/models/content_block_edition_test.rb
index 3333b36739d..bcc1fef66bf 100644
--- a/lib/engines/content_block_manager/test/unit/app/models/content_block_edition_test.rb
+++ b/lib/engines/content_block_manager/test/unit/app/models/content_block_edition_test.rb
@@ -242,7 +242,9 @@ class ContentBlockManager::ContentBlockEditionTest < ActiveSupport::TestCase
:content_block_edition, :email_address,
title: "Some title",
details: { "my" => "details" },
- state: "published"
+ state: "published",
+ change_note: "Something",
+ internal_change_note: "Something else"
)
creator = create(:user)
@@ -254,6 +256,8 @@ class ContentBlockManager::ContentBlockEditionTest < ActiveSupport::TestCase
assert_equal new_edition.creator, creator
assert_equal new_edition.title, content_block_edition.title
assert_equal new_edition.details, content_block_edition.details
+ assert_equal new_edition.change_note, nil
+ assert_equal new_edition.internal_change_note, nil
end
end
From 154bf79ef91264ef6d0656b9f8dc801501617db9 Mon Sep 17 00:00:00 2001
From: pezholio
Date: Thu, 27 Feb 2025 16:33:57 +0000
Subject: [PATCH 2/6] Add embeddd object columns to versions
This will allow us to capture additional information about an when an
embedded object has been created.
---
...0250226161012_add_event_details_to_versions.rb | 15 +++++++++++++++
db/schema.rb | 4 +++-
2 files changed, 18 insertions(+), 1 deletion(-)
create mode 100644 db/migrate/20250226161012_add_event_details_to_versions.rb
diff --git a/db/migrate/20250226161012_add_event_details_to_versions.rb b/db/migrate/20250226161012_add_event_details_to_versions.rb
new file mode 100644
index 00000000000..9c04012c55f
--- /dev/null
+++ b/db/migrate/20250226161012_add_event_details_to_versions.rb
@@ -0,0 +1,15 @@
+class AddEventDetailsToVersions < ActiveRecord::Migration[8.0]
+ def up
+ change_table :content_block_versions, bulk: true do |t|
+ t.string :updated_embedded_object_type
+ t.string :updated_embedded_object_name
+ end
+ end
+
+ def down
+ change_table :content_block_versions, bulk: true do |t|
+ t.remove :updated_embedded_object_type
+ t.remove :updated_embedded_object_name
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 39e6c4780d1..9a0290494f7 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[8.0].define(version: 2025_02_20_131003) do
+ActiveRecord::Schema[8.0].define(version: 2025_02_26_161012) do
create_table "assets", charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t|
t.string "asset_manager_id", null: false
t.string "variant", null: false
@@ -250,6 +250,8 @@
t.datetime "created_at", precision: nil, null: false
t.text "state", size: :medium
t.json "field_diffs"
+ t.string "updated_embedded_object_type"
+ t.string "updated_embedded_object_name"
t.index ["item_id"], name: "index_content_block_versions_on_item_id"
t.index ["item_type"], name: "index_content_block_versions_on_item_type"
end
From 56f61b351bd4f055b339066e9924630f6ddec802 Mon Sep 17 00:00:00 2001
From: pezholio
Date: Thu, 27 Feb 2025 15:12:43 +0000
Subject: [PATCH 3/6] Allow event details to be passed to a version
This adds a virutal field to allow us to pass information about an event
to a version.
---
.../content_block/edition/has_audit_trail.rb | 10 ++++++++-
.../has_audit_trail_test.rb | 21 +++++++++++++++++++
2 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/lib/engines/content_block_manager/app/models/content_block_manager/content_block/edition/has_audit_trail.rb b/lib/engines/content_block_manager/app/models/content_block_manager/content_block/edition/has_audit_trail.rb
index e90b6105ede..05885f4b2a4 100644
--- a/lib/engines/content_block_manager/app/models/content_block_manager/content_block/edition/has_audit_trail.rb
+++ b/lib/engines/content_block_manager/app/models/content_block_manager/content_block/edition/has_audit_trail.rb
@@ -19,6 +19,8 @@ def self.acting_as(actor)
after_update :record_update
end
+ attr_accessor :updated_embedded_object_type, :updated_embedded_object_name
+
private
def record_create
@@ -30,7 +32,13 @@ def record_update
unless draft?
user = Current.user
state = try(:state)
- versions.create!(event: "updated", user:, state:, field_diffs: generate_diff)
+ versions.create!(
+ event: "updated",
+ user:, state:,
+ field_diffs: generate_diff,
+ updated_embedded_object_type:,
+ updated_embedded_object_name:
+ )
end
end
end
diff --git a/lib/engines/content_block_manager/test/unit/app/models/content_block_edition/has_audit_trail_test.rb b/lib/engines/content_block_manager/test/unit/app/models/content_block_edition/has_audit_trail_test.rb
index 45338f578c8..6ee9505ff13 100644
--- a/lib/engines/content_block_manager/test/unit/app/models/content_block_edition/has_audit_trail_test.rb
+++ b/lib/engines/content_block_manager/test/unit/app/models/content_block_edition/has_audit_trail_test.rb
@@ -49,6 +49,27 @@ class ContentBlockManager::HasAuditTrailTest < ActiveSupport::TestCase
assert_equal "scheduled", version.state
end
+ it "adds event details if provided" do
+ Current.user = user
+ edition = create(
+ :content_block_edition,
+ creator: user,
+ document: create(:content_block_document, :email_address),
+ )
+ edition.expects(:generate_diff).returns({})
+ edition.updated_embedded_object_type = "something"
+ edition.updated_embedded_object_name = "here"
+
+ assert_changes -> { edition.versions.count }, from: 1, to: 2 do
+ edition.publish!
+ end
+
+ version = edition.versions.first
+
+ assert_equal edition.updated_embedded_object_type, version.updated_embedded_object_type
+ assert_equal edition.updated_embedded_object_name, version.updated_embedded_object_name
+ end
+
it "does not record a version when updating an existing draft" do
edition = create(
:content_block_edition,
From 2cad96229cc33e0f068c5267a8f6de7ec9c3cad0 Mon Sep 17 00:00:00 2001
From: pezholio
Date: Thu, 27 Feb 2025 15:15:02 +0000
Subject: [PATCH 4/6] Add event details when updating an embedded object
---
.../content_block/editions/embedded_objects_controller.rb | 2 ++
.../features/step_definitions/embedded_object_steps.rb | 4 ++++
2 files changed, 6 insertions(+)
diff --git a/lib/engines/content_block_manager/app/controllers/content_block_manager/content_block/editions/embedded_objects_controller.rb b/lib/engines/content_block_manager/app/controllers/content_block_manager/content_block/editions/embedded_objects_controller.rb
index 96281722f56..e344855b984 100644
--- a/lib/engines/content_block_manager/app/controllers/content_block_manager/content_block/editions/embedded_objects_controller.rb
+++ b/lib/engines/content_block_manager/app/controllers/content_block_manager/content_block/editions/embedded_objects_controller.rb
@@ -59,6 +59,8 @@ def publish
object_name: params[:object_name],
)
else
+ @content_block_edition.updated_embedded_object_type = @subschema.block_type
+ @content_block_edition.updated_embedded_object_name = params[:object_name]
ContentBlockManager::PublishEditionService.new.call(@content_block_edition)
flash[:notice] = "#{@subschema.name.singularize} created"
redirect_path = content_block_manager.content_block_manager_content_block_document_path(@content_block_edition.document)
diff --git a/lib/engines/content_block_manager/features/step_definitions/embedded_object_steps.rb b/lib/engines/content_block_manager/features/step_definitions/embedded_object_steps.rb
index 29814da2b77..963a32f01a2 100644
--- a/lib/engines/content_block_manager/features/step_definitions/embedded_object_steps.rb
+++ b/lib/engines/content_block_manager/features/step_definitions/embedded_object_steps.rb
@@ -43,6 +43,10 @@
@details.keys.each do |k|
assert_equal edition.details[object_type.parameterize.pluralize][key][k], @details[k]
end
+
+ version = edition.versions.order("created_at asc").first
+ assert_equal version.updated_embedded_object_type, object_type.pluralize
+ assert_equal version.updated_embedded_object_name, @object_name
end
Then("I should see errors for the required {string} fields") do |object_type|
From 68c7a6002461376ab0c806c609359508a429ffd5 Mon Sep 17 00:00:00 2001
From: pezholio
Date: Thu, 27 Feb 2025 15:16:31 +0000
Subject: [PATCH 5/6] Add helper to check if embedded object was updated
This checks for the presence of the relevant event details, which we
can then use to generate the history in the next commit
---
.../content_block_manager/content_block/version.rb | 4 ++++
.../unit/app/models/content_block_version_test.rb | 13 +++++++++++++
2 files changed, 17 insertions(+)
diff --git a/lib/engines/content_block_manager/app/models/content_block_manager/content_block/version.rb b/lib/engines/content_block_manager/app/models/content_block_manager/content_block/version.rb
index d5b6a6695cd..551facdfe42 100644
--- a/lib/engines/content_block_manager/app/models/content_block_manager/content_block/version.rb
+++ b/lib/engines/content_block_manager/app/models/content_block_manager/content_block/version.rb
@@ -10,6 +10,10 @@ class Version < ApplicationRecord
def field_diffs
self[:field_diffs] ? ContentBlock::DiffItem.from_hash(self[:field_diffs]) : {}
end
+
+ def is_embedded_update?
+ updated_embedded_object_type && updated_embedded_object_name
+ end
end
end
end
diff --git a/lib/engines/content_block_manager/test/unit/app/models/content_block_version_test.rb b/lib/engines/content_block_manager/test/unit/app/models/content_block_version_test.rb
index 3de7d71f34e..4c425a977bf 100644
--- a/lib/engines/content_block_manager/test/unit/app/models/content_block_version_test.rb
+++ b/lib/engines/content_block_manager/test/unit/app/models/content_block_version_test.rb
@@ -71,4 +71,17 @@ class ContentBlockManager::ContentBlockVersionTest < ActiveSupport::TestCase
assert_equal ({}), content_block_version.field_diffs
end
end
+
+ describe "#is_embedded_update?" do
+ it "returns false by default" do
+ assert_not content_block_version.is_embedded_update?
+ end
+
+ it "returns true when updated_embedded_object_type and updated_embedded_object_name are set" do
+ content_block_version.updated_embedded_object_type = "something"
+ content_block_version.updated_embedded_object_name = "something"
+
+ assert content_block_version.is_embedded_update?
+ end
+ end
end
From c2539253491748df7b39191d3cff8288756630d5 Mon Sep 17 00:00:00 2001
From: pezholio
Date: Thu, 27 Feb 2025 15:19:31 +0000
Subject: [PATCH 6/6] Support embedded items in component
---
.../timeline_item_component.html.erb | 11 +++-
.../timeline_item_component.rb | 17 ++++--
.../timeline_item_component_test.rb | 52 +++++++++++++++++++
3 files changed, 76 insertions(+), 4 deletions(-)
diff --git a/lib/engines/content_block_manager/app/components/content_block_manager/content_block/document/show/document_timeline/timeline_item_component.html.erb b/lib/engines/content_block_manager/app/components/content_block_manager/content_block/document/show/document_timeline/timeline_item_component.html.erb
index e767301a4bb..771c72d2375 100644
--- a/lib/engines/content_block_manager/app/components/content_block_manager/content_block/document/show/document_timeline/timeline_item_component.html.erb
+++ b/lib/engines/content_block_manager/app/components/content_block_manager/content_block/document/show/document_timeline/timeline_item_component.html.erb
@@ -12,7 +12,16 @@
<%= date %>
- <% if details_of_changes.present? %>
+ <% if version.is_embedded_update? %>
+
+ <% new_subschema_item_details.each do |field_name, value| %>
+ -
+ <%= field_name %>:
+ <%= value %>
+
+ <% end %>
+
+ <% elsif details_of_changes.present? %>
<%= render "govuk_publishing_components/components/details", {
title: "Details of changes",
diff --git a/lib/engines/content_block_manager/app/components/content_block_manager/content_block/document/show/document_timeline/timeline_item_component.rb b/lib/engines/content_block_manager/app/components/content_block_manager/content_block/document/show/document_timeline/timeline_item_component.rb
index 0dd0b0af749..230e75b0b3a 100644
--- a/lib/engines/content_block_manager/app/components/content_block_manager/content_block/document/show/document_timeline/timeline_item_component.rb
+++ b/lib/engines/content_block_manager/app/components/content_block_manager/content_block/document/show/document_timeline/timeline_item_component.rb
@@ -13,16 +13,27 @@ def initialize(version:, schema:, is_first_published_version:, is_latest:)
attr_reader :version, :schema, :is_first_published_version, :is_latest
def title
- case version.state
- when "published"
+ if version.is_embedded_update?
+ "#{updated_subschema_id.humanize.singularize} created"
+ elsif version.state == "published"
is_first_published_version ? "#{version.item.block_type.humanize} created" : version.state.capitalize
- when "scheduled"
+ elsif version.state == "scheduled"
"Scheduled for publishing on #{version.item.scheduled_publication.to_fs(:long_ordinal_with_at)}"
else
"#{version.item.block_type.humanize} #{version.state}"
end
end
+ def updated_subschema_id
+ version.updated_embedded_object_type
+ end
+
+ def new_subschema_item_details
+ version.field_diffs.dig("details", updated_subschema_id, version.updated_embedded_object_name).map do |field_name, diff|
+ [field_name.humanize, diff.new_value]
+ end
+ end
+
def date
tag.time(
version.created_at.to_fs(:long_ordinal_with_at),
diff --git a/lib/engines/content_block_manager/test/components/content_block/document/show/document_timeline/timeline_item_component_test.rb b/lib/engines/content_block_manager/test/components/content_block/document/show/document_timeline/timeline_item_component_test.rb
index 223541c076f..b1bc435d8cf 100644
--- a/lib/engines/content_block_manager/test/components/content_block/document/show/document_timeline/timeline_item_component_test.rb
+++ b/lib/engines/content_block_manager/test/components/content_block/document/show/document_timeline/timeline_item_component_test.rb
@@ -230,4 +230,56 @@ class ContentBlockManager::ContentBlock::Document::Show::DocumentTimeline::Timel
render_inline component
end
end
+
+ describe "when the version is an embedded update" do
+ let(:subschema) { stub(:subschema, id: "embedded_schema", name: "Embedded schema") }
+ let(:schema) { stub(:schema, subschemas: [subschema]) }
+
+ let(:field_diffs) do
+ {
+ "details" => {
+ "embedded_schema" => {
+ "something" => {
+ "field1" => ContentBlockManager::ContentBlock::DiffItem.new(previous_value: nil, new_value: "Field 1 value"),
+ "field2" => ContentBlockManager::ContentBlock::DiffItem.new(previous_value: nil, new_value: "Field 2 value"),
+ },
+ },
+ },
+ }
+ end
+
+ let(:version) do
+ build_stubbed(
+ :content_block_version,
+ event: "created",
+ whodunnit: user.id,
+ state: "published",
+ created_at: 4.days.ago,
+ item: content_block_edition,
+ field_diffs:,
+ updated_embedded_object_type: "embedded_schema",
+ updated_embedded_object_name: "something",
+ )
+ end
+
+ before do
+ schema.stubs(:subschema).with("embedded_schema").returns(subschema)
+ end
+
+ it "renders the correct title" do
+ render_inline component
+
+ assert_selector ".timeline__title", text: "Embedded schema created"
+ end
+
+ it "renders the details of the updated object" do
+ render_inline component
+
+ assert_selector ".timeline__embedded-item-list .timeline__embedded-item-list__item:nth-child(1) .timeline__embedded-item-list__key", text: "Field1:"
+ assert_selector ".timeline__embedded-item-list .timeline__embedded-item-list__item:nth-child(1) .timeline__embedded-item-list__value", text: "Field 1 value"
+
+ assert_selector ".timeline__embedded-item-list .timeline__embedded-item-list__item:nth-child(2) .timeline__embedded-item-list__key", text: "Field2:"
+ assert_selector ".timeline__embedded-item-list .timeline__embedded-item-list__item:nth-child(2) .timeline__embedded-item-list__value", text: "Field 2 value"
+ end
+ end
end