Skip to content
Snippets Groups Projects
Commit acd5573c authored by Chris Beer's avatar Chris Beer Committed by Jack Reed
Browse files

Add WindowSideBarCollectionPanel to navigate collections within a window

parent dd17e8d1
No related branches found
No related tags found
No related merge requests found
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import Typography from '@material-ui/core/Typography';
import Skeleton from '@material-ui/lab/Skeleton';
import ArrowUpwardIcon from '@material-ui/icons/ArrowUpwardSharp';
import CompanionWindow from '../containers/CompanionWindow';
import IIIFThumbnail from '../containers/IIIFThumbnail';
/** */
export class WindowSideBarCollectionPanel extends Component {
/** */
static getUseableLabel(resource, index) {
return (resource
&& resource.getLabel
&& resource.getLabel().length > 0)
? resource.getLabel().map(label => label.value)[0]
: resource.id;
}
/** */
isMultipart() {
const { collection } = this.props;
if (!collection) return false;
const behaviors = collection.getProperty('behavior');
if (Array.isArray(behaviors)) return collection.includes('multi-part');
return behaviors === 'multi-part';
}
/** */
render() {
const {
canvasNavigation,
classes,
collectionPath,
collection,
id,
isFetching,
manifestId,
parentCollection,
updateCompanionWindow,
updateWindow,
t,
variant,
windowId,
} = this.props;
/** */
const Item = ({ manifest, ...otherProps }) => (
<ListItem
className={classes.listItem}
alignItems="flex-start"
button
component="li"
selected={manifestId === manifest.id}
{...otherProps}
>
{ variant === 'thumbnail' && (
<ListItemIcon>
<IIIFThumbnail
resource={manifest}
maxHeight={canvasNavigation.height}
maxWidth={canvasNavigation.width}
/>
</ListItemIcon>
)}
<ListItemText>{WindowSideBarCollectionPanel.getUseableLabel(manifest)}</ListItemText>
</ListItem>
);
return (
<CompanionWindow
title={t(this.isMultipart() ? 'multipartCollection' : 'collection')}
windowId={windowId}
id={id}
titleControls={(
<>
{ parentCollection && (
<List>
<ListItem
button
onClick={
() => updateCompanionWindow({ collectionPath: collectionPath.slice(0, -1) })
}
>
<ListItemIcon>
<ArrowUpwardIcon />
</ListItemIcon>
<ListItemText primaryTypographyProps={{ variant: 'body1' }}>
{WindowSideBarCollectionPanel.getUseableLabel(parentCollection)}
</ListItemText>
</ListItem>
</List>
)}
<Typography primaryTypographyProps={{ variant: 'h6' }}>
{ collection && WindowSideBarCollectionPanel.getUseableLabel(collection)}
{ isFetching && <Skeleton className={classes.placeholder} variant="text" />}
</Typography>
</>
)}
>
<List>
{ isFetching && (
<ListItem>
<ListItemText>
<Skeleton className={classes.placeholder} variant="text" />
<Skeleton className={classes.placeholder} variant="text" />
<Skeleton className={classes.placeholder} variant="text" />
</ListItemText>
</ListItem>
)}
{
collection && collection.getCollections().map((manifest) => {
/** select the new manifest and go back to the normal index */
const onClick = () => {
// close collection
updateCompanionWindow({ collectionPath: [...collectionPath, manifest.id] });
};
return (
<Item key={manifest.id} onClick={onClick} manifest={manifest} />
);
})
}
{
collection && collection.getManifests().map((manifest) => {
/** select the new manifest and go back to the normal index */
const onClick = () => {
// select new manifest
updateWindow({ canvasId: null, collectionPath, manifestId: manifest.id });
// close collection
updateCompanionWindow({ multipart: false });
};
return (
<Item key={manifest.id} onClick={onClick} manifest={manifest} />
);
})
}
</List>
</CompanionWindow>
);
}
}
WindowSideBarCollectionPanel.propTypes = {
canvasNavigation: PropTypes.shape({
height: PropTypes.number,
width: PropTypes.number,
}).isRequired,
classes: PropTypes.objectOf(PropTypes.string).isRequired,
collection: PropTypes.object, // eslint-disable-line react/forbid-prop-types
collectionId: PropTypes.string.isRequired,
collectionPath: PropTypes.arrayOf(PropTypes.string),
error: PropTypes.string,
id: PropTypes.string.isRequired,
isFetching: PropTypes.bool,
manifestId: PropTypes.string.isRequired,
parentCollection: PropTypes.object, // eslint-disable-line react/forbid-prop-types
ready: PropTypes.bool,
t: PropTypes.func,
updateCompanionWindow: PropTypes.func.isRequired,
updateWindow: PropTypes.func.isRequired,
variant: PropTypes.string,
windowId: PropTypes.string.isRequired,
};
WindowSideBarCollectionPanel.defaultProps = {
collection: null,
collectionPath: [],
error: null,
isFetching: false,
parentCollection: null,
ready: false,
t: k => k,
variant: null,
};
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 * as actions from '../state/actions';
import {
getCompanionWindow,
getManifest,
getManifestoInstance,
getDefaultSidebarVariant,
getWindow,
} from '../state/selectors';
import { WindowSideBarCollectionPanel } from '../components/WindowSideBarCollectionPanel';
/**
* mapStateToProps - to hook up connect
*/
const mapStateToProps = (state, { id, windowId }) => {
const window = getWindow(state, { windowId });
const companionWindow = getCompanionWindow(state, { companionWindowId: id });
const { collectionPath: localCollectionPath } = companionWindow;
const collectionPath = localCollectionPath || window.collectionPath;
const collectionId = collectionPath && collectionPath[collectionPath.length - 1];
const parentCollectionId = collectionPath && collectionPath[collectionPath.length - 2];
const collection = collectionId && getManifest(state, { manifestId: collectionId });
const parentCollection = parentCollectionId
&& getManifest(state, { manifestId: parentCollectionId });
const manifest = getManifest(state, { windowId });
return {
canvasNavigation: state.config.canvasNavigation,
collection: collection && getManifestoInstance(state, { manifestId: collection.id }),
collectionId,
collectionPath,
error: collection && collection.error,
isFetching: collection && collection.isFetching,
manifestId: manifest && manifest.id,
parentCollection: parentCollection
&& getManifestoInstance(state, { manifestId: parentCollection.id }),
ready: collection && !!collection.json,
variant: companionWindow.variant
|| getDefaultSidebarVariant(state, { windowId }),
};
};
/**
* mapStateToProps - used to hook up connect to state
* @memberof SidebarIndexList
* @private
*/
const mapDispatchToProps = (dispatch, { id, windowId }) => ({
updateCompanionWindow: (...args) => dispatch(
actions.updateCompanionWindow(windowId, id, ...args),
),
updateWindow: (...args) => dispatch(actions.updateWindow(windowId, ...args)),
});
/**
* Styles for withStyles HOC
*/
const styles = theme => ({
label: {
paddingLeft: theme.spacing(1),
},
listItem: {
borderBottom: `0.5px solid ${theme.palette.divider}`,
paddingRight: theme.spacing(1),
},
});
const enhance = compose(
withStyles(styles),
withTranslation(),
connect(mapStateToProps, mapDispatchToProps),
withPlugins('WindowSideBarCollectionPanel'),
);
export default enhance(WindowSideBarCollectionPanel);
......@@ -6,11 +6,13 @@ import AttributionPanel from '../containers/AttributionPanel';
import SearchPanel from '../containers/SearchPanel';
import LayersPanel from '../containers/LayersPanel';
import CustomPanel from '../containers/CustomPanel';
import WindowSideBarCollectionPanel from '../containers/WindowSideBarCollectionPanel';
const map = {
annotations: WindowSideBarAnnotationsPanel,
attribution: AttributionPanel,
canvas: WindowSideBarCanvasPanel,
collection: WindowSideBarCollectionPanel,
custom: CustomPanel,
info: WindowSideBarInfoPanel,
layers: LayersPanel,
......
......@@ -45,6 +45,14 @@ export function* fetchWindowManifest(action) {
yield call(setWindowDefaultSearchQuery, action);
}
/** */
export function* fetchCollectionManifests(action) {
const { collectionPath } = action.payload;
if (!collectionPath) return;
yield call(fetchManifests, ...collectionPath);
}
/** @private */
export function* setWindowStartingCanvas(action) {
const { canvasId, canvasIndex, manifestId } = action.payload || action.window;
......@@ -210,6 +218,7 @@ export default function* windowsSaga() {
takeEvery(ActionTypes.UPDATE_WINDOW, fetchWindowManifest),
takeEvery(ActionTypes.SET_CANVAS, setCurrentAnnotationsOnCurrentCanvas),
takeEvery(ActionTypes.SET_CANVAS, fetchInfoResponses),
takeEvery(ActionTypes.UPDATE_COMPANION_WINDOW, fetchCollectionManifests),
takeEvery(ActionTypes.SET_WINDOW_VIEW_TYPE, updateVisibleCanvases),
takeEvery(ActionTypes.RECEIVE_SEARCH, setCanvasOfFirstSearchResult),
takeEvery(ActionTypes.SELECT_ANNOTATION, setCanvasforSelectedAnnotation),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment