diff --git a/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/entry_json_seed_helper.rb b/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/entry_json_seed_helper.rb
index cb7d45ee7..c5a643ae7 100644
--- a/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/entry_json_seed_helper.rb
+++ b/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/entry_json_seed_helper.rb
@@ -17,6 +17,7 @@ def scrolled_entry_editor_json_seed(json, scrolled_entry)
scrolled_entry,
skip_files: true,
skip_i18n: true,
+ include_hidden_sections: true,
include_unused_additional_seed_data: true)
end
diff --git a/entry_types/scrolled/app/helpers/pageflow_scrolled/entry_json_seed_helper.rb b/entry_types/scrolled/app/helpers/pageflow_scrolled/entry_json_seed_helper.rb
index 46dcfe906..6ebc86d40 100644
--- a/entry_types/scrolled/app/helpers/pageflow_scrolled/entry_json_seed_helper.rb
+++ b/entry_types/scrolled/app/helpers/pageflow_scrolled/entry_json_seed_helper.rb
@@ -24,12 +24,12 @@ def scrolled_entry_json_seed_script_tag(scrolled_entry, options = {})
def scrolled_entry_json_seed(json, scrolled_entry, options = {})
main_storyline = Storyline.all_for_revision(scrolled_entry.revision).first || Storyline.new
- sections = scrolled_entry_json_seed_sections(scrolled_entry, main_storyline)
+ sections = scrolled_entry_json_seed_sections(scrolled_entry, main_storyline, options)
json.partial!('pageflow_scrolled/entry_json_seed/entry',
entry: scrolled_entry,
entry_config: Pageflow.config_for(scrolled_entry),
- chapters: main_storyline.chapters,
+ chapters: scrolled_entry_json_seed_chapters(main_storyline, options),
sections:,
content_elements: main_storyline.content_elements.where(section: sections),
widgets: scrolled_entry.resolve_widgets(insert_point: :react),
@@ -38,12 +38,43 @@ def scrolled_entry_json_seed(json, scrolled_entry, options = {})
private
- def scrolled_entry_json_seed_sections(scrolled_entry, main_storyline)
- if scrolled_entry.cutoff_mode_enabled_for?(request)
- main_storyline.sections_before_cutoff_section
- else
- main_storyline.sections
+ def scrolled_entry_json_seed_sections(scrolled_entry, main_storyline, options)
+ sections =
+ if scrolled_entry.cutoff_mode_enabled_for?(request)
+ main_storyline.sections_before_cutoff_section
+ else
+ main_storyline.sections
+ end
+
+ return sections if options[:include_hidden_sections]
+
+ sections.reject { |section| section.configuration['hidden'] }
+ end
+
+ def scrolled_entry_json_seed_chapters(main_storyline, options)
+ return main_storyline.chapters if options[:include_hidden_sections]
+
+ has_visible_sections, has_hidden_sections =
+ scrolled_entry_json_seed_chapter_section_visibilites(main_storyline)
+
+ main_storyline.chapters.reject do |chapter|
+ has_hidden_sections[chapter.id] && !has_visible_sections[chapter.id]
end
end
+
+ def scrolled_entry_json_seed_chapter_section_visibilites(main_storyline)
+ has_visible_sections = []
+ has_hidden_sections = []
+
+ main_storyline.sections.each do |section|
+ if section.configuration['hidden']
+ has_hidden_sections[section.chapter_id] = true
+ else
+ has_visible_sections[section.chapter_id] = true
+ end
+ end
+
+ [has_visible_sections, has_hidden_sections]
+ end
end
end
diff --git a/entry_types/scrolled/config/locales/new/hide_section.de.yml b/entry_types/scrolled/config/locales/new/hide_section.de.yml
new file mode 100644
index 000000000..0909fb3b1
--- /dev/null
+++ b/entry_types/scrolled/config/locales/new/hide_section.de.yml
@@ -0,0 +1,7 @@
+de:
+ pageflow_scrolled:
+ editor:
+ section_item:
+ hide: Außerhalb des Editors ausblenden
+ show: Außerhalb des Editors einblenden
+ hidden: Nur im Editor sichtbar
diff --git a/entry_types/scrolled/config/locales/new/hide_section.en.yml b/entry_types/scrolled/config/locales/new/hide_section.en.yml
new file mode 100644
index 000000000..78dda93f7
--- /dev/null
+++ b/entry_types/scrolled/config/locales/new/hide_section.en.yml
@@ -0,0 +1,7 @@
+en:
+ pageflow_scrolled:
+ editor:
+ section_item:
+ hide: Hide outside of the editor
+ show: Show outside of the editor
+ hidden: Only visible in editor
diff --git a/entry_types/scrolled/package/spec/editor/views/SectionItemView-spec.js b/entry_types/scrolled/package/spec/editor/views/SectionItemView-spec.js
index 2927d2ad8..e792def82 100644
--- a/entry_types/scrolled/package/spec/editor/views/SectionItemView-spec.js
+++ b/entry_types/scrolled/package/spec/editor/views/SectionItemView-spec.js
@@ -9,6 +9,8 @@ describe('SectionItemView', () => {
useFakeXhr();
useFakeTranslations({
+ 'pageflow_scrolled.editor.section_item.hide': 'Hide',
+ 'pageflow_scrolled.editor.section_item.show': 'Show',
'pageflow_scrolled.editor.section_item.set_cutoff': 'Set cutoff point',
'pageflow_scrolled.editor.section_item.reset_cutoff': 'Remove cutoff point',
'pageflow_scrolled.editor.section_item.cutoff': 'Cutoff point',
@@ -17,6 +19,29 @@ describe('SectionItemView', () => {
const {createEntry} = useEditorGlobals();
const {render} = useReactBasedBackboneViews();
+ it('offer menu item to hide and show section', async () => {
+ const entry = createEntry({
+ sections: [
+ {id: 1, permaId: 100}
+ ]
+ });
+ const section = entry.sections.get(1)
+ const view = new SectionItemView({
+ entry,
+ model: section
+ });
+
+ const user = userEvent.setup();
+ const {getByRole} = render(view);
+ await user.click(getByRole('link', {name: 'Hide'}));
+
+ expect(section.configuration.get('hidden')).toEqual(true);
+
+ await user.click(getByRole('link', {name: 'Show'}));
+
+ expect(section.configuration.get('hidden')).toBeUndefined();
+ });
+
it('does not offer menu item to set cutoff section by default', () => {
const entry = createEntry({
sections: [
diff --git a/entry_types/scrolled/package/src/editor/views/SectionItemView.js b/entry_types/scrolled/package/src/editor/views/SectionItemView.js
index 6546623dc..8211e96a9 100644
--- a/entry_types/scrolled/package/src/editor/views/SectionItemView.js
+++ b/entry_types/scrolled/package/src/editor/views/SectionItemView.js
@@ -7,6 +7,7 @@ import {cssModulesUtils} from 'pageflow/ui';
import {SectionThumbnailView} from './SectionThumbnailView'
import arrowsIcon from './images/arrows.svg';
+import hiddenIcon from './images/hidden.svg';
import styles from './SectionItemView.module.css';
@@ -38,6 +39,11 @@ export const SectionItemView = Marionette.ItemView.extend({
+
`,
@@ -83,11 +89,16 @@ export const SectionItemView = Marionette.ItemView.extend({
this.listenTo(this.options.entry.cutoff, 'change', () => {
this.updateCutoffIndicator();
});
+
+ this.listenTo(this.model.configuration, 'change:hidden', () => {
+ this.updateHidden();
+ });
},
onRender() {
this.updateTransition();
this.updateCutoffIndicator();
+ this.updateHidden();
if (this.updateActive()) {
setTimeout(() => this.$el[0].scrollIntoView({block: 'nearest'}), 10)
@@ -124,6 +135,10 @@ export const SectionItemView = Marionette.ItemView.extend({
this.model.chapter.insertSection({after: this.model})
}));
+ dropDownMenuItems.add(new HideShowMenuItem({}, {
+ section: this.model
+ }));
+
if (this.options.entry.cutoff.isEnabled()) {
dropDownMenuItems.add(new CutoffMenuItem({}, {
cutoff: this.options.entry.cutoff,
@@ -155,16 +170,16 @@ export const SectionItemView = Marionette.ItemView.extend({
);
},
- cutoffModeEnabled() {
- return !!this.options.entry.site.get('cutoff_mode_name');
- },
-
updateActive() {
const active =
this.options.entry.sections.indexOf(this.model) === this.options.entry.get('currentSectionIndex');
this.$el.toggleClass(styles.active, active);
return active;
+ },
+
+ updateHidden() {
+ this.$el.toggleClass(styles.hidden, !!this.model.configuration.get('hidden'));
}
});
@@ -204,3 +219,29 @@ const CutoffMenuItem = Backbone.Model.extend({
));
}
});
+
+const HideShowMenuItem = Backbone.Model.extend({
+ initialize: function(attributes, {section}) {
+ this.section = section;
+
+ this.listenTo(section.configuration, 'change:hidden', this.update);
+ this.update();
+ },
+
+ selected() {
+ if (this.section.configuration.get('hidden')) {
+ this.section.configuration.unset('hidden')
+ }
+ else {
+ this.section.configuration.set('hidden', true)
+ }
+ },
+
+ update() {
+ this.set('label', I18n.t(
+ this.section.configuration.get('hidden') ?
+ 'pageflow_scrolled.editor.section_item.show' :
+ 'pageflow_scrolled.editor.section_item.hide'
+ ));
+ }
+});
diff --git a/entry_types/scrolled/package/src/editor/views/SectionItemView.module.css b/entry_types/scrolled/package/src/editor/views/SectionItemView.module.css
index 3c923d7f1..b7d112ad8 100644
--- a/entry_types/scrolled/package/src/editor/views/SectionItemView.module.css
+++ b/entry_types/scrolled/package/src/editor/views/SectionItemView.module.css
@@ -9,6 +9,18 @@
composes: sectionWithTransition from './outline.module.css';
}
+.hiddenIndicator {
+ display: none;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+}
+
+.hidden .hiddenIndicator {
+ display: block;
+}
+
.outline {
position: relative;
border: solid selectionWidth transparent;
@@ -29,6 +41,8 @@
align-items: center;
gap: 5px;
padding: 5px 0;
+ font-weight: 500;
+ color: var(--ui-error-color);
}
.cutoffIndicator::before,
@@ -40,9 +54,12 @@
.thumbnailContainer {
position: relative;
+ background-color: var(--ui-surface-color);
}
-.thumbnail {}
+.hidden .thumbnail > * > * {
+ opacity: 0.3;
+}
.clickMask {
position: absolute;
diff --git a/entry_types/scrolled/package/src/editor/views/images/hidden.svg b/entry_types/scrolled/package/src/editor/views/images/hidden.svg
new file mode 100644
index 000000000..1997f6380
--- /dev/null
+++ b/entry_types/scrolled/package/src/editor/views/images/hidden.svg
@@ -0,0 +1,3 @@
+
diff --git a/entry_types/scrolled/spec/helpers/pageflow_scrolled/editor/entry_json_seed_helper_spec.rb b/entry_types/scrolled/spec/helpers/pageflow_scrolled/editor/entry_json_seed_helper_spec.rb
index 8a74df52d..be93d915b 100644
--- a/entry_types/scrolled/spec/helpers/pageflow_scrolled/editor/entry_json_seed_helper_spec.rb
+++ b/entry_types/scrolled/spec/helpers/pageflow_scrolled/editor/entry_json_seed_helper_spec.rb
@@ -31,6 +31,23 @@ def render(helper, entry)
})
end
+ it 'renders hidden chapters and sections' do
+ entry = create(:draft_entry, type_name: 'scrolled')
+ chapter = create(:scrolled_chapter, revision: entry.revision)
+ section = create(:section, chapter:, configuration: {hidden: true})
+ content_element = create(:content_element, section:)
+
+ result = render(helper, entry)
+
+ expect(result)
+ .to include_json(collections: {
+ entries: [],
+ chapters: [{id: chapter.id}],
+ sections: [{id: section.id}],
+ contentElements: [{id: content_element.id}],
+ })
+ end
+
it 'does not render files' do
entry = create(:draft_entry, type_name: 'scrolled')
create_used_file(:image_file, entry: entry)
diff --git a/entry_types/scrolled/spec/helpers/pageflow_scrolled/entry_json_seed_helper_spec.rb b/entry_types/scrolled/spec/helpers/pageflow_scrolled/entry_json_seed_helper_spec.rb
index 836decbc0..b3b2e8e0c 100644
--- a/entry_types/scrolled/spec/helpers/pageflow_scrolled/entry_json_seed_helper_spec.rb
+++ b/entry_types/scrolled/spec/helpers/pageflow_scrolled/entry_json_seed_helper_spec.rb
@@ -109,6 +109,39 @@ def render(helper, entry, options = {})
JSON.parse(result).dig('collections', 'chapters').map { |chapter| chapter['id'] }
).to eq([chapter1.id, chapter2.id])
end
+
+ it 'filters out chapters with only hidden sections' do
+ entry = create(:published_entry, type_name: 'scrolled')
+ chapter1 = create(:scrolled_chapter, revision: entry.revision)
+ create(:section, chapter: chapter1)
+ create(:section, chapter: chapter1, configuration: {hidden: true})
+ chapter2 = create(:scrolled_chapter, revision: entry.revision)
+ create(:section, chapter: chapter2, configuration: {hidden: true})
+ create(:section, chapter: chapter2, configuration: {hidden: true})
+ chapter3 = create(:scrolled_chapter, revision: entry.revision)
+
+ result = render(helper, entry)
+
+ expect(
+ JSON.parse(result).dig('collections', 'chapters').map { |chapter| chapter['id'] }
+ ).to eq([chapter1.id, chapter3.id])
+ end
+
+ it 'supports including chapters with only hidden sections' do
+ entry = create(:published_entry, type_name: 'scrolled')
+ chapter1 = create(:scrolled_chapter, revision: entry.revision)
+ create(:section, chapter: chapter1)
+ create(:section, chapter: chapter1, configuration: {hidden: true})
+ chapter2 = create(:scrolled_chapter, revision: entry.revision)
+ create(:section, chapter: chapter2, configuration: {hidden: true})
+ create(:section, chapter: chapter2, configuration: {hidden: true})
+
+ result = render(helper, entry, include_hidden_sections: true)
+
+ expect(
+ JSON.parse(result).dig('collections', 'chapters').map { |chapter| chapter['id'] }
+ ).to eq([chapter1.id, chapter2.id])
+ end
end
context 'sections' do
@@ -305,6 +338,34 @@ def render(helper, entry, options = {})
JSON.parse(result).dig('collections', 'sections').map { |s| s['id'] }
).to eq([section11.id, section12.id, section21.id, section22.id])
end
+
+ it 'filters out hidden sections' do
+ entry = create(:published_entry, type_name: 'scrolled')
+
+ chapter1 = create(:scrolled_chapter, position: 1, revision: entry.revision)
+ section11 = create(:section, chapter: chapter1, position: 1)
+ create(:section, chapter: chapter1, position: 2, configuration: {hidden: true})
+
+ result = render(helper, entry)
+
+ expect(
+ JSON.parse(result).dig('collections', 'sections').map { |s| s['id'] }
+ ).to eq([section11.id])
+ end
+
+ it 'supports including hidden sections' do
+ entry = create(:published_entry, type_name: 'scrolled')
+
+ chapter1 = create(:scrolled_chapter, position: 1, revision: entry.revision)
+ section11 = create(:section, chapter: chapter1, position: 1)
+ section12 = create(:section, chapter: chapter1, position: 2, configuration: {hidden: true})
+
+ result = render(helper, entry, include_hidden_sections: true)
+
+ expect(
+ JSON.parse(result).dig('collections', 'sections').map { |s| s['id'] }
+ ).to eq([section11.id, section12.id])
+ end
end
context 'content_elements' do
@@ -409,6 +470,38 @@ def render(helper, entry, options = {})
JSON.parse(result).dig('collections', 'contentElements').map { |c| c['id'] }
).to eq([content_element11.id, content_element12.id])
end
+
+ it 'supports filtering content elements of hidden sections' do
+ entry = create(:published_entry, type_name: 'scrolled')
+
+ chapter1 = create(:scrolled_chapter, revision: entry.revision)
+ section11 = create(:section, chapter: chapter1, configuration: {hidden: true})
+ create(:content_element, section: section11)
+ section12 = create(:section, chapter: chapter1)
+ content_element12 = create(:content_element, section: section12)
+
+ result = render(helper, entry)
+
+ expect(
+ JSON.parse(result).dig('collections', 'contentElements').map { |c| c['id'] }
+ ).to eq([content_element12.id])
+ end
+
+ it 'supports including content elements of hidden sections' do
+ entry = create(:published_entry, type_name: 'scrolled')
+
+ chapter1 = create(:scrolled_chapter, revision: entry.revision)
+ section11 = create(:section, chapter: chapter1, configuration: {hidden: true})
+ content_element11 = create(:content_element, section: section11)
+ section12 = create(:section, chapter: chapter1)
+ content_element12 = create(:content_element, section: section12)
+
+ result = render(helper, entry, include_hidden_sections: true)
+
+ expect(
+ JSON.parse(result).dig('collections', 'contentElements').map { |c| c['id'] }
+ ).to eq([content_element11.id, content_element12.id])
+ end
end
describe 'widgets' do