diff --git a/app/helpers/pageflow/widgets_helper.rb b/app/helpers/pageflow/widgets_helper.rb index 30f8c73e83..e4a97114b0 100644 --- a/app/helpers/pageflow/widgets_helper.rb +++ b/app/helpers/pageflow/widgets_helper.rb @@ -33,7 +33,8 @@ def widget_types_json_seeds(config) result[role] << { name: widget_type.name, translationKey: widget_type.translation_key, - insertPoint: widget_type.insert_point + insertPoint: widget_type.insert_point, + enabledInEditor: widget_type.enabled_in_editor? } end }.to_json.html_safe diff --git a/entry_types/scrolled/package/spec/entryState/widgets-spec.js b/entry_types/scrolled/package/spec/entryState/widgets-spec.js index 4b3ca416eb..99c65a67bd 100644 --- a/entry_types/scrolled/package/spec/entryState/widgets-spec.js +++ b/entry_types/scrolled/package/spec/entryState/widgets-spec.js @@ -59,6 +59,30 @@ describe('useWidget', () => { expect(widget).toBeUndefined(); }); + it('filters out react widgets disabled in editor', () => { + const {result} = renderHookInEntry(() => useWidget({role: 'consent'}), { + setup: dispatch => + watchCollections( + factories.entry(ScrolledEntry, {}, { + widgetTypes: factories.widgetTypes([{ + role: 'consent', + name: 'consent_dialog', + insertPoint: 'react', + enabledInEditor: false + }]), + widgetsAttributes: [{ + type_name: 'consent_dialog', + role: 'consent' + }], + entryTypeSeed: normalizeSeed() + }), + {dispatch} + ) + }); + + expect(result.current).toBeUndefined(); + }); + it('reads data from seed', () => { const {result} = renderHookInEntry( () => useWidget({role: 'navigation'}), diff --git a/entry_types/scrolled/package/src/entryState/watchCollections.js b/entry_types/scrolled/package/src/entryState/watchCollections.js index 1b1979e504..328753b939 100644 --- a/entry_types/scrolled/package/src/entryState/watchCollections.js +++ b/entry_types/scrolled/package/src/entryState/watchCollections.js @@ -47,7 +47,10 @@ export function watchCollections(entry, {dispatch}) { dispatch })); - teardownFns.push(watchCollection(widgets.withInsertPoint('react'), { + // Only sync widgets whose frontend packs the server loads in the editor. + // Editor-disabled widgets have no registered widget type here, so rendering + // them in the preview would fail. + teardownFns.push(watchCollection(widgets.withWidgetType({insertPoint: 'react', enabledInEditor: true}), { name: 'widgets', attributes: [{typeName: 'type_name'}, 'role', {permaId: 'role'}], keyAttribute: 'permaId', diff --git a/package/spec/editor/collections/widgetsCollection-spec.js b/package/spec/editor/collections/widgetsCollection-spec.js index 416f316e8e..8a65f96016 100644 --- a/package/spec/editor/collections/widgetsCollection-spec.js +++ b/package/spec/editor/collections/widgetsCollection-spec.js @@ -3,7 +3,7 @@ import {CheckBoxInputView, ConfigurationEditorTabView} from 'pageflow/ui'; import {factories} from '$support'; describe('WidgetsCollection', () => { - it('supports gettting subset collection for insert point', () => { + it('supports getting subset collection by widget type property', () => { const widgetTypes = factories.widgetTypes([ {role: 'navigation', name: 'some_navigation_bar', insertPoint: 'react'}, {role: 'consent', name: 'some_consent_provider', insertPoint: 'bottom_of_entry'} @@ -14,11 +14,28 @@ describe('WidgetsCollection', () => { ], {widgetTypes}); expect( - widgets.withInsertPoint('react').pluck('type_name') + widgets.withWidgetType({insertPoint: 'react'}).pluck('type_name') ).toEqual(['some_navigation_bar']); }); - it('keeps insert point subset collection up to date when type name changes', () => { + it('supports filtering by multiple widget type properties', () => { + const widgetTypes = factories.widgetTypes([ + {role: 'consent', name: 'consent_bar', insertPoint: 'react'}, + {role: 'consent', name: 'consent_dialog', insertPoint: 'react', + enabledInEditor: false} + ]); + const widgets = new WidgetsCollection([ + {type_name: 'consent_bar'}, + {type_name: 'consent_dialog'}, + ], {widgetTypes}); + + expect( + widgets.withWidgetType({insertPoint: 'react', enabledInEditor: true}) + .pluck('type_name') + ).toEqual(['consent_bar']); + }); + + it('keeps subset collection up to date when type name changes', () => { const widgetTypes = factories.widgetTypes([ {role: 'consent', name: 'consent_bar', insertPoint: 'react'}, {role: 'consent', name: 'some_consent_provider', insertPoint: 'bottom_of_entry'} @@ -28,7 +45,7 @@ describe('WidgetsCollection', () => { ], {widgetTypes}); widgets.subject = factories.entry(); - const subsetCollection = widgets.withInsertPoint('react'); + const subsetCollection = widgets.withWidgetType({insertPoint: 'react'}); widgets.first().set('type_name', 'consent_bar'); expect(subsetCollection.pluck('type_name')).toEqual(['consent_bar']); @@ -44,7 +61,7 @@ describe('WidgetsCollection', () => { ], {widgetTypes}); widgets.subject = factories.entry(); - const subsetCollection = widgets.withInsertPoint('react'); + const subsetCollection = widgets.withWidgetType({insertPoint: 'react'}); expect(subsetCollection.pluck('type_name')).toEqual(['consent_bar']); }); diff --git a/package/src/editor/api/WidgetType.js b/package/src/editor/api/WidgetType.js index ed6cc6d439..4410567691 100644 --- a/package/src/editor/api/WidgetType.js +++ b/package/src/editor/api/WidgetType.js @@ -6,6 +6,7 @@ export const WidgetType = Object.extend({ this.name = serverSideConfig.name; this.translationKey = serverSideConfig.translationKey; this.insertPoint = serverSideConfig.insertPoint; + this.enabledInEditor = serverSideConfig.enabledInEditor !== false; this.configurationEditorView = clientSideConfig.configurationEditorView; this.configurationEditorTabViewGroups = clientSideConfig.configurationEditorTabViewGroups || {}; this.isOptional = clientSideConfig.isOptional; diff --git a/package/src/editor/collections/WidgetsCollection.js b/package/src/editor/collections/WidgetsCollection.js index c55db289a4..05ce70d493 100644 --- a/package/src/editor/collections/WidgetsCollection.js +++ b/package/src/editor/collections/WidgetsCollection.js @@ -49,13 +49,16 @@ export const WidgetsCollection = Backbone.Collection.extend({ this.each(widget => widget.defineConfigurationEditorTabViewGroups(groups)); }, - withInsertPoint(insertPoint) { + withWidgetType(properties) { return new SubsetCollection({ parent: this, watchAttribute: 'type_name', - filter: widget => ( - widget.widgetType() && widget.widgetType().insertPoint === insertPoint - ) + filter: widget => { + const widgetType = widget.widgetType(); + + return !!widgetType && + Object.keys(properties).every(name => widgetType[name] === properties[name]); + } }); } }); diff --git a/spec/helpers/pageflow/widgets_helper_spec.rb b/spec/helpers/pageflow/widgets_helper_spec.rb index 71334ba8b2..0a8dc64438 100644 --- a/spec/helpers/pageflow/widgets_helper_spec.rb +++ b/spec/helpers/pageflow/widgets_helper_spec.rb @@ -229,6 +229,20 @@ module Pageflow .to eq('pageflow.fancy_bar.widget_type_name') expect(result['navigation'][0]['insertPoint']).to eq('react') end + + it 'renders enabledInEditor by role' do + widget_type = TestWidgetType.new(name: 'fancy_bar', + roles: ['navigation'], + enabled_in_editor: false) + pageflow_configure do |config| + config.widget_types.clear + config.widget_types.register(widget_type) + end + + result = JSON.parse(helper.widget_types_json_seeds(Pageflow.config)) + + expect(result['navigation'][0]['enabledInEditor']).to eq(false) + end end describe '#widgets_json_seeds' do