diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 1db055a319..7df58c0919 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -15,6 +15,7 @@ Changelog * Add `AbstractImage.get_renditions()` for efficient generation of multiple renditions (Andy Babic) * Optimise queries in collection permission policies using cache on the user object (Sage Abdullah) * Phone numbers entered via a link chooser will now have any spaces stripped out, ensuring a valid href="tel:..." attribute (Sahil Jangra) + * Auto-select the `StreamField` block when only one block type is declared (Sébastien Corbin) * Fix: Prevent choosers from failing when initial value is an unrecognised ID, e.g. when moving a page from a location where `parent_page_types` would disallow it (Dan Braghis) * Fix: Move comment notifications toggle to the comments side panel (Sage Abdullah) * Fix: Remove comment button on InlinePanel fields (Sage Abdullah) diff --git a/client/src/components/StreamField/blocks/StreamBlock.js b/client/src/components/StreamField/blocks/StreamBlock.js index 495589d2ed..ff6c5bfff6 100644 --- a/client/src/components/StreamField/blocks/StreamBlock.js +++ b/client/src/components/StreamField/blocks/StreamBlock.js @@ -85,6 +85,18 @@ class StreamBlockMenu extends BaseInsertionControl { $(placeholder).replaceWith(dom); this.element = dom.get(0); this.addButton = dom.find('button'); + + const blockItems = this.blockItems; + if (blockItems.length === 1 && blockItems[0].items.length === 1) { + // Only one child type can be added, bypass the combobox + this.addButton.click(() => { + if (this.onRequestInsert) { + this.onRequestInsert(this.index, blockItems[0].items[0]); + } + }); + return; + } + this.combobox = document.createElement('div'); this.canAddBlock = true; this.disabledBlockTypes = new Set(); @@ -104,8 +116,8 @@ class StreamBlockMenu extends BaseInsertionControl { }); } - renderMenu() { - const items = this.groupedChildBlockDefs.map(([group, blockDefs]) => { + get blockItems() { + return this.groupedChildBlockDefs.map(([group, blockDefs]) => { const groupItems = blockDefs // Allow adding all blockDefs even when disabled, so validation only impedes when saving. // Keeping the previous filtering here for future reference. @@ -122,12 +134,15 @@ class StreamBlockMenu extends BaseInsertionControl { items: groupItems, }; }); + } + renderMenu() { + const blockItems = this.blockItems; ReactDOM.render( item.label} getItemDescription={(item) => item.label} getSearchFields={(item) => [item.label, item.type]} diff --git a/client/src/components/StreamField/blocks/StreamBlock.test.js b/client/src/components/StreamField/blocks/StreamBlock.test.js index 37b3fb0e3f..c45c5c8389 100644 --- a/client/src/components/StreamField/blocks/StreamBlock.test.js +++ b/client/src/components/StreamField/blocks/StreamBlock.test.js @@ -925,3 +925,77 @@ describe('telepath: wagtail.blocks.StreamBlock with blockCounts.max_num set', () assertCanAddBlock(); }); }); + +describe('telepath: wagtail.blocks.StreamBlock with unique block type', () => { + let boundBlock; + + beforeEach(() => { + // Create mocks for callbacks + constructor = jest.fn(); + setState = jest.fn(); + getState = jest.fn(); + getValue = jest.fn(); + focus = jest.fn(); + + // Define a test block + const blockDef = new StreamBlockDefinition( + '', + [ + [ + '', + [ + new FieldBlockDefinition( + 'test_block_a', + new DummyWidgetDefinition('Block A widget'), + { + label: 'Test Block A', + required: true, + icon: 'placeholder', + classname: 'w-field w-field--char_field w-field--text_input', + }, + ), + ], + ], + ], + { + test_block_a: 'Block A options', + }, + { + label: '', + required: true, + icon: 'placeholder', + classname: null, + helpText: 'use plenty of this', + helpIcon: '', + maxNum: null, + minNum: null, + blockCounts: {}, + strings: { + MOVE_UP: 'Move up', + MOVE_DOWN: 'Move down', + DELETE: 'Delete', + DUPLICATE: 'Duplicate', + ADD: 'Add', + }, + }, + ); + + // Render it + document.body.innerHTML = '
'; + boundBlock = blockDef.render($('#placeholder'), 'the-prefix', []); + }); + + test('it renders correctly without combobox', () => { + expect(document.body.innerHTML).toMatchSnapshot(); + expect(document.querySelector('[role="listbox"]')).toBe(null); + expect(boundBlock.children.length).toEqual(0); + }); + + test('it can add block', () => { + boundBlock.inserters[0].addButton.click(); + + expect(document.body.innerHTML).toMatchSnapshot(); + expect(boundBlock.children.length).toEqual(1); + expect(boundBlock.children[0].type).toEqual('test_block_a'); + }); +}); diff --git a/client/src/components/StreamField/blocks/__snapshots__/StreamBlock.test.js.snap b/client/src/components/StreamField/blocks/__snapshots__/StreamBlock.test.js.snap index 0f28c14612..006acd9143 100644 --- a/client/src/components/StreamField/blocks/__snapshots__/StreamBlock.test.js.snap +++ b/client/src/components/StreamField/blocks/__snapshots__/StreamBlock.test.js.snap @@ -923,3 +923,97 @@ exports[`telepath: wagtail.blocks.StreamBlock setError renders error messages 1` `; exports[`telepath: wagtail.blocks.StreamBlock with labels that need escaping it renders correctly 1`] = `"
Test Block <A>
Test Block <B>
"`; + +exports[`telepath: wagtail.blocks.StreamBlock with unique block type it can add block 1`] = ` +"
+
+ use plenty of this +
+
+ +
+ +
+ + + + +
+
+ + + + + + +

+ + Test Block A + * +

+ + + + + +
+
+
+
+
+
+
+ +
+
+
+

Block A widget

+
+
+
+
+
+
+ +
+
" +`; + +exports[`telepath: wagtail.blocks.StreamBlock with unique block type it renders correctly without combobox 1`] = ` +"
+
+ use plenty of this +
+
+ +
+ +
+
" +`; diff --git a/docs/releases/5.1.md b/docs/releases/5.1.md index 162c610ecb..019fc77fab 100644 --- a/docs/releases/5.1.md +++ b/docs/releases/5.1.md @@ -39,6 +39,7 @@ Thank you to Damilola for his work, and to Google for sponsoring this project. * Add [`AbstractImage.get_renditions()`](image_renditions_multiple) for efficient generation of multiple renditions (Andy Babic) * Optimise queries in collection permission policies using cache on the user object (Sage Abdullah) * Phone numbers entered via a link chooser will now have any spaces stripped out, ensuring a valid `href="tel:..."` attribute (Sahil Jangra) + * Auto-select the `StreamField` block when only one block type is declared (Sébastien Corbin) ### Bug fixes