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({
// (`importAnnotations` will be falsey if this is not the case).
const importReady = Boolean(
store.focusedGroup() &&
store.mainFrame() &&
store.defaultContentFrame() &&
store.hasFetchedAnnotations() &&
!store.isFetchingAnnotations() &&
importAnnotations,
......
......@@ -23,7 +23,7 @@ describe('ImportAnnotations', () => {
isFeatureEnabled: sinon.stub().returns(true),
hasFetchedAnnotations: sinon.stub().returns(true),
isFetchingAnnotations: sinon.stub().returns(false),
mainFrame: sinon.stub().returns({}),
defaultContentFrame: sinon.stub().returns({}),
profile: sinon.stub().returns({ userid: 'acct:john@example.com' }),
};
......@@ -78,7 +78,7 @@ describe('ImportAnnotations', () => {
});
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.hasFetchedAnnotations.returns(false); // Annotations still loading
fakeStore.isFetchingAnnotations.returns(true);
......@@ -102,7 +102,7 @@ describe('ImportAnnotations', () => {
// to perform the import.
assert.isTrue(importDisabled(wrapper));
fakeStore.mainFrame.returns({}); // Document metadata available
fakeStore.defaultContentFrame.returns({}); // Document metadata available
wrapper.setProps({});
assert.isTrue(importDisabled(wrapper));
......
......@@ -178,7 +178,7 @@ export class ImportAnnotationsService {
}
const existingAnns = this._store.allAnnotations();
const currentFrame = this._store.mainFrame();
const currentFrame = this._store.defaultContentFrame();
const importAnn = async (ann: APIAnnotationData): Promise<ImportResult> => {
const existingAnn = existingAnns.find(ex => duplicateMatch(ann, ex));
......
......@@ -18,7 +18,7 @@ describe('ImportAnnotationsService', () => {
beginImport: sinon.stub(),
completeImport: sinon.stub(),
focusedGroupId: sinon.stub().returns('group-a'),
mainFrame: sinon.stub().returns(null),
defaultContentFrame: sinon.stub().returns(null),
profile: sinon.stub().returns({
userid: 'acct:foo@example.org',
}),
......@@ -139,7 +139,7 @@ describe('ImportAnnotationsService', () => {
it('sets annotation URI and document metadata to match current document', async () => {
const newUri = 'new_document_uri';
const newTitle = 'new_document_title';
fakeStore.mainFrame.returns({
fakeStore.defaultContentFrame.returns({
uri: newUri,
metadata: { title: newTitle },
});
......
......@@ -132,6 +132,9 @@ function frames(state: State) {
return state.frames;
}
const firstFrameWithoutId = (frames: Frame[]) =>
frames.find(f => !f.id) || null;
/**
* Return the "main" frame that the sidebar is connected to.
*
......@@ -147,7 +150,20 @@ const mainFrame = createSelector(
// Sub-frames will all have a "frame identifier" set. The main frame is the
// 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[] {
......@@ -208,6 +224,7 @@ export const framesModule = createStoreModule(initialState, {
getContentInfo,
frames,
mainFrame,
defaultContentFrame,
searchUris,
},
});
......@@ -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', () => {
[
{
......
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