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

Display annotation tags in CanvasAnnotation list fixes #3051

parent 59f07427
No related branches found
No related tags found
No related merge requests found
...@@ -286,11 +286,18 @@ ...@@ -286,11 +286,18 @@
"target": "https://iiif.bodleian.ox.ac.uk/iiif/canvas/9cca8fdd-4a61-4429-8ac1-f648764b4d6d.json#xywh=2000,500,2000,2000" "target": "https://iiif.bodleian.ox.ac.uk/iiif/canvas/9cca8fdd-4a61-4429-8ac1-f648764b4d6d.json#xywh=2000,500,2000,2000"
}, },
{ {
"body": { "body": [
{
"language": "en", "language": "en",
"type": "TextualBody", "type": "TextualBody",
"value": "this is a face" "value": "this is a face"
}, },
{
"type": "TextualBody",
"value": "Face",
"purpose": "tagging"
}
],
"id": "https://example.org/iiif/book1/page/manifest/9c6934ee-1026-4a10-8a97-aaf513513020", "id": "https://example.org/iiif/book1/page/manifest/9c6934ee-1026-4a10-8a97-aaf513513020",
"motivation": "commenting", "motivation": "commenting",
"target": { "target": {
...@@ -301,6 +308,30 @@ ...@@ -301,6 +308,30 @@
} }
}, },
"type": "Annotation" "type": "Annotation"
},
{
"id": "https://example.org/iiif/book1/page/manifest/a3",
"type": "Annotation",
"motivation": "tagging",
"body": [
{
"type": "TextualBody",
"value": "Tree"
},
{
"type": "TextualBody",
"value": "Drawing"
},
{
"type": "TextualBody",
"value": "Coniferous"
},
{
"type": "TextualBody",
"value": "Stanford Cardinal"
}
],
"target": "https://iiif.bodleian.ox.ac.uk/iiif/canvas/9cca8fdd-4a61-4429-8ac1-f648764b4d6d.json#xywh=1605,961,437,625"
} }
] ]
}, },
......
import React from 'react'; import React from 'react';
import { shallow } from 'enzyme'; import { shallow } from 'enzyme';
import Typography from '@material-ui/core/Typography'; import Typography from '@material-ui/core/Typography';
import Chip from '@material-ui/core/Chip';
import List from '@material-ui/core/List'; import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem'; import ListItem from '@material-ui/core/ListItem';
import { CanvasAnnotations } from '../../../src/components/CanvasAnnotations'; import { CanvasAnnotations } from '../../../src/components/CanvasAnnotations';
...@@ -30,11 +31,13 @@ describe('CanvasAnnotations', () => { ...@@ -30,11 +31,13 @@ describe('CanvasAnnotations', () => {
{ {
content: 'First Annotation', content: 'First Annotation',
id: 'abc123', id: 'abc123',
tags: ['abc123', 'def456'],
targetId: 'example.com/iiif/12345', targetId: 'example.com/iiif/12345',
}, },
{ {
content: 'Last Annotation', content: 'Last Annotation',
id: 'xyz321', id: 'xyz321',
tags: [],
targetId: 'example.com/iiif/54321', targetId: 'example.com/iiif/54321',
}, },
]; ];
...@@ -61,6 +64,12 @@ describe('CanvasAnnotations', () => { ...@@ -61,6 +64,12 @@ describe('CanvasAnnotations', () => {
expect(wrapper.find(ListItem).length).toEqual(2); expect(wrapper.find(ListItem).length).toEqual(2);
}); });
it('renders a Chip for every tag', () => {
wrapper = createWrapper({ annotations });
expect(wrapper.find(Chip).length).toEqual(2);
});
it('pass through the annotation to make plugins life easier', () => { it('pass through the annotation to make plugins life easier', () => {
wrapper = createWrapper({ annotations }); wrapper = createWrapper({ annotations });
expect(wrapper.find(ListItem).first().dive().props().annotation.id).toEqual('abc123'); expect(wrapper.find(ListItem).first().dive().props().annotation.id).toEqual('abc123');
...@@ -107,6 +116,7 @@ describe('CanvasAnnotations', () => { ...@@ -107,6 +116,7 @@ describe('CanvasAnnotations', () => {
{ {
content: 'Annotation', content: 'Annotation',
id: 'annoId', id: 'annoId',
tags: [],
targetId: 'example.com/iiif/12345', targetId: 'example.com/iiif/12345',
}, },
], ],
...@@ -130,6 +140,7 @@ describe('CanvasAnnotations', () => { ...@@ -130,6 +140,7 @@ describe('CanvasAnnotations', () => {
{ {
content: 'Annotation', content: 'Annotation',
id: 'annoId', id: 'annoId',
tags: [],
targetId: 'example.com/iiif/12345', targetId: 'example.com/iiif/12345',
}, },
], ],
...@@ -148,6 +159,7 @@ describe('CanvasAnnotations', () => { ...@@ -148,6 +159,7 @@ describe('CanvasAnnotations', () => {
{ {
content: 'Annotation', content: 'Annotation',
id: 'annoId', id: 'annoId',
tags: [],
targetId: 'example.com/iiif/12345', targetId: 'example.com/iiif/12345',
}, },
], ],
...@@ -166,6 +178,7 @@ describe('CanvasAnnotations', () => { ...@@ -166,6 +178,7 @@ describe('CanvasAnnotations', () => {
{ {
content: 'Annotation', content: 'Annotation',
id: 'annoId', id: 'annoId',
tags: [],
targetId: 'example.com/iiif/12345', targetId: 'example.com/iiif/12345',
}, },
], ],
......
...@@ -12,6 +12,33 @@ describe('AnnotationItem', () => { ...@@ -12,6 +12,33 @@ describe('AnnotationItem', () => {
}); });
}); });
describe('isOnlyTag', () => {
it('when the only motivation is tagging', () => {
expect(new AnnotationItem({ motivation: 'tagging' }).isOnlyTag())
.toBe(true);
});
it('when there are other motivations besides tagging', () => {
expect(new AnnotationItem({ motivation: ['commenting', 'tagging'] }).isOnlyTag())
.toBe(false);
});
});
describe('tags', () => {
it('when only motivation', () => {
expect(
new AnnotationItem({ body: [{ purpose: 'tagging', value: 'yo' }, { purpose: 'tagging', value: 'lo' }] }).tags,
).toEqual(['yo', 'lo']);
});
it('when multiple motivations', () => {
expect(
new AnnotationItem({
body: [{ purpose: 'commenting', value: 'yo' }, { purpose: 'tagging', value: 'lo' }],
motivation: ['commenting', 'tagging'],
}).tags,
).toEqual(['lo']);
});
});
describe('targetId', () => { describe('targetId', () => {
it('removes fragmentSelector coords from string targets', () => { it('removes fragmentSelector coords from string targets', () => {
expect( expect(
......
...@@ -12,6 +12,33 @@ describe('AnnotationResource', () => { ...@@ -12,6 +12,33 @@ describe('AnnotationResource', () => {
}); });
}); });
describe('isOnlyTag', () => {
it('when the only motivation is tagging', () => {
expect(new AnnotationResource({ motivation: 'oa:tagging' }).isOnlyTag())
.toBe(true);
});
it('when there are other motivations besides tagging', () => {
expect(new AnnotationResource({ motivation: ['oa:commenting', 'oa:tagging'] }).isOnlyTag())
.toBe(false);
});
});
describe('tags', () => {
it('when only motivation', () => {
expect(
new AnnotationResource({ resource: [{ '@type': 'oa:Tag', value: 'yo' }, { '@type': 'oa:Tag', value: 'lo' }] }).tags,
).toEqual(['yo', 'lo']);
});
it('when multiple motivations', () => {
expect(
new AnnotationResource({
motivation: ['oa:commenting', 'oa:tagging'],
resource: [{ '@type': 'oa:commenting', value: 'yo' }, { '@type': 'oa:Tag', value: 'lo' }],
}).tags,
).toEqual(['lo']);
});
});
describe('targetId', () => { describe('targetId', () => {
it('removes fragmentSelector coords from string targets', () => { it('removes fragmentSelector coords from string targets', () => {
expect( expect(
......
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Chip from '@material-ui/core/Chip';
import List from '@material-ui/core/List'; import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem'; import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText'; import ListItemText from '@material-ui/core/ListItemText';
...@@ -89,6 +90,13 @@ export class CanvasAnnotations extends Component { ...@@ -89,6 +90,13 @@ export class CanvasAnnotations extends Component {
ruleSet={htmlSanitizationRuleSet} ruleSet={htmlSanitizationRuleSet}
htmlString={annotation.content} htmlString={annotation.content}
/> />
<div>
{
annotation.tags.map(tag => (
<Chip size="small" variant="outlined" label={tag} id={tag} className={classes.chip} />
))
}
</div>
</ListItemText> </ListItemText>
</ListItem> </ListItem>
)) ))
......
...@@ -216,7 +216,7 @@ export default { ...@@ -216,7 +216,7 @@ export default {
}, },
annotations: { annotations: {
htmlSanitizationRuleSet: 'iiif', // See src/lib/htmlRules.js for acceptable values htmlSanitizationRuleSet: 'iiif', // See src/lib/htmlRules.js for acceptable values
filteredMotivations: ['oa:commenting', 'sc:painting', 'commenting'], filteredMotivations: ['oa:commenting', 'oa:tagging', 'sc:painting', 'commenting', 'tagging'],
}, },
classPrefix: 'mirador', classPrefix: 'mirador',
displayAllAnnotations: false, // Configure if annotations to be displayed on the canvas by default when fetched displayAllAnnotations: false, // Configure if annotations to be displayed on the canvas by default when fetched
......
...@@ -20,6 +20,7 @@ function getIdAndContentOfResources(resources) { ...@@ -20,6 +20,7 @@ function getIdAndContentOfResources(resources) {
return resources.map((resource, i) => ({ return resources.map((resource, i) => ({
content: resource.chars, content: resource.chars,
id: resource.id, id: resource.id,
tags: resource.tags,
targetId: resource.targetId, targetId: resource.targetId,
})); }));
} }
...@@ -60,6 +61,11 @@ const styles = theme => ({ ...@@ -60,6 +61,11 @@ const styles = theme => ({
borderBottom: `0.5px solid ${theme.palette.divider}`, borderBottom: `0.5px solid ${theme.palette.divider}`,
cursor: 'pointer', cursor: 'pointer',
}, },
chip: {
backgroundColor: theme.palette.background.paper,
marginRight: theme.spacing(0.5),
marginTop: theme.spacing(1),
},
sectionHeading: { sectionHeading: {
paddingLeft: theme.spacing(2), paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(1), paddingRight: theme.spacing(1),
......
...@@ -11,6 +11,11 @@ export default class AnnotationItem { ...@@ -11,6 +11,11 @@ export default class AnnotationItem {
this.resource = resource; this.resource = resource;
} }
/** */
isOnlyTag() {
return (this.motivations.length === 1 && this.motivations[0] === 'tagging');
}
/** */ /** */
get id() { get id() {
this._id = this._id || this.resource.id || uuid(); // eslint-disable-line no-underscore-dangle this._id = this._id || this.resource.id || uuid(); // eslint-disable-line no-underscore-dangle
...@@ -47,6 +52,14 @@ export default class AnnotationItem { ...@@ -47,6 +52,14 @@ export default class AnnotationItem {
return this.body; return this.body;
} }
/** */
get tags() {
if (this.isOnlyTag()) {
return this.body.map(r => r.value);
}
return this.body.filter(r => r.purpose === 'tagging').map(r => r.value);
}
/** */ /** */
get target() { get target() {
return flatten(compact(new Array(this.resource.target))); return flatten(compact(new Array(this.resource.target)));
...@@ -54,7 +67,8 @@ export default class AnnotationItem { ...@@ -54,7 +67,8 @@ export default class AnnotationItem {
/** */ /** */
get chars() { get chars() {
return this.body.map(r => r.value).join(' '); if (this.isOnlyTag()) return null;
return this.body.filter(r => r.purpose !== 'tagging').map(r => r.value).join(' ');
} }
/** */ /** */
......
...@@ -9,6 +9,11 @@ export default class AnnotationResource { ...@@ -9,6 +9,11 @@ export default class AnnotationResource {
this.resource = resource; this.resource = resource;
} }
/** */
isOnlyTag() {
return (this.motivations.length === 1 && this.motivations[0] === 'oa:tagging');
}
/** */ /** */
get id() { get id() {
this._id = this._id || this.resource['@id'] || uuid(); // eslint-disable-line no-underscore-dangle this._id = this._id || this.resource['@id'] || uuid(); // eslint-disable-line no-underscore-dangle
...@@ -45,9 +50,17 @@ export default class AnnotationResource { ...@@ -45,9 +50,17 @@ export default class AnnotationResource {
return flatten(compact(new Array(this.resource.on))); return flatten(compact(new Array(this.resource.on)));
} }
/** */
get tags() {
if (this.isOnlyTag()) {
return this.resources.map(r => r.value);
}
return this.resources.filter(r => r['@type'] === 'oa:Tag').map(r => r.value);
}
/** */ /** */
get chars() { get chars() {
return this.resources.map(r => r.chars).join(' '); return this.resources.filter(r => r['@type'] !== 'oa:Tag').map(r => r.chars).join(' ');
} }
/** */ /** */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment