Merge pull request #1847 from mspalti/iiif-multi-fix

Bug fix for multiple IIIF image property
This commit is contained in:
Tim Donohue
2022-09-28 17:02:29 -05:00
committed by GitHub
3 changed files with 78 additions and 31 deletions

View File

@@ -12,6 +12,7 @@ import { createPaginatedList } from '../../shared/testing/utils.test';
import { of as observableOf } from 'rxjs';
import { MiradorViewerService } from './mirador-viewer.service';
import { HostWindowService } from '../../shared/host-window.service';
import { BundleDataService } from '../../core/data/bundle-data.service';
function getItem(metadata: MetadataMap) {
@@ -46,6 +47,7 @@ describe('MiradorViewerComponent with search', () => {
declarations: [MiradorViewerComponent],
providers: [
{ provide: BitstreamDataService, useValue: {} },
{ provide: BundleDataService, useValue: {} },
{ provide: HostWindowService, useValue: mockHostWindowService }
],
schemas: [NO_ERRORS_SCHEMA]
@@ -108,6 +110,7 @@ describe('MiradorViewerComponent with multiple images', () => {
declarations: [MiradorViewerComponent],
providers: [
{ provide: BitstreamDataService, useValue: {} },
{ provide: BundleDataService, useValue: {} },
{ provide: HostWindowService, useValue: mockHostWindowService }
],
schemas: [NO_ERRORS_SCHEMA]
@@ -167,6 +170,7 @@ describe('MiradorViewerComponent with a single image', () => {
declarations: [MiradorViewerComponent],
providers: [
{ provide: BitstreamDataService, useValue: {} },
{ provide: BundleDataService, useValue: {} },
{ provide: HostWindowService, useValue: mockHostWindowService }
],
schemas: [NO_ERRORS_SCHEMA]
@@ -225,6 +229,7 @@ describe('MiradorViewerComponent in development mode', () => {
set: {
providers: [
{ provide: MiradorViewerService, useValue: viewerService },
{ provide: BundleDataService, useValue: {} },
{ provide: HostWindowService, useValue: mockHostWindowService }
]
}

View File

@@ -8,6 +8,7 @@ import { map, take } from 'rxjs/operators';
import { isPlatformBrowser } from '@angular/common';
import { MiradorViewerService } from './mirador-viewer.service';
import { HostWindowService, WidthCategory } from '../../shared/host-window.service';
import { BundleDataService } from '../../core/data/bundle-data.service';
@Component({
selector: 'ds-mirador-viewer',
@@ -55,6 +56,7 @@ export class MiradorViewerComponent implements OnInit {
constructor(private sanitizer: DomSanitizer,
private viewerService: MiradorViewerService,
private bitstreamDataService: BitstreamDataService,
private bundleDataService: BundleDataService,
private hostWindowService: HostWindowService,
@Inject(PLATFORM_ID) private platformId: any) {
}
@@ -107,10 +109,10 @@ export class MiradorViewerComponent implements OnInit {
this.notMobile = !(category === WidthCategory.XS || category === WidthCategory.SM);
});
// We need to set the multi property to true if the
// item is searchable or when the ORIGINAL bundle contains more
// than 1 image. (The multi property determines whether the
// Mirador side thumbnail navigation panel is shown.)
// Set the multi property. The default mirador configuration adds a right
// thumbnail navigation panel to the viewer when multi is 'true'.
// Set the multi property to 'true' if the item is searchable.
if (this.searchable) {
this.multi = true;
const observable = of('');
@@ -120,8 +122,12 @@ export class MiradorViewerComponent implements OnInit {
})
);
} else {
// Sets the multi value based on the image count.
this.iframeViewerUrl = this.viewerService.getImageCount(this.object, this.bitstreamDataService).pipe(
// Set the multi property based on the image count in IIIF-eligible bundles.
// Any count greater than 1 sets the value to 'true'.
this.iframeViewerUrl = this.viewerService.getImageCount(
this.object,
this.bitstreamDataService,
this.bundleDataService).pipe(
map(c => {
if (c > 1) {
this.multi = true;

View File

@@ -1,14 +1,18 @@
import { Injectable, isDevMode } from '@angular/core';
import { Observable } from 'rxjs';
import { Item } from '../../core/shared/item.model';
import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload } from '../../core/shared/operators';
import { last, map, switchMap } from 'rxjs/operators';
import {
getFirstCompletedRemoteData,
} from '../../core/shared/operators';
import { filter, last, map, mergeMap, switchMap } from 'rxjs/operators';
import { RemoteData } from '../../core/data/remote-data';
import { PaginatedList } from '../../core/data/paginated-list.model';
import { Bitstream } from '../../core/shared/bitstream.model';
import { BitstreamFormat } from '../../core/shared/bitstream-format.model';
import { BitstreamDataService } from '../../core/data/bitstream-data.service';
import { followLink, FollowLinkConfig } from '../../shared/utils/follow-link-config.model';
import { Bundle } from '../../core/shared/bundle.model';
import { BundleDataService } from '../../core/data/bundle-data.service';
@Injectable()
export class MiradorViewerService {
@@ -26,32 +30,64 @@ export class MiradorViewerService {
}
/**
* Returns observable of the number of images in the ORIGINAL bundle
* Returns observable of the number of images found in eligible IIIF bundles. Checks
* the mimetype of the first 5 bitstreams in each bundle.
* @param item
* @param bitstreamDataService
* @param bundleDataService
* @returns the total image count
*/
getImageCount(item: Item, bitstreamDataService: BitstreamDataService): Observable<number> {
let count = 0;
return bitstreamDataService.findAllByItemAndBundleName(item, 'ORIGINAL', {
currentPage: 1,
elementsPerPage: 10
}, true, true, ...this.LINKS_TO_FOLLOW)
.pipe(
getFirstCompletedRemoteData(),
map((bitstreamsRD: RemoteData<PaginatedList<Bitstream>>) => bitstreamsRD.payload),
map((paginatedList: PaginatedList<Bitstream>) => paginatedList.page),
switchMap((bitstreams: Bitstream[]) => bitstreams),
switchMap((bitstream: Bitstream) => bitstream.format.pipe(
getFirstSucceededRemoteDataPayload(),
map((format: BitstreamFormat) => format)
)),
map((format: BitstreamFormat) => {
if (format.mimetype.includes('image')) {
count++;
}
return count;
}),
last()
getImageCount(item: Item, bitstreamDataService: BitstreamDataService, bundleDataService: BundleDataService):
Observable<number> {
let count = 0;
return bundleDataService.findAllByItem(item).pipe(
getFirstCompletedRemoteData(),
map((bundlesRD: RemoteData<PaginatedList<Bundle>>) => {
return bundlesRD.payload;
}),
map((paginatedList: PaginatedList<Bundle>) => paginatedList.page),
switchMap((bundles: Bundle[]) => bundles),
filter((b: Bundle) => this.isIiifBundle(b.name)),
mergeMap((bundle: Bundle) => {
return bitstreamDataService.findAllByItemAndBundleName(item, bundle.name, {
currentPage: 1,
elementsPerPage: 5
}, true, true, ...this.LINKS_TO_FOLLOW).pipe(
getFirstCompletedRemoteData(),
map((bitstreamsRD: RemoteData<PaginatedList<Bitstream>>) => {
return bitstreamsRD.payload;
}),
map((paginatedList: PaginatedList<Bitstream>) => paginatedList.page),
switchMap((bitstreams: Bitstream[]) => bitstreams),
switchMap((bitstream: Bitstream) => bitstream.format.pipe(
getFirstCompletedRemoteData(),
map((formatRD: RemoteData<BitstreamFormat>) => {
return formatRD.payload;
}),
map((format: BitstreamFormat) => {
if (format.mimetype.includes('image')) {
count++;
}
return count;
}),
)
)
);
}),
last()
);
}
isIiifBundle(bundleName: string): boolean {
return !(
bundleName === 'OtherContent' ||
bundleName === 'LICENSE' ||
bundleName === 'THUMBNAIL' ||
bundleName === 'TEXT' ||
bundleName === 'METADATA' ||
bundleName === 'CC-LICENSE' ||
bundleName === 'BRANDED_PREVIEW'
);
}
}