diff --git a/__tests__/src/selectors/canvases.test.js b/__tests__/src/selectors/canvases.test.js new file mode 100644 index 0000000000000000000000000000000000000000..ba35f9a865c950e37e6da93ce850ef1957bf45f1 --- /dev/null +++ b/__tests__/src/selectors/canvases.test.js @@ -0,0 +1,102 @@ +import manifestFixture019 from '../../fixtures/version-2/019.json'; +import { + getSelectedCanvas, + getSelectedCanvases, +} from '../../../src/state/selectors/canvases'; + +describe('getSelectedCanvas', () => { + const state = { + windows: { + a: { + id: 'a', + manifestId: 'x', + canvasIndex: 1, + }, + }, + manifests: { + x: { + id: 'x', + json: manifestFixture019, + }, + }, + }; + + const noManifestationState = { + windows: { + a: { + id: 'a', + manifestId: 'x', + canvasIndex: 1, + }, + }, + manifests: { + x: { + id: 'x', + }, + }, + }; + + it('should return canvas based on the canvas index stored window state', () => { + const selectedCanvas = getSelectedCanvas(state, { windowId: 'a' }); + + expect(selectedCanvas.id).toEqual( + 'https://purl.stanford.edu/fr426cg9537/iiif/canvas/fr426cg9537_1', + ); + }); + + it('should return undefined when there is no manifestation to get a canvas from', () => { + const selectedCanvas = getSelectedCanvas(noManifestationState, { windowId: 'a' }); + + expect(selectedCanvas).toBeUndefined(); + }); +}); + +describe('getSelectedCanvases', () => { + const state = { + windows: { + a: { + id: 'a', + manifestId: 'x', + canvasIndex: 1, + view: 'book', + }, + }, + manifests: { + x: { + id: 'x', + json: manifestFixture019, + }, + }, + }; + + const noManifestationState = { + windows: { + a: { + id: 'a', + manifestId: 'x', + canvasIndex: 1, + }, + }, + manifests: { + x: { + id: 'x', + }, + }, + }; + + it('should return canvas groupings based on the canvas index stored window state', () => { + const selectedCanvases = getSelectedCanvases(state, { windowId: 'a' }); + + expect(selectedCanvases.length).toEqual(2); + expect(selectedCanvases.map(canvas => canvas.id)).toEqual([ + 'https://purl.stanford.edu/fr426cg9537/iiif/canvas/fr426cg9537_1', + 'https://purl.stanford.edu/rz176rt6531/iiif/canvas/rz176rt6531_1', + ]); + }); + + it('should return undefined when there is no manifestation to get a canvas from', () => { + const selectedCanvas = getSelectedCanvases(noManifestationState, { windowId: 'a' }); + + expect(selectedCanvas).toBeUndefined(); + }); +}); diff --git a/__tests__/src/selectors/index.test.js b/__tests__/src/selectors/index.test.js index a98295d5a03f5c8c02c6953dd6739a9e26847803..fdd9ae417dffce6bafbda95487853d8e2d2dde61 100644 --- a/__tests__/src/selectors/index.test.js +++ b/__tests__/src/selectors/index.test.js @@ -6,20 +6,12 @@ import manifestFixtureWithAProvider from '../../fixtures/version-3/with_a_provid import { getCanvasLabel, getCompanionWindowForPosition, - getDestructuredMetadata, getAnnotationResourcesByMotivation, getIdAndContentOfResources, getLanguagesFromConfigWithCurrent, getSelectedCanvas, getSelectedCanvases, - getManifest, - getManifestLogo, - getManifestCanvases, - getManifestDescription, getThumbnailNavigationPosition, - getManifestProvider, - getManifestTitle, - getManifestThumbnail, getSelectedAnnotationIds, getSelectedTargetAnnotations, getSelectedTargetsAnnotations, @@ -27,123 +19,11 @@ import { getWindowViewType, getIdAndLabelOfCanvases, getCompanionWindowsOfWindow, - getManifestMetadata, getWindowTitles, } from '../../../src/state/selectors'; import Annotation from '../../../src/lib/Annotation'; import AnnotationResource from '../../../src/lib/AnnotationResource'; - -describe('getManifest()', () => { - const state = { - windows: { - a: { id: 'a', manifestId: 'x' }, - b: { id: 'b', manifestId: 'y' }, - c: { id: 'c' }, - }, - manifests: { - x: { id: 'x' }, - }, - }; - - it('should return the manifest of a certain id', () => { - const received = getManifest(state, { manifestId: 'x' }); - const expected = { id: 'x' }; - expect(received).toEqual(expected); - }); - - - it('should return the manifest of a certain window', () => { - const received = getManifest(state, { windowId: 'a' }); - const expected = { id: 'x' }; - expect(received).toEqual(expected); - }); - - it('should return undefined if window doesnt exist', () => { - const received = getManifest(state, { windowId: 'unknown' }); - expect(received).toBeUndefined(); - }); - - it('should return undefined if window has no manifest id', () => { - const received = getManifest(state, { windowId: 'c' }); - expect(received).toBeUndefined(); - }); - - it('should return undefined if manifest does not exist', () => { - const received = getManifest(state, { windowId: 'b' }); - expect(received).toBeUndefined(); - }); -}); - -describe('getManifestLogo()', () => { - it('should return manifest logo id', () => { - const received = getManifestLogo({ manifests: { x: { json: manifestFixture001 } } }, { manifestId: 'x' }); - expect(received).toEqual(manifestFixture001.logo['@id']); - }); - - it('should return null if manifest has no logo', () => { - const received = getManifestLogo({ manifests: { x: {} } }, { manifestId: 'x' }); - expect(received).toBeUndefined(); - }); -}); - -describe('getManifestThumbnail()', () => { - it('should return manifest thumbnail id', () => { - const state = { manifests: { x: { json: manifestFixture001 } } }; - const received = getManifestThumbnail(state, { manifestId: 'x' }); - expect(received).toEqual(manifestFixture001.thumbnail['@id']); - }); - - it('returns the first canvas thumbnail id', () => { - const manifest = { - '@context': 'http://iiif.io/api/presentation/2/context.json', - '@id': - 'http://iiif.io/api/presentation/2.1/example/fixtures/19/manifest.json', - '@type': 'sc:Manifest', - sequences: [ - { - canvases: [ - { - thumbnail: { id: 'xyz' }, - }, - ], - }, - ], - }; - - const state = { manifests: { x: { json: manifest } } }; - const received = getManifestThumbnail(state, { manifestId: 'x' }); - expect(received).toEqual('xyz'); - }); - - it('returns a thumbnail sized image url from the first canvas', () => { - const state = { manifests: { x: { json: manifestFixture019 } } }; - const received = getManifestThumbnail(state, { manifestId: 'x' }); - expect(received).toEqual('https://stacks.stanford.edu/image/iiif/hg676jb4964%2F0380_796-44/full/,80/0/default.jpg'); - }); - - it('should return null if manifest has no thumbnail', () => { - const state = { manifests: { x: {} } }; - const received = getManifestThumbnail(state, { manifestId: 'x' }); - expect(received).toBeNull(); - }); -}); - -describe('getManifestCanvases', () => { - it('returns an empty array if the manifestation is not loaded', () => { - const state = { manifests: { x: {} } }; - const received = getManifestCanvases(state, { manifestId: 'x' }); - expect(received).toEqual([]); - }); - - it('returns canvases from the manifest', () => { - const state = { manifests: { x: { json: manifestFixture001 } } }; - const received = getManifestCanvases(state, { manifestId: 'x' }); - expect(received.length).toBe(1); - expect(received[0].id).toBe('https://iiif.bodleian.ox.ac.uk/iiif/canvas/9cca8fdd-4a61-4429-8ac1-f648764b4d6d.json'); - }); -}); - describe('getThumbnailNavigationPosition', () => { const state = { windows: { @@ -171,42 +51,6 @@ describe('getThumbnailNavigationPosition', () => { }); }); -describe('getManifestTitle', () => { - it('should return manifest title', () => { - const state = { manifests: { x: { json: manifestFixture001 } } }; - const received = getManifestTitle(state, { manifestId: 'x' }); - expect(received).toBe('Bodleian Library Human Freaks 2 (33)'); - }); - - it('should return undefined if manifest undefined', () => { - const received = getManifestTitle({ manifests: {} }, { manifestId: 'x' }); - expect(received).toBeUndefined(); - }); -}); - -describe('getWindowTitles', () => { - it('should return manifest titles for the open windows', () => { - const state = { - windows: { - a: { manifestId: 'amanifest' }, - b: { manifestId: 'bmanifest' }, - }, - manifests: { - amanifest: { json: manifestFixture001 }, - bmanifest: { json: manifestFixture002 }, - cmanifest: { json: manifestFixture019 }, - }, - }; - - const received = getWindowTitles(state); - - expect(received).toEqual({ - a: 'Bodleian Library Human Freaks 2 (33)', - b: 'Test 2 Manifest: Metadata Pairs', - }); - }); -}); - describe('getWindowViewType', () => { const state = { windows: { @@ -231,128 +75,6 @@ describe('getWindowViewType', () => { }); }); -describe('getManifestDescription', () => { - it('should return manifest description', () => { - const state = { manifests: { x: { json: manifestFixture001 } } }; - const received = getManifestDescription(state, { manifestId: 'x' }); - expect(received).toBe('[Handbill of Mr. Becket, [1787] ]'); - }); - - it('should return undefined if manifest undefined', () => { - const received = getManifestDescription({ manifests: {} }, { manifestId: 'x' }); - expect(received).toBeUndefined(); - }); -}); - -describe('getManifestProvider', () => { - it('should return manifest provider label', () => { - const state = { manifests: { x: { json: manifestFixtureWithAProvider } } }; - const received = getManifestProvider(state, { manifestId: 'x' }); - expect(received).toBe('Example Organization'); - }); - - it('should return undefined if manifest undefined', () => { - const received = getManifestProvider({ manifests: {} }, { manifestId: 'x' }); - expect(received).toBeUndefined(); - }); -}); -describe('getSelectedCanvas', () => { - const state = { - windows: { - a: { - id: 'a', - manifestId: 'x', - canvasIndex: 1, - }, - }, - manifests: { - x: { - id: 'x', - json: manifestFixture019, - }, - }, - }; - - const noManifestationState = { - windows: { - a: { - id: 'a', - manifestId: 'x', - canvasIndex: 1, - }, - }, - manifests: { - x: { - id: 'x', - }, - }, - }; - - it('should return canvas based on the canvas index stored window state', () => { - const selectedCanvas = getSelectedCanvas(state, { windowId: 'a' }); - - expect(selectedCanvas.id).toEqual( - 'https://purl.stanford.edu/fr426cg9537/iiif/canvas/fr426cg9537_1', - ); - }); - - it('should return undefined when there is no manifestation to get a canvas from', () => { - const selectedCanvas = getSelectedCanvas(noManifestationState, { windowId: 'a' }); - - expect(selectedCanvas).toBeUndefined(); - }); -}); - -describe('getSelectedCanvases', () => { - const state = { - windows: { - a: { - id: 'a', - manifestId: 'x', - canvasIndex: 1, - view: 'book', - }, - }, - manifests: { - x: { - id: 'x', - json: manifestFixture019, - }, - }, - }; - - const noManifestationState = { - windows: { - a: { - id: 'a', - manifestId: 'x', - canvasIndex: 1, - }, - }, - manifests: { - x: { - id: 'x', - }, - }, - }; - - it('should return canvas groupings based on the canvas index stored window state', () => { - const selectedCanvases = getSelectedCanvases(state, { windowId: 'a' }); - - expect(selectedCanvases.length).toEqual(2); - expect(selectedCanvases.map(canvas => canvas.id)).toEqual([ - 'https://purl.stanford.edu/fr426cg9537/iiif/canvas/fr426cg9537_1', - 'https://purl.stanford.edu/rz176rt6531/iiif/canvas/rz176rt6531_1', - ]); - }); - - it('should return undefined when there is no manifestation to get a canvas from', () => { - const selectedCanvas = getSelectedCanvases(noManifestationState, { windowId: 'a' }); - - expect(selectedCanvas).toBeUndefined(); - }); -}); - describe('getCanvasLabel', () => { it('should return label of the canvas', () => { const canvas = manifesto @@ -375,45 +97,6 @@ describe('getCanvasLabel', () => { }); }); -describe('getDestructuredMetadata', () => { - it('should return the first value of label/value attributes for each object in the array ', () => { - const iiifResource = manifesto.create(manifestFixture002); - const received = getDestructuredMetadata(iiifResource); - const expected = [{ - label: 'date', - value: 'some date', - }]; - - expect(received).toEqual(expected); - }); - - it('returns an empty array if there is no metadata', () => { - const iiifResource = manifesto.create(manifestFixture019); - const received = getDestructuredMetadata(iiifResource); - - expect(received).toEqual([]); - }); -}); - -describe('getManifestMetadata', () => { - it('should return the first value of label/value attributes for each object in the array ', () => { - const state = { manifests: { x: { json: manifestFixture002 } } }; - const received = getManifestMetadata(state, { manifestId: 'x' }); - const expected = [{ - label: 'date', - value: 'some date', - }]; - - expect(received).toEqual(expected); - }); - - it('returns an empty array if there is no metadata', () => { - const iiifResource = manifesto.create(manifestFixture019); - const received = getDestructuredMetadata(iiifResource); - - expect(received).toEqual([]); - }); -}); describe('getSelectedTargetAnnotations', () => { it('returns annotations for the given canvasId that have resources', () => { diff --git a/__tests__/src/selectors/manifests.test.js b/__tests__/src/selectors/manifests.test.js new file mode 100644 index 0000000000000000000000000000000000000000..cdebc905d6eb9116fb97dc18978febb78e2075d1 --- /dev/null +++ b/__tests__/src/selectors/manifests.test.js @@ -0,0 +1,205 @@ +import manifesto from 'manifesto.js'; +import manifestFixture001 from '../../fixtures/version-2/001.json'; +import manifestFixture002 from '../../fixtures/version-2/002.json'; +import manifestFixture019 from '../../fixtures/version-2/019.json'; +import manifestFixtureWithAProvider from '../../fixtures/version-3/with_a_provider.json'; +import { + getDestructuredMetadata, + getManifest, + getManifestLogo, + getManifestCanvases, + getManifestDescription, + getManifestProvider, + getManifestTitle, + getManifestThumbnail, + getManifestMetadata, +} from '../../../src/state/selectors/manifests'; + + +describe('getManifest()', () => { + const state = { + windows: { + a: { id: 'a', manifestId: 'x' }, + b: { id: 'b', manifestId: 'y' }, + c: { id: 'c' }, + }, + manifests: { + x: { id: 'x' }, + }, + }; + + it('should return the manifest of a certain id', () => { + const received = getManifest(state, { manifestId: 'x' }); + const expected = { id: 'x' }; + expect(received).toEqual(expected); + }); + + + it('should return the manifest of a certain window', () => { + const received = getManifest(state, { windowId: 'a' }); + const expected = { id: 'x' }; + expect(received).toEqual(expected); + }); + + it('should return undefined if window doesnt exist', () => { + const received = getManifest(state, { windowId: 'unknown' }); + expect(received).toBeUndefined(); + }); + + it('should return undefined if window has no manifest id', () => { + const received = getManifest(state, { windowId: 'c' }); + expect(received).toBeUndefined(); + }); + + it('should return undefined if manifest does not exist', () => { + const received = getManifest(state, { windowId: 'b' }); + expect(received).toBeUndefined(); + }); +}); + +describe('getManifestLogo()', () => { + it('should return manifest logo id', () => { + const received = getManifestLogo({ manifests: { x: { json: manifestFixture001 } } }, { manifestId: 'x' }); + expect(received).toEqual(manifestFixture001.logo['@id']); + }); + + it('should return null if manifest has no logo', () => { + const received = getManifestLogo({ manifests: { x: {} } }, { manifestId: 'x' }); + expect(received).toBeUndefined(); + }); +}); + +describe('getManifestThumbnail()', () => { + it('should return manifest thumbnail id', () => { + const state = { manifests: { x: { json: manifestFixture001 } } }; + const received = getManifestThumbnail(state, { manifestId: 'x' }); + expect(received).toEqual(manifestFixture001.thumbnail['@id']); + }); + + it('returns the first canvas thumbnail id', () => { + const manifest = { + '@context': 'http://iiif.io/api/presentation/2/context.json', + '@id': + 'http://iiif.io/api/presentation/2.1/example/fixtures/19/manifest.json', + '@type': 'sc:Manifest', + sequences: [ + { + canvases: [ + { + thumbnail: { id: 'xyz' }, + }, + ], + }, + ], + }; + + const state = { manifests: { x: { json: manifest } } }; + const received = getManifestThumbnail(state, { manifestId: 'x' }); + expect(received).toEqual('xyz'); + }); + + it('returns a thumbnail sized image url from the first canvas', () => { + const state = { manifests: { x: { json: manifestFixture019 } } }; + const received = getManifestThumbnail(state, { manifestId: 'x' }); + expect(received).toEqual('https://stacks.stanford.edu/image/iiif/hg676jb4964%2F0380_796-44/full/,80/0/default.jpg'); + }); + + it('should return null if manifest has no thumbnail', () => { + const state = { manifests: { x: {} } }; + const received = getManifestThumbnail(state, { manifestId: 'x' }); + expect(received).toBeNull(); + }); +}); + +describe('getManifestCanvases', () => { + it('returns an empty array if the manifestation is not loaded', () => { + const state = { manifests: { x: {} } }; + const received = getManifestCanvases(state, { manifestId: 'x' }); + expect(received).toEqual([]); + }); + + it('returns canvases from the manifest', () => { + const state = { manifests: { x: { json: manifestFixture001 } } }; + const received = getManifestCanvases(state, { manifestId: 'x' }); + expect(received.length).toBe(1); + expect(received[0].id).toBe('https://iiif.bodleian.ox.ac.uk/iiif/canvas/9cca8fdd-4a61-4429-8ac1-f648764b4d6d.json'); + }); +}); + +describe('getManifestTitle', () => { + it('should return manifest title', () => { + const state = { manifests: { x: { json: manifestFixture001 } } }; + const received = getManifestTitle(state, { manifestId: 'x' }); + expect(received).toBe('Bodleian Library Human Freaks 2 (33)'); + }); + + it('should return undefined if manifest undefined', () => { + const received = getManifestTitle({ manifests: {} }, { manifestId: 'x' }); + expect(received).toBeUndefined(); + }); +}); + +describe('getManifestDescription', () => { + it('should return manifest description', () => { + const state = { manifests: { x: { json: manifestFixture001 } } }; + const received = getManifestDescription(state, { manifestId: 'x' }); + expect(received).toBe('[Handbill of Mr. Becket, [1787] ]'); + }); + + it('should return undefined if manifest undefined', () => { + const received = getManifestDescription({ manifests: {} }, { manifestId: 'x' }); + expect(received).toBeUndefined(); + }); +}); + +describe('getManifestProvider', () => { + it('should return manifest provider label', () => { + const state = { manifests: { x: { json: manifestFixtureWithAProvider } } }; + const received = getManifestProvider(state, { manifestId: 'x' }); + expect(received).toBe('Example Organization'); + }); + + it('should return undefined if manifest undefined', () => { + const received = getManifestProvider({ manifests: {} }, { manifestId: 'x' }); + expect(received).toBeUndefined(); + }); +}); +describe('getDestructuredMetadata', () => { + it('should return the first value of label/value attributes for each object in the array ', () => { + const iiifResource = manifesto.create(manifestFixture002); + const received = getDestructuredMetadata(iiifResource); + const expected = [{ + label: 'date', + value: 'some date', + }]; + + expect(received).toEqual(expected); + }); + + it('returns an empty array if there is no metadata', () => { + const iiifResource = manifesto.create(manifestFixture019); + const received = getDestructuredMetadata(iiifResource); + + expect(received).toEqual([]); + }); +}); + +describe('getManifestMetadata', () => { + it('should return the first value of label/value attributes for each object in the array ', () => { + const state = { manifests: { x: { json: manifestFixture002 } } }; + const received = getManifestMetadata(state, { manifestId: 'x' }); + const expected = [{ + label: 'date', + value: 'some date', + }]; + + expect(received).toEqual(expected); + }); + + it('returns an empty array if there is no metadata', () => { + const iiifResource = manifesto.create(manifestFixture019); + const received = getDestructuredMetadata(iiifResource); + + expect(received).toEqual([]); + }); +}); diff --git a/__tests__/src/selectors/windows.test.js b/__tests__/src/selectors/windows.test.js new file mode 100644 index 0000000000000000000000000000000000000000..996599b87edb5ddffc1cf10f2c96cbb12c6144aa --- /dev/null +++ b/__tests__/src/selectors/windows.test.js @@ -0,0 +1,30 @@ +import manifestFixture001 from '../../fixtures/version-2/001.json'; +import manifestFixture002 from '../../fixtures/version-2/002.json'; +import manifestFixture019 from '../../fixtures/version-2/019.json'; +import { + getWindowTitles, +} from '../../../src/state/selectors/windows'; + + +describe('getWindowTitles', () => { + it('should return manifest titles for the open windows', () => { + const state = { + windows: { + a: { manifestId: 'amanifest' }, + b: { manifestId: 'bmanifest' }, + }, + manifests: { + amanifest: { json: manifestFixture001 }, + bmanifest: { json: manifestFixture002 }, + cmanifest: { json: manifestFixture019 }, + }, + }; + + const received = getWindowTitles(state); + + expect(received).toEqual({ + a: 'Bodleian Library Human Freaks 2 (33)', + b: 'Test 2 Manifest: Metadata Pairs', + }); + }); +}); diff --git a/src/state/selectors/canvases.js b/src/state/selectors/canvases.js new file mode 100644 index 0000000000000000000000000000000000000000..26d74e5dac2ca23be28bc48141b0a56c37e0f73e --- /dev/null +++ b/src/state/selectors/canvases.js @@ -0,0 +1,43 @@ +import { createSelector } from 'reselect'; +import CanvasGroupings from '../../lib/CanvasGroupings'; +import { getManifestoInstance } from './manifests'; + +/** +* Return the current canvas selected in a window +* @param {object} state +* @param {object} props +* @param {string} props.manifestId +* @param {string} props.windowId +* @return {Object} +*/ +export const getSelectedCanvas = createSelector( + [ + getManifestoInstance, + (state, { windowId }) => state.windows[windowId].canvasIndex, + ], + (manifest, canvasIndex) => manifest + && manifest + .getSequences()[0] + .getCanvasByIndex(canvasIndex), +); + +/** +* Return the current canvases selected in a window +* For book view returns 2, for single returns 1 +* @param {object} state +* @param {object} props +* @param {string} props.manifestId +* @param {string} props.windowId +* @return {Array} +*/ +export const getSelectedCanvases = createSelector( + [ + getManifestoInstance, + (state, { windowId }) => state.windows[windowId], + ], + (manifest, { canvasIndex, view }) => manifest + && new CanvasGroupings( + manifest.getSequences()[0].getCanvases(), + view, + ).getCanvases(canvasIndex), +); diff --git a/src/state/selectors/index.js b/src/state/selectors/index.js index 4665330727c3ecbbe2f053a9ff915763b3efa9ed..c51fdf2df3a9c7a298bffb59357da71d29a90c83 100644 --- a/src/state/selectors/index.js +++ b/src/state/selectors/index.js @@ -1,117 +1,10 @@ -import { createSelector } from 'reselect'; import filter from 'lodash/filter'; import flatten from 'lodash/flatten'; -import manifesto, { LanguageMap } from 'manifesto.js'; import Annotation from '../../lib/Annotation'; -import ManifestoCanvas from '../../lib/ManifestoCanvas'; -import CanvasGroupings from '../../lib/CanvasGroupings'; -/** Get the relevant manifest information */ -export function getManifest(state, { manifestId, windowId }) { - return state.manifests[ - manifestId - || (windowId && state.windows[windowId] && state.windows[windowId].manifestId) - ]; -} - -/** Instantiate a manifesto instance */ -export const getManifestoInstance = createSelector( - [getManifest], - manifest => manifest && manifest.json && manifesto.create(manifest.json), -); - -/** - * Get the logo for a manifest - * @param {object} state - * @param {object} props - * @param {string} props.manifestId - * @param {string} props.windowId - * @return {String|null} - */ -export const getManifestLogo = createSelector( - [getManifestoInstance], - manifest => manifest && manifest.getLogo(), -); - -/** -* Return the IIIF v3 provider of a manifest or null -* @param {object} state -* @param {object} props -* @param {string} props.manifestId -* @param {string} props.windowId -* @return {String|null} -*/ -export const getManifestProvider = createSelector( - [getManifestoInstance], - manifest => manifest - && manifest.getProperty('provider') - && manifest.getProperty('provider')[0].label - && LanguageMap.parse(manifest.getProperty('provider')[0].label, manifest.options.locale).map(label => label.value)[0], -); - -/** -* Return the supplied thumbnail for a manifest or null -* @param {object} state -* @param {object} props -* @param {string} props.manifestId -* @param {string} props.windowId -* @return {String|null} -*/ -export function getManifestThumbnail(state, props) { - /** */ - function getTopLevelManifestThumbnail() { - const manifest = getManifestoInstance(state, props); - - return manifest - && manifest.getThumbnail() - && manifest.getThumbnail().id; - } - - /** */ - function getFirstCanvasThumbnail() { - const canvases = getManifestCanvases(state, props); - - return canvases.length > 0 && canvases[0].getThumbnail() && canvases[0].getThumbnail().id; - } - - /** */ - function generateThumbnailFromFirstCanvas() { - const canvases = getManifestCanvases(state, props); - - if (canvases.length === 0) return null; - - const manifestoCanvas = new ManifestoCanvas(canvases[0]); - - return manifestoCanvas.thumbnail(null, 80); - } - - return getTopLevelManifestThumbnail() - || getFirstCanvasThumbnail() - || generateThumbnailFromFirstCanvas(); -} - -/** -* Return the logo of a manifest or null -* @param {object} state -* @param {object} props -* @param {string} props.manifestId -* @param {string} props.windowId -* @return {String|null} -*/ -export const getManifestCanvases = createSelector( - [getManifestoInstance], - (manifest) => { - if (!manifest) { - return []; - } - - if (!manifest.getSequences || !manifest.getSequences()[0]) { - return []; - } - - return manifest.getSequences()[0].getCanvases(); - }, -); +export * from './canvases'; +export * from './manifests'; +export * from './windows'; /** * Return ids and labels of canvases @@ -125,46 +18,6 @@ export function getIdAndLabelOfCanvases(canvases) { })); } -/** -* Return the current canvas selected in a window -* @param {object} state -* @param {object} props -* @param {string} props.manifestId -* @param {string} props.windowId -* @return {Object} -*/ -export const getSelectedCanvas = createSelector( - [ - getManifestoInstance, - (state, { windowId }) => state.windows[windowId].canvasIndex, - ], - (manifest, canvasIndex) => manifest - && manifest - .getSequences()[0] - .getCanvasByIndex(canvasIndex), -); - -/** -* Return the current canvases selected in a window -* For book view returns 2, for single returns 1 -* @param {object} state -* @param {object} props -* @param {string} props.manifestId -* @param {string} props.windowId -* @return {Array} -*/ -export const getSelectedCanvases = createSelector( - [ - getManifestoInstance, - (state, { windowId }) => state.windows[windowId], - ], - (manifest, { canvasIndex, view }) => manifest - && new CanvasGroupings( - manifest.getSequences()[0].getCanvases(), - view, - ).getCanvases(canvasIndex), -); - /** * Return annotations for an array of targets * @param {object} state @@ -235,34 +88,6 @@ export function getThumbnailNavigationPosition(state, windowId) { && state.companionWindows[state.windows[windowId].thumbnailNavigationId].position; } -/** -* Return manifest title -* @param {object} state -* @param {object} props -* @param {string} props.manifestId -* @param {string} props.windowId -* @return {String} -*/ -export const getManifestTitle = createSelector( - [getManifestoInstance], - manifest => manifest - && manifest.getLabel().map(label => label.value)[0], -); - -/** - * Return the manifest titles for all open windows - * @param {object} state - * @return {object} - */ -export function getWindowTitles(state) { - const result = {}; - - Object.keys(state.windows).forEach((windowId) => { - result[windowId] = getManifestTitle(state, { windowId }); - }); - - return result; -} /** Return type of view in a certain window. * @param {object} state @@ -275,20 +100,6 @@ export function getWindowViewType(state, windowId) { return state.windows[windowId] && state.windows[windowId].view; } -/** -* Return manifest description -* @param {object} state -* @param {object} props -* @param {string} props.manifestId -* @param {string} props.windowId -* @return {String} -*/ -export const getManifestDescription = createSelector( - [getManifestoInstance], - manifest => manifest - && manifest.getDescription().map(label => label.value)[0], -); - /** * Return canvas label, or alternatively return the given index + 1 to be displayed * @param {object} canvas @@ -304,36 +115,6 @@ export function getCanvasLabel(canvas, canvasIndex) { return String(canvasIndex + 1); } -/** -* Return metadata in a label / value structure -* This is a potential seam for pulling the i18n locale from -* state and plucking out the appropriate language. -* For now we're just getting the first. -* @param {object} Manifesto IIIF Resource (e.g. canvas, manifest) -* @return {Array[Object]} -*/ -export function getDestructuredMetadata(iiifResource) { - return (iiifResource - && iiifResource.getMetadata().map(labelValuePair => ({ - label: labelValuePair.getLabel(), - value: labelValuePair.getValue(), - })) - ); -} - -/** - * Return manifest metadata in a label / value structure - * @param {object} state - * @param {object} props - * @param {string} props.manifestId - * @param {string} props.windowId - * @return {Array[Object]} - */ -export const getManifestMetadata = createSelector( - [getManifestoInstance], - manifest => manifest && getDestructuredMetadata(manifest), -); - /** * Return canvas description * @param {object} canvas diff --git a/src/state/selectors/manifests.js b/src/state/selectors/manifests.js new file mode 100644 index 0000000000000000000000000000000000000000..2d57c9607f1d696b19c279bf7c3b31b877cec9e9 --- /dev/null +++ b/src/state/selectors/manifests.js @@ -0,0 +1,168 @@ +import { createSelector } from 'reselect'; +import manifesto, { LanguageMap } from 'manifesto.js'; +import ManifestoCanvas from '../../lib/ManifestoCanvas'; + +/** Get the relevant manifest information */ +export function getManifest(state, { manifestId, windowId }) { + return state.manifests[ + manifestId + || (windowId && state.windows[windowId] && state.windows[windowId].manifestId) + ]; +} + +/** Instantiate a manifesto instance */ +export const getManifestoInstance = createSelector( + [getManifest], + manifest => manifest && manifest.json && manifesto.create(manifest.json), +); + +/** + * Get the logo for a manifest + * @param {object} state + * @param {object} props + * @param {string} props.manifestId + * @param {string} props.windowId + * @return {String|null} + */ +export const getManifestLogo = createSelector( + [getManifestoInstance], + manifest => manifest && manifest.getLogo(), +); + +/** +* Return the IIIF v3 provider of a manifest or null +* @param {object} state +* @param {object} props +* @param {string} props.manifestId +* @param {string} props.windowId +* @return {String|null} +*/ +export const getManifestProvider = createSelector( + [getManifestoInstance], + manifest => manifest + && manifest.getProperty('provider') + && manifest.getProperty('provider')[0].label + && LanguageMap.parse(manifest.getProperty('provider')[0].label, manifest.options.locale).map(label => label.value)[0], +); + +/** +* Return the supplied thumbnail for a manifest or null +* @param {object} state +* @param {object} props +* @param {string} props.manifestId +* @param {string} props.windowId +* @return {String|null} +*/ +export function getManifestThumbnail(state, props) { + /** */ + function getTopLevelManifestThumbnail() { + const manifest = getManifestoInstance(state, props); + + return manifest + && manifest.getThumbnail() + && manifest.getThumbnail().id; + } + + /** */ + function getFirstCanvasThumbnail() { + const canvases = getManifestCanvases(state, props); + + return canvases.length > 0 && canvases[0].getThumbnail() && canvases[0].getThumbnail().id; + } + + /** */ + function generateThumbnailFromFirstCanvas() { + const canvases = getManifestCanvases(state, props); + + if (canvases.length === 0) return null; + + const manifestoCanvas = new ManifestoCanvas(canvases[0]); + + return manifestoCanvas.thumbnail(null, 80); + } + + return getTopLevelManifestThumbnail() + || getFirstCanvasThumbnail() + || generateThumbnailFromFirstCanvas(); +} + +/** +* Return the logo of a manifest or null +* @param {object} state +* @param {object} props +* @param {string} props.manifestId +* @param {string} props.windowId +* @return {String|null} +*/ +export const getManifestCanvases = createSelector( + [getManifestoInstance], + (manifest) => { + if (!manifest) { + return []; + } + + if (!manifest.getSequences || !manifest.getSequences()[0]) { + return []; + } + + return manifest.getSequences()[0].getCanvases(); + }, +); + +/** +* Return manifest title +* @param {object} state +* @param {object} props +* @param {string} props.manifestId +* @param {string} props.windowId +* @return {String} +*/ +export const getManifestTitle = createSelector( + [getManifestoInstance], + manifest => manifest + && manifest.getLabel().map(label => label.value)[0], +); + +/** +* Return manifest description +* @param {object} state +* @param {object} props +* @param {string} props.manifestId +* @param {string} props.windowId +* @return {String} +*/ +export const getManifestDescription = createSelector( + [getManifestoInstance], + manifest => manifest + && manifest.getDescription().map(label => label.value)[0], +); + +/** +* Return metadata in a label / value structure +* This is a potential seam for pulling the i18n locale from +* state and plucking out the appropriate language. +* For now we're just getting the first. +* @param {object} Manifesto IIIF Resource (e.g. canvas, manifest) +* @return {Array[Object]} +*/ +export function getDestructuredMetadata(iiifResource) { + return (iiifResource + && iiifResource.getMetadata().map(labelValuePair => ({ + label: labelValuePair.getLabel(), + value: labelValuePair.getValue(), + })) + ); +} + +/** + * Return manifest metadata in a label / value structure + * @param {object} state + * @param {object} props + * @param {string} props.manifestId + * @param {string} props.windowId + * @return {Array[Object]} + */ +export const getManifestMetadata = createSelector( + [getManifestoInstance], + manifest => manifest && getDestructuredMetadata(manifest), +); diff --git a/src/state/selectors/windows.js b/src/state/selectors/windows.js new file mode 100644 index 0000000000000000000000000000000000000000..3832c0c3fa549c87ee80d074929435d56e964a2f --- /dev/null +++ b/src/state/selectors/windows.js @@ -0,0 +1,16 @@ +import { getManifestTitle } from './manifests'; + +/** + * Return the manifest titles for all open windows + * @param {object} state + * @return {object} + */ +export function getWindowTitles(state) { + const result = {}; + + Object.keys(state.windows).forEach((windowId) => { + result[windowId] = getManifestTitle(state, { windowId }); + }); + + return result; +}