From ade8aa1bf2ff5d30348594174744bfafec4b5f20 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Wed, 30 Dec 2020 20:44:01 +0000 Subject: [PATCH 1/4] Add RFC for EnumBlock --- text/xxx-enumblock.md | 81 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 text/xxx-enumblock.md diff --git a/text/xxx-enumblock.md b/text/xxx-enumblock.md new file mode 100644 index 00000000..103e51f3 --- /dev/null +++ b/text/xxx-enumblock.md @@ -0,0 +1,81 @@ +# RFC X: EnumBlock + +* RFC: +* Authors: Karl Hobley +* Created: 2020-12-30 +* Last Modified: 2020-12-30 + +## Abstract + +This RFC proposes to add a new ``EnumBlock`` block type into Wagtail. +This would be a new structural block type that allows the user to choose the type of a single block from a list of choices. + +## Examples + +### Link chooser + +Perhaps the most common use for this block type would be adding link choosers that support both internal and external links. For example: + +```python +from wagtail import blocks + + +class LinkBlock(blocks.EnumBlock): + internal = blocks.PageChooserBlock() + external = blocks.URLBlock() +``` + +This could also be used at the root of the ``StreamField`` so that a link field could be added to a model: + +```python +from wagtail.fields import StreamField +from wagtail.models import Page + +from .blocks import LinkBlock + + +class MyPage(Page): + link = StreamField(LinkBlock()) +``` + +### Form fields + +Another use case this could be helpful for is when you have a list of blocks that share common attributes but have some additional type-specific attributes. For example, a form field type: + +```python +from wagtail import blocks + + +class TextFieldBlock(blocks.StructBlock): + max_length = blocks.IntegerBlock() + + +class ChoiceFieldBlock(blocks.StructBlock): + choices = blocks.ListBlock(blocks.CharBlock()) + + +class FormFieldBlock(blocks.StructBlock): + name = blocks.CharBlock() + required = blocks.BooleanBlock() + field_type = blocks.EnumBlock([ + ('text', TextFieldBlock()), + ('choices', ChoiceFieldBlock()), + ]) +``` + +## Implementation details + +I've started an implementation on [kaedroho/enum-block](https://github.com/wagtail/wagtail/compare/master...kaedroho:enum-block). It's currently missing tests and UI. + +### JSON representation + +The JSON representation would be similar to ``StreamBlock``, the differences are there will be only one item so there's no need for a list, and the item will not have an ``id``. + +For example, an external link using the block definition in the "Link chooser" example above would look like the following in the database: + +```json +{ + "type": "external", + "value": "https://wagtail.io" +} +``` From 854ef028653fac10a45f43e70625b5ead4b2a1cd Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Wed, 30 Dec 2020 20:45:03 +0000 Subject: [PATCH 2/4] Assign number 66 --- text/{xxx-enumblock.md => 066-enumblock.md} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename text/{xxx-enumblock.md => 066-enumblock.md} (98%) diff --git a/text/xxx-enumblock.md b/text/066-enumblock.md similarity index 98% rename from text/xxx-enumblock.md rename to text/066-enumblock.md index 103e51f3..ae1b93b9 100644 --- a/text/xxx-enumblock.md +++ b/text/066-enumblock.md @@ -1,6 +1,6 @@ -# RFC X: EnumBlock +# RFC 66: EnumBlock -* RFC: +* RFC: 66 * Authors: Karl Hobley * Created: 2020-12-30 * Last Modified: 2020-12-30 From 071542220d4c9a4c6ce5e490eec0fca061a80a82 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Sun, 3 Jan 2021 10:29:32 +0000 Subject: [PATCH 3/4] Add special case JSON representation for when an EnumBlock is in a ListBlock --- text/066-enumblock.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/text/066-enumblock.md b/text/066-enumblock.md index ae1b93b9..a1989e16 100644 --- a/text/066-enumblock.md +++ b/text/066-enumblock.md @@ -79,3 +79,19 @@ For example, an external link using the block definition in the "Link chooser" e "value": "https://wagtail.io" } ``` + +One exception to this is when an ``EnumBlock`` is used in a ``ListBlock``. In this case, the ``EnumBlock``, ``type`` field will be added to the ``ListBlock`` item, alongside its existing ``id`` field. For example: + +```json +[ + { + "id": "", + "type": "paragraph", + "value": "Hello world!" + } +] +``` + +This assumes that [RFC 65](https://github.com/wagtail/rfcs/pull/65) is implemented first. + +This means that ``ListBlock(EnumBlock(X))`` always has the exact same database representation as ``StreamBlock(X)`` which will simplify switching between the two. I think this would also make it easier to implement StreamField migrations later, as this would mean we only have three simple structural types to deal with. From 5595dda9cb01d6589468202de3fe223d7d0e6349 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Sun, 3 Jan 2021 10:34:42 +0000 Subject: [PATCH 4/4] Update 066-enumblock.md --- text/066-enumblock.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/066-enumblock.md b/text/066-enumblock.md index a1989e16..5b0d1be5 100644 --- a/text/066-enumblock.md +++ b/text/066-enumblock.md @@ -94,4 +94,4 @@ One exception to this is when an ``EnumBlock`` is used in a ``ListBlock``. In th This assumes that [RFC 65](https://github.com/wagtail/rfcs/pull/65) is implemented first. -This means that ``ListBlock(EnumBlock(X))`` always has the exact same database representation as ``StreamBlock(X)`` which will simplify switching between the two. I think this would also make it easier to implement StreamField migrations later, as this would mean we only have three simple structural types to deal with. +This means that ``ListBlock(EnumBlock(X))`` always has the exact same database representation as ``StreamBlock(X)`` which will simplify switching between the two. I think this would also make it easier to implement StreamField migrations later, as this would mean we only have three simple structural types to deal with (``StructBlock``, ``ListBlock``, and ``EnumBlock``. ``StreamBlock(X)`` can be interpreted as ``ListBlock(EnumBlock(X))`` for the purpose of data migrations).