From 229260acf39e41077be5b1ec81b387d0f2d5e52a Mon Sep 17 00:00:00 2001 From: Tim Fischbach Date: Wed, 27 Sep 2023 12:08:13 +0200 Subject: [PATCH 1/2] Display section transitions in outline and allow editing REDMINE-20217 --- .../locales/new/duplicate_section.de.yml | 7 +++ .../locales/new/duplicate_section.en.yml | 7 +++ .../PreviewMessageController-spec.js | 21 ++++++++ .../controllers/PreviewMessageController.js | 10 ++++ .../src/editor/views/ChapterItemView.js | 2 +- .../editor/views/ChapterItemView.module.css | 9 ++++ .../src/editor/views/SectionItemView.js | 49 +++++++++++++------ .../editor/views/SectionItemView.module.css | 44 +++++++++++++++-- .../src/editor/views/images/arrows.svg | 1 + .../src/editor/views/outline.module.css | 12 +++++ 10 files changed, 142 insertions(+), 20 deletions(-) create mode 100644 entry_types/scrolled/package/src/editor/views/images/arrows.svg diff --git a/entry_types/scrolled/config/locales/new/duplicate_section.de.yml b/entry_types/scrolled/config/locales/new/duplicate_section.de.yml index a442526228..e6264dc4b0 100644 --- a/entry_types/scrolled/config/locales/new/duplicate_section.de.yml +++ b/entry_types/scrolled/config/locales/new/duplicate_section.de.yml @@ -5,3 +5,10 @@ de: duplicate: Duplizieren insert_section_above: Abschnitt oberhalb einfügen insert_section_below: Abschnitt unterhalb einfügen + transitions: + beforeAfter: Statische Hintergründe + fade: Überblenden (inkl. Inhalt) + fadeBg: Überblenden + reveal: Freilegen + scroll: Aus-/Einscrollen + scrollOver: Überlagern diff --git a/entry_types/scrolled/config/locales/new/duplicate_section.en.yml b/entry_types/scrolled/config/locales/new/duplicate_section.en.yml index 6f43cc45c1..eb50ded430 100644 --- a/entry_types/scrolled/config/locales/new/duplicate_section.en.yml +++ b/entry_types/scrolled/config/locales/new/duplicate_section.en.yml @@ -5,3 +5,10 @@ en: duplicate: Duplicate insert_section_above: Insert section above insert_section_below: Insert section below + transitions: + beforeAfter: Static Backgrounds + fade: Cross fade (incl. content) + fadeBg: Cross fade + reveal: Reveal + scroll: Scroll + scrollOver: Scroll over diff --git a/entry_types/scrolled/package/spec/editor/controllers/PreviewMessageController-spec.js b/entry_types/scrolled/package/spec/editor/controllers/PreviewMessageController-spec.js index ee863ab593..b8016a2079 100644 --- a/entry_types/scrolled/package/spec/editor/controllers/PreviewMessageController-spec.js +++ b/entry_types/scrolled/package/spec/editor/controllers/PreviewMessageController-spec.js @@ -163,6 +163,27 @@ describe('PreviewMessageController', () => { })).resolves.toMatchObject({type: 'SELECT', payload: {id: 1, type: 'sectionSettings'}}); }); + it('sends SELECT message to iframe on selectSectionTransition event on model', async () => { + const entry = factories.entry(ScrolledEntry, {}, { + entryTypeSeed: normalizeSeed({ + sections: [{id: 1}] + }) + }); + const iframeWindow = createIframeWindow(); + controller = new PreviewMessageController({entry, iframeWindow}); + + await postReadyMessageAndWaitForAcknowledgement(iframeWindow); + + return expect(new Promise(resolve => { + iframeWindow.addEventListener('message', event => { + if (event.data.type === 'SELECT') { + resolve(event.data); + } + }); + entry.trigger('selectSectionTransition', entry.sections.first()); + })).resolves.toMatchObject({type: 'SELECT', payload: {id: 1, type: 'sectionTransition'}}); + }); + it('supports sending CONTENT_ELEMENT_EDITOR_COMMAND message to iframe', async () => { const entry = factories.entry(ScrolledEntry, {}, { entryTypeSeed: normalizeSeed({ diff --git a/entry_types/scrolled/package/src/editor/controllers/PreviewMessageController.js b/entry_types/scrolled/package/src/editor/controllers/PreviewMessageController.js index 7ec9db7152..b015d86b9d 100644 --- a/entry_types/scrolled/package/src/editor/controllers/PreviewMessageController.js +++ b/entry_types/scrolled/package/src/editor/controllers/PreviewMessageController.js @@ -69,6 +69,16 @@ export const PreviewMessageController = Object.extend({ }) ); + this.listenTo(this.entry, 'selectSectionTransition', section => + postMessage({ + type: 'SELECT', + payload: { + id: section.id, + type: 'sectionTransition' + } + }) + ); + this.listenTo(this.entry, 'selectContentElement', (contentElement, options) => { postMessage({ type: 'SELECT', diff --git a/entry_types/scrolled/package/src/editor/views/ChapterItemView.js b/entry_types/scrolled/package/src/editor/views/ChapterItemView.js index 71c7ec1718..0be746b189 100644 --- a/entry_types/scrolled/package/src/editor/views/ChapterItemView.js +++ b/entry_types/scrolled/package/src/editor/views/ChapterItemView.js @@ -10,7 +10,7 @@ import styles from './ChapterItemView.module.css'; export const ChapterItemView = Marionette.Layout.extend({ tagName: 'li', - className: styles.root, + className: `${styles.root} ${styles.withTransitions}`, mixins: [modelLifecycleTrackingView({classNames: styles})], diff --git a/entry_types/scrolled/package/src/editor/views/ChapterItemView.module.css b/entry_types/scrolled/package/src/editor/views/ChapterItemView.module.css index 04b79b0023..9ff72dcd3a 100644 --- a/entry_types/scrolled/package/src/editor/views/ChapterItemView.module.css +++ b/entry_types/scrolled/package/src/editor/views/ChapterItemView.module.css @@ -1,6 +1,7 @@ @value indicatorIconColor from './colors.module.css'; .root { + composes: chapter from './outline.module.css'; margin-bottom: 10px; padding: 0 10px 10px 10px; background-color: var(--ui-surface-color); @@ -57,6 +58,14 @@ min-height: 20px; } +.withTransitions .sections { + margin-top: 20px; +} + +.root:first-child .sections { + margin-top: 10px; +} + .creating .creatingIndicator { display: block; } .destroying .destroyingIndicator { display: block; } .failed .failedIndicator { display: block; } diff --git a/entry_types/scrolled/package/src/editor/views/SectionItemView.js b/entry_types/scrolled/package/src/editor/views/SectionItemView.js index aaff20d1a2..80f2ad9a9a 100644 --- a/entry_types/scrolled/package/src/editor/views/SectionItemView.js +++ b/entry_types/scrolled/package/src/editor/views/SectionItemView.js @@ -6,42 +6,55 @@ import {cssModulesUtils} from 'pageflow/ui'; import {SectionThumbnailView} from './SectionThumbnailView' +import arrowsIcon from './images/arrows.svg'; + import styles from './SectionItemView.module.css'; export const SectionItemView = Marionette.ItemView.extend({ tagName: 'li', - className: styles.root, + className: `${styles.root} ${styles.withTransition}`, mixins: [modelLifecycleTrackingView({classNames: styles})], template: (data) => ` -
-
-
-
-
+ +
+
+
+
+
+
+
+ + +
- - - `, - ui: cssModulesUtils.ui(styles, 'thumbnail', 'dropDownButton'), + ui: cssModulesUtils.ui(styles, 'thumbnail', 'dropDownButton', 'editTransition', 'transition'), - events: { - [`click .${styles.clickMask}`]: function() { + events: cssModulesUtils.events(styles, { + 'click clickMask': function() { this.options.entry.trigger('selectSection', this.model); this.options.entry.trigger('scrollToSection', this.model); }, - [`dblclick .${styles.clickMask}`]: function() { + 'dblclick clickMask': function() { this.options.entry.trigger('selectSectionSettings', this.model); this.options.entry.trigger('scrollToSection', this.model); + }, + + 'click editTransition': function() { + this.options.entry.trigger('selectSectionTransition', this.model); + this.options.entry.trigger('scrollToSection', this.model); } - }, + }), initialize() { this.listenTo(this.options.entry, 'change:currentSectionIndex', () => { @@ -62,6 +75,10 @@ export const SectionItemView = Marionette.ItemView.extend({ } this.$el.toggleClass(styles.invert, !!this.model.configuration.get('invert')); + this.ui.transition.text( + I18n.t(this.model.configuration.get('transition'), + {scope: 'pageflow_scrolled.editor.section_item.transitions'}) + ); this.subview(new SectionThumbnailView({ el: this.ui.thumbnail, 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 eccd8e4659..25f3b38ca7 100644 --- a/entry_types/scrolled/package/src/editor/views/SectionItemView.module.css +++ b/entry_types/scrolled/package/src/editor/views/SectionItemView.module.css @@ -5,12 +5,16 @@ position: relative; border: solid selectionWidth transparent; border-radius: rounded(); - padding: 3px; + padding: 1px; margin-left: -6px; margin-right: -6px; text-align: right; } +.withTransition { + composes: sectionWithTransition from './outline.module.css'; +} + .selectable:hover, .active { border: solid selectionWidth selectionColor; @@ -42,7 +46,7 @@ text-shadow: 0 0 2px #fff; } -.root:hover .dragHandle { +.inner:hover .dragHandle { opacity: 1; } @@ -66,11 +70,45 @@ color: var(--ui-primary-color) !important; } -.root:hover .dropDownButton button, +.inner:hover .dropDownButton button, .dropDownButton button:global(.hover) { opacity: 1; } +.creating .dropDownButton, +.destroying .dropDownButton, +.failed .dropDownButton { + display: none; +} + +.editTransition { + composes: transition from './outline.module.css'; + position: absolute; + bottom: 100%; + left: 1px; + width: 100%; + border: 0; + background: transparent; + padding: 5px 5px 5px 2px; + cursor: pointer; + color: var(--ui-on-surface-color-light); + opacity: 0.8; + text-align: left; + display: flex; + gap: 9px; +} + +.editTransition:hover, +.editTransition:focus { + opacity: 1; +} + +.editTransition img { + vertical-align: top; +} + +.transition {} + .creating .creatingIndicator { display: block; } .destroying .destroyingIndicator { display: block; } .failed .failedIndicator { display: block; } diff --git a/entry_types/scrolled/package/src/editor/views/images/arrows.svg b/entry_types/scrolled/package/src/editor/views/images/arrows.svg new file mode 100644 index 0000000000..ef4f24c450 --- /dev/null +++ b/entry_types/scrolled/package/src/editor/views/images/arrows.svg @@ -0,0 +1 @@ + diff --git a/entry_types/scrolled/package/src/editor/views/outline.module.css b/entry_types/scrolled/package/src/editor/views/outline.module.css index 38f08310ca..9d06e3d577 100644 --- a/entry_types/scrolled/package/src/editor/views/outline.module.css +++ b/entry_types/scrolled/package/src/editor/views/outline.module.css @@ -1,5 +1,17 @@ @value indicatorIconColor, errorIconColor from './colors.module.css'; +.sectionWithTransition { + margin-top: 20px; +} + +.chapter:first-child .sectionWithTransition:first-child { + margin-top: 0; +} + +.chapter:first-child .sectionWithTransition:first-child .transition { + display: none; +} + .indicator { display: none; position: absolute; From e7eec4a3a0c18166089c434a8b95962767d39d60 Mon Sep 17 00:00:00 2001 From: Tim Fischbach Date: Wed, 27 Sep 2023 12:08:58 +0200 Subject: [PATCH 2/2] Hide inline edit transition button of next section Only display the "edit transition" button of the currently selected section boundary. Before, there also was a button at the end of the selected section. --- .../src/frontend/inlineEditing/SectionDecorator.module.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/entry_types/scrolled/package/src/frontend/inlineEditing/SectionDecorator.module.css b/entry_types/scrolled/package/src/frontend/inlineEditing/SectionDecorator.module.css index 13806e2eac..bbdf676f02 100644 --- a/entry_types/scrolled/package/src/frontend/inlineEditing/SectionDecorator.module.css +++ b/entry_types/scrolled/package/src/frontend/inlineEditing/SectionDecorator.module.css @@ -43,7 +43,7 @@ display: block; } -.transitionSelected .editToolbar { +.transitionSelected .transitionToolbar-after { visibility: hidden; }