Skip to content

Commit efc99f3

Browse files
committed
Extract IIIFResourceLabel component for rendering the contextually appropriate label for a IIIF resource.
1 parent bf66306 commit efc99f3

10 files changed

Lines changed: 50 additions & 60 deletions

__tests__/src/components/GalleryViewThumbnail.test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ describe('GalleryView', () => {
7373
describe('on-demand annotation fetching', () => {
7474
const canvas = {
7575
getHeight: () => 50,
76+
getLabel: () => ({ getValue: () => 'label' }),
7677
getServices: vi.fn(),
7778
getThumbnail: vi.fn(),
7879
getType: vi.fn(),

__tests__/src/components/WindowSideBarCanvasPanel.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ function createWrapper(props) {
1313
let sequences;
1414

1515
if (props.multipleSequences) {
16-
sequences = [{ id: 'a', label: 'seq1' },
17-
{ id: 'b', label: 'seq2' }];
16+
sequences = [{ getLabel: () => ({ getValue: () => undefined }), id: 'a', label: 'seq1' },
17+
{ getLabel: () => ({ getValue: () => undefined }), id: 'b', label: 'seq2' }];
1818
} else {
1919
sequences = Utils.parseManifest(manifestJson).getSequences();
2020
}

src/components/CanvasLayers.js

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { useTranslation } from 'react-i18next';
1717
import { DragDropContext, Droppable, Draggable } from '@hello-pangea/dnd';
1818
import MiradorMenuButton from '../containers/MiradorMenuButton';
1919
import IIIFThumbnail from '../containers/IIIFThumbnail';
20+
import { IIIFResourceLabel } from './IIIFResourceLabel';
2021

2122
const StyledDragHandle = styled('div')(({ theme }) => ({
2223
alignItems: 'center',
@@ -40,15 +41,6 @@ const reorder = (list, startIndex, endIndex) => {
4041
return result;
4142
};
4243

43-
/** */
44-
function getUseableLabel(resource, index) {
45-
return (resource
46-
&& resource.getLabel
47-
&& resource.getLabel().length > 0)
48-
? resource.getLabel().getValue()
49-
: String(index + 1);
50-
}
51-
5244
/** @private */
5345
function Layer({
5446
resource, layerMetadata = {}, index, handleOpacityChange, setLayerVisibility, moveToTop,
@@ -78,7 +70,7 @@ function Layer({
7870
component="div"
7971
variant="body1"
8072
>
81-
{getUseableLabel(resource, index)}
73+
<IIIFResourceLabel resource={resource} fallback={index + 1} />
8274
<div>
8375
<MiradorMenuButton aria-label={t(layer.visibility ? 'layer_hide' : 'layer_show')} edge="start" size="small" onClick={() => { setLayerVisibility(resource.id, !layer.visibility); }}>
8476
{ layer.visibility ? <VisibilityIcon /> : <VisibilityOffIcon /> }

src/components/CollectionDialog.js

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import CollapsibleSection from '../containers/CollapsibleSection';
2121
import ScrollIndicatedDialogContent from '../containers/ScrollIndicatedDialogContent';
2222
import ManifestInfo from '../containers/ManifestInfo';
2323
import WorkspaceContext from '../contexts/WorkspaceContext';
24+
import { IIIFResourceLabel } from './IIIFResourceLabel';
2425

2526
const StyledScrollIndicatedDialogContent = styled(ScrollIndicatedDialogContent)(() => ({
2627
padding: (theme) => theme.spacing(1),
@@ -38,15 +39,6 @@ const StyledCollectionFilter = styled('div')(() => ({
3839
paddingTop: 0,
3940
}));
4041

41-
/** */
42-
function getUseableLabel(resource, index) {
43-
return (resource
44-
&& resource.getLabel
45-
&& resource.getLabel().length > 0)
46-
? resource.getLabel().getValue()
47-
: String(index + 1);
48-
}
49-
5042
/** */
5143
const Placeholder = ({ onClose, container }) => (
5244
<Dialog
@@ -149,7 +141,7 @@ export function CollectionDialog({
149141
{ t(isMultipart ? 'multipartCollection' : 'collection') }
150142
</Typography>
151143
<Typography component="div" variant="h3">
152-
{getUseableLabel(manifest)}
144+
<IIIFResourceLabel resource={manifest} />
153145
</Typography>
154146
</DialogTitle>
155147
<StyledScrollIndicatedDialogContent>
@@ -158,7 +150,7 @@ export function CollectionDialog({
158150
startIcon={<ArrowBackIcon />}
159151
onClick={() => goToPreviousCollection()}
160152
>
161-
{getUseableLabel(collection)}
153+
<IIIFResourceLabel resource={collection} />
162154
</Button>
163155
)}
164156

@@ -204,7 +196,7 @@ export function CollectionDialog({
204196
onClick={() => { selectCollection(c); }}
205197
variant="multiline"
206198
>
207-
{getUseableLabel(c)}
199+
<IIIFResourceLabel resource={c} />
208200
</MenuItem>
209201
))
210202
}
@@ -219,7 +211,7 @@ export function CollectionDialog({
219211
onClick={() => { selectManifest(m); }}
220212
variant="multiline"
221213
>
222-
{getUseableLabel(m)}
214+
<IIIFResourceLabel resource={m} />
223215
</MenuItem>
224216
))
225217
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { useContext } from 'react';
2+
import { useSelector } from 'react-redux';
3+
import PropTypes from 'prop-types';
4+
import {
5+
getLocale,
6+
} from '../state/selectors';
7+
import LocaleContext from '../contexts/LocaleContext';
8+
9+
/**
10+
* Render the contextually appropriate label for the resource
11+
*/
12+
export function IIIFResourceLabel({ fallback, resource }) {
13+
const contextLocale = useContext(LocaleContext);
14+
const fallbackLocale = useSelector(state => getLocale(state, {}));
15+
16+
if (!resource) return fallback;
17+
18+
const label = resource.getLabel();
19+
20+
if (!label) return fallback;
21+
22+
return label.getValue(contextLocale || fallbackLocale || '') ?? (fallback || resource.id);
23+
}
24+
25+
IIIFResourceLabel.propTypes = {
26+
fallback: PropTypes.string,
27+
resource: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
28+
};

src/components/IIIFThumbnail.js

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import PropTypes from 'prop-types';
55
import { styled } from '@mui/material/styles';
66
import { useInView } from 'react-intersection-observer';
77
import getThumbnail from '../lib/ThumbnailFactory';
8+
import { IIIFResourceLabel } from './IIIFResourceLabel';
89

910
const Root = styled('div', { name: 'IIIFThumbnail', slot: 'root' })({});
1011

@@ -129,14 +130,6 @@ LazyLoadedImage.propTypes = {
129130
}),
130131
thumbnailsConfig: PropTypes.object, // eslint-disable-line react/forbid-prop-types
131132
};
132-
/** */
133-
function getUseableLabel(resource, index) {
134-
return (resource
135-
&& resource.getLabel
136-
&& resource.getLabel().length > 0)
137-
? resource.getLabel().getValue()
138-
: String(index + 1);
139-
}
140133

141134
const defaultPlaceholder = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mMMDQmtBwADgwF/Op8FmAAAAABJRU5ErkJggg==';
142135

@@ -173,7 +166,7 @@ export function IIIFThumbnail({
173166

174167
{ labelled && (
175168
<Label ownerState={ownerState}>
176-
{label || getUseableLabel(resource)}
169+
{label || <IIIFResourceLabel resource={resource} />}
177170
</Label>
178171
)}
179172
{children}

src/components/WindowSideBarCanvasPanel.js

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,13 @@ import { useTranslation } from 'react-i18next';
1717
import CompanionWindow from '../containers/CompanionWindow';
1818
import SidebarIndexList from '../containers/SidebarIndexList';
1919
import SidebarIndexTableOfContents from '../containers/SidebarIndexTableOfContents';
20+
import { IIIFResourceLabel } from './IIIFResourceLabel';
2021

2122
const StyledBreak = styled('div')(() => ({
2223
flexBasis: '100%',
2324
height: 0,
2425
}));
2526

26-
/** */
27-
function getUseableLabel(resource, index) {
28-
return (resource
29-
&& resource.getLabel
30-
&& resource.getLabel().length > 0)
31-
? resource.getLabel().getValue()
32-
: resource.id;
33-
}
34-
3527
/**
3628
* a panel showing the canvases for a given manifest
3729
*/
@@ -113,7 +105,7 @@ export function WindowSideBarCanvasPanel({
113105
}}
114106
data-testid="sequence-select"
115107
>
116-
{ sequences.map((s, i) => <MenuItem value={s.id} key={s.id}><Typography variant="body2">{ getUseableLabel(s, i) }</Typography></MenuItem>) }
108+
{ sequences.map((s, i) => <MenuItem value={s.id} key={s.id}><Typography variant="body2"><IIIFResourceLabel resource={s} /></Typography></MenuItem>) }
117109
</Select>
118110
</FormControl>
119111
)
@@ -143,7 +135,7 @@ export function WindowSideBarCanvasPanel({
143135
endIcon={<ArrowForwardIcon />}
144136
>
145137
<Typography sx={{ textTransform: 'none' }}>
146-
{getUseableLabel(collection)}
138+
<IIIFResourceLabel resource={collection} />
147139
</Typography>
148140
</Button>
149141
)}

src/components/WindowSideBarCollectionPanel.js

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,7 @@ import ArrowUpwardIcon from '@mui/icons-material/ArrowUpwardSharp';
1111
import { useTranslation } from 'react-i18next';
1212
import CompanionWindow from '../containers/CompanionWindow';
1313
import IIIFThumbnail from '../containers/IIIFThumbnail';
14-
15-
/** */
16-
function getUseableLabel(resource, index) {
17-
return (resource
18-
&& resource.getLabel
19-
&& resource.getLabel().length > 0)
20-
? resource.getLabel().getValue()
21-
: resource.id;
22-
}
14+
import { IIIFResourceLabel } from './IIIFResourceLabel';
2315

2416
/** */
2517
function Item({
@@ -46,7 +38,7 @@ function Item({
4638
/>
4739
</ListItemIcon>
4840
)}
49-
<ListItemText>{getUseableLabel(manifest)}</ListItemText>
41+
<ListItemText><IIIFResourceLabel resource={manifest} /></ListItemText>
5042
</MenuItem>
5143
);
5244
}
@@ -105,13 +97,13 @@ export function WindowSideBarCollectionPanel({
10597
<ArrowUpwardIcon />
10698
</ListItemIcon>
10799
<ListItemText primaryTypographyProps={{ variant: 'body1' }}>
108-
{getUseableLabel(parentCollection)}
100+
<IIIFResourceLabel resource={parentCollection} />
109101
</ListItemText>
110102
</ListItem>
111103
</List>
112104
)}
113105
<Typography variant="h6">
114-
{ collection && getUseableLabel(collection)}
106+
{ collection && <IIIFResourceLabel resource={collection} />}
115107
{ isFetching && <Skeleton variant="text" />}
116108
</Typography>
117109
</>

src/lib/MiradorCanvas.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,9 @@ export default class MiradorCanvas {
177177
/**
178178
* Get the canvas label
179179
*/
180-
getLabel() {
180+
getLabel(locale = undefined) {
181181
return this.canvas.getLabel().length > 0
182-
? this.canvas.getLabel().getValue()
182+
? this.canvas.getLabel().getValue(locale)
183183
: String(this.canvas.index + 1);
184184
}
185185
}

src/state/selectors/manifests.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ function createManifestoInstance(json, locale) {
2020
}
2121

2222
/** */
23-
const getLocale = createSelector(
23+
export const getLocale = createSelector(
2424
[
2525
getCompanionWindow,
2626
getConfig,

0 commit comments

Comments
 (0)