Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions app/assets/stylesheets/pageflow/ui/properties.scss
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@
--ui-accent-color-lightest: hsla(44, 100%, 65%, 0.1);
--ui-on-accent-color: #795f0f;

--ui-accent-grey-color: hsl(44, 0%, 75%);
--ui-accent-grey-color-light: hsla(44, 0%, 75%, 0.6);
--ui-accent-grey-color-lighter: hsla(44, 0%, 75%, 0.3);
--ui-accent-grey-color-lightest: hsla(44, 0%, 75%, 0.1);
--ui-on-accent-grey-color: hsl(44, 0%, 27%);

--ui-on-button-color: var(--ui-primary-color);
--ui-button-border-color: var(--ui-primary-color-light);
--ui-button-hover-border-color: var(--ui-primary-color);
Expand Down
2 changes: 2 additions & 0 deletions entry_types/scrolled/config/locales/de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1586,6 +1586,7 @@ de:
comments: Kommentare
comments_view:
new_thread: Neues Thema
section: Abschnitt
tabs:
comments: Alle Kommentare
selection: Für Auswahl
Expand Down Expand Up @@ -1925,6 +1926,7 @@ de:
add_comment: Kommentar hinzufügen
cancel_add_comment: Abbrechen
select_content_element: Zum Kommentieren auswählen
select_section: Abschnitt zum Kommentieren auswählen
select_text_to_comment: Text zum Kommentieren auswählen
new_topic: Neues Thema
add_comment_placeholder: Kommentar hinzufügen...
Expand Down
2 changes: 2 additions & 0 deletions entry_types/scrolled/config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1569,6 +1569,7 @@ en:
comments: Comments
comments_view:
new_thread: New topic
section: Section
tabs:
comments: All comments
selection: For selection
Expand Down Expand Up @@ -1754,6 +1755,7 @@ en:
add_comment: Add comment
cancel_add_comment: Cancel
select_content_element: Select to comment
select_section: Select section to comment
select_text_to_comment: Select text to comment
new_topic: New topic
add_comment_placeholder: Add a comment...
Expand Down
6 changes: 5 additions & 1 deletion entry_types/scrolled/package/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ module.exports = {
"plugin:storybook/recommended"
],
"rules": {
"no-trailing-spaces": "error"
"no-trailing-spaces": "error",
// react-app enables no-unused-expressions, but ESLint 6 predates
// ChainExpression and flags optional-chaining call statements like
// `node?.focus()` as unused. The other packages do not enable the rule.
"no-unused-expressions": "off"
},
"settings": {
"import/resolver": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,15 +193,15 @@ describe('PreviewMessageController', () => {
}
});
entry.trigger('selectNewThread', {
id: 10,
subjectId: 10,
subjectType: 'ContentElement',
range
});
})).resolves.toMatchObject({
type: 'SELECT',
payload: {
type: 'newThread',
id: 10,
subjectId: 10,
subjectType: 'ContentElement',
range
}
Expand Down Expand Up @@ -561,6 +561,22 @@ describe('PreviewMessageController', () => {
})).resolves.toBe('/scrolled/comments?tab=selection');
});

it('navigates to comments route with tab=selection on SELECTED sectionComments', () => {
const editor = factories.editorApi();
const entry = factories.entry(ScrolledEntry, {}, {
entryTypeSeed: normalizeSeed({
sections: [{id: 5, permaId: 50}]
})
});
const iframeWindow = createIframeWindow();
controller = new PreviewMessageController({entry, iframeWindow, editor});

return expect(new Promise(resolve => {
editor.on('navigate', resolve);
window.postMessage({type: 'SELECTED', payload: {id: 5, type: 'sectionComments'}}, '*');
})).resolves.toBe('/scrolled/comments?tab=selection');
});

it('does not navigate on SELECTED contentElementComments while on the comments route', async () => {
Backbone.history.fragment = 'scrolled/comments';

Expand Down Expand Up @@ -646,22 +662,22 @@ describe('PreviewMessageController', () => {
})).resolves.toBeUndefined();
});

it('sets selectedContentElementCommentsId on SELECTED contentElementComments', () => {
it('sets selectedCommentsSubject on SELECTED contentElementComments', () => {
const editor = factories.editorApi();
const entry = factories.entry(ScrolledEntry, {}, {entryTypeSeed: normalizeSeed()});
const iframeWindow = createIframeWindow();
controller = new PreviewMessageController({entry, iframeWindow, editor});

return expect(new Promise(resolve => {
entry.once('change:selectedContentElementCommentsId', (model, value) => resolve(value));
entry.once('change:selectedCommentsSubject', (model, value) => resolve(value));
window.postMessage({
type: 'SELECTED',
payload: {id: 7, type: 'contentElementComments'}
}, '*');
})).resolves.toBe(7);
})).resolves.toEqual({subjectType: 'ContentElement', id: 7});
});

