diff --git a/entry_types/scrolled/package/spec/editor/models/Chapter-spec.js b/entry_types/scrolled/package/spec/editor/models/Chapter-spec.js index 954d52aa2a..022e340646 100644 --- a/entry_types/scrolled/package/spec/editor/models/Chapter-spec.js +++ b/entry_types/scrolled/package/spec/editor/models/Chapter-spec.js @@ -31,6 +31,18 @@ describe('Chapter', () => { expect(section.configuration.get('transition')).toEqual('beforeAfter'); }); + + it('handles sparse positions correctly', () => { + const {entry} = testContext; + + const chapter = entry.chapters.first() + const firstSection = chapter.addSection(); + chapter.addSection(); + firstSection.destroy(); + chapter.addSection(); + + expect(chapter.sections.pluck('position')).toEqual([1, 2]); + }); }); describe('#insertSection', () => { diff --git a/entry_types/scrolled/package/spec/editor/models/Section-spec.js b/entry_types/scrolled/package/spec/editor/models/Section-spec.js new file mode 100644 index 0000000000..1598aad9b6 --- /dev/null +++ b/entry_types/scrolled/package/spec/editor/models/Section-spec.js @@ -0,0 +1,49 @@ +import {ScrolledEntry} from 'editor/models/ScrolledEntry'; +import {factories} from 'pageflow/testHelpers'; +import {normalizeSeed} from 'support'; + +describe('Section', () => { + describe('getTransition', () => { + it('returns transition from configuration', () => { + const entry = factories.entry(ScrolledEntry, {}, { + entryTypeSeed: normalizeSeed({ + sections: [ + {id: 10, position: 0}, + {id: 11, position: 1, configuration: {transition: 'reveal'}} + ] + }) + }); + const section = entry.sections.get(11); + + expect(section.getTransition()).toEqual('reveal'); + }); + + it('turns fade into scroll if fade transition is not available', () => { + const entry = factories.entry(ScrolledEntry, {}, { + entryTypeSeed: normalizeSeed({ + sections: [ + {id: 10, position: 0, configuration: {fullHeight: false}}, + {id: 11, position: 1, configuration: {transition: 'fade', fullHeight: true}} + ] + }) + }); + const section = entry.sections.get(11); + + expect(section.getTransition()).toEqual('scroll'); + }); + + it('keeps fade if fade transition is available', () => { + const entry = factories.entry(ScrolledEntry, {}, { + entryTypeSeed: normalizeSeed({ + sections: [ + {id: 10, position: 0, configuration: {fullHeight: true}}, + {id: 11, position: 1, configuration: {transition: 'fade', fullHeight: true}} + ] + }) + }); + const section = entry.sections.get(11); + + expect(section.getTransition()).toEqual('fade'); + }); + }); +}); diff --git a/entry_types/scrolled/package/src/editor/models/Chapter.js b/entry_types/scrolled/package/src/editor/models/Chapter.js index 677890adce..34798b3537 100644 --- a/entry_types/scrolled/package/src/editor/models/Chapter.js +++ b/entry_types/scrolled/package/src/editor/models/Chapter.js @@ -36,7 +36,7 @@ export const Chapter = Backbone.Model.extend({ const section = this.sections.create( new Section( { - position: this.sections.length, + position: this.sections.length ? Math.max(...this.sections.pluck('position')) + 1 : 0, chapterId: this.id, configuration: { transition: this.entry.metadata.configuration.get('defaultTransition') diff --git a/entry_types/scrolled/package/src/editor/models/Section.js b/entry_types/scrolled/package/src/editor/models/Section.js index b81dfe389e..652ee4514d 100644 --- a/entry_types/scrolled/package/src/editor/models/Section.js +++ b/entry_types/scrolled/package/src/editor/models/Section.js @@ -1,4 +1,5 @@ import Backbone from 'backbone'; +import {getAvailableTransitionNames} from 'pageflow-scrolled/frontend'; import { configurationContainer, @@ -35,4 +36,31 @@ export const Section = Backbone.Model.extend({ chapterPosition: function() { return this.chapter && this.chapter.has('position') ? this.chapter.get('position') : -1; }, + + getTransition() { + const entry = this.chapter?.entry; + + if (!entry) { + return 'scroll'; + } + + const sectionIndex = entry.sections.indexOf(this); + const previousSection = entry.sections.at(sectionIndex - 1); + + const availableTransitions = + previousSection ? + getAvailableTransitionNames( + this.configuration.attributes, + previousSection.configuration.attributes + ) : []; + + const transition = this.configuration.get('transition'); + + if (availableTransitions.includes(transition)) { + return transition; + } + else { + return 'scroll'; + } + } }); diff --git a/entry_types/scrolled/package/src/editor/views/SectionItemView.js b/entry_types/scrolled/package/src/editor/views/SectionItemView.js index 097a7717df..61861e865e 100644 --- a/entry_types/scrolled/package/src/editor/views/SectionItemView.js +++ b/entry_types/scrolled/package/src/editor/views/SectionItemView.js @@ -68,18 +68,21 @@ export const SectionItemView = Marionette.ItemView.extend({ }); } }); + + this.listenTo(this.options.entry.sections, 'add', () => { + this.updateActive(); + this.updateTransition(); + }); }, onRender() { + this.updateTransition(); + if (this.updateActive()) { setTimeout(() => this.$el[0].scrollIntoView({block: 'nearest'}), 10) } this.$el.toggleClass(styles.invert, !!this.model.configuration.get('invert')); - this.ui.transition.text( - I18n.t(this.getTransition(), - {scope: 'pageflow_scrolled.editor.section_item.transitions'}) - ); this.subview(new SectionThumbnailView({ el: this.ui.thumbnail, @@ -118,26 +121,11 @@ export const SectionItemView = Marionette.ItemView.extend({ }), {to: this.ui.dropDownButton}); }, - getTransition() { - const entry = this.options.entry; - const sectionIndex = entry.sections.indexOf(this.model); - const previousSection = entry.sections.at(sectionIndex - 1); - - const availableTransitions = - previousSection ? - getAvailableTransitionNames( - this.model.configuration.attributes, - previousSection.configuration.attributes - ) : []; - - const transition = this.model.configuration.get('transition'); - - if (availableTransitions.includes(transition)) { - return transition; - } - else { - return 'scroll'; - } + updateTransition() { + this.ui.transition.text( + I18n.t(this.model.getTransition(), + {scope: 'pageflow_scrolled.editor.section_item.transitions'}) + ); }, updateActive() { diff --git a/package/spec/editor/collections/ForeignKeySubsetCollection-spec.js b/package/spec/editor/collections/ForeignKeySubsetCollection-spec.js index 4992061935..cd56830d2f 100644 --- a/package/spec/editor/collections/ForeignKeySubsetCollection-spec.js +++ b/package/spec/editor/collections/ForeignKeySubsetCollection-spec.js @@ -180,6 +180,24 @@ describe('ForeignKeySubsetCollection', () => { expect(postComments.last().post).toBe(post); }); + it('sets reference before intial sort of parent', () => { + const post = new Backbone.Model({id: 5}); + const comments = new Backbone.Collection([ + ], {comparator: 'position'}); + const postComments = new ForeignKeySubsetCollection({ + parentModel: post, + parent: comments, + foreignKeyAttribute: 'postId', + parentReferenceAttribute: 'post' + }); + let referenceOnInitialSort; + + comments.once('sort', () => referenceOnInitialSort = comments.first().post); + postComments.add({id: 2}) + + expect(referenceOnInitialSort).toBe(post); + }); + it('removes reference to parent model when model is removed from collection', () => { const post = new Backbone.Model({id: 5}); const comments = new Backbone.Collection([ diff --git a/package/src/editor/collections/ForeignKeySubsetCollection.js b/package/src/editor/collections/ForeignKeySubsetCollection.js index 6939be9da6..c32a52597c 100644 --- a/package/src/editor/collections/ForeignKeySubsetCollection.js +++ b/package/src/editor/collections/ForeignKeySubsetCollection.js @@ -27,6 +27,14 @@ export const ForeignKeySubsetCollection = SubsetCollection.extend({ this.autoConsolidatePositions = options.autoConsolidatePositions; + this.listenTo(this, 'add', function(model) { + if (options.parentReferenceAttribute) { + model[options.parentReferenceAttribute] = parentModel; + } + + model.set(options.foreignKeyAttribute, parentModel.id); + }); + SubsetCollection.prototype.constructor.call(this, { parent, parentModel, @@ -41,14 +49,6 @@ export const ForeignKeySubsetCollection = SubsetCollection.extend({ } }); - this.listenTo(this, 'add', function(model) { - if (options.parentReferenceAttribute) { - model[options.parentReferenceAttribute] = parentModel; - } - - model.set(options.foreignKeyAttribute, parentModel.id); - }); - this.listenTo(parentModel, 'destroy dependentDestroy', function() { this.invoke('trigger', 'dependentDestroy'); this.clear();