-
Notifications
You must be signed in to change notification settings - Fork 198
Spike - simple child pages (shared content ID) [WHIT-3520] #11513
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 9 commits
3c4b972
3e78904
c26db21
f505d63
72dfa7a
bd18a63
284149f
de9919a
02ec9c0
f93db31
06fe704
c57b768
cfcca7a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| module ConfigurableContentBlocks | ||
| class DefaultTextarea < BaseBlock | ||
| private | ||
|
|
||
| def template_name | ||
| "default_textarea" | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,6 +30,30 @@ | |
| } | ||
| } | ||
| }, | ||
| "about": { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It appears I cannot, in fact, imagine 😅 How would you extend this for multiple corporate information pages? Add all the types there as new forms, with their own fields, and part "/corporate-thing-blah"? 💀
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, exactly! Or every corporate information page on one tab (like we have for Travel Advice pages): "corporate_information_pages": {
"dynamic": true,
"label": "Corporate information pages",
"fields": {
"recruitment_summary": {
"title": "Recruitment page summary (leave blank if not needed)",
"block": "govspeak",
"attribute_path": ["block_content", "recruitment_summary"],
"part": "/recruitment",
"part_name": "summary",
"translatable": true
},
"recruitment_body": {
"title": "Recruitment page body (leave blank if not needed)",
"block": "govspeak",
"attribute_path": ["block_content", "recruitment_body"],
"part": "/recruitment",
"part_name": "body",
"translatable": true
},
"accessibility_statement_summary": {
"title": "Accessibility statement summary (leave blank if not needed)",
...etc
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's really busy 😵💫
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Less bad in latest commits (each 'part' would be its own nested default_object, and there are fewer properties needed, e.g. part_name/part). But agree it's still not great.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Though could very well scale to Travel Advice 🤔 |
||
| "dynamic": true, | ||
| "label": "About page", | ||
| "fields": { | ||
| "about": { | ||
| "block": "default_object", | ||
| "attribute_path": ["block_content", "about"], | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does the block_content save as, now, in wh? You seem to call block_content -> namespace -> field in the builder so I suppose the "about" is now stored in the block_content. Sorry don't seem to be able to save an edition when I run the app - still getting pub api errors even with the branch checked out, not sure if that was meant to work now?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, it should work locally 🤔 It stores as: |
||
| "fields": { | ||
| "title": { | ||
| "title": "Title", | ||
| "block": "default_string", | ||
| "attribute_path": ["title"], | ||
| "translatable": true | ||
| }, | ||
| "body": { | ||
| "title": "Body", | ||
| "block": "govspeak", | ||
| "attribute_path": ["body"], | ||
| "translatable": true | ||
| } | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "social_media_accounts": { | ||
| "dynamic": true, | ||
| "label": "Social media accounts", | ||
|
|
@@ -128,6 +152,17 @@ | |
| "body": { | ||
| "type": "string" | ||
| }, | ||
| "about": { | ||
| "type": "object", | ||
| "attributes": { | ||
| "title": { | ||
| "type": "string" | ||
| }, | ||
| "body": { | ||
| "type": "string" | ||
| } | ||
| } | ||
| }, | ||
| "social_media_links": { | ||
| "type": "array", | ||
| "attributes": { | ||
|
|
@@ -174,8 +209,15 @@ | |
| "presenters": { | ||
| "publishing_api": { | ||
| "details": { | ||
| "body": "govspeak", | ||
| "social_media_links": "social_media_links" | ||
| "body": { "field": "body", "type": "compiled_govspeak" }, | ||
| "social_media_links": { "field": "social_media_links", "type": "social_media_links" }, | ||
| "parts": [ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is I appreciate it's handy to fetch the parts for the additional routes as well, but could we try something like this, for the actual implementation? And then you'd have, say, Maybe trying to fix the recursion in the payload builder would make this easy to do.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I went with |
||
| { | ||
| "title": { "field": "about.title", "type": "raw" }, | ||
| "body": { "field": "about.body", "type": "compiled_and_raw_govspeak" }, | ||
| "slug": { "hardcoded_value": "/about" } | ||
| } | ||
| ] | ||
| }, | ||
| "links": [ | ||
| "organisations" | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,7 +16,24 @@ def call | |
| return {} unless mapping | ||
|
|
||
| mapping.each_with_object({}) { |(attribute, builder), details| | ||
| details[attribute.to_sym] = send(builder, attribute) | ||
| details[attribute.to_sym] = if builder.is_a?(Array) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the implementation version:
|
||
| builder.map do |part_builder| | ||
| part_builder.each_with_object({}) do |(part_attribute, part_builder_type), part_details| | ||
| if part_builder_type["hardcoded_value"] | ||
| part_details[part_attribute.to_sym] = part_builder_type["hardcoded_value"] | ||
| elsif part_builder_type["field"].include?(".") | ||
| # TODO: again, support recursion for infinite depths | ||
| namespace = part_builder_type["field"].split(".").first | ||
| field = part_builder_type["field"].split(".").last | ||
| part_details[part_attribute.to_sym] = send(part_builder_type["type"], item.block_content&.public_send(namespace)&.[](field)) | ||
| else | ||
| part_details[part_attribute.to_sym] = send(part_builder_type["type"], item.block_content&.public_send(part_builder_type["field"])) | ||
| end | ||
| end | ||
| end | ||
| else | ||
| send(builder["type"], item.block_content&.public_send(attribute)) | ||
| end | ||
| }.compact | ||
| end | ||
|
|
||
|
|
@@ -25,22 +42,35 @@ def call | |
| attr_reader :item | ||
|
|
||
| def raw(attribute) | ||
| item.block_content&.public_send(attribute) | ||
| attribute | ||
| end | ||
|
|
||
| def govspeak(attribute) | ||
| content = item.block_content&.public_send(attribute) | ||
| def compiled_govspeak(content) | ||
| return nil if content.nil? | ||
|
|
||
| govspeak_to_html(content, images: item.images, attachments: item.attachments) | ||
| end | ||
|
|
||
| def compiled_and_raw_govspeak(content) | ||
| return nil if content.nil? | ||
|
|
||
| [ | ||
| { | ||
| content_type: "text/html", | ||
| content: compiled_govspeak(content), | ||
| }, | ||
| { | ||
| content_type: "text/govspeak", | ||
| content: content, | ||
| }, | ||
| ] | ||
| end | ||
|
|
||
| def rfc3339_date(attribute) | ||
| item.block_content&.public_send(attribute)&.rfc3339 | ||
| attribute&.rfc3339 | ||
| end | ||
|
|
||
| def social_media_links(attribute) | ||
| content = item.block_content&.public_send(attribute) | ||
| def social_media_links(content) | ||
| return [] if content.blank? | ||
|
|
||
| content.map do |item| | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| <%= render "govuk_publishing_components/components/textarea", { | ||
| textarea_id: block.path.form_control_id, | ||
| label: { | ||
| text: block.title + (block.required ? " (required)" : ""), | ||
| heading_size: "m", | ||
| }, | ||
| name: block.path.form_control_name, | ||
| value: block.value, | ||
| hint: block.hint_text, | ||
| right_to_left: block.edition.translation_locale.rtl?, | ||
| error_items: errors_for(block.edition.errors, block.path.validation_error_attribute.to_sym), | ||
| } %> | ||
| <% if block.primary_locale_value.present? %> | ||
| <%= render "govuk_publishing_components/components/details", { | ||
| title: "Primary locale content for #{block.title}", | ||
| } do %> | ||
| <%= block.primary_locale_value %> | ||
| <% end %> | ||
| <% end %> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This parts method is now only called from the payload builder right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indirectly - it's only called by the
additional_routesmethod, which is called by the presenter only in determining what routes to send.The actual content for the parts is now just using our standard payload methods (
rawetc)