it('sets selectedContentElementCommentsId on SELECTED contentElement', () => {
it('sets selectedCommentsSubject on SELECTED contentElement', () => {
const editor = factories.editorApi();
const entry = factories.entry(ScrolledEntry, {}, {
entryTypeSeed: normalizeSeed({contentElements: [{id: 4}]})
Expand All @@ -670,15 +686,48 @@ describe('PreviewMessageController', () => {
controller = new PreviewMessageController({entry, iframeWindow, editor});

return expect(new Promise(resolve => {
entry.once('change:selectedContentElementCommentsId', (model, value) => resolve(value));
entry.once('change:selectedCommentsSubject', (model, value) => resolve(value));
window.postMessage({
type: 'SELECTED',
payload: {id: 4, type: 'contentElement'}
}, '*');
})).resolves.toBe(4);
})).resolves.toEqual({subjectType: 'ContentElement', id: 4});
});

it('sets selectedCommentsSubject on SELECTED sectionComments', () => {
const editor = factories.editorApi();
const entry = factories.entry(ScrolledEntry, {}, {
entryTypeSeed: normalizeSeed({sections: [{id: 5, permaId: 50}]})
});
const iframeWindow = createIframeWindow();
controller = new PreviewMessageController({entry, iframeWindow, editor});

return expect(new Promise(resolve => {
entry.once('change:selectedCommentsSubject', (model, value) => resolve(value));
window.postMessage({
type: 'SELECTED',
payload: {id: 5, type: 'sectionComments'}
}, '*');
})).resolves.toEqual({subjectType: 'Section', id: 5});
});

['sectionSettings', 'sectionPaddings', 'sectionTransition'].forEach(type => {
it(`sets selectedCommentsSubject to the section on SELECTED ${type}`, () => {
const editor = factories.editorApi();
const entry = factories.entry(ScrolledEntry, {}, {
entryTypeSeed: normalizeSeed({sections: [{id: 5, permaId: 50}]})
});
const iframeWindow = createIframeWindow();
controller = new PreviewMessageController({entry, iframeWindow, editor});

return expect(new Promise(resolve => {
entry.once('change:selectedCommentsSubject', (model, value) => resolve(value));
window.postMessage({type: 'SELECTED', payload: {id: 5, type}}, '*');
})).resolves.toEqual({subjectType: 'Section', id: 5});
});
});

it('sets selectedContentElementCommentsId from permaId on SELECTED newThread', () => {
it('sets selectedCommentsSubject from permaId on SELECTED newThread', () => {
const editor = factories.editorApi();
const entry = factories.entry(ScrolledEntry, {}, {
entryTypeSeed: normalizeSeed({contentElements: [{id: 4, permaId: 100}]})
Expand All @@ -687,32 +736,53 @@ describe('PreviewMessageController', () => {
controller = new PreviewMessageController({entry, iframeWindow, editor});

return expect(new Promise(resolve => {
entry.once('change:selectedContentElementCommentsId', (model, value) => resolve(value));
entry.once('change:selectedCommentsSubject', (model, value) => resolve(value));
window.postMessage({
type: 'SELECTED',
payload: {
id: 100,
type: 'newThread',
subjectType: 'ContentElement',
subjectId: 100,
range: {anchor: {path: [0, 0], offset: 0}, focus: {path: [0, 0], offset: 1}}
}
}, '*');
})).resolves.toBe(4);
})).resolves.toEqual({subjectType: 'ContentElement', id: 4});
});

it('sets selectedCommentsSubject from permaId on SELECTED newThread for a section', () => {
const editor = factories.editorApi();
const entry = factories.entry(ScrolledEntry, {}, {
entryTypeSeed: normalizeSeed({sections: [{id: 5, permaId: 50}]})
});
const iframeWindow = createIframeWindow();
controller = new PreviewMessageController({entry, iframeWindow, editor});

return expect(new Promise(resolve => {
entry.once('change:selectedCommentsSubject', (model, value) => resolve(value));
window.postMessage({
type: 'SELECTED',
payload: {
type: 'newThread',
subjectType: 'Section',
subjectId: 50
}
}, '*');
})).resolves.toEqual({subjectType: 'Section', id: 5});
});

it('clears selectedContentElementCommentsId on SELECTED with non-content-element type', () => {
it('clears selectedCommentsSubject on SELECTED with non-comment type', () => {
const editor = factories.editorApi();
const entry = factories.entry(ScrolledEntry, {}, {entryTypeSeed: normalizeSeed()});
entry.set('selectedContentElementCommentsId', 9);
entry.set('selectedCommentsSubject', {subjectType: 'ContentElement', id: 9});

const iframeWindow = createIframeWindow();
controller = new PreviewMessageController({entry, iframeWindow, editor});

return expect(new Promise(resolve => {
entry.once('change:selectedContentElementCommentsId', (model, value) => resolve(value));
entry.once('change:selectedCommentsSubject', (model, value) => resolve(value));
window.postMessage({
type: 'SELECTED',
payload: {id: 10, type: 'sectionSettings'}
payload: {id: 10, type: 'widget'}
}, '*');
})).resolves.toBeUndefined();
});
Expand All @@ -734,8 +804,8 @@ describe('PreviewMessageController', () => {
type: 'SELECTED',
payload: {
type: 'newThread',
id: 10,
subjectType: 'ContentElement',
subjectId: 10,
range
}
}, '*');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ describe('CommentsView', () => {
const entry = createEntry({
contentElements: [{id: 1, permaId: 10, typeName: 'textBlock'}]
});
entry.set('selectedContentElementCommentsId', 1);
entry.set('selectedCommentsSubject', {subjectType: 'ContentElement', id: 1});
entry.reviewSession = factories.reviewSession({
commentThreads: [{
id: 1,
Expand Down Expand Up @@ -128,30 +128,30 @@ describe('CommentsView', () => {

it('enables the new-thread button when a content element is selected', () => {
const entry = unselectedEntry(createEntry);
entry.set('selectedContentElementCommentsId', 1);
entry.set('selectedCommentsSubject', {subjectType: 'ContentElement', id: 1});

const view = new CommentsView({entry, editor});
const {getByRole} = renderBackboneView(view);

expect(getByRole('button', {name: 'New topic'})).not.toBeDisabled();
});

it("toggles the new-thread button when entry.selectedContentElementCommentsId changes", () => {
it("toggles the new-thread button when entry.selectedCommentsSubject changes", () => {
const entry = unselectedEntry(createEntry);

const view = new CommentsView({entry, editor});
const {getByRole} = renderBackboneView(view);

expect(getByRole('button', {name: 'New topic'})).toBeDisabled();

act(() => { entry.set('selectedContentElementCommentsId', 1); });
act(() => { entry.set('selectedCommentsSubject', {subjectType: 'ContentElement', id: 1}); });

expect(getByRole('button', {name: 'New topic'})).not.toBeDisabled();
});

it('triggers selectNewThread on entry when the new-thread button is clicked', () => {
const entry = unselectedEntry(createEntry);
entry.set('selectedContentElementCommentsId', 1);
entry.set('selectedCommentsSubject', {subjectType: 'ContentElement', id: 1});
const range = {anchor: {path: [0, 0], offset: 0}, focus: {path: [0, 0], offset: 5}};
entry.contentElements.get(1).transientState
.set('newCommentThreadSubjectRange', range);
Expand All @@ -165,12 +165,34 @@ describe('CommentsView', () => {
fireEvent.click(getByRole('button', {name: 'New topic'}));

expect(listener).toHaveBeenCalledWith({
id: 10,
subjectId: 10,
subjectType: 'ContentElement',
range
});
});

it('triggers selectNewThread for a selected section without a range', () => {
const entry = createEntry({
sections: [{id: 5, permaId: 50}],
contentElements: [{id: 1, permaId: 10, typeName: 'textBlock', sectionId: 5}]
});
entry.reviewSession = factories.reviewSession();
entry.set('selectedCommentsSubject', {subjectType: 'Section', id: 5});

const view = new CommentsView({entry, editor});
const {getByRole} = renderBackboneView(view);

const listener = jest.fn();
entry.on('selectNewThread', listener);

fireEvent.click(getByRole('button', {name: 'New topic'}));

expect(listener).toHaveBeenCalledWith({
subjectId: 50,
subjectType: 'Section'
});
});

it('does not trigger selectNewThread when clicking the button while disabled', () => {
const entry = unselectedEntry(createEntry);

Expand Down
Loading
Loading