Skip to content
Snippets Groups Projects
Verified Commit 73bff104 authored by Loïs Poujade's avatar Loïs Poujade
Browse files

Merge branch 'master' into 3-update-mirador

parents 2de71320 86443088
No related branches found
No related tags found
No related merge requests found
Showing
with 125 additions and 78 deletions
......@@ -8,9 +8,7 @@ export class WindowTopBarPluginArea extends Component {
/** */
render() {
return (
<>
<PluginHook {...this.props} />
</>
);
}
}
......@@ -49,7 +49,7 @@ export class WindowTopBarPluginMenu extends Component {
} = this.props;
const { anchorEl } = this.state;
if (!PluginComponents || PluginComponents.length === 0) return (<></>);
if (!PluginComponents || PluginComponents.length === 0) return null;
return (
<>
......
......@@ -4,6 +4,19 @@ import Typography from '@material-ui/core/Typography';
import Skeleton from '@material-ui/lab/Skeleton';
import ErrorIcon from '@material-ui/icons/ErrorOutlineSharp';
/** */
function TitleTypography({ children, ...props }) {
return (
<Typography variant="h2" noWrap color="inherit" {...props}>
{children}
</Typography>
);
}
TitleTypography.propTypes = {
children: PropTypes.node.isRequired,
};
/**
* WindowTopBarTitle
*/
......@@ -17,17 +30,10 @@ export class WindowTopBarTitle extends Component {
classes, error, hideWindowTitle, isFetching, manifestTitle,
} = this.props;
/** */
const TitleTypography = props => (
<Typography variant="h2" noWrap color="inherit" className={classes.title} {...props}>
{props.children}
</Typography>
);
let title = null;
if (isFetching) {
title = (
<TitleTypography>
<TitleTypography className={classes.title}>
<Skeleton variant="text" />
</TitleTypography>
);
......@@ -35,7 +41,7 @@ export class WindowTopBarTitle extends Component {
title = (
<>
<ErrorIcon color="error" />
<TitleTypography color="textSecondary">
<TitleTypography color="textSecondary" className={classes.title}>
{error}
</TitleTypography>
</>
......@@ -44,7 +50,7 @@ export class WindowTopBarTitle extends Component {
title = (<div className={classes.title} />);
} else {
title = (
<TitleTypography>
<TitleTypography className={classes.title}>
{manifestTitle}
</TitleTypography>
);
......
......@@ -29,9 +29,7 @@ export class WindowViewer extends Component {
const { hasError } = this.state;
if (hasError) {
return <></>;
}
if (hasError) return null;
return (
<Suspense fallback={<div />}>
......
......@@ -179,7 +179,10 @@ export class WorkspaceAdd extends React.Component {
WorkspaceAdd.propTypes = {
addResource: PropTypes.func,
catalog: PropTypes.arrayOf(PropTypes.object),
catalog: PropTypes.arrayOf(PropTypes.shape({
manifestId: PropTypes.string.isRequired,
provider: PropTypes.string,
})),
classes: PropTypes.objectOf(PropTypes.string),
setWorkspaceAddVisibility: PropTypes.func.isRequired,
t: PropTypes.func,
......
......@@ -29,9 +29,7 @@ function getIdAndContentOfResources(resources) {
/** For connect */
const mapStateToProps = (state, { canvasId, windowId }) => ({
annotations: getIdAndContentOfResources(
getAnnotationResourcesByMotivationForCanvas(
state, { canvasId, windowId },
),
getAnnotationResourcesByMotivationForCanvas(state, { canvasId, windowId }),
),
autoScroll: getWindow(state, { windowId }).autoScrollAnnotationList,
htmlSanitizationRuleSet: getConfig(state).annotations.htmlSanitizationRuleSet,
......
......@@ -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';
......@@ -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 = {
......
......@@ -24,11 +24,14 @@ const mapStateToProps = (state, {
}) => {
const realAnnoId = annotationId || hit.annotations[0];
const hitAnnotation = getResourceAnnotationForSearchHit(
state, { annotationUri: realAnnoId, companionWindowId, windowId },
);
const annotationLabel = getResourceAnnotationLabel(
state, { annotationUri: realAnnoId, companionWindowId, windowId },
state,
{
annotationUri: realAnnoId,
companionWindowId,
windowId,
},
);
const annotationLabel = getResourceAnnotationLabel(state, { annotationUri: realAnnoId, companionWindowId, windowId });
const selectedCanvasIds = getVisibleCanvasIds(state, { windowId });
const selectedContentSearchAnnotationsIds = getSelectedContentSearchAnnotationIds(state, {
......
......@@ -13,9 +13,7 @@ import { WindowAuthenticationBar } from '../components/WindowAuthenticationBar';
const styles = theme => ({
buttonInvert: {
'&:hover': {
backgroundColor: alpha(
theme.palette.secondary.contrastText, 1 - theme.palette.action.hoverOpacity,
),
backgroundColor: alpha(theme.palette.secondary.contrastText, 1 - theme.palette.action.hoverOpacity),
},
backgroundColor: theme.palette.secondary.contrastText,
marginLeft: theme.spacing(5),
......
......@@ -136,7 +136,7 @@ export default class CanvasWorld {
/** Get the IIIF content resource for an image */
contentResource(infoResponseId) {
const miradorCanvas = this.canvases.find(c => c.imageServiceIds.some(id => (
normalizeUrl(id, { stripAuthentication: false })
id && infoResponseId && normalizeUrl(id, { stripAuthentication: false })
=== normalizeUrl(infoResponseId, { stripAuthentication: false }))));
if (!miradorCanvas) return undefined;
return miradorCanvas.imageResources
......@@ -203,8 +203,8 @@ export default class CanvasWorld {
* lined up horizontally starting from left to right.
*/
worldBounds() {
const worldWidth = Math.max(...this.canvasDimensions.map(c => c.x + c.width));
const worldHeight = Math.max(...this.canvasDimensions.map(c => c.y + c.height));
const worldWidth = Math.max(0, ...this.canvasDimensions.map(c => c.x + c.width));
const worldHeight = Math.max(0, ...this.canvasDimensions.map(c => c.y + c.height));
return [
0,
......
......@@ -19,11 +19,14 @@ class MiradorViewer {
this.store = viewerConfig.store
|| createPluggableStore(this.config, this.plugins);
if (config.id) {
this.container = document.getElementById(config.id);
config.id && ReactDOM.render(
this.render(),
document.getElementById(config.id),
this.container,
);
}
}
/**
* Render the mirador viewer
......@@ -40,7 +43,7 @@ class MiradorViewer {
* Cleanup method to unmount Mirador from the dom
*/
unmount() {
this.config.id && ReactDOM.unmountComponentAtNode(document.getElementById(this.config.id));
this.container && ReactDOM.unmountComponentAtNode(this.container);
}
}
......
......@@ -90,8 +90,7 @@ class ThumbnailFactory {
const imageFitness = (test) => test.width * test.height - targetArea;
/** Look for the size that's just bigger than we prefer... */
closestSize = sizes.reduce(
(best, test) => {
closestSize = sizes.reduce((best, test) => {
const score = imageFitness(test);
if (score < 0) return best;
......@@ -99,18 +98,15 @@ class ThumbnailFactory {
return Math.abs(score) < Math.abs(imageFitness(best))
? test
: best;
}, closestSize,
);
}, closestSize);
/** .... but not "too" big; we'd rather scale up an image than download too much */
if (closestSize.width * closestSize.height > targetArea * 6) {
closestSize = sizes.reduce(
(best, test) => (
closestSize = sizes.reduce((best, test) => (
Math.abs(imageFitness(test)) < Math.abs(imageFitness(best))
? test
: best
), closestSize,
);
), closestSize);
}
if (closestSize.default) return undefined;
......@@ -313,4 +309,5 @@ function getBestThumbnail(resource, iiifOpts) {
return new ThumbnailFactory(resource, iiifOpts).get();
}
export { getBestThumbnail as default, ThumbnailFactory };
export { ThumbnailFactory };
export default getBestThumbnail;
......@@ -25,16 +25,12 @@ export default class TruncatedHit {
/** */
get before() {
if (!this.hit.before) return '';
return this.hit.before.substring(
this.hit.before.length - this.charsOnSide, this.hit.before.length,
);
return this.hit.before.substring(this.hit.before.length - this.charsOnSide, this.hit.before.length);
}
/** */
get after() {
if (!this.hit.after) return '';
return this.hit.after.substring(
0, Math.min(this.hit.after.length, this.charsOnSide),
);
return this.hit.after.substring(0, Math.min(this.hit.after.length, this.charsOnSide));
}
}
......@@ -57,6 +57,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",
......
......@@ -59,6 +59,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",
......
......@@ -27,9 +27,7 @@ function configureStore(pluginReducers, pluginSagas = []) {
const store = createStore(
rootReducer,
composeWithDevTools(
applyMiddleware(
thunkMiddleware, sagaMiddleware,
),
applyMiddleware(thunkMiddleware, sagaMiddleware),
),
);
......
......@@ -64,7 +64,10 @@ function* fetchIiifResourceWithAuth(url, iiifResource, options, { degraded, fail
}
const { error, json, response } = yield call(
fetchIiifResource, url, urlOptions, { failure: arg => arg, success: arg => arg },
fetchIiifResource,
url,
urlOptions,
{ failure: arg => arg, success: arg => arg },
);
// Hard error either requesting the resource or deserializing the JSON.
......
......@@ -94,9 +94,7 @@ export function* setWindowStartingCanvas(action) {
const windowId = action.id || action.window.id;
if (canvasId) {
const thunk = yield call(
setCanvas, windowId, canvasId, null, { preserveViewport: !!action.payload },
);
const thunk = yield call(setCanvas, windowId, canvasId, null, { preserveViewport: !!action.payload });
yield put(thunk);
} else {
const manifestoInstance = yield select(getManifestoInstance, { manifestId });
......@@ -157,7 +155,12 @@ export function* setCurrentAnnotationsOnCurrentCanvas({
if (companionWindowIds.length === 0) return;
const annotationBySearch = yield select(
getAnnotationsBySearch, { canvasIds: visibleCanvases, companionWindowIds, windowId },
getAnnotationsBySearch,
{
canvasIds: visibleCanvases,
companionWindowIds,
windowId,
},
);
yield all(
......@@ -213,9 +216,7 @@ export function* setCanvasOfFirstSearchResult({ companionWindowId, windowId }) {
if (selectedIds.length !== 0) return;
const annotations = yield select(
getSortedSearchAnnotationsForCompanionWindow, { companionWindowId, windowId },
);
const annotations = yield select(getSortedSearchAnnotationsForCompanionWindow, { companionWindowId, windowId });
if (!annotations || annotations.length === 0) return;
yield put(selectAnnotation(windowId, annotations[0].id));
......
......@@ -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,
......@@ -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
......
......@@ -111,8 +111,8 @@ export const getSortedSearchHitsForCompanionWindow = createSelector(
[
getSearchHitsForCompanionWindow,
getCanvases,
(state, { companionWindowId, windowId }) => annotationUri => getResourceAnnotationForSearchHit(
state, { annotationUri, companionWindowId, windowId },
(state, { companionWindowId, windowId }) => (
annotationUri => getResourceAnnotationForSearchHit(state, { annotationUri, companionWindowId, windowId })
),
],
(searchHits, canvases, annotationForSearchHit) => {
......@@ -232,9 +232,7 @@ const getAnnotationById = createSelector(
export const getCanvasForAnnotation = createSelector(
[
getAnnotationById,
(state, { windowId }) => canvasId => getCanvas(
state, { canvasId, windowId },
),
(state, { windowId }) => canvasId => getCanvas(state, { canvasId, windowId }),
],
(annotation, getCanvasById) => {
const canvasId = annotation && annotation.targetId;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment