Skip to content
Snippets Groups Projects
Commit 8dae6b6e authored by Lutz Helm's avatar Lutz Helm Committed by Chris Beer
Browse files

Fix #3522, add selector and UI for related

parent 5bb2cb14
No related branches found
No related tags found
No related merge requests found
{
"@context": "http://iiif.io/api/presentation/2/context.json",
"@id": "http://example.com/iiif/manifest/related-urls.json",
"@type": "sc:Manifest",
"related": [
"http://example.com/related1",
{
"@id": "http://example.com/related2"
},
{
"@id": "http://example.com/related3",
"format": "text/html",
"label": "Something related"
}
]
}
......@@ -21,6 +21,16 @@ describe('ManifestRelatedLinks', () => {
},
]}
manifestUrl="http://example.com/"
related={[
{
value: 'http://example.com/related',
},
{
format: 'video/ogg',
label: 'Video',
value: 'http://example.com/video',
},
]}
renderings={[
{
label: 'PDF Version',
......@@ -81,16 +91,42 @@ describe('ManifestRelatedLinks', () => {
).toBe(true);
});
it('renders manifest seeAlso information', () => {
it('renders related information', () => {
expect(
wrapper.find(Typography).at(5)
.matchesElement(
<Typography component="dt">iiif_seeAlso</Typography>,
<Typography component="dt">iiif_related</Typography>,
),
).toBe(true);
expect(
wrapper.find(Typography).at(6)
.matchesElement(
<Typography component="dd"><Link href="http://example.com/related">http://example.com/related</Link></Typography>,
),
).toBe(true);
expect(
wrapper.find(Typography).at(7)
.matchesElement(
<Typography component="dd">
<Link href="http://example.com/video">Video</Link>
<Typography>(video/ogg)</Typography>
</Typography>,
),
).toBe(true);
});
it('renders manifest seeAlso information', () => {
expect(
wrapper.find(Typography).at(9)
.matchesElement(
<Typography component="dt">iiif_seeAlso</Typography>,
),
).toBe(true);
expect(
wrapper.find(Typography).at(10)
.matchesElement(
<Typography component="dd">
<Link href="http://example.com/a">A</Link>
......@@ -100,7 +136,7 @@ describe('ManifestRelatedLinks', () => {
).toBe(true);
expect(
wrapper.find(Typography).at(8)
wrapper.find(Typography).at(12)
.matchesElement(
<Typography component="dd"><Link href="http://example.com/b">http://example.com/b</Link></Typography>,
),
......@@ -109,14 +145,14 @@ describe('ManifestRelatedLinks', () => {
it('renders manifest links', () => {
expect(
wrapper.find(Typography).at(9)
wrapper.find(Typography).at(13)
.matchesElement(
<Typography component="dt">iiif_manifest</Typography>,
),
).toBe(true);
expect(
wrapper.find(Typography).at(10)
wrapper.find(Typography).at(14)
.matchesElement(
<Typography component="dd"><Link href="http://example.com/">http://example.com/</Link></Typography>,
),
......
......@@ -6,6 +6,7 @@ import manifestFixtureSn904cj3429 from '../../fixtures/version-2/sn904cj3429.jso
import manifestFixturev3001 from '../../fixtures/version-3/001.json';
import manifestFixtureWithAProvider from '../../fixtures/version-3/with_a_provider.json';
import manifestFixtureFg165hz3589 from '../../fixtures/version-2/fg165hz3589.json';
import manifestFixtureRelated from '../../fixtures/version-2/related.json';
import {
getManifestoInstance,
getManifestLocale,
......@@ -18,8 +19,10 @@ import {
getManifestTitle,
getManifestThumbnail,
getManifestMetadata,
getManifestRelated,
getManifestRelatedContent,
getManifestRenderings,
getManifestSeeAlso,
getManifestUrl,
getMetadataLocales,
getRequiredStatement,
......@@ -210,6 +213,33 @@ describe('getManifestRenderings', () => {
});
});
describe('getManifestRelated', () => {
it('should return manifest related', () => {
const state = { manifests: { x: { json: manifestFixtureRelated } } };
const received = getManifestRelated(state, { manifestId: 'x' });
expect(received).toEqual([
{
value: 'http://example.com/related1',
},
{
format: undefined,
label: null,
value: 'http://example.com/related2',
},
{
format: 'text/html',
label: 'Something related',
value: 'http://example.com/related3',
},
]);
});
it('should return undefined if manifest undefined', () => {
const received = getManifestRelated({ manifests: {} }, { manifestId: 'x' });
expect(received).toBeUndefined();
});
});
describe('getManifestRelatedContent', () => {
it('should return manifest seeAlso content', () => {
const state = { manifests: { x: { json: manifestFixtureSn904cj3429 } } };
......@@ -229,6 +259,25 @@ describe('getManifestRelatedContent', () => {
});
});
describe('getManifestSeeAlso', () => {
it('should return manifest seeAlso content', () => {
const state = { manifests: { x: { json: manifestFixtureSn904cj3429 } } };
const received = getManifestSeeAlso(state, { manifestId: 'x' });
expect(received).toEqual([
{
format: 'application/mods+xml',
label: null,
value: 'https://purl.stanford.edu/sn904cj3429.mods',
},
]);
});
it('should return undefined if manifest undefined', () => {
const received = getManifestSeeAlso({ manifests: {} }, { manifestId: 'x' });
expect(received).toBeUndefined();
});
});
describe('getManifestUrl', () => {
it('should return manifest url', () => {
const state = { manifests: { x: { json: manifestFixtureWithAProvider } } };
......
......@@ -20,6 +20,7 @@ export class ManifestRelatedLinks extends Component {
classes,
homepage,
manifestUrl,
related,
renderings,
seeAlso,
id,
......@@ -68,17 +69,34 @@ export class ManifestRelatedLinks extends Component {
}
</>
)}
{ related && (
<>
<Typography variant="subtitle2" component="dt">{t('iiif_related')}</Typography>
{
related.map(relatedItem => (
<Typography key={relatedItem.value} variant="body1" component="dd">
<Link target="_blank" rel="noopener noreferrer" href={relatedItem.value}>
{relatedItem.label || relatedItem.value}
</Link>
{ relatedItem.format && (
<Typography component="span">{` (${relatedItem.format})`}</Typography>
)}
</Typography>
))
}
</>
)}
{ seeAlso && (
<>
<Typography variant="subtitle2" component="dt">{t('iiif_seeAlso')}</Typography>
{
seeAlso.map(related => (
<Typography key={related.value} variant="body1" component="dd">
<Link target="_blank" rel="noopener noreferrer" href={related.value}>
{related.label || related.value}
seeAlso.map(seeAlsoItem => (
<Typography key={seeAlsoItem.value} variant="body1" component="dd">
<Link target="_blank" rel="noopener noreferrer" href={seeAlsoItem.value}>
{seeAlsoItem.label || seeAlsoItem.value}
</Link>
{ related.format && (
<Typography component="span">{` (${related.format})`}</Typography>
{ seeAlsoItem.format && (
<Typography component="span">{` (${seeAlsoItem.format})`}</Typography>
)}
</Typography>
))
......@@ -110,6 +128,11 @@ ManifestRelatedLinks.propTypes = {
})),
id: PropTypes.string.isRequired,
manifestUrl: PropTypes.string,
related: PropTypes.arrayOf(PropTypes.shape({
format: PropTypes.string,
label: PropTypes.string,
value: PropTypes.string,
})),
renderings: PropTypes.arrayOf(PropTypes.shape({
label: PropTypes.string,
value: PropTypes.string,
......@@ -125,6 +148,7 @@ ManifestRelatedLinks.propTypes = {
ManifestRelatedLinks.defaultProps = {
homepage: null,
manifestUrl: null,
related: null,
renderings: null,
seeAlso: null,
t: key => key,
......
......@@ -5,8 +5,9 @@ import { withStyles } from '@material-ui/core/styles';
import { withPlugins } from '../extend/withPlugins';
import {
getManifestHomepage,
getManifestRelatedContent,
getManifestRelated,
getManifestRenderings,
getManifestSeeAlso,
getManifestUrl,
} from '../state/selectors';
import { ManifestRelatedLinks } from '../components/ManifestRelatedLinks';
......@@ -19,8 +20,9 @@ import { ManifestRelatedLinks } from '../components/ManifestRelatedLinks';
const mapStateToProps = (state, { id, windowId }) => ({
homepage: getManifestHomepage(state, { windowId }),
manifestUrl: getManifestUrl(state, { windowId }),
related: getManifestRelated(state, { windowId }),
renderings: getManifestRenderings(state, { windowId }),
seeAlso: getManifestRelatedContent(state, { windowId }),
seeAlso: getManifestSeeAlso(state, { windowId }),
});
const styles = {
......
......@@ -57,6 +57,7 @@
"hideZoomControls": "Zoomsteuerung verbergen",
"iiif_homepage": "Über diese Ressource",
"iiif_manifest": "IIIF-Manifest",
"iiif_related": "Verwandtes",
"iiif_renderings": "Alternative Formate",
"iiif_seeAlso": "Siehe auch",
"import" : "Importieren",
......
......@@ -59,6 +59,7 @@
"hideZoomControls": "Hide zoom controls",
"iiif_homepage": "About this resource",
"iiif_manifest": "IIIF manifest",
"iiif_related": "Related",
"iiif_renderings": "Alternate formats",
"iiif_seeAlso": "See also",
"import" : "Import",
......
......@@ -153,13 +153,14 @@ export const getManifestRenderings = createSelector(
/**
* Return the IIIF v2/v3 seeAlso data from a manifest or null
*
* @param {object} state
* @param {object} props
* @param {string} props.manifestId
* @param {string} props.windowId
* @return {String|null}
*/
export const getManifestRelatedContent = createSelector(
export const getManifestSeeAlso = createSelector(
[
getProperty('seeAlso'),
getManifestLocale,
......@@ -175,6 +176,48 @@ export const getManifestRelatedContent = createSelector(
)),
);
/**
* Return the IIIF v2/v3 seeAlso data from a manifest or null
*
* @param {object} state
* @param {object} props
* @param {string} props.manifestId
* @param {string} props.windowId
* @return {String|null}
* @deprecated This does not actually return the content of "related" and
* might be removed in a future version.
* @see getManifestSeeAlso
*/
export const getManifestRelatedContent = getManifestSeeAlso;
/**
* Return the IIIF v2 realated links manifest or null
* @param {object} state
* @param {object} props
* @param {string} props.manifestId
* @param {string} props.windowId
* @return {String|null}
*/
export const getManifestRelated = createSelector(
[
getProperty('related'),
getManifestLocale,
],
(relatedLinks, locale) => relatedLinks
&& asArray(relatedLinks).map(related => (
typeof related === 'string'
? {
value: related,
}
: {
format: related.format,
label: PropertyValue.parse(related.label, locale)
.getValue(),
value: related.id || related['@id'],
}
)),
);
/**
* Return the IIIF requiredStatement (v3) or attribution (v2) data from a manifest or null
* @param {object} state
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment