Commit 2daa913f authored by Alejandro Celaya's avatar Alejandro Celaya Committed by Alejandro Celaya

Add defaultContentFrame store selector to fix importing to VitalSource

parent ab8ec27d
...@@ -143,7 +143,7 @@ function ImportAnnotations({ ...@@ -143,7 +143,7 @@ function ImportAnnotations({
// (`importAnnotations` will be falsey if this is not the case). // (`importAnnotations` will be falsey if this is not the case).
const importReady = Boolean( const importReady = Boolean(
store.focusedGroup() && store.focusedGroup() &&
store.mainFrame() && store.defaultContentFrame() &&
store.hasFetchedAnnotations() && store.hasFetchedAnnotations() &&
!store.isFetchingAnnotations() && !store.isFetchingAnnotations() &&
importAnnotations, importAnnotations,
......
...@@ -23,7 +23,7 @@ describe('ImportAnnotations', () => { ...@@ -23,7 +23,7 @@ describe('ImportAnnotations', () => {
isFeatureEnabled: sinon.stub().returns(true), isFeatureEnabled: sinon.stub().returns(true),
hasFetchedAnnotations: sinon.stub().returns(true), hasFetchedAnnotations: sinon.stub().returns(true),
isFetchingAnnotations: sinon.stub().returns(false), isFetchingAnnotations: sinon.stub().returns(false),
mainFrame: sinon.stub().returns({}), defaultContentFrame: sinon.stub().returns({}),
profile: sinon.stub().returns({ userid: 'acct:john@example.com' }), profile: sinon.stub().returns({ userid: 'acct:john@example.com' }),
}; };
...@@ -78,7 +78,7 @@ describe('ImportAnnotations', () => { ...@@ -78,7 +78,7 @@ describe('ImportAnnotations', () => {
}); });
it('disables import button if group, document or annotations are not loaded', async () => { it('disables import button if group, document or annotations are not loaded', async () => {
fakeStore.mainFrame.returns(null); // Document metadata not available fakeStore.defaultContentFrame.returns(null); // Document metadata not available
fakeStore.focusedGroup.returns(null); // No group set fakeStore.focusedGroup.returns(null); // No group set
fakeStore.hasFetchedAnnotations.returns(false); // Annotations still loading fakeStore.hasFetchedAnnotations.returns(false); // Annotations still loading
fakeStore.isFetchingAnnotations.returns(true); fakeStore.isFetchingAnnotations.returns(true);
...@@ -102,7 +102,7 @@ describe('ImportAnnotations', () => { ...@@ -102,7 +102,7 @@ describe('ImportAnnotations', () => {
// to perform the import. // to perform the import.
assert.isTrue(importDisabled(wrapper)); assert.isTrue(importDisabled(wrapper));
fakeStore.mainFrame.returns({}); // Document metadata available fakeStore.defaultContentFrame.returns({}); // Document metadata available
wrapper.setProps({}); wrapper.setProps({});
assert.isTrue(importDisabled(wrapper)); assert.isTrue(importDisabled(wrapper));
......
...@@ -178,7 +178,7 @@ export class ImportAnnotationsService { ...@@ -178,7 +178,7 @@ export class ImportAnnotationsService {
} }
const existingAnns = this._store.allAnnotations(); const existingAnns = this._store.allAnnotations();
const currentFrame = this._store.mainFrame(); const currentFrame = this._store.defaultContentFrame();
const importAnn = async (ann: APIAnnotationData): Promise<ImportResult> => { const importAnn = async (ann: APIAnnotationData): Promise<ImportResult> => {
const existingAnn = existingAnns.find(ex => duplicateMatch(ann, ex)); const existingAnn = existingAnns.find(ex => duplicateMatch(ann, ex));
......
...@@ -18,7 +18,7 @@ describe('ImportAnnotationsService', () => { ...@@ -18,7 +18,7 @@ describe('ImportAnnotationsService', () => {
beginImport: sinon.stub(), beginImport: sinon.stub(),
completeImport: sinon.stub(), completeImport: sinon.stub(),
focusedGroupId: sinon.stub().returns('group-a'), focusedGroupId: sinon.stub().returns('group-a'),
mainFrame: sinon.stub().returns(null), defaultContentFrame: sinon.stub().returns(null),
profile: sinon.stub().returns({ profile: sinon.stub().returns({
userid: 'acct:foo@example.org', userid: 'acct:foo@example.org',
}), }),
...@@ -139,7 +139,7 @@ describe('ImportAnnotationsService', () => { ...@@ -139,7 +139,7 @@ describe('ImportAnnotationsService', () => {
it('sets annotation URI and document metadata to match current document', async () => { it('sets annotation URI and document metadata to match current document', async () => {
const newUri = 'new_document_uri'; const newUri = 'new_document_uri';
const newTitle = 'new_document_title'; const newTitle = 'new_document_title';
fakeStore.mainFrame.returns({ fakeStore.defaultContentFrame.returns({
uri: newUri, uri: newUri,
metadata: { title: newTitle }, metadata: { title: newTitle },
}); });
......
...@@ -132,6 +132,9 @@ function frames(state: State) { ...@@ -132,6 +132,9 @@ function frames(state: State) {
return state.frames; return state.frames;
} }
const firstFrameWithoutId = (frames: Frame[]) =>
frames.find(f => !f.id) || null;
/** /**
* Return the "main" frame that the sidebar is connected to. * Return the "main" frame that the sidebar is connected to.
* *
...@@ -147,7 +150,20 @@ const mainFrame = createSelector( ...@@ -147,7 +150,20 @@ const mainFrame = createSelector(
// Sub-frames will all have a "frame identifier" set. The main frame is the // Sub-frames will all have a "frame identifier" set. The main frame is the
// one with a `null` id. // one with a `null` id.
frames => frames.find(f => !f.id) || null, firstFrameWithoutId,
);
/**
* Return the default frame that annotations are assumed to be associated with,
* if they can't be matched to a more specific frame.
*
* For most document types this is the same as ({@see mainFrame}), but for
* eg. VitalSource books there is no main frame, but instead only a frame with
* the current chapter content.
*/
const defaultContentFrame = createSelector(
(state: State) => state.frames,
frames => firstFrameWithoutId(frames) ?? frames[0] ?? null,
); );
function searchUrisForFrame(frame: Frame): string[] { function searchUrisForFrame(frame: Frame): string[] {
...@@ -208,6 +224,7 @@ export const framesModule = createStoreModule(initialState, { ...@@ -208,6 +224,7 @@ export const framesModule = createStoreModule(initialState, {
getContentInfo, getContentInfo,
frames, frames,
mainFrame, mainFrame,
defaultContentFrame,
searchUris, searchUris,
}, },
}); });
...@@ -108,6 +108,39 @@ describe('sidebar/store/modules/frames', () => { ...@@ -108,6 +108,39 @@ describe('sidebar/store/modules/frames', () => {
}); });
}); });
describe('#defaultContentFrame', () => {
it('returns `null` if no frames are connected', () => {
assert.isNull(store.defaultContentFrame());
});
[
{
frames: [{ id: null, uri: 'https://example.org' }],
expectedFrame: 0,
},
{
frames: [
{ id: 'iframe1', uri: 'https://foo.com/' },
{ id: 'iframe2', uri: 'https://foo.com/' },
{ id: null, uri: 'https://example.org' },
],
expectedFrame: 2,
},
{
frames: [
{ id: 'iframe1', uri: 'https://foo.com/' },
{ id: 'iframe2', uri: 'https://example.org' },
],
expectedFrame: 0,
},
].forEach(({ frames, expectedFrame }) => {
it('returns the main frame or first connected frame', () => {
frames.forEach(frame => store.connectFrame(frame));
assert.equal(store.defaultContentFrame(), frames[expectedFrame]);
});
});
});
describe('#searchUris', () => { describe('#searchUris', () => {
[ [
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment