Skip to content

Commit

Permalink
Basic implementation of Table of Contents view
Browse files Browse the repository at this point in the history
  • Loading branch information
mejackreed committed Dec 18, 2019
1 parent b0626e9 commit 91247a9
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 3 deletions.
29 changes: 29 additions & 0 deletions __tests__/integration/mirador/toc.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<title>Mirador - Table of contents</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500">
</head>
<body>
<div id="mirador" style="position: absolute; top: 0; bottom: 0; left: 0; right: 0;"></div>
<script>document.write("<script type='text/javascript' src='../../../dist/mirador.min.js?v=" + Date.now() + "'><\/script>");</script>
<script type="text/javascript">
var miradorInstance = Mirador.viewer({
id: 'mirador',
windows: [{
manifestId: 'https://iiif.bodleian.ox.ac.uk/iiif/manifest/390fd0e8-9eae-475d-9564-ed916ab9035c.json',
canvasId: 'https://iiif.bodleian.ox.ac.uk/iiif/canvas/a024a538-aef3-44b3-ad11-51c6a8b04ea2.json'
}],
window: {
sideBarOpenByDefault: true,
defaultSideBarPanel: 'canvas'
},
manifests: {
}
});
</script>
</body>
</html>
1 change: 1 addition & 0 deletions __tests__/src/selectors/manifests.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
getManifestRenderings,
getManifestUrl,
getManifestViewingHint,
getManifestTreeStructure,
getMetadataLocales,
getRequiredStatement,
getRights,
Expand Down
66 changes: 66 additions & 0 deletions src/components/SidebarIndexTableOfContents.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import TreeView from '@material-ui/lab/TreeView';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
import TreeItem from '@material-ui/lab/TreeItem';

/** */
export class SidebarIndexTableOfContents extends Component {
/** */
selectTreeItem(node) {
const { setCanvas, windowId } = this.props;
// Do not select if there are child nodes
if (node.nodes.length > 0) {
return;
}
const canvas = node.data.getCanvasIds()[0];
setCanvas(windowId, canvas);
}

/** */
buildTreeItems(nodes) {
return (
nodes.map(node => (
<TreeItem
key={node.id}
nodeId={node.id}
label={node.label}
onClick={() => this.selectTreeItem(node)}
>
{node.nodes.length > 0 ? this.buildTreeItems(node.nodes) : null}
</TreeItem>
))
);
}

/** */
render() {
const {
classes, treeStructure,
} = this.props;

if (!treeStructure) {
return <></>;
}

return (
<>
<TreeView
className={classes.root}
defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpandIcon={<ChevronRightIcon />}
>
{this.buildTreeItems(treeStructure.nodes)}
</TreeView>
</>
);
}
}

SidebarIndexTableOfContents.propTypes = {
classes: PropTypes.objectOf(PropTypes.string).isRequired,
setCanvas: PropTypes.func.isRequired,
treeStructure: PropTypes.objectOf().isRequired,
windowId: PropTypes.string.isRequired,
};
26 changes: 23 additions & 3 deletions src/components/WindowSideBarCanvasPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import RootRef from '@material-ui/core/RootRef';
import Select from '@material-ui/core/Select';
import CompanionWindow from '../containers/CompanionWindow';
import SidebarIndexList from '../containers/SidebarIndexList';
import SidebarIndexTableOfContents from '../containers/SidebarIndexTableOfContents';

/**
* a panel showing the canvases for a given manifest
Expand Down Expand Up @@ -46,6 +47,24 @@ export class WindowSideBarCanvasPanel extends Component {
} = this.props;

const { variantSelectionOpened } = this.state;
let listComponent;
if (variant === 'tableOfContents') {
listComponent = (
<SidebarIndexTableOfContents
id={id}
containerRef={this.containerRef}
windowId={windowId}
/>
);
} else {
listComponent = (
<SidebarIndexList
id={id}
containerRef={this.containerRef}
windowId={windowId}
/>
);
}
return (
<RootRef rootRef={this.containerRef}>
<CompanionWindow
Expand Down Expand Up @@ -80,11 +99,12 @@ export class WindowSideBarCanvasPanel extends Component {
>
<MenuItem value="compact"><Typography variant="body2">{ t('compactList') }</Typography></MenuItem>
<MenuItem value="thumbnail"><Typography variant="body2">{ t('thumbnailList') }</Typography></MenuItem>
<MenuItem value="tableOfContents"><Typography variant="body2">{ t('tableOfContentsList') }</Typography></MenuItem>
</Select>
</FormControl>
)}
>
<SidebarIndexList id={id} containerRef={this.containerRef} windowId={windowId} />
{listComponent}
</CompanionWindow>
</RootRef>
);
Expand All @@ -97,10 +117,10 @@ WindowSideBarCanvasPanel.propTypes = {
t: PropTypes.func.isRequired,
toggleDraggingEnabled: PropTypes.func.isRequired,
updateVariant: PropTypes.func.isRequired,
variant: PropTypes.oneOf(['compact', 'thumbnail']),
variant: PropTypes.oneOf(['compact', 'thumbnail', 'tableOfContents']),
windowId: PropTypes.string.isRequired,
};

WindowSideBarCanvasPanel.defaultProps = {
variant: 'thumbnail',
variant: 'tableOfContents',
};
49 changes: 49 additions & 0 deletions src/containers/SidebarIndexTableOfContents.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { compose } from 'redux';
import { connect } from 'react-redux';
import { withTranslation } from 'react-i18next';
import { withStyles } from '@material-ui/core/styles';
import { withPlugins } from '../extend/withPlugins';
import { SidebarIndexTableOfContents } from '../components/SidebarIndexTableOfContents';
import {
getManifestoInstance,
getManifestTreeStructure,
getVisibleCanvases,
} from '../state/selectors';
import * as actions from '../state/actions';


/**
* mapStateToProps - to hook up connect
*/
const mapStateToProps = (state, { id, windowId }) => ({
canvases: getVisibleCanvases(state, { windowId }),
manifesto: getManifestoInstance(state, { windowId }),
treeStructure: getManifestTreeStructure(state, { windowId }),
});

/**
* mapStateToProps - used to hook up connect to state
* @memberof SidebarIndexTableOfContents
* @private
*/
const mapDispatchToProps = (dispatch, { id, windowId }) => ({
setCanvas: (...args) => dispatch(actions.setCanvas(...args)),
});

/**
* Styles for withStyles HOC
*/
const styles = theme => ({
root: {
flexGrow: 1,
},
});

const enhance = compose(
withStyles(styles),
withTranslation(),
connect(mapStateToProps, mapDispatchToProps),
withPlugins('SidebarIndexTableOfContents'),
);

export default enhance(SidebarIndexTableOfContents);
1 change: 1 addition & 0 deletions src/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
"single": "Single",
"startHere": "Start Here",
"suggestSearch": "Search this document for \"{{ query }}\"",
"tableOfContentsList": "Table of contents",
"theme": "Theme",
"thumbnailList": "Thumbnail list",
"thumbnailNavigation": "Thumbnails",
Expand Down
9 changes: 9 additions & 0 deletions src/state/selectors/manifests.js
Original file line number Diff line number Diff line change
Expand Up @@ -432,3 +432,12 @@ export const getManifestAutocompleteService = createSelector(
return autocompleteService && autocompleteService;
},
);

/** */
export const getManifestTreeStructure = createSelector(
[getManifestoInstance],
(manifest) => {
if (!manifest) return null;
return manifest.getDefaultTree();
},
);

0 comments on commit 91247a9

Please sign in to comment.