You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As we have refactored configurable document types to use the new forms schema,
the documentation is a bit obsolete and I've just made it up to date based on
the latest changes.
Copy file name to clipboardExpand all lines: docs/configurable_document_types.md
+77-51Lines changed: 77 additions & 51 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -15,15 +15,16 @@ Configurable document types are defined as JSON. The JSON files are stored in th
15
15
The JSON for each type has these top level keys:
16
16
17
17
- 'key': The unique identifier for the document type. This is what will be stored in the edition's `configurable_document_type` column.
18
-
- 'schema': The schema for the document type. Each type must have a root schema of the type "object". This root object contains the `properties` for the document type, which map to [content blocks](#content-blocks) in the application.
18
+
- 'forms': The forms configuration for the document type. This describes how the document type's fields are presented on the UI. Each form (e.g., `documents`, `images`) contains a hash of `fields` hash whose keys should match attributes defined in `schema.attributes`. See [Block Rendering](#block-rendering) section for more details on how forms are rendered.
19
+
- 'schema': The schema for the document type. It contains `attributes` to define the data type for each form field and `validations` to specify what validations to run against the attributes. More details about attributes in [content blocks](#content-blocks).
20
+
- 'presenters': The presenters for the document type. This helps to define a liist of presenters that will consume the document type's content. Each presenter contains a set of schema keys (as defined in `schema.attributes`) whose values should map to their presenter's corresponding BlockContent payload builder method - see the [Publishing API Payload](#publishing-api-payload) section for more details.
19
21
- 'associations': The associations for the document type. This is a list of strings that map to a set of association objects in the Rails app. All associations are included as concerns on the corresponding edition model (such as `StandardEdition`), and then required depending on whether they are included in the document type's configuration.
20
22
- 'settings': A set of configurations for the content type, including edition behaviours that we want to turn on, downstream information or admin-side rendering details.
21
23
22
24
These are the settings available for configurable document types.
| edit_screens | Y | A list of rendered screens (tabs) for the content type. Controls which content blocks appear on which editing screens (such as the document and images tabs). |
27
28
| base_path_prefix | Y | The prefix for the base path at which the document will be published e.g. '/government/history for the page /government/history/10-downing-street'. |
28
29
| configurable_document_group | N | Optional grouping for document types. Used for categorisation in the admin interface, including search filters. Typically matches the `publishing_api_schema_name`. For example, both `news_story` and `government_response` types would have the group `news_article`. |
29
30
| publishing_api_schema_name | Y | Name of the schema in the Publishing API for this document type. Different types might share the same schema name. For example, `news_story` and `government_response` types both use the `news_article` schema. |
@@ -39,41 +40,40 @@ These are the settings available for configurable document types.
39
40
40
41
## Content Blocks
41
42
42
-
Each property within a configurable document schema is represented in the application as a content block. The content block is specified via the "type" and "format" options on the property schema. Content blocks are defined in the `app/models/configurable_content_blocks` directory.
43
+
Each attribute in `schema.attributes` holds the data type for its corresponding content block.
44
+
Content blocks are specified via the "block" property in the forms configuration. All available content blocks are defined in the `app/models/configurable_content_blocks` directory.
43
45
44
46
NB: The `title` and `summary` attributes for standard editions are not stored in the block content, but rather as first-class attributes on the edition model itself.
45
47
46
48
Content blocks are instantiated via the [content block factory](../app/models/configurable_content_blocks/factory.rb) at the point of rendering the form or generating the Publishing API payload. The factory uses the `type` and `format` specified in the schema to determine which block class to instantiate. The block's `type` is used for automatic type casting in the [block content model](../app/models/standard_edition/block_content.rb).
47
49
48
50
Each content block implements the following methods:
49
-
50
-
-`publishing_api_payload(content)`: Returns the value to be sent to Publishing API for the property. This can return any type. If returning a hash, ensure you use symbols for the keys.
51
51
-`to_partial_path`: Returns the path to the view that renders the form control for the property.
52
52
53
53
### Block rendering
54
54
55
-
When we render the [form](../app/views/admin/standard_editions/_form.html.erb) for a standard edition, we initialise a "root" block" of type `object`. When this root block's [view](../app/views/admin/configurable_content_blocks/_default_object.html.erb) gets rendered at the view specified in the `DefaultObject`'s block `to_partial_path`, we loop through the block's schema properties and in turn initialise and render blocks matching the specified schemas. The blocks will render in the order they are defined in the schema.
55
+
When we render the [form](../app/views/admin/standard_editions/_form.html.erb) for a standard edition, we initialise a "root" block" of type `object`. When this root block's [view](../app/views/admin/configurable_content_blocks/_default_object.html.erb) gets rendered at the view specified in the `DefaultObject`'s block `to_partial_path`, we loop through the block's schema properties and in turn initialise and render blocks matching the specified schemas. The blocks will render in the order they are defined in the forms property.
56
56
57
-
The default object block is a recursive block type, as it can contain other **object** blocks within its properties. This allows us to build arbitrarily deep trees of content blocks, as defined by the document type's schema. The following is an example of a simple schema with nested object properties:
57
+
The default object block is a recursive block type, as it can contain other **object** blocks within its properties. This allows us to build arbitrarily deep trees of content blocks, as defined by the document type's schema. The following is an example of a forms configuration that would display two form tabs on the standard edition form (i.e "documents" and "images"). The "documents" tab contains a `Govspeak` block, and the "images" tab contains an `ImageSelect` block nested within a `DefaultObject` block.
58
58
59
59
```json
60
60
{
61
-
"root_object": {
62
-
"title": "Root Object",
63
-
"type": "object",
64
-
"properties": {
65
-
"leaf_property_one": {
66
-
"title": "Leaf Property One",
67
-
"type": "string",
68
-
"format": "govspeak"
69
-
},
70
-
"object_property": {
71
-
"properties": {
72
-
"leaf_property_two": {
73
-
"title": "Leaf Property Two",
74
-
"type": "string",
75
-
"format": "image_select"
76
-
}
61
+
"forms": {
62
+
"documents": {
63
+
"fields": {
64
+
"body": {
65
+
"title": "Body",
66
+
"description": "The main content of the page",
67
+
"block": "govspeak"
68
+
}
69
+
}
70
+
},
71
+
"images": {
72
+
"fields": {
73
+
"image": {
74
+
"title": "Image",
75
+
"description": "Select an image to display on the page",
76
+
"block": "image_select"
77
77
}
78
78
}
79
79
}
@@ -82,12 +82,10 @@ The default object block is a recursive block type, as it can contain other **ob
82
82
```
83
83
The rendering process would be as follows:
84
84
- renders the standard edition [form](../app/views/admin/standard_editions/_form.html.erb)
85
-
- renders `root_object` which is a `DefaultObject` block (using the `_default_object.html.erb` partial)
86
-
- loops through the `root_object` properties:
87
-
- renders `leaf_property_one` which is a `Govspeak` block (using the `_govspeak.html.erb` partial)
88
-
- renders `object_property` which is a `DefaultObject` block (using the `_default_object.html.erb` partial)
89
-
- loops through the `object_property` properties:
90
-
- renders `leaf_property_two` which is an `ImageSelect` block (using the `_image_select.html.erb` partial)
85
+
- Loops through each form `documents` and `images`, each of which is a `DefaultObject` block (using the `_default_object.html.erb` partial)
86
+
- loops through the `fields` properties:
87
+
- renders each field e.g `body` which is a `Govspeak` block (using the `_govspeak.html.erb` partial)
88
+
91
89
92
90
Block views use the following [partial-local](https://guides.rubyonrails.org/action_view_overview.html#passing-data-to-partials-with-locals-option) variables:
93
91
- The property `schema` and `content` (default `{}`) are provided for the specific part of the tree being rendered by the content block. The content is for the edition's primary locale.
@@ -100,8 +98,26 @@ Block views use the following [partial-local](https://guides.rubyonrails.org/act
100
98
101
99
### Publishing API Payload
102
100
103
-
In order to compose the `details` hash for Publishing API, The `StandardEditionPresenter`calls the `DefaultObject`'s `publishing_api_payload`. This then loops through all its nested blocks, calling their `publishing_api_payload` methods respectively.
104
-
Relevant payload settings for Publishing API are `base_path_prefix`, `publishing_api_schema_name`, and `publishing_api_document_type`, defined in the document type's [configuration](#document-type-configuration).
101
+
The `StandardEditionPresenter` uses the document type's `presenters` configuration to compose the `details` hash for Publishing API. The `presenters` hash maps each attribute (defined in `schema.attributes`) to its corresponding block content payload builder method.
102
+
103
+
For example, a presenter configuration will look like:
104
+
105
+
```json
106
+
{
107
+
"presenters": {
108
+
"publishing_api": {
109
+
"body": "govspeak",
110
+
"image": "image_select"
111
+
}
112
+
}
113
+
}
114
+
```
115
+
116
+
This instructs the presenter that the `body` attribute should use the `govspeak` payload builder and the `image` attribute should use the `image_select` payload builder.
117
+
118
+
Each block type implements its own publishing API payload method (see [app/presenters/publishing_api/payload_builder/block_content.rb](../app/presenters/publishing_api/payload_builder/block_content.rb)), which is called for the attributes configured in the presenter.
119
+
120
+
This separation allows the same attribute to be presented differently in the UI (via the forms configuration) and in the Publishing API payload, providing flexibility for future changes to either without affecting the other.
105
121
106
122
### Create a new content block type
107
123
@@ -113,12 +129,20 @@ Relevant payload settings for Publishing API are `base_path_prefix`, `publishing
113
129
- The name of the partial should correspond to the block class name.
114
130
115
131
### Using a content block in the schema
116
-
To use a block, include it in the schema with the following properties:
117
-
-`title`: Display label for the content block.
118
-
-`description`: (Optional) Description of the content block's purpose. Usually used for hint text.
119
-
-`type`: Data type for the content block. Should map to an active record type, with the exception of the `object` and `array` type.
120
-
-`format`: Format for the content block, e.g., 'govspeak' for rich text, 'image_select' for image picker. Formats represent specific use cases of some of the types. This must match one of the formats registered in the [blocks factory](../app/models/configurable_content_blocks/factory.rb).
121
-
-`validations`: (Optional) Validations to be applied to the content block. See the [Content Block Validation](#content-block-validation) section for more details.
132
+
To use a content block, you need to define it in both the schema and forms:
133
+
134
+
- Define the UI in `forms.<form_tab>.fields.<field_name>`:
135
+
-`title`: Display label for the field.
136
+
-`description`: (Optional) Help text shown to the user.
137
+
-`block`: Block component to use (e.g., `govspeak`, `image_select`). Must match a format registered in the [blocks factory](../app/models/configurable_content_blocks/factory.rb).
138
+
139
+
- Define the data type in `schema.attributes.<field_name>`:
140
+
-`type`: Data type for the attribute (e.g., `string`, `integer`, `date`). Used for type casting in the [block content model](../app/models/standard_edition/block_content.rb).
141
+
142
+
- Define the Publishing API mapping in `presenters.publishing_api`:
143
+
- Maps the attribute name to its payload builder method (e.g., `"body": "govspeak"`).
144
+
145
+
- Add other presenters as needed, following the same mapping structure above.
0 commit comments