Skip to content

Commit 8dae6b6

Browse files
lutzhelmcbeer
authored andcommitted
Fix #3522, add selector and UI for related
1 parent 5bb2cb1 commit 8dae6b6

File tree

8 files changed

+186
-14
lines changed

8 files changed

+186
-14
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"@context": "http://iiif.io/api/presentation/2/context.json",
3+
"@id": "http://example.com/iiif/manifest/related-urls.json",
4+
"@type": "sc:Manifest",
5+
"related": [
6+
"http://example.com/related1",
7+
{
8+
"@id": "http://example.com/related2"
9+
},
10+
{
11+
"@id": "http://example.com/related3",
12+
"format": "text/html",
13+
"label": "Something related"
14+
}
15+
]
16+
}

__tests__/src/components/ManifestRelatedLinks.test.js

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ describe('ManifestRelatedLinks', () => {
2121
},
2222
]}
2323
manifestUrl="http://example.com/"
24+
related={[
25+
{
26+
value: 'http://example.com/related',
27+
},
28+
{
29+
format: 'video/ogg',
30+
label: 'Video',
31+
value: 'http://example.com/video',
32+
},
33+
]}
2434
renderings={[
2535
{
2636
label: 'PDF Version',
@@ -81,16 +91,42 @@ describe('ManifestRelatedLinks', () => {
8191
).toBe(true);
8292
});
8393

84-
it('renders manifest seeAlso information', () => {
94+
it('renders related information', () => {
8595
expect(
8696
wrapper.find(Typography).at(5)
8797
.matchesElement(
88-
<Typography component="dt">iiif_seeAlso</Typography>,
98+
<Typography component="dt">iiif_related</Typography>,
8999
),
90100
).toBe(true);
91101

92102
expect(
93103
wrapper.find(Typography).at(6)
104+
.matchesElement(
105+
<Typography component="dd"><Link href="http://example.com/related">http://example.com/related</Link></Typography>,
106+
),
107+
).toBe(true);
108+
109+
expect(
110+
wrapper.find(Typography).at(7)
111+
.matchesElement(
112+
<Typography component="dd">
113+
<Link href="http://example.com/video">Video</Link>
114+
<Typography>(video/ogg)</Typography>
115+
</Typography>,
116+
),
117+
).toBe(true);
118+
});
119+
120+
it('renders manifest seeAlso information', () => {
121+
expect(
122+
wrapper.find(Typography).at(9)
123+
.matchesElement(
124+
<Typography component="dt">iiif_seeAlso</Typography>,
125+
),
126+
).toBe(true);
127+
128+
expect(
129+
wrapper.find(Typography).at(10)
94130
.matchesElement(
95131
<Typography component="dd">
96132
<Link href="http://example.com/a">A</Link>
@@ -100,7 +136,7 @@ describe('ManifestRelatedLinks', () => {
100136
).toBe(true);
101137

102138
expect(
103-
wrapper.find(Typography).at(8)
139+
wrapper.find(Typography).at(12)
104140
.matchesElement(
105141
<Typography component="dd"><Link href="http://example.com/b">http://example.com/b</Link></Typography>,
106142
),
@@ -109,14 +145,14 @@ describe('ManifestRelatedLinks', () => {
109145

110146
it('renders manifest links', () => {
111147
expect(
112-
wrapper.find(Typography).at(9)
148+
wrapper.find(Typography).at(13)
113149
.matchesElement(
114150
<Typography component="dt">iiif_manifest</Typography>,
115151
),
116152
).toBe(true);
117153

118154
expect(
119-
wrapper.find(Typography).at(10)
155+
wrapper.find(Typography).at(14)
120156
.matchesElement(
121157
<Typography component="dd"><Link href="http://example.com/">http://example.com/</Link></Typography>,
122158
),

__tests__/src/selectors/manifests.test.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import manifestFixtureSn904cj3429 from '../../fixtures/version-2/sn904cj3429.jso
66
import manifestFixturev3001 from '../../fixtures/version-3/001.json';
77
import manifestFixtureWithAProvider from '../../fixtures/version-3/with_a_provider.json';
88
import manifestFixtureFg165hz3589 from '../../fixtures/version-2/fg165hz3589.json';
9+
import manifestFixtureRelated from '../../fixtures/version-2/related.json';
910
import {
1011
getManifestoInstance,
1112
getManifestLocale,
@@ -18,8 +19,10 @@ import {
1819
getManifestTitle,
1920
getManifestThumbnail,
2021
getManifestMetadata,
22+
getManifestRelated,
2123
getManifestRelatedContent,
2224
getManifestRenderings,
25+
getManifestSeeAlso,
2326
getManifestUrl,
2427
getMetadataLocales,
2528
getRequiredStatement,
@@ -210,6 +213,33 @@ describe('getManifestRenderings', () => {
210213
});
211214
});
212215

216+
describe('getManifestRelated', () => {
217+
it('should return manifest related', () => {
218+
const state = { manifests: { x: { json: manifestFixtureRelated } } };
219+
const received = getManifestRelated(state, { manifestId: 'x' });
220+
expect(received).toEqual([
221+
{
222+
value: 'http://example.com/related1',
223+
},
224+
{
225+
format: undefined,
226+
label: null,
227+
value: 'http://example.com/related2',
228+
},
229+
{
230+
format: 'text/html',
231+
label: 'Something related',
232+
value: 'http://example.com/related3',
233+
},
234+
]);
235+
});
236+
237+
it('should return undefined if manifest undefined', () => {
238+
const received = getManifestRelated({ manifests: {} }, { manifestId: 'x' });
239+
expect(received).toBeUndefined();
240+
});
241+
});
242+
213243
describe('getManifestRelatedContent', () => {
214244
it('should return manifest seeAlso content', () => {
215245
const state = { manifests: { x: { json: manifestFixtureSn904cj3429 } } };
@@ -229,6 +259,25 @@ describe('getManifestRelatedContent', () => {
229259
});
230260
});
231261

262+
describe('getManifestSeeAlso', () => {
263+
it('should return manifest seeAlso content', () => {
264+
const state = { manifests: { x: { json: manifestFixtureSn904cj3429 } } };
265+
const received = getManifestSeeAlso(state, { manifestId: 'x' });
266+
expect(received).toEqual([
267+
{
268+
format: 'application/mods+xml',
269+
label: null,
270+
value: 'https://purl.stanford.edu/sn904cj3429.mods',
271+
},
272+
]);
273+
});
274+
275+
it('should return undefined if manifest undefined', () => {
276+
const received = getManifestSeeAlso({ manifests: {} }, { manifestId: 'x' });
277+
expect(received).toBeUndefined();
278+
});
279+
});
280+
232281
describe('getManifestUrl', () => {
233282
it('should return manifest url', () => {
234283
const state = { manifests: { x: { json: manifestFixtureWithAProvider } } };

src/components/ManifestRelatedLinks.js

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export class ManifestRelatedLinks extends Component {
2020
classes,
2121
homepage,
2222
manifestUrl,
23+
related,
2324
renderings,
2425
seeAlso,
2526
id,
@@ -68,17 +69,34 @@ export class ManifestRelatedLinks extends Component {
6869
}
6970
</>
7071
)}
72+
{ related && (
73+
<>
74+
<Typography variant="subtitle2" component="dt">{t('iiif_related')}</Typography>
75+
{
76+
related.map(relatedItem => (
77+
<Typography key={relatedItem.value} variant="body1" component="dd">
78+
<Link target="_blank" rel="noopener noreferrer" href={relatedItem.value}>
79+
{relatedItem.label || relatedItem.value}
80+
</Link>
81+
{ relatedItem.format && (
82+
<Typography component="span">{` (${relatedItem.format})`}</Typography>
83+
)}
84+
</Typography>
85+
))
86+
}
87+
</>
88+
)}
7189
{ seeAlso && (
7290
<>
7391
<Typography variant="subtitle2" component="dt">{t('iiif_seeAlso')}</Typography>
7492
{
75-
seeAlso.map(related => (
76-
<Typography key={related.value} variant="body1" component="dd">
77-
<Link target="_blank" rel="noopener noreferrer" href={related.value}>
78-
{related.label || related.value}
93+
seeAlso.map(seeAlsoItem => (
94+
<Typography key={seeAlsoItem.value} variant="body1" component="dd">
95+
<Link target="_blank" rel="noopener noreferrer" href={seeAlsoItem.value}>
96+
{seeAlsoItem.label || seeAlsoItem.value}
7997
</Link>
80-
{ related.format && (
81-
<Typography component="span">{` (${related.format})`}</Typography>
98+
{ seeAlsoItem.format && (
99+
<Typography component="span">{` (${seeAlsoItem.format})`}</Typography>
82100
)}
83101
</Typography>
84102
))
@@ -110,6 +128,11 @@ ManifestRelatedLinks.propTypes = {
110128
})),
111129
id: PropTypes.string.isRequired,
112130
manifestUrl: PropTypes.string,
131+
related: PropTypes.arrayOf(PropTypes.shape({
132+
format: PropTypes.string,
133+
label: PropTypes.string,
134+
value: PropTypes.string,
135+
})),
113136
renderings: PropTypes.arrayOf(PropTypes.shape({
114137
label: PropTypes.string,
115138
value: PropTypes.string,
@@ -125,6 +148,7 @@ ManifestRelatedLinks.propTypes = {
125148
ManifestRelatedLinks.defaultProps = {
126149
homepage: null,
127150
manifestUrl: null,
151+
related: null,
128152
renderings: null,
129153
seeAlso: null,
130154
t: key => key,

src/containers/ManifestRelatedLinks.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import { withStyles } from '@material-ui/core/styles';
55
import { withPlugins } from '../extend/withPlugins';
66
import {
77
getManifestHomepage,
8-
getManifestRelatedContent,
8+
getManifestRelated,
99
getManifestRenderings,
10+
getManifestSeeAlso,
1011
getManifestUrl,
1112
} from '../state/selectors';
1213
import { ManifestRelatedLinks } from '../components/ManifestRelatedLinks';
@@ -19,8 +20,9 @@ import { ManifestRelatedLinks } from '../components/ManifestRelatedLinks';
1920
const mapStateToProps = (state, { id, windowId }) => ({
2021
homepage: getManifestHomepage(state, { windowId }),
2122
manifestUrl: getManifestUrl(state, { windowId }),
23+
related: getManifestRelated(state, { windowId }),
2224
renderings: getManifestRenderings(state, { windowId }),
23-
seeAlso: getManifestRelatedContent(state, { windowId }),
25+
seeAlso: getManifestSeeAlso(state, { windowId }),
2426
});
2527

2628
const styles = {

src/locales/de/translation.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
"hideZoomControls": "Zoomsteuerung verbergen",
5858
"iiif_homepage": "Über diese Ressource",
5959
"iiif_manifest": "IIIF-Manifest",
60+
"iiif_related": "Verwandtes",
6061
"iiif_renderings": "Alternative Formate",
6162
"iiif_seeAlso": "Siehe auch",
6263
"import" : "Importieren",

src/locales/en/translation.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
"hideZoomControls": "Hide zoom controls",
6060
"iiif_homepage": "About this resource",
6161
"iiif_manifest": "IIIF manifest",
62+
"iiif_related": "Related",
6263
"iiif_renderings": "Alternate formats",
6364
"iiif_seeAlso": "See also",
6465
"import" : "Import",

src/state/selectors/manifests.js

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,13 +153,14 @@ export const getManifestRenderings = createSelector(
153153

154154
/**
155155
* Return the IIIF v2/v3 seeAlso data from a manifest or null
156+
*
156157
* @param {object} state
157158
* @param {object} props
158159
* @param {string} props.manifestId
159160
* @param {string} props.windowId
160161
* @return {String|null}
161162
*/
162-
export const getManifestRelatedContent = createSelector(
163+
export const getManifestSeeAlso = createSelector(
163164
[
164165
getProperty('seeAlso'),
165166
getManifestLocale,
@@ -175,6 +176,48 @@ export const getManifestRelatedContent = createSelector(
175176
)),
176177
);
177178

179+
/**
180+
* Return the IIIF v2/v3 seeAlso data from a manifest or null
181+
*
182+
* @param {object} state
183+
* @param {object} props
184+
* @param {string} props.manifestId
185+
* @param {string} props.windowId
186+
* @return {String|null}
187+
* @deprecated This does not actually return the content of "related" and
188+
* might be removed in a future version.
189+
* @see getManifestSeeAlso
190+
*/
191+
export const getManifestRelatedContent = getManifestSeeAlso;
192+
193+
/**
194+
* Return the IIIF v2 realated links manifest or null
195+
* @param {object} state
196+
* @param {object} props
197+
* @param {string} props.manifestId
198+
* @param {string} props.windowId
199+
* @return {String|null}
200+
*/
201+
export const getManifestRelated = createSelector(
202+
[
203+
getProperty('related'),
204+
getManifestLocale,
205+
],
206+
(relatedLinks, locale) => relatedLinks
207+
&& asArray(relatedLinks).map(related => (
208+
typeof related === 'string'
209+
? {
210+
value: related,
211+
}
212+
: {
213+
format: related.format,
214+
label: PropertyValue.parse(related.label, locale)
215+
.getValue(),
216+
value: related.id || related['@id'],
217+
}
218+
)),
219+
);
220+
178221
/**
179222
* Return the IIIF requiredStatement (v3) or attribution (v2) data from a manifest or null
180223
* @param {object} state

0 commit comments

Comments
 (0)