-
Notifications
You must be signed in to change notification settings - Fork 255
/
WindowViewer.js
144 lines (127 loc) · 4.12 KB
/
WindowViewer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import OSDViewer from '../containers/OpenSeadragonViewer';
import WindowCanvasNavigationControls from '../containers/WindowCanvasNavigationControls';
import ManifestoCanvas from '../lib/ManifestoCanvas';
/**
* Represents a WindowViewer in the mirador workspace. Responsible for mounting
* OSD and Navigation
*/
export class WindowViewer extends Component {
/** */
constructor(props) {
super(props);
this.state = {};
}
/** */
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
/**
* componentDidMount - React lifecycle method
* Request the initial canvas on mount
*/
componentDidMount() {
const {
currentCanvases, fetchInfoResponse, fetchAnnotation, receiveAnnotation,
} = this.props;
if (!this.infoResponseIsInStore()) {
currentCanvases.forEach((canvas) => {
const manifestoCanvas = new ManifestoCanvas(canvas);
const { imageResource } = manifestoCanvas;
if (imageResource) {
fetchInfoResponse({ imageResource });
}
manifestoCanvas.processAnnotations(fetchAnnotation, receiveAnnotation);
});
}
}
/**
* componentDidUpdate - React lifecycle method
* Request a new canvas if it is needed
*/
componentDidUpdate(prevProps) {
const {
currentCanvasId, currentCanvases, view, fetchInfoResponse, fetchAnnotation, receiveAnnotation,
} = this.props;
if (prevProps.view !== view
|| (prevProps.currentCanvasId !== currentCanvasId && !this.infoResponseIsInStore())
) {
currentCanvases.forEach((canvas) => {
const manifestoCanvas = new ManifestoCanvas(canvas);
const { imageResource } = manifestoCanvas;
if (imageResource) {
fetchInfoResponse({ imageResource });
}
manifestoCanvas.processAnnotations(fetchAnnotation, receiveAnnotation);
});
}
}
/**
* infoResponseIsInStore - checks whether or not an info response is already
* in the store. No need to request it again.
* @return [Boolean]
*/
infoResponseIsInStore() {
const { currentCanvases } = this.props;
const responses = this.currentInfoResponses();
if (responses.length === currentCanvases.length) {
return true;
}
return false;
}
/**
* currentInfoResponses - Selects infoResponses that are relevent to existing
* canvases to be displayed.
*/
currentInfoResponses() {
const { currentCanvases, infoResponses } = this.props;
return currentCanvases.map(canvas => (
infoResponses[new ManifestoCanvas(canvas).imageId]
)).filter(infoResponse => (infoResponse !== undefined
&& infoResponse.isFetching === false
&& infoResponse.error === undefined));
}
/**
* Return an image information response from the store for the correct image
*/
tileInfoFetchedFromStore() {
const { currentCanvases } = this.props;
const responses = this.currentInfoResponses()
.map(infoResponse => infoResponse.json);
// Only return actual tileSources when all current canvases have completed.
if (responses.length === currentCanvases.length) {
return responses;
}
return [];
}
/**
* Renders things
*/
render() {
const { windowId } = this.props;
const { hasError } = this.state;
if (hasError) {
return <></>;
}
return (
<OSDViewer
tileSources={this.tileInfoFetchedFromStore()}
windowId={windowId}
>
<WindowCanvasNavigationControls key="canvas_nav" windowId={windowId} />
</OSDViewer>
);
}
}
WindowViewer.propTypes = {
currentCanvases: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
currentCanvasId: PropTypes.string.isRequired,
fetchAnnotation: PropTypes.func.isRequired,
fetchInfoResponse: PropTypes.func.isRequired,
infoResponses: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
receiveAnnotation: PropTypes.func.isRequired,
view: PropTypes.string.isRequired,
windowId: PropTypes.string.isRequired,
};