Skip to content
Snippets Groups Projects
Unverified Commit a5d4684b authored by aeschylus's avatar aeschylus Committed by GitHub
Browse files

Merge pull request #1990 from ProjectMirador/1772-blank-canvases

Fix error in manifests that have a canvas w/o images
parents 0df96829 926d8141
Branches
Tags
No related merge requests found
This diff is collapsed.
......@@ -5,13 +5,14 @@ import { WindowViewer } from '../../../src/components/WindowViewer';
import OSDViewer from '../../../src/containers/OpenSeadragonViewer';
import ViewerNavigation from '../../../src/containers/ViewerNavigation';
import fixture from '../../fixtures/version-2/019.json';
import emptyCanvasFixture from '../../fixtures/version-2/emptyCanvas.json';
const mockManifest = {
let mockManifest = {
id: 123,
manifestation: manifesto.create(fixture),
};
const mockWindow = {
let mockWindow = {
canvasIndex: 0,
view: 'single',
};
......@@ -121,4 +122,53 @@ describe('WindowViewer', () => {
});
expect(wrapper.instance().canvasGroupings.groupings().length).toEqual(2);
});
describe('componentDidMount', () => {
it('does not call fetchInfoResponse for a canvas that has no images', () => {
const mockFnCanvas0 = jest.fn();
const mockFnCanvas2 = jest.fn();
mockManifest = {
id: 123,
manifestation: manifesto.create(emptyCanvasFixture),
};
mockWindow = {
canvasIndex: 0,
view: 'single',
};
wrapper = createWrapper(
{ manifest: mockManifest, fetchInfoResponse: mockFnCanvas0, window: mockWindow },
);
expect(mockFnCanvas0).toHaveBeenCalledTimes(1);
wrapper = createWrapper(
{
manifest: mockManifest,
fetchInfoResponse: mockFnCanvas2,
window: { canvasIndex: 2, view: 'single' },
},
);
expect(mockFnCanvas2).toHaveBeenCalledTimes(0);
});
});
describe('componentDidUpdate', () => {
it('does not call fetchInfoResponse for a canvas that has no images', () => {
const mockFn = jest.fn();
mockManifest = {
id: 123,
manifestation: manifesto.create(emptyCanvasFixture),
};
mockWindow = {
canvasIndex: 2,
view: 'single',
};
wrapper = createWrapper(
{ manifest: mockManifest, fetchInfoResponse: mockFn, window: mockWindow },
);
wrapper.setProps({ window: { canvasIndex: 3, view: 'single' } });
expect(mockFn).toHaveBeenCalledTimes(0);
});
});
});
......@@ -2,6 +2,7 @@ import manifesto from 'manifesto.js';
import ManifestoCanvas from '../../../src/lib/ManifestoCanvas';
import fixture from '../../fixtures/version-2/019.json';
import imagev1Fixture from '../../fixtures/version-2/Osbornfa1.json';
import emptyCanvasFixture from '../../fixtures/version-2/emptyCanvas.json';
describe('ManifestoCanvas', () => {
let instance;
......@@ -27,6 +28,14 @@ describe('ManifestoCanvas', () => {
);
expect(imagev1Instance.imageInformationUri).toEqual('https://images.britishart.yale.edu/iiif/b38081da-8991-4464-a71e-d9891226a35f/info.json');
});
it('is undefined if a canvas is empty (e.g. has no images)', () => {
const emptyCanvasInstance = new ManifestoCanvas(
manifesto.create(emptyCanvasFixture).getSequences()[0].getCanvases()[3],
);
expect(emptyCanvasInstance.imageInformationUri).toBeUndefined();
});
});
describe('aspectRatio', () => {
it('calculates a width / height aspectRatio', () => {
......@@ -44,5 +53,13 @@ describe('ManifestoCanvas', () => {
'https://stacks.stanford.edu/image/iiif/hg676jb4964%2F0380_796-44/full/100,/0/default.jpg',
);
});
it('returns undefined if there are no images to generate a thumbnail from', () => {
const emptyCanvasInstance = new ManifestoCanvas(
manifesto.create(emptyCanvasFixture).getSequences()[0].getCanvases()[3],
);
expect(emptyCanvasInstance.thumbnail()).toBeUndefined();
});
});
});
......@@ -22,7 +22,7 @@ export class CanvasThumbnail extends Component {
handleIntersection(event) {
const { imageUrl } = this.props;
const { loaded } = this.state;
if (loaded || !event.isIntersecting) return;
if (loaded || !event.isIntersecting || !imageUrl) return;
const image = new Image();
image.src = imageUrl;
this.setState({
......@@ -32,13 +32,37 @@ export class CanvasThumbnail extends Component {
}
/**
* Return a the image URL if it is loaded and valid, otherwise return a placeholder
*/
render() {
const {
height, isValid, onClick, style,
} = this.props;
imageSrc() {
const { isValid } = this.props;
const { loaded, image } = this.state;
const imgStyle = { height, width: '100%', ...style };
if (loaded && isValid && image && image.src) {
return image.src;
}
return CanvasThumbnail.defaultImgPlaceholder;
}
/**
*
*/
imageStyles() {
const { height, style } = this.props;
const { image } = this.state;
return {
height,
width: (image && image.src) ? '100%' : '110px',
...style,
};
}
/**
*/
render() {
const { onClick } = this.props;
return (
<>
<IntersectionObserver onChange={this.handleIntersection}>
......@@ -47,8 +71,8 @@ export class CanvasThumbnail extends Component {
onClick={onClick}
onKeyPress={onClick}
role="presentation"
src={loaded && isValid ? image.src : CanvasThumbnail.defaultImgPlaceholder}
style={imgStyle}
src={this.imageSrc()}
style={this.imageStyles()}
/>
</IntersectionObserver>
</>
......
......@@ -30,7 +30,10 @@ export class WindowViewer extends Component {
if (!this.infoResponseIsInStore()) {
this.currentCanvases().forEach((canvas) => {
fetchInfoResponse(new ManifestoCanvas(canvas).imageInformationUri);
const { imageInformationUri } = new ManifestoCanvas(canvas);
if (imageInformationUri) {
fetchInfoResponse(imageInformationUri);
}
});
}
}
......@@ -45,7 +48,10 @@ export class WindowViewer extends Component {
|| (prevProps.window.canvasIndex !== window.canvasIndex && !this.infoResponseIsInStore())
) {
this.currentCanvases().forEach((canvas) => {
fetchInfoResponse(new ManifestoCanvas(canvas).imageInformationUri);
const { imageInformationUri } = new ManifestoCanvas(canvas);
if (imageInformationUri) {
fetchInfoResponse(imageInformationUri);
}
});
}
// If the view changes, create a new instance
......
......@@ -25,6 +25,15 @@ export default class ManifestoCanvas {
/**
*/
get imageInformationUri() {
if (!(
this.canvas.getImages()[0]
&& this.canvas.getImages()[0].getResource()
&& this.canvas.getImages()[0].getResource().getServices()[0]
&& this.canvas.getImages()[0].getResource().getServices()[0].id
)) {
return undefined;
}
return `${
this.canvas.getImages()[0].getResource().getServices()[0].id.replace(/\/$/, '')
}/info.json`;
......@@ -36,6 +45,11 @@ export default class ManifestoCanvas {
*/
thumbnail(height = 150) {
const width = Math.floor(height * this.aspectRatio);
if (!this.imageInformationUri) {
return undefined;
}
return this.canonicalImageUri.replace(/\/full\/.*\/0\//, `/full/${width},/0/`);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment