Skip to content
Snippets Groups Projects
Commit 5dd569d0 authored by Chris Beer's avatar Chris Beer
Browse files

Extract configuration for view types

parent 051f4c2c
No related branches found
No related tags found
No related merge requests found
...@@ -7,11 +7,12 @@ import { WindowViewSettings } from '../../../src/components/WindowViewSettings'; ...@@ -7,11 +7,12 @@ import { WindowViewSettings } from '../../../src/components/WindowViewSettings';
/** create wrapper */ /** create wrapper */
function createWrapper(props) { function createWrapper(props) {
return shallow( return mount(
<WindowViewSettings <WindowViewSettings
classes={{}} classes={{}}
windowId="xyz" windowId="xyz"
setWindowViewType={() => {}} setWindowViewType={() => {}}
viewTypes={['single', 'book', 'scroll', 'gallery']}
windowViewType="single" windowViewType="single"
{...props} {...props}
/>, />,
...@@ -64,6 +65,7 @@ describe('WindowViewSettings', () => { ...@@ -64,6 +65,7 @@ describe('WindowViewSettings', () => {
classes={{}} classes={{}}
windowId="xyz" windowId="xyz"
setWindowViewType={() => {}} setWindowViewType={() => {}}
viewTypes={['single', 'book', 'scroll', 'gallery']}
windowViewType="single" windowViewType="single"
/>, />,
); );
......
...@@ -11,6 +11,7 @@ import { ...@@ -11,6 +11,7 @@ import {
getWindowManifests, getWindowManifests,
getWindows, getWindows,
getMaximizedWindowsIds, getMaximizedWindowsIds,
getAllowedWindowViewTypes,
} from '../../../src/state/selectors/windows'; } from '../../../src/state/selectors/windows';
describe('getWindows', () => { describe('getWindows', () => {
...@@ -104,6 +105,12 @@ describe('getWindowViewType', () => { ...@@ -104,6 +105,12 @@ describe('getWindowViewType', () => {
config: { config: {
window: { window: {
defaultView: 'default', defaultView: 'default',
views: [
{ behaviors: ['individuals'], key: 'single' },
{ behaviors: ['paged'], key: 'book' },
{ behaviors: ['continuous'], key: 'scroll' },
{ key: 'gallery' },
],
}, },
}, },
manifests: { manifests: {
...@@ -150,6 +157,36 @@ describe('getWindowViewType', () => { ...@@ -150,6 +157,36 @@ describe('getWindowViewType', () => {
}); });
}); });
describe('getAllowedWindowViewTypes', () => {
const state = {
config: {
window: {
defaultView: 'single',
views: [
{ behaviors: ['individuals'], key: 'single' },
{ behaviors: ['paged'], key: 'book' },
{ behaviors: ['continuous'], key: 'scroll' },
{ key: 'gallery' },
],
},
},
manifests: {
x: { json: { ...manifestFixture001 } },
y: { json: { ...manifestFixture015 } },
},
};
it('should return unrestricted view types', () => {
const received = getAllowedWindowViewTypes(state, { manifestId: 'x' });
expect(received).toEqual(['single', 'gallery']);
});
it('should return view types where behaviors match', () => {
const received = getAllowedWindowViewTypes(state, { manifestId: 'y' });
expect(received).toEqual(['single', 'book', 'gallery']);
});
});
describe('getViewer', () => { describe('getViewer', () => {
const state = { const state = {
viewers: { viewers: {
......
...@@ -4,6 +4,7 @@ import FormControlLabel from '@material-ui/core/FormControlLabel'; ...@@ -4,6 +4,7 @@ import FormControlLabel from '@material-ui/core/FormControlLabel';
import MenuItem from '@material-ui/core/MenuItem'; import MenuItem from '@material-ui/core/MenuItem';
import ListSubheader from '@material-ui/core/ListSubheader'; import ListSubheader from '@material-ui/core/ListSubheader';
import SingleIcon from '@material-ui/icons/CropOriginalSharp'; import SingleIcon from '@material-ui/icons/CropOriginalSharp';
import ScrollViewIcon from '@material-ui/icons/ViewColumn';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import BookViewIcon from './icons/BookViewIcon'; import BookViewIcon from './icons/BookViewIcon';
import GalleryViewIcon from './icons/GalleryViewIcon'; import GalleryViewIcon from './icons/GalleryViewIcon';
...@@ -55,53 +56,41 @@ export class WindowViewSettings extends Component { ...@@ -55,53 +56,41 @@ export class WindowViewSettings extends Component {
*/ */
render() { render() {
const { const {
classes, handleClose, t, windowViewType, classes, handleClose, t, windowViewType, viewTypes,
} = this.props; } = this.props;
return ( if (viewTypes.length === 0) return null;
<>
<ListSubheader role="presentation" disableSticky tabIndex="-1">{t('view')}</ListSubheader>
const iconMap = {
book: BookViewIcon,
gallery: GalleryViewIcon,
scroll: ScrollViewIcon,
single: SingleIcon,
};
/** */
const ViewItem = ({ Icon, value }) => (
<MenuItem <MenuItem
className={classes.MenuItem} className={classes.MenuItem}
ref={ref => this.handleSelectedRef(ref)} ref={ref => this.handleSelectedRef(ref)}
onClick={() => { this.handleChange('single'); handleClose(); }} onClick={() => { this.handleChange(value); handleClose(); }}
> >
<FormControlLabel <FormControlLabel
value="single" value={value}
classes={{ label: windowViewType === 'single' ? classes.selectedLabel : classes.label }} classes={{ label: windowViewType === value ? classes.selectedLabel : classes.label }}
control={<SingleIcon color={windowViewType === 'single' ? 'secondary' : undefined} />} control={Icon && <Icon color={windowViewType === value ? 'secondary' : undefined} />}
label={t('single')} label={t(value)}
labelPlacement="bottom"
/>
</MenuItem>
<MenuItem className={classes.MenuItem} onClick={() => { this.handleChange('book'); handleClose(); }}>
<FormControlLabel
value="book"
classes={{ label: windowViewType === 'book' ? classes.selectedLabel : classes.label }}
control={<BookViewIcon color={windowViewType === 'book' ? 'secondary' : undefined} />}
label={t('book')}
labelPlacement="bottom"
/>
</MenuItem>
<MenuItem className={classes.MenuItem} onClick={() => { this.handleChange('scroll'); handleClose(); }}>
<FormControlLabel
value="scroll"
classes={{ label: windowViewType === 'scroll' ? classes.selectedLabel : classes.label }}
control={<BookViewIcon color={windowViewType === 'scroll' ? 'secondary' : undefined} />}
label={t('scroll')}
labelPlacement="bottom"
/>
</MenuItem>
<MenuItem className={classes.MenuItem} onClick={() => { this.handleChange('gallery'); handleClose(); }}>
<FormControlLabel
value="gallery"
classes={{ label: windowViewType === 'gallery' ? classes.selectedLabel : classes.label }}
control={<GalleryViewIcon color={windowViewType === 'gallery' ? 'secondary' : undefined} />}
label={t('gallery')}
labelPlacement="bottom" labelPlacement="bottom"
/> />
</MenuItem> </MenuItem>
);
return (
<>
<ListSubheader role="presentation" disableSticky tabIndex="-1">{t('view')}</ListSubheader>
{viewTypes.map(value => (
<ViewItem Icon={iconMap[value]} key={value} value={value} />
))}
</> </>
); );
} }
...@@ -112,10 +101,12 @@ WindowViewSettings.propTypes = { ...@@ -112,10 +101,12 @@ WindowViewSettings.propTypes = {
handleClose: PropTypes.func, handleClose: PropTypes.func,
setWindowViewType: PropTypes.func.isRequired, setWindowViewType: PropTypes.func.isRequired,
t: PropTypes.func, t: PropTypes.func,
viewTypes: PropTypes.arrayOf(PropTypes.string),
windowId: PropTypes.string.isRequired, windowId: PropTypes.string.isRequired,
windowViewType: PropTypes.string.isRequired, windowViewType: PropTypes.string.isRequired,
}; };
WindowViewSettings.defaultProps = { WindowViewSettings.defaultProps = {
handleClose: () => {}, handleClose: () => {},
t: key => key, t: key => key,
viewTypes: [],
}; };
...@@ -242,7 +242,13 @@ export default { ...@@ -242,7 +242,13 @@ export default {
canvas: true, canvas: true,
annotations: true, annotations: true,
search: true, search: true,
} },
views: [
{ key: 'single', behaviors: ['individuals'] },
{ key: 'book', behaviors: ['paged'] },
{ key: 'scroll', behaviors: ['continuous'] },
{ key: 'gallery' },
],
}, },
windows: [ // Array of windows to be open when mirador initializes (each object should at least provide a manifestId key with the value of the IIIF presentation manifest to load) windows: [ // Array of windows to be open when mirador initializes (each object should at least provide a manifestId key with the value of the IIIF presentation manifest to load)
/** /**
......
...@@ -4,7 +4,7 @@ import { withTranslation } from 'react-i18next'; ...@@ -4,7 +4,7 @@ import { withTranslation } from 'react-i18next';
import { withStyles } from '@material-ui/core/styles'; import { withStyles } from '@material-ui/core/styles';
import { withPlugins } from '../extend/withPlugins'; import { withPlugins } from '../extend/withPlugins';
import * as actions from '../state/actions'; import * as actions from '../state/actions';
import { getWindowViewType } from '../state/selectors'; import { getAllowedWindowViewTypes, getWindowViewType } from '../state/selectors';
import { WindowViewSettings } from '../components/WindowViewSettings'; import { WindowViewSettings } from '../components/WindowViewSettings';
/** /**
...@@ -21,6 +21,7 @@ const mapDispatchToProps = { setWindowViewType: actions.setWindowViewType }; ...@@ -21,6 +21,7 @@ const mapDispatchToProps = { setWindowViewType: actions.setWindowViewType };
*/ */
const mapStateToProps = (state, { windowId }) => ( const mapStateToProps = (state, { windowId }) => (
{ {
viewTypes: getAllowedWindowViewTypes(state, { windowId }),
windowViewType: getWindowViewType(state, { windowId }), windowViewType: getWindowViewType(state, { windowId }),
} }
); );
......
...@@ -52,6 +52,11 @@ export const getDefaultView = createSelector( ...@@ -52,6 +52,11 @@ export const getDefaultView = createSelector(
({ window }) => window && window.defaultView, ({ window }) => window && window.defaultView,
); );
export const getViewConfigs = createSelector(
[getConfig],
({ window }) => (window && window.views) || [],
);
export const getThemeDirection = createSelector( export const getThemeDirection = createSelector(
[getConfig], [getConfig],
({ theme }) => theme.direction || 'ltr', ({ theme }) => theme.direction || 'ltr',
......
...@@ -5,7 +5,7 @@ import { ...@@ -5,7 +5,7 @@ import {
getManifestViewingHint, getManifestViewingHint,
getManifestoInstance, getManifestoInstance,
} from './manifests'; } from './manifests';
import { getDefaultView } from './config'; import { getDefaultView, getViewConfigs } from './config';
import { getWorkspaceType } from './workspace'; import { getWorkspaceType } from './workspace';
/** /**
...@@ -85,19 +85,41 @@ export const getWindowViewType = createSelector( ...@@ -85,19 +85,41 @@ export const getWindowViewType = createSelector(
getManifestViewingHint, getManifestViewingHint,
getManifestBehaviors, getManifestBehaviors,
getDefaultView, getDefaultView,
getViewConfigs,
], ],
(window, manifestViewingHint, manifestBehaviors, defaultView) => { (window, manifestViewingHint, manifestBehaviors, defaultView, viewConfig) => {
const lookup = { if (window && window.view) return window.view;
continuous: 'scroll',
individuals: 'single', const config = viewConfig.find(view => (
paged: 'book', view.behaviors
}; && view.behaviors.some(b => manifestViewingHint === b || manifestBehaviors.includes(b))
return (window && window.view) ));
|| lookup[manifestBehaviors.find(b => lookup[b]) || manifestViewingHint]
|| defaultView; return (config && config.key) || defaultView;
}, },
); );
/** */
export const getAllowedWindowViewTypes = createSelector(
[
getManifestViewingHint,
getManifestBehaviors,
getDefaultView,
getViewConfigs,
],
(manifestViewingHint, manifestBehaviors, defaultView, viewConfig) => (
viewConfig.reduce((allowedViews, view) => {
if (
view.key === defaultView
|| !view.behaviors
|| view.behaviors.some(b => (
manifestViewingHint === b || manifestBehaviors.includes(b)
))) allowedViews.push(view.key);
return allowedViews;
}, [])
),
);
export const getViewer = createSelector( export const getViewer = createSelector(
[ [
state => state.viewers, state => state.viewers,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment