Skip to content

Commit

Permalink
Fix ProjectMirador#3522, add selector and UI for related
Browse files Browse the repository at this point in the history
  • Loading branch information
lutzhelm authored and morpheus-87 committed Nov 15, 2024
1 parent 8faddcc commit ce08348
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 14 deletions.
16 changes: 16 additions & 0 deletions __tests__/fixtures/version-2/related.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"@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"
}
]
}
46 changes: 41 additions & 5 deletions __tests__/src/components/ManifestRelatedLinks.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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>
Expand All @@ -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>,
),
Expand All @@ -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>,
),
Expand Down
49 changes: 49 additions & 0 deletions __tests__/src/selectors/manifests.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -18,8 +19,10 @@ import {
getManifestTitle,
getManifestThumbnail,
getManifestMetadata,
getManifestRelated,
getManifestRelatedContent,
getManifestRenderings,
getManifestSeeAlso,
getManifestUrl,
getMetadataLocales,
getRequiredStatement,
Expand Down Expand Up @@ -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 } } };
Expand All @@ -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 } } };
Expand Down
36 changes: 30 additions & 6 deletions src/components/ManifestRelatedLinks.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export class ManifestRelatedLinks extends Component {
classes,
homepage,
manifestUrl,
related,
renderings,
seeAlso,
id,
Expand Down Expand Up @@ -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>
))
Expand Down Expand Up @@ -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,
Expand All @@ -125,6 +148,7 @@ ManifestRelatedLinks.propTypes = {
ManifestRelatedLinks.defaultProps = {
homepage: null,
manifestUrl: null,
related: null,
renderings: null,
seeAlso: null,
t: key => key,
Expand Down
6 changes: 4 additions & 2 deletions src/containers/ManifestRelatedLinks.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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 = {
Expand Down
1 change: 1 addition & 0 deletions src/locales/de/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,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",
Expand Down
1 change: 1 addition & 0 deletions src/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,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",
Expand Down
45 changes: 44 additions & 1 deletion src/state/selectors/manifests.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand Down

0 comments on commit ce08348

Please sign in to comment.