Skip to content

Commit

Permalink
Merge pull request #6229 from wellcomecollection/repetitive-structures
Browse files Browse the repository at this point in the history
Repetitive structures
  • Loading branch information
gestchild authored Mar 22, 2021
2 parents 8219c81 + 56c686f commit fec1514
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 4 deletions.
1 change: 1 addition & 0 deletions common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"jest": "^24.9.0",
"koa-compose": "^4.1.0",
"lazysizes": "^5.2.1",
"lodash.clonedeep": "^4.5.0",
"lodash.debounce": "^4.0.8",
"lodash.flattendeep": "^4.4.0",
"lodash.groupby": "^4.6.0",
Expand Down
85 changes: 85 additions & 0 deletions common/test/utils/iiif.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { getCanvases, groupStructures } from '../../utils/iiif';
import manifest from '../../../common/__mocks__/iiif-manifest';

const canvases = getCanvases(manifest);
const structures = [
{
'@id': 'https://wellcomelibrary.org/iiif/b21538906/range/r-0',
'@type': 'sc:Range',
label: 'First',
canvases: [
'https://wellcomelibrary.org/iiif/b21538906/canvas/c0',
'https://wellcomelibrary.org/iiif/b21538906/canvas/c1',
],
},
{
'@id': 'https://wellcomelibrary.org/iiif/b21538906/range/r-1',
'@type': 'sc:Range',
label: 'First',
canvases: ['https://wellcomelibrary.org/iiif/b21538906/canvas/c2'],
},
{
'@id': 'https://wellcomelibrary.org/iiif/b21538906/range/r-2',
'@type': 'sc:Range',
label: 'First',
canvases: ['https://wellcomelibrary.org/iiif/b21538906/canvas/c5'],
},
{
'@id': 'https://wellcomelibrary.org/iiif/b21538906/range/r-3',
'@type': 'sc:Range',
label: 'Second',
canvases: ['https://wellcomelibrary.org/iiif/b21538906/canvas/c6'],
},
{
'@id': 'https://wellcomelibrary.org/iiif/b21538906/range/r-4',
'@type': 'sc:Range',
label: 'Third',
canvases: ['https://wellcomelibrary.org/iiif/b21538906/canvas/c8'],
},
{
'@id': 'https://wellcomelibrary.org/iiif/b21538906/range/r-5',
'@type': 'sc:Range',
label: 'Third',
canvases: ['https://wellcomelibrary.org/iiif/b21538906/canvas/c9'],
},
];

const correctResult = [
{
'@id': 'https://wellcomelibrary.org/iiif/b21538906/range/r-0',
'@type': 'sc:Range',
label: 'First',
canvases: [
'https://wellcomelibrary.org/iiif/b21538906/canvas/c0',
'https://wellcomelibrary.org/iiif/b21538906/canvas/c1',
'https://wellcomelibrary.org/iiif/b21538906/canvas/c2',
],
},
{
'@id': 'https://wellcomelibrary.org/iiif/b21538906/range/r-2',
'@type': 'sc:Range',
label: 'First',
canvases: ['https://wellcomelibrary.org/iiif/b21538906/canvas/c5'],
},
{
'@id': 'https://wellcomelibrary.org/iiif/b21538906/range/r-3',
'@type': 'sc:Range',
label: 'Second',
canvases: ['https://wellcomelibrary.org/iiif/b21538906/canvas/c6'],
},
{
'@id': 'https://wellcomelibrary.org/iiif/b21538906/range/r-4',
'@type': 'sc:Range',
label: 'Third',
canvases: [
'https://wellcomelibrary.org/iiif/b21538906/canvas/c8',
'https://wellcomelibrary.org/iiif/b21538906/canvas/c9',
],
},
];
describe('Group repetitive iiif structures', () => {
it('groups iiifStructures with consecutive canvases and the same label', () => {
const groupedStructures = groupStructures(canvases, structures);
expect(groupedStructures).toEqual(correctResult);
});
});
46 changes: 45 additions & 1 deletion common/utils/iiif.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
AuthServiceService,
IIIFAnnotationResource,
} from '../model/iiif';
import cloneDeep from 'lodash.clonedeep';

export function getServiceId(canvas?: IIIFCanvas): string | undefined {
const serviceSrc = canvas?.images[0]?.resource?.service;
Expand Down Expand Up @@ -93,7 +94,10 @@ export function getUiExtensions(
}
}

export function isUiEnabled(uiExtensions: Service | undefined, uiName: string) {
export function isUiEnabled(
uiExtensions: Service | undefined,
uiName: string
): boolean {
const disableUI = uiExtensions && uiExtensions.disableUI;
if (disableUI) {
return !(
Expand Down Expand Up @@ -159,6 +163,46 @@ export function getStructures(iiifManifest: IIIFManifest): IIIFStructure[] {
return iiifManifest?.structures || [];
}

// When lots of the works were digitised, structures with multiple pages such as table of contents
// were created individually, rather than as a single structure with a range of pages.
// This means we will often display repetitive links to the essentially the same thing.
// Until we can improve the data at source, this function groups structures that have the same label attached to consecutive pages into a single structure.
export function groupStructures(
canvases: IIIFCanvas[],
structures: IIIFStructure[]
): IIIFStructure[] {
const clonedStructures = cloneDeep(structures);
return clonedStructures.reduce(
(acc, structure) => {
const [lastCanvasInRange] = structure.canvases.slice(-1);
const [firstCanvasInRange] = structure.canvases;
const firstCanvasIndex = canvases.findIndex(
canvas => canvas['@id'] === firstCanvasInRange
);
if (
acc.previousLabel === structure.label &&
firstCanvasIndex === acc.previousLastCanvasIndex + 1
) {
acc.groupedArray[acc.groupedArray.length - 1].canvases.push(
lastCanvasInRange
);
} else {
acc.groupedArray.push(structure);
}
acc.previousLabel = structure.label;
acc.previousLastCanvasIndex = canvases.findIndex(
canvas => canvas['@id'] === lastCanvasInRange
);
return acc;
},
{
previousLastCanvasIndex: null,
previousLabel: null,
groupedArray: [],
}
).groupedArray;
}

export function getVideo(
iiifManifest: IIIFManifest
): IIIFMediaElement | undefined {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { getStructures, getCanvases } from '@weco/common/utils/iiif';
import { IIIFManifest } from '@weco/common/model/iiif';
import {
getStructures,
groupStructures,
getCanvases,
} from '@weco/common/utils/iiif';
import { useContext, FunctionComponent, RefObject } from 'react';
import { FixedSizeList } from 'react-window';
import ItemViewerContext from '../ItemViewerContext/ItemViewerContext';
Expand All @@ -15,10 +20,11 @@ const ViewerStructuresPrototype: FunctionComponent<Props> = ({
);
const structures = manifest ? getStructures(manifest) : [];
const canvases = manifest ? getCanvases(manifest) : [];
const groupedStructures = groupStructures(canvases, structures);

return structures.length > 0 ? (
return groupedStructures.length > 0 ? (
<ul>
{structures.map((structure, i) => {
{groupedStructures.map((structure, i) => {
const firstCanvasInRange = structure.canvases[0];
const canvasIndex = canvases.findIndex(
canvas => canvas['@id'] === firstCanvasInRange
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -15279,6 +15279,11 @@ lodash-es@^4.17.15:
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78"
integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ==

lodash.clonedeep@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=

lodash.debounce@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
Expand Down

0 comments on commit fec1514

Please sign in to comment.