Select Git revision
CanvasAnnotations.js

Anthony authored
CanvasAnnotations.js 6.18 KiB
import { Component } from 'react';
import PropTypes from 'prop-types';
import clsx from 'clsx';
import Chip from '@material-ui/core/Chip';
import MenuList from '@material-ui/core/MenuList';
import MenuItem from '@material-ui/core/MenuItem';
import ListItemText from '@material-ui/core/ListItemText';
import Typography from '@material-ui/core/Typography';
import SearchIcon from '@material-ui/icons/SearchSharp';
import InputBase from '@material-ui/core/InputBase';
import SanitizedHtml from '../containers/SanitizedHtml';
import { ScrollTo } from './ScrollTo';
import AnnotationManifestsAccordion from '../containers/AnnotationManifestsAccordion';
import { filterAnnotation } from '../helper/utils';
/**
* CanvasAnnotations ~
*/
export class CanvasAnnotations extends Component {
/**
* constructor -
*/
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
this.handleAnnotationHover = this.handleAnnotationHover.bind(this);
this.handleAnnotationBlur = this.handleAnnotationBlur.bind(this);
this.handleAnnotationSearch = this.handleAnnotationSearch.bind(this);
this.state = { };
}
/**
* Handle click event of an annotation.
*/
handleClick(event, annotation) {
const {
deselectAnnotation, selectAnnotation, selectedAnnotationId, windowId,
} = this.props;
if (selectedAnnotationId === annotation.id) {
deselectAnnotation(windowId, annotation.id);
} else {
selectAnnotation(windowId, annotation.id);
}
}
/** */
handleAnnotationHover(annotation) {
const { hoverAnnotation, windowId } = this.props;
hoverAnnotation(windowId, [annotation.id]);
}
/** */
handleAnnotationBlur() {
const { hoverAnnotation, windowId } = this.props;
hoverAnnotation(windowId, []);
}
/** */
handleAnnotationSearch(event) {
this.setState({ inputSearch: event.target.value });
}
/**
* Returns the rendered component
*/
render() {
const {
autoScroll, classes, index, label, selectedAnnotationId, t, totalSize,
listContainerComponent, htmlSanitizationRuleSet, hoveredAnnotationIds,
containerRef,
} = this.props;
let { annotations } = this.props;
const { inputSearch } = this.state;
if (inputSearch != undefined && inputSearch !== '') {
annotations = filterAnnotation(annotations, inputSearch);
}
return (
<>
<Typography className={classes.sectionHeading} variant="overline">
{t('annotationCanvasLabel', { context: `${index + 1}/${totalSize}`, label })}
</Typography>
<div className={classes.search}>
<div className={classes.searchIcon}>
<SearchIcon />
</div>
<InputBase
placeholder="Search…"
classes={{
input: classes.inputInput,
root: classes.inputRoot,
}}
inputProps={{ 'aria-label': 'search' }}
onChange={this.handleAnnotationSearch}
/>
</div>
<MenuList autoFocusItem variant="selectedMenu">
{
annotations.map(annotation => (
<ScrollTo
containerRef={containerRef}
key={`${annotation.id}-scroll`}
offsetTop={96} // offset for the height of the form above
scrollTo={autoScroll ? (selectedAnnotationId === annotation.id) : false}
>
<MenuItem
button
component={listContainerComponent}
className={clsx(
classes.annotationListItem,
{
[classes.hovered]: hoveredAnnotationIds.includes(annotation.id),
},
)}
key={annotation.id}
annotationid={annotation.id}
selected={selectedAnnotationId === annotation.id}
onClick={e => this.handleClick(e, annotation)}
onFocus={() => this.handleAnnotationHover(annotation)}
onBlur={this.handleAnnotationBlur}
onMouseEnter={() => this.handleAnnotationHover(annotation)}
onMouseLeave={this.handleAnnotationBlur}
>
<ListItemText primaryTypographyProps={{ variant: 'body2' }}>
<SanitizedHtml
ruleSet={htmlSanitizationRuleSet}
htmlString={annotation.content}
/>
<div>
{
annotation.tags.map(tag => (
<Chip size="small" variant="outlined" label={tag} id={tag} className={classes.chip} key={tag.toString()} />
))
}
<AnnotationManifestsAccordion
annotation={annotation}
t={t}
/>
</div>
</ListItemText>
</MenuItem>
</ScrollTo>
))
}
</MenuList>
</>
);
}
}
CanvasAnnotations.propTypes = {
annotations: PropTypes.arrayOf(
PropTypes.shape({
content: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
}),
),
autoScroll: PropTypes.bool,
classes: PropTypes.objectOf(PropTypes.string),
containerRef: PropTypes.oneOfType([
PropTypes.func,
PropTypes.shape({ current: PropTypes.instanceOf(Element) }),
]),
deselectAnnotation: PropTypes.func.isRequired,
hoverAnnotation: PropTypes.func.isRequired,
hoveredAnnotationIds: PropTypes.arrayOf(PropTypes.string),
htmlSanitizationRuleSet: PropTypes.string,
index: PropTypes.number.isRequired,
label: PropTypes.string.isRequired,
listContainerComponent: PropTypes.elementType,
selectAnnotation: PropTypes.func.isRequired,
selectedAnnotationId: PropTypes.string,
t: PropTypes.func.isRequired,
totalSize: PropTypes.number.isRequired,
windowId: PropTypes.string.isRequired,
};
CanvasAnnotations.defaultProps = {
annotations: [],
autoScroll: true,
classes: {},
containerRef: undefined,
hoveredAnnotationIds: [],
htmlSanitizationRuleSet: 'iiif',
listContainerComponent: 'li',
selectedAnnotationId: undefined,
};