mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
Merge remote-tracking branch 'origin/iiif-mirador' into iiif-mirador
This commit is contained in:
13
package.json
13
package.json
@@ -46,7 +46,12 @@
|
|||||||
"clean": "yarn run clean:prod && yarn run clean:env && yarn run clean:node",
|
"clean": "yarn run clean:prod && yarn run clean:env && yarn run clean:node",
|
||||||
"clean:env": "rimraf src/environments/environment.ts",
|
"clean:env": "rimraf src/environments/environment.ts",
|
||||||
"sync-i18n": "yarn run config:dev && ts-node --project ./tsconfig.ts-node.json scripts/sync-i18n-files.ts",
|
"sync-i18n": "yarn run config:dev && ts-node --project ./tsconfig.ts-node.json scripts/sync-i18n-files.ts",
|
||||||
"postinstall": "ngcc"
|
"postinstall": "ngcc",
|
||||||
|
"build:mirador": "webpack --config webpack/webpack.mirador.config.ts",
|
||||||
|
"build:client-and-server-bundles:mirador": "node --max-old-space-size=4096 ./node_modules/@angular/cli/bin/ng build --prod && ./node_modules/@angular/cli/bin/ng run dspace-angular:server:production --bundleDependencies true",
|
||||||
|
"build:ssr:mirador": "yarn run build:client-and-server-bundles:mirador && yarn run compile:server",
|
||||||
|
"start:prod:mirador": "yarn run build:ssr:mirador && yarn run serve:ssr",
|
||||||
|
"start:mirador:prod": "yarn run build:mirador && yarn run start:prod:mirador"
|
||||||
},
|
},
|
||||||
"browser": {
|
"browser": {
|
||||||
"fs": false,
|
"fs": false,
|
||||||
@@ -103,6 +108,9 @@
|
|||||||
"jsonschema": "1.4.0",
|
"jsonschema": "1.4.0",
|
||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^3.1.2",
|
||||||
"klaro": "^0.7.10",
|
"klaro": "^0.7.10",
|
||||||
|
"mirador": "^3.0.0",
|
||||||
|
"mirador-dl-plugin": "^0.13.0",
|
||||||
|
"mirador-share-plugin": "^0.10.0",
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
"morgan": "^1.10.0",
|
"morgan": "^1.10.0",
|
||||||
"ng-mocks": "10.5.4",
|
"ng-mocks": "10.5.4",
|
||||||
@@ -115,6 +123,8 @@
|
|||||||
"nouislider": "^14.6.3",
|
"nouislider": "^14.6.3",
|
||||||
"pem": "1.14.4",
|
"pem": "1.14.4",
|
||||||
"postcss-cli": "^8.3.0",
|
"postcss-cli": "^8.3.0",
|
||||||
|
"react": "^16.14.0",
|
||||||
|
"react-dom": "^16.14.0",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rxjs": "^6.6.3",
|
"rxjs": "^6.6.3",
|
||||||
"rxjs-spy": "^7.5.3",
|
"rxjs-spy": "^7.5.3",
|
||||||
@@ -151,6 +161,7 @@
|
|||||||
"deep-freeze": "0.0.1",
|
"deep-freeze": "0.0.1",
|
||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
"fork-ts-checker-webpack-plugin": "^6.0.3",
|
"fork-ts-checker-webpack-plugin": "^6.0.3",
|
||||||
|
"html-loader": "^1.3.2",
|
||||||
"html-webpack-plugin": "^4.5.0",
|
"html-webpack-plugin": "^4.5.0",
|
||||||
"http-proxy-middleware": "^1.0.5",
|
"http-proxy-middleware": "^1.0.5",
|
||||||
"jasmine-core": "^3.6.0",
|
"jasmine-core": "^3.6.0",
|
||||||
|
@@ -41,6 +41,8 @@ import { UIServerConfig } from './src/config/ui-server-config.interface';
|
|||||||
* Set path for the browser application's dist folder
|
* Set path for the browser application's dist folder
|
||||||
*/
|
*/
|
||||||
const DIST_FOLDER = join(process.cwd(), 'dist/browser');
|
const DIST_FOLDER = join(process.cwd(), 'dist/browser');
|
||||||
|
// Set path fir IIIF viewer.
|
||||||
|
const IIIF_VIEWER = join(process.cwd(), 'dist/iiif');
|
||||||
|
|
||||||
const indexHtml = existsSync(join(DIST_FOLDER, 'index.html')) ? 'index.html' : 'index';
|
const indexHtml = existsSync(join(DIST_FOLDER, 'index.html')) ? 'index.html' : 'index';
|
||||||
|
|
||||||
@@ -135,6 +137,10 @@ export function app() {
|
|||||||
* Serve static resources (images, i18n messages, …)
|
* Serve static resources (images, i18n messages, …)
|
||||||
*/
|
*/
|
||||||
server.get('*.*', cacheControl, express.static(DIST_FOLDER, { index: false }));
|
server.get('*.*', cacheControl, express.static(DIST_FOLDER, { index: false }));
|
||||||
|
/*
|
||||||
|
* Fallthrough to the IIIF viewer (must be included in the build).
|
||||||
|
*/
|
||||||
|
server.use('/iiif', express.static(IIIF_VIEWER, {index:false}));
|
||||||
|
|
||||||
// Register the ngApp callback function to handle incoming requests
|
// Register the ngApp callback function to handle incoming requests
|
||||||
server.get('*', ngApp);
|
server.get('*', ngApp);
|
||||||
|
@@ -12,7 +12,6 @@ import { ItemPageAbstractFieldComponent } from './simple/field-components/specif
|
|||||||
import { ItemPageUriFieldComponent } from './simple/field-components/specific-field/uri/item-page-uri-field.component';
|
import { ItemPageUriFieldComponent } from './simple/field-components/specific-field/uri/item-page-uri-field.component';
|
||||||
import { ItemPageTitleFieldComponent } from './simple/field-components/specific-field/title/item-page-title-field.component';
|
import { ItemPageTitleFieldComponent } from './simple/field-components/specific-field/title/item-page-title-field.component';
|
||||||
import { ItemPageFieldComponent } from './simple/field-components/specific-field/item-page-field.component';
|
import { ItemPageFieldComponent } from './simple/field-components/specific-field/item-page-field.component';
|
||||||
import { FileSectionComponent } from './simple/field-components/file-section/file-section.component';
|
|
||||||
import { CollectionsComponent } from './field-components/collections/collections.component';
|
import { CollectionsComponent } from './field-components/collections/collections.component';
|
||||||
import { FullItemPageComponent } from './full/full-item-page.component';
|
import { FullItemPageComponent } from './full/full-item-page.component';
|
||||||
import { FullFileSectionComponent } from './full/field-components/file-section/full-file-section.component';
|
import { FullFileSectionComponent } from './full/field-components/file-section/full-file-section.component';
|
||||||
@@ -27,6 +26,7 @@ import { JournalEntitiesModule } from '../entity-groups/journal-entities/journal
|
|||||||
import { ResearchEntitiesModule } from '../entity-groups/research-entities/research-entities.module';
|
import { ResearchEntitiesModule } from '../entity-groups/research-entities/research-entities.module';
|
||||||
import { ThemedItemPageComponent } from './simple/themed-item-page.component';
|
import { ThemedItemPageComponent } from './simple/themed-item-page.component';
|
||||||
import { ThemedFullItemPageComponent } from './full/themed-full-item-page.component';
|
import { ThemedFullItemPageComponent } from './full/themed-full-item-page.component';
|
||||||
|
import { IIIFEntitiesModule } from '../entity-groups/iiif-entities/iiif-entities.module';
|
||||||
import { MediaViewerComponent } from './media-viewer/media-viewer.component';
|
import { MediaViewerComponent } from './media-viewer/media-viewer.component';
|
||||||
import { MediaViewerVideoComponent } from './media-viewer/media-viewer-video/media-viewer-video.component';
|
import { MediaViewerVideoComponent } from './media-viewer/media-viewer-video/media-viewer-video.component';
|
||||||
import { MediaViewerImageComponent } from './media-viewer/media-viewer-image/media-viewer-image.component';
|
import { MediaViewerImageComponent } from './media-viewer/media-viewer-image/media-viewer-image.component';
|
||||||
@@ -50,7 +50,6 @@ const DECLARATIONS = [
|
|||||||
ItemPageUriFieldComponent,
|
ItemPageUriFieldComponent,
|
||||||
ItemPageTitleFieldComponent,
|
ItemPageTitleFieldComponent,
|
||||||
ItemPageFieldComponent,
|
ItemPageFieldComponent,
|
||||||
FileSectionComponent,
|
|
||||||
CollectionsComponent,
|
CollectionsComponent,
|
||||||
FullFileSectionComponent,
|
FullFileSectionComponent,
|
||||||
PublicationComponent,
|
PublicationComponent,
|
||||||
@@ -72,7 +71,8 @@ const DECLARATIONS = [
|
|||||||
StatisticsModule.forRoot(),
|
StatisticsModule.forRoot(),
|
||||||
JournalEntitiesModule.withEntryComponents(),
|
JournalEntitiesModule.withEntryComponents(),
|
||||||
ResearchEntitiesModule.withEntryComponents(),
|
ResearchEntitiesModule.withEntryComponents(),
|
||||||
NgxGalleryModule,
|
IIIFEntitiesModule.withEntryComponents(),
|
||||||
|
NgxGalleryModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
...DECLARATIONS
|
...DECLARATIONS
|
||||||
|
50
src/app/entity-groups/iiif-entities/iiif-entities.module.ts
Normal file
50
src/app/entity-groups/iiif-entities/iiif-entities.module.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import {IIIFSearchableComponent} from './item-pages/iiif-searchable/iiif-searchable.component';
|
||||||
|
import {CUSTOM_ELEMENTS_SCHEMA, NgModule} from '@angular/core';
|
||||||
|
import {CommonModule} from '@angular/common';
|
||||||
|
import {SharedModule} from '../../shared/shared.module';
|
||||||
|
import {IIIFSearchableGridElementComponent} from './item-grid-elements/iiif-searchable/iiif-searchable-grid-element.component';
|
||||||
|
import {IIIFSearchableSearchResultListElementComponent} from './item-list-elements/search-result-list-elements/iiif-searchable/iiif-searchable-search-result-list-element.component';
|
||||||
|
import {IIIFSearchableSearchResultGridElementComponent} from './item-grid-elements/search-result-grid-elements/iiif-searchable/iiif-searchable-search-result-grid-element.component';
|
||||||
|
import {MiradorViewerComponent} from './mirador-viewer/mirador-viewer.component';
|
||||||
|
import {IIIFSearchableListElementComponent} from './item-list-elements/iiif-searchable/iiif-searchable-list-element.component';
|
||||||
|
import {IIIFComponent} from './item-pages/iiif/iiif.component';
|
||||||
|
import {IIIFListElementComponent} from './item-list-elements/iiif/iiif-list-element.component';
|
||||||
|
import {IIIFGridElementComponent} from './item-grid-elements/iiif/iiif-grid-element.component';
|
||||||
|
import {IIIFSearchResultListElementComponent} from './item-list-elements/search-result-list-elements/iiif/iiif-search-result-list-element.component';
|
||||||
|
import {IIIFSearchResultGridElementComponent} from './item-grid-elements/search-result-grid-elements/iiif/iiif-search-result-grid-element.component';
|
||||||
|
|
||||||
|
const ENTRY_COMPONENTS = [
|
||||||
|
IIIFComponent,
|
||||||
|
IIIFSearchableComponent,
|
||||||
|
IIIFListElementComponent,
|
||||||
|
IIIFSearchableListElementComponent,
|
||||||
|
IIIFGridElementComponent,
|
||||||
|
IIIFSearchableGridElementComponent,
|
||||||
|
IIIFSearchResultListElementComponent,
|
||||||
|
IIIFSearchableSearchResultListElementComponent,
|
||||||
|
IIIFSearchResultGridElementComponent,
|
||||||
|
IIIFSearchableSearchResultGridElementComponent,
|
||||||
|
MiradorViewerComponent
|
||||||
|
];
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
SharedModule,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
...ENTRY_COMPONENTS
|
||||||
|
],
|
||||||
|
entryComponents: [
|
||||||
|
...ENTRY_COMPONENTS
|
||||||
|
],
|
||||||
|
schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
|
||||||
|
})
|
||||||
|
export class IIIFEntitiesModule {
|
||||||
|
|
||||||
|
static withEntryComponents() {
|
||||||
|
return {
|
||||||
|
ngModule: IIIFEntitiesModule,
|
||||||
|
providers: ENTRY_COMPONENTS.map((component) => ({provide: component}))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1 @@
|
|||||||
|
<ds-iiif-searchable-result-grid-element [showLabel]="showLabel" [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-iiif-searchable-result-grid-element>
|
@@ -0,0 +1,17 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { ViewMode } from '../../../../core/shared/view-mode.model';
|
||||||
|
import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||||
|
import { AbstractListableElementComponent } from '../../../../shared/object-collection/shared/object-collection-element/abstract-listable-element.component';
|
||||||
|
import { Item } from '../../../../core/shared/item.model';
|
||||||
|
|
||||||
|
@listableObjectComponent('IIIFSearchable', ViewMode.GridElement)
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-iiif-searchable-grid-element',
|
||||||
|
styleUrls: ['./iiif-searchable-grid-element.component.scss'],
|
||||||
|
templateUrl: './iiif-searchable-grid-element.component.html'
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* The component for displaying a list element for an item of the type IIIFSearchable.
|
||||||
|
*/
|
||||||
|
export class IIIFSearchableGridElementComponent extends AbstractListableElementComponent<Item> {
|
||||||
|
}
|
@@ -0,0 +1 @@
|
|||||||
|
<ds-iiif-result-grid-element [showLabel]="showLabel" [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-iiif-result-grid-element>
|
@@ -0,0 +1,17 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { ViewMode } from '../../../../core/shared/view-mode.model';
|
||||||
|
import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||||
|
import { AbstractListableElementComponent } from '../../../../shared/object-collection/shared/object-collection-element/abstract-listable-element.component';
|
||||||
|
import { Item } from '../../../../core/shared/item.model';
|
||||||
|
|
||||||
|
@listableObjectComponent('IIIF', ViewMode.GridElement)
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-iiif-grid-element',
|
||||||
|
styleUrls: ['./iiif-grid-element.component.scss'],
|
||||||
|
templateUrl: './iiif-grid-element.component.html'
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* The component for displaying a list element for an item of the type IIIF.
|
||||||
|
*/
|
||||||
|
export class IIIFGridElementComponent extends AbstractListableElementComponent<Item> {
|
||||||
|
}
|
@@ -0,0 +1,19 @@
|
|||||||
|
<ds-item-type-badge *ngIf="showLabel" [object]="dso"></ds-item-type-badge>
|
||||||
|
<ds-truncatable [id]="dso.id">
|
||||||
|
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer"
|
||||||
|
[routerLink]="['/items/' + dso.id]" class="lead"
|
||||||
|
[innerHTML]="firstMetadataValue('dc.title')"></a>
|
||||||
|
<span *ngIf="linkType == linkTypes.None"
|
||||||
|
class="lead"
|
||||||
|
[innerHTML]="firstMetadataValue('dc.title')"></span>
|
||||||
|
<span class="text-muted">
|
||||||
|
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
||||||
|
<span *ngIf="dso.allMetadata(['creativeworkseries.issn']).length > 0"
|
||||||
|
class="item-list-journals">
|
||||||
|
<span *ngFor="let value of allMetadataValues(['creativeworkseries.issn']); let last=last;">
|
||||||
|
<span [innerHTML]="value"><span [innerHTML]="value"></span></span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</ds-truncatable-part>
|
||||||
|
</span>
|
||||||
|
</ds-truncatable>
|
@@ -0,0 +1,18 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component';
|
||||||
|
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
|
||||||
|
import { Item } from '../../../../../core/shared/item.model';
|
||||||
|
import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||||
|
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||||
|
|
||||||
|
@listableObjectComponent('IIIFSearchableSearchResult', ViewMode.GridElement)
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-iiif-searchable-result-grid-element',
|
||||||
|
styleUrls: ['./iiif-searchable-search-result-grid-element.component.scss'],
|
||||||
|
templateUrl: './iiif-searchable-search-result-grid-element.component.html'
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* The component for displaying a list element for an item search result of the type IIIFSearchable.
|
||||||
|
*/
|
||||||
|
export class IIIFSearchableSearchResultGridElementComponent extends SearchResultListElementComponent<ItemSearchResult, Item> {
|
||||||
|
}
|
@@ -0,0 +1,19 @@
|
|||||||
|
<ds-item-type-badge *ngIf="showLabel" [object]="dso"></ds-item-type-badge>
|
||||||
|
<ds-truncatable [id]="dso.id">
|
||||||
|
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer"
|
||||||
|
[routerLink]="['/items/' + dso.id]" class="lead"
|
||||||
|
[innerHTML]="firstMetadataValue('dc.title')"></a>
|
||||||
|
<span *ngIf="linkType == linkTypes.None"
|
||||||
|
class="lead"
|
||||||
|
[innerHTML]="firstMetadataValue('dc.title')"></span>
|
||||||
|
<span class="text-muted">
|
||||||
|
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
||||||
|
<span *ngIf="dso.allMetadata(['creativeworkseries.issn']).length > 0"
|
||||||
|
class="item-list-journals">
|
||||||
|
<span *ngFor="let value of allMetadataValues(['creativeworkseries.issn']); let last=last;">
|
||||||
|
<span [innerHTML]="value"><span [innerHTML]="value"></span></span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</ds-truncatable-part>
|
||||||
|
</span>
|
||||||
|
</ds-truncatable>
|
@@ -0,0 +1,18 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component';
|
||||||
|
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
|
||||||
|
import { Item } from '../../../../../core/shared/item.model';
|
||||||
|
import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||||
|
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||||
|
|
||||||
|
@listableObjectComponent('IIIFSearchResult', ViewMode.GridElement)
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-iiif-result-grid-element',
|
||||||
|
styleUrls: ['./iiif-search-result-grid-element.component.scss'],
|
||||||
|
templateUrl: './iiif-search-result-grid-element.component.html'
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* The component for displaying a list element for an item search result of the type IIIF
|
||||||
|
*/
|
||||||
|
export class IIIFSearchResultGridElementComponent extends SearchResultListElementComponent<ItemSearchResult, Item> {
|
||||||
|
}
|
@@ -0,0 +1 @@
|
|||||||
|
<ds-iiif-searchable-search-result-list-element [showLabel]="showLabel" [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-iiif-searchable-search-result-list-element>
|
@@ -0,0 +1,17 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { ViewMode } from '../../../../core/shared/view-mode.model';
|
||||||
|
import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||||
|
import { AbstractListableElementComponent } from '../../../../shared/object-collection/shared/object-collection-element/abstract-listable-element.component';
|
||||||
|
import { Item } from '../../../../core/shared/item.model';
|
||||||
|
|
||||||
|
@listableObjectComponent('IIIFSearchable', ViewMode.ListElement)
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-iiif-searchable-list-element',
|
||||||
|
styleUrls: ['./iiif-searchable-list-element.component.scss'],
|
||||||
|
templateUrl: './iiif-searchable-list-element.component.html'
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* The component for displaying a list element for an item of the type IIIFSearchable
|
||||||
|
*/
|
||||||
|
export class IIIFSearchableListElementComponent extends AbstractListableElementComponent<Item> {
|
||||||
|
}
|
@@ -0,0 +1 @@
|
|||||||
|
<ds-iiif-search-result-list-element [showLabel]="showLabel" [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-iiif-search-result-list-element>
|
@@ -0,0 +1,17 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { ViewMode } from '../../../../core/shared/view-mode.model';
|
||||||
|
import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||||
|
import { AbstractListableElementComponent } from '../../../../shared/object-collection/shared/object-collection-element/abstract-listable-element.component';
|
||||||
|
import { Item } from '../../../../core/shared/item.model';
|
||||||
|
|
||||||
|
@listableObjectComponent('IIIF', ViewMode.ListElement)
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-iiif-list-element',
|
||||||
|
styleUrls: ['./iiif-list-element.component.scss'],
|
||||||
|
templateUrl: './iiif-list-element.component.html'
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* The component for displaying a list element for an item of the type IIIF
|
||||||
|
*/
|
||||||
|
export class IIIFListElementComponent extends AbstractListableElementComponent<Item> {
|
||||||
|
}
|
@@ -0,0 +1,19 @@
|
|||||||
|
<ds-item-type-badge *ngIf="showLabel" [object]="dso"></ds-item-type-badge>
|
||||||
|
<ds-truncatable [id]="dso.id">
|
||||||
|
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer"
|
||||||
|
[routerLink]="['/items/' + dso.id]" class="lead"
|
||||||
|
[innerHTML]="firstMetadataValue('dc.title')"></a>
|
||||||
|
<span *ngIf="linkType == linkTypes.None"
|
||||||
|
class="lead"
|
||||||
|
[innerHTML]="firstMetadataValue('dc.title')"></span>
|
||||||
|
<span class="text-muted">
|
||||||
|
<!-- <ds-truncatable-part [id]="dso.id" [minLines]="1">-->
|
||||||
|
<!-- <span *ngIf="dso.allMetadata(['creativeworkseries.issn']).length > 0"-->
|
||||||
|
<!-- class="item-list-journals">-->
|
||||||
|
<!-- <span *ngFor="let value of allMetadataValues(['creativeworkseries.issn']); let last=last;">-->
|
||||||
|
<!-- <span [innerHTML]="value"><span [innerHTML]="value"></span></span>-->
|
||||||
|
<!-- </span>-->
|
||||||
|
<!-- </span>-->
|
||||||
|
<!-- </ds-truncatable-part>-->
|
||||||
|
</span>
|
||||||
|
</ds-truncatable>
|
@@ -0,0 +1,18 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component';
|
||||||
|
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
|
||||||
|
import { Item } from '../../../../../core/shared/item.model';
|
||||||
|
import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||||
|
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||||
|
|
||||||
|
@listableObjectComponent('IIIFSearchableSearchResult', ViewMode.ListElement)
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-iiif-searchable-search-result-list-element',
|
||||||
|
styleUrls: ['./iiif-searchable-search-result-list-element.component.scss'],
|
||||||
|
templateUrl: './iiif-searchable-search-result-list-element.component.html'
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* The component for displaying a list element for an item search result of the type IIIFSearchable
|
||||||
|
*/
|
||||||
|
export class IIIFSearchableSearchResultListElementComponent extends SearchResultListElementComponent<ItemSearchResult, Item> {
|
||||||
|
}
|
@@ -0,0 +1,19 @@
|
|||||||
|
<ds-item-type-badge *ngIf="showLabel" [object]="dso"></ds-item-type-badge>
|
||||||
|
<ds-truncatable [id]="dso.id">
|
||||||
|
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer"
|
||||||
|
[routerLink]="['/items/' + dso.id]" class="lead"
|
||||||
|
[innerHTML]="firstMetadataValue('dc.title')"></a>
|
||||||
|
<span *ngIf="linkType == linkTypes.None"
|
||||||
|
class="lead"
|
||||||
|
[innerHTML]="firstMetadataValue('dc.title')"></span>
|
||||||
|
<span class="text-muted">
|
||||||
|
<!-- <ds-truncatable-part [id]="dso.id" [minLines]="1">-->
|
||||||
|
<!-- <span *ngIf="dso.allMetadata(['creativeworkseries.issn']).length > 0"-->
|
||||||
|
<!-- class="item-list-journals">-->
|
||||||
|
<!-- <span *ngFor="let value of allMetadataValues(['creativeworkseries.issn']); let last=last;">-->
|
||||||
|
<!-- <span [innerHTML]="value"><span [innerHTML]="value"></span></span>-->
|
||||||
|
<!-- </span>-->
|
||||||
|
<!-- </span>-->
|
||||||
|
<!-- </ds-truncatable-part>-->
|
||||||
|
</span>
|
||||||
|
</ds-truncatable>
|
@@ -0,0 +1,18 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component';
|
||||||
|
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
|
||||||
|
import { Item } from '../../../../../core/shared/item.model';
|
||||||
|
import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||||
|
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||||
|
|
||||||
|
@listableObjectComponent('IIIFSearchResult', ViewMode.ListElement)
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-iiif-search-result-list-element',
|
||||||
|
styleUrls: ['./iiif-search-result-list-element.component.scss'],
|
||||||
|
templateUrl: './iiif-search-result-list-element.component.html'
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* The component for displaying a list element for an item search result of the type IIIF
|
||||||
|
*/
|
||||||
|
export class IIIFSearchResultListElementComponent extends SearchResultListElementComponent<ItemSearchResult, Item> {
|
||||||
|
}
|
@@ -0,0 +1,40 @@
|
|||||||
|
<ds-mirador-viewer id="iiif-viewer" [item]="object" [searchable]="searchable" [query]="query | async"></ds-mirador-viewer>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-12 col-md-4">
|
||||||
|
<ds-metadata-field-wrapper>
|
||||||
|
<ds-thumbnail [thumbnail]="getThumbnail() | async"></ds-thumbnail>
|
||||||
|
</ds-metadata-field-wrapper>
|
||||||
|
<ds-item-page-file-section [item]="object"></ds-item-page-file-section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-xs-12 col-md-6">
|
||||||
|
<div class="item-page-title-field">
|
||||||
|
<h5>{{'iiifsearchable.page.titleprefix' | translate}}</h5><h3><ds-metadata-values [mdValues]="object?.allMetadata(['dc.title'])"></ds-metadata-values></h3>
|
||||||
|
</div>
|
||||||
|
<ds-generic-item-page-field class="item-page-fields" [item]="object"
|
||||||
|
[fields]="['dc.identifier.citation']"
|
||||||
|
[label]="'iiifsearchable.page.issue'">
|
||||||
|
</ds-generic-item-page-field>
|
||||||
|
<ds-generic-item-page-field class="item-page-fields" [item]="object"
|
||||||
|
[fields]="['dc.identifier.uri']"
|
||||||
|
[label]="'item.page.uri'">
|
||||||
|
</ds-generic-item-page-field>
|
||||||
|
<ds-generic-item-page-field class="item-page-fields" [item]="object"
|
||||||
|
[fields]="['dc.identifier.other']"
|
||||||
|
[label]="'iiifsearchable.page.doi'">
|
||||||
|
</ds-generic-item-page-field>
|
||||||
|
<ds-metadata-field-wrapper>
|
||||||
|
|
||||||
|
<ds-metadata-representation-list
|
||||||
|
[parentItem]="object"
|
||||||
|
[itemType]="'Person'"
|
||||||
|
[metadataField]="'dc.contributor.author'"
|
||||||
|
[label]="'relationships.isAuthorOf' | translate">
|
||||||
|
</ds-metadata-representation-list>
|
||||||
|
<a class="btn btn-outline-primary" [routerLink]="['/items/' + object.id + '/full']">
|
||||||
|
{{"item.page.link.full" | translate}}
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</ds-metadata-field-wrapper>
|
||||||
|
</div>
|
||||||
|
</div>
|
@@ -0,0 +1,3 @@
|
|||||||
|
#iiif-viewer {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
@@ -0,0 +1,199 @@
|
|||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { ChangeDetectionStrategy, DebugElement, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { GenericItemPageFieldComponent } from '../../../../+item-page/simple/field-components/specific-field/generic/generic-item-page-field.component';
|
||||||
|
import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service';
|
||||||
|
import { ObjectCacheService } from '../../../../core/cache/object-cache.service';
|
||||||
|
import { BitstreamDataService } from '../../../../core/data/bitstream-data.service';
|
||||||
|
import { CommunityDataService } from '../../../../core/data/community-data.service';
|
||||||
|
import { DefaultChangeAnalyzer } from '../../../../core/data/default-change-analyzer.service';
|
||||||
|
import { DSOChangeAnalyzer } from '../../../../core/data/dso-change-analyzer.service';
|
||||||
|
import { ItemDataService } from '../../../../core/data/item-data.service';
|
||||||
|
import { buildPaginatedList } from '../../../../core/data/paginated-list.model';
|
||||||
|
import { RemoteData } from '../../../../core/data/remote-data';
|
||||||
|
import { Bitstream } from '../../../../core/shared/bitstream.model';
|
||||||
|
import { HALEndpointService } from '../../../../core/shared/hal-endpoint.service';
|
||||||
|
import { Item } from '../../../../core/shared/item.model';
|
||||||
|
import { PageInfo } from '../../../../core/shared/page-info.model';
|
||||||
|
import { UUIDService } from '../../../../core/shared/uuid.service';
|
||||||
|
import { isNotEmpty } from '../../../../shared/empty.util';
|
||||||
|
import { TranslateLoaderMock } from '../../../../shared/mocks/translate-loader.mock';
|
||||||
|
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
||||||
|
import { createSuccessfulRemoteDataObject$ } from '../../../../shared/remote-data.utils';
|
||||||
|
import { TruncatableService } from '../../../../shared/truncatable/truncatable.service';
|
||||||
|
import { TruncatePipe } from '../../../../shared/utils/truncate.pipe';
|
||||||
|
import { IIIFSearchableComponent } from './iiif-searchable.component';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { RelationshipService } from '../../../../core/data/relationship.service';
|
||||||
|
import { RouteService } from '../../../../core/services/route.service';
|
||||||
|
|
||||||
|
let comp: IIIFSearchableComponent;
|
||||||
|
let fixture: ComponentFixture<IIIFSearchableComponent>;
|
||||||
|
|
||||||
|
const mockItem: Item = Object.assign(new Item(), {
|
||||||
|
bundles: createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [])),
|
||||||
|
metadata: {
|
||||||
|
'dc.identifier.citation': [
|
||||||
|
{
|
||||||
|
language: 'en_US',
|
||||||
|
value: 'issue'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'dc.identifier.uri': [
|
||||||
|
{
|
||||||
|
language: 'en_US',
|
||||||
|
value: 'uri'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
,
|
||||||
|
'dc.identifier.other': [
|
||||||
|
{
|
||||||
|
language: 'en_US',
|
||||||
|
value: 'other'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('IIIFSearchableComponent', () => {
|
||||||
|
|
||||||
|
const routeServiceStub = jasmine.createSpyObj('routeService', {
|
||||||
|
getHistory: observableOf(['/browse',''])
|
||||||
|
});
|
||||||
|
|
||||||
|
const mockBitstreamDataService = {
|
||||||
|
getThumbnailFor(item: Item): Observable<RemoteData<Bitstream>> {
|
||||||
|
return createSuccessfulRemoteDataObject$(new Bitstream());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
beforeEach(waitForAsync(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [TranslateModule.forRoot({
|
||||||
|
loader: {
|
||||||
|
provide: TranslateLoader,
|
||||||
|
useClass: TranslateLoaderMock
|
||||||
|
}
|
||||||
|
})],
|
||||||
|
declarations: [IIIFSearchableComponent, GenericItemPageFieldComponent, TruncatePipe],
|
||||||
|
providers: [
|
||||||
|
{ provide: ItemDataService, useValue: {} },
|
||||||
|
{ provide: TruncatableService, useValue: {} },
|
||||||
|
{ provide: RelationshipService, useValue: {} },
|
||||||
|
{ provide: ObjectCacheService, useValue: {} },
|
||||||
|
{ provide: UUIDService, useValue: {} },
|
||||||
|
{ provide: Store, useValue: {} },
|
||||||
|
{ provide: RemoteDataBuildService, useValue: {} },
|
||||||
|
{ provide: CommunityDataService, useValue: {} },
|
||||||
|
{ provide: HALEndpointService, useValue: {} },
|
||||||
|
{ provide: HttpClient, useValue: {} },
|
||||||
|
{ provide: DSOChangeAnalyzer, useValue: {} },
|
||||||
|
{ provide: NotificationsService, useValue: {} },
|
||||||
|
{ provide: DefaultChangeAnalyzer, useValue: {} },
|
||||||
|
{ provide: BitstreamDataService, useValue: mockBitstreamDataService },
|
||||||
|
{ provide: RouteService, useValue: routeServiceStub }
|
||||||
|
],
|
||||||
|
|
||||||
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
}).overrideComponent(IIIFSearchableComponent, {
|
||||||
|
set: { changeDetection: ChangeDetectionStrategy.Default }
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(waitForAsync(() => {
|
||||||
|
fixture = TestBed.createComponent(IIIFSearchableComponent);
|
||||||
|
comp = fixture.componentInstance;
|
||||||
|
comp.object = mockItem;
|
||||||
|
fixture.detectChanges();
|
||||||
|
}));
|
||||||
|
// TODO: fix test
|
||||||
|
// it(`should set searchable attribute to true`, () => {
|
||||||
|
// comp.ngOnInit();
|
||||||
|
// fixture.detectChanges();
|
||||||
|
// const miradorEl = fixture.debugElement.query(By.css('ds-mirador-viewer'));
|
||||||
|
// expect(miradorEl.nativeElement.getAttribute('searchable')).toBeTruthy();
|
||||||
|
// });
|
||||||
|
|
||||||
|
for (const key of Object.keys(mockItem.metadata)) {
|
||||||
|
it(`should be calling a component with metadata field ${key}`, () => {
|
||||||
|
const fields = fixture.debugElement.queryAll(By.css('.item-page-fields'));
|
||||||
|
expect(containsFieldInput(fields, key)).toBeTruthy();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('IIIFSearchableComponent with query', () => {
|
||||||
|
|
||||||
|
const routeServiceStub = jasmine.createSpyObj('routeService', {
|
||||||
|
getHistory: observableOf(['/search?page=1&query=test',''])
|
||||||
|
});
|
||||||
|
|
||||||
|
const mockBitstreamDataService = {
|
||||||
|
getThumbnailFor(item: Item): Observable<RemoteData<Bitstream>> {
|
||||||
|
return createSuccessfulRemoteDataObject$(new Bitstream());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
beforeEach(waitForAsync(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [TranslateModule.forRoot({
|
||||||
|
loader: {
|
||||||
|
provide: TranslateLoader,
|
||||||
|
useClass: TranslateLoaderMock
|
||||||
|
}
|
||||||
|
})],
|
||||||
|
declarations: [IIIFSearchableComponent, GenericItemPageFieldComponent, TruncatePipe],
|
||||||
|
providers: [
|
||||||
|
{ provide: ItemDataService, useValue: {} },
|
||||||
|
{ provide: TruncatableService, useValue: {} },
|
||||||
|
{ provide: RelationshipService, useValue: {} },
|
||||||
|
{ provide: ObjectCacheService, useValue: {} },
|
||||||
|
{ provide: UUIDService, useValue: {} },
|
||||||
|
{ provide: Store, useValue: {} },
|
||||||
|
{ provide: RemoteDataBuildService, useValue: {} },
|
||||||
|
{ provide: CommunityDataService, useValue: {} },
|
||||||
|
{ provide: HALEndpointService, useValue: {} },
|
||||||
|
{ provide: HttpClient, useValue: {} },
|
||||||
|
{ provide: DSOChangeAnalyzer, useValue: {} },
|
||||||
|
{ provide: NotificationsService, useValue: {} },
|
||||||
|
{ provide: DefaultChangeAnalyzer, useValue: {} },
|
||||||
|
{ provide: BitstreamDataService, useValue: mockBitstreamDataService },
|
||||||
|
{ provide: RouteService, useValue: routeServiceStub }
|
||||||
|
],
|
||||||
|
|
||||||
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
}).overrideComponent(IIIFSearchableComponent, {
|
||||||
|
set: { changeDetection: ChangeDetectionStrategy.Default }
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(waitForAsync(() => {
|
||||||
|
fixture = TestBed.createComponent(IIIFSearchableComponent);
|
||||||
|
comp = fixture.componentInstance;
|
||||||
|
comp.object = mockItem;
|
||||||
|
fixture.detectChanges();
|
||||||
|
}));
|
||||||
|
// TODO: fix test
|
||||||
|
// it(`should set query search value`, () => {
|
||||||
|
// comp.ngOnInit();
|
||||||
|
// fixture.detectChanges();
|
||||||
|
// const miradorEl = fixture.debugElement.query(By.css('#iiif-viewer'));
|
||||||
|
// expect(miradorEl.nativeElement.getAttribute('query')).toMatch('test');
|
||||||
|
// });
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
function containsFieldInput(fields: DebugElement[], metadataKey: string): boolean {
|
||||||
|
for (const field of fields) {
|
||||||
|
const fieldComp = field.componentInstance;
|
||||||
|
if (isNotEmpty(fieldComp.fields)) {
|
||||||
|
if (fieldComp.fields.indexOf(metadataKey) > -1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
@@ -0,0 +1,50 @@
|
|||||||
|
import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||||
|
import { ViewMode } from '../../../../core/shared/view-mode.model';
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component';
|
||||||
|
import { RouteService } from '../../../../core/services/route.service';
|
||||||
|
import { Observable } from 'rxjs/internal/Observable';
|
||||||
|
import { filter, map, take } from 'rxjs/operators';
|
||||||
|
import { BitstreamDataService } from '../../../../core/data/bitstream-data.service';
|
||||||
|
|
||||||
|
@listableObjectComponent('IIIFSearchable', ViewMode.StandalonePage)
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-iiif-searchable',
|
||||||
|
styleUrls: ['./iiif-searchable.component.scss'],
|
||||||
|
templateUrl: './iiif-searchable.component.html'
|
||||||
|
})
|
||||||
|
|
||||||
|
export class IIIFSearchableComponent extends ItemComponent implements OnInit {
|
||||||
|
|
||||||
|
searchable: boolean;
|
||||||
|
|
||||||
|
query: Observable<string>;
|
||||||
|
|
||||||
|
constructor(protected routeService: RouteService,
|
||||||
|
protected bitstreamService: BitstreamDataService) {
|
||||||
|
super(bitstreamService);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
// Load iiif viewer in searchable configuration.
|
||||||
|
this.searchable = true;
|
||||||
|
// Use the route history to get the query from a
|
||||||
|
// previous search and use this value to initialize the
|
||||||
|
// viewer with search results.
|
||||||
|
// TODO: is there is a better way to look the previous search
|
||||||
|
this.query = this.routeService.getHistory().pipe(
|
||||||
|
take(1),
|
||||||
|
map(routes => routes[routes.length - 2 ]),
|
||||||
|
filter(r => {
|
||||||
|
return r.includes('/search');
|
||||||
|
}),
|
||||||
|
map(r => {
|
||||||
|
const arr = r.split('&');
|
||||||
|
const q = arr[1];
|
||||||
|
const v = q.split('=');
|
||||||
|
return v[1];
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,40 @@
|
|||||||
|
<ds-mirador-viewer id="iiif-viewer" [item]="object" [searchable]="searchable"></ds-mirador-viewer>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-12 col-md-4">
|
||||||
|
<ds-metadata-field-wrapper>
|
||||||
|
<ds-thumbnail [thumbnail]="getThumbnail() | async"></ds-thumbnail>
|
||||||
|
</ds-metadata-field-wrapper>
|
||||||
|
<ds-item-page-file-section [item]="object"></ds-item-page-file-section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-xs-12 col-md-6">
|
||||||
|
<div class="item-page-title-field">
|
||||||
|
<h5>{{'iiifsearchable.page.titleprefix' | translate}}</h5><h3><ds-metadata-values [mdValues]="object?.allMetadata(['dc.title'])"></ds-metadata-values></h3>
|
||||||
|
</div>
|
||||||
|
<ds-generic-item-page-field class="item-page-fields" [item]="object"
|
||||||
|
[fields]="['dc.identifier.citation']"
|
||||||
|
[label]="'iiifsearchable.page.issue'">
|
||||||
|
</ds-generic-item-page-field>
|
||||||
|
<ds-generic-item-page-field class="item-page-fields" [item]="object"
|
||||||
|
[fields]="['dc.identifier.uri']"
|
||||||
|
[label]="'item.page.uri'">
|
||||||
|
</ds-generic-item-page-field>
|
||||||
|
<ds-generic-item-page-field class="item-page-fields" [item]="object"
|
||||||
|
[fields]="['dc.identifier.other']"
|
||||||
|
[label]="'iiifsearchable.page.doi'">
|
||||||
|
</ds-generic-item-page-field>
|
||||||
|
<ds-metadata-field-wrapper>
|
||||||
|
|
||||||
|
<ds-metadata-representation-list
|
||||||
|
[parentItem]="object"
|
||||||
|
[itemType]="'Person'"
|
||||||
|
[metadataField]="'dc.contributor.author'"
|
||||||
|
[label]="'relationships.isAuthorOf' | translate">
|
||||||
|
</ds-metadata-representation-list>
|
||||||
|
<a class="btn btn-outline-primary" [routerLink]="['/items/' + object.id + '/full']">
|
||||||
|
{{"item.page.link.full" | translate}}
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</ds-metadata-field-wrapper>
|
||||||
|
</div>
|
||||||
|
</div>
|
@@ -0,0 +1,127 @@
|
|||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { ChangeDetectionStrategy, DebugElement, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { GenericItemPageFieldComponent } from '../../../../+item-page/simple/field-components/specific-field/generic/generic-item-page-field.component';
|
||||||
|
import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service';
|
||||||
|
import { ObjectCacheService } from '../../../../core/cache/object-cache.service';
|
||||||
|
import { BitstreamDataService } from '../../../../core/data/bitstream-data.service';
|
||||||
|
import { CommunityDataService } from '../../../../core/data/community-data.service';
|
||||||
|
import { DefaultChangeAnalyzer } from '../../../../core/data/default-change-analyzer.service';
|
||||||
|
import { DSOChangeAnalyzer } from '../../../../core/data/dso-change-analyzer.service';
|
||||||
|
import { ItemDataService } from '../../../../core/data/item-data.service';
|
||||||
|
import { buildPaginatedList } from '../../../../core/data/paginated-list.model';
|
||||||
|
import { RemoteData } from '../../../../core/data/remote-data';
|
||||||
|
import { Bitstream } from '../../../../core/shared/bitstream.model';
|
||||||
|
import { HALEndpointService } from '../../../../core/shared/hal-endpoint.service';
|
||||||
|
import { Item } from '../../../../core/shared/item.model';
|
||||||
|
import { PageInfo } from '../../../../core/shared/page-info.model';
|
||||||
|
import { UUIDService } from '../../../../core/shared/uuid.service';
|
||||||
|
import { isNotEmpty } from '../../../../shared/empty.util';
|
||||||
|
import { TranslateLoaderMock } from '../../../../shared/mocks/translate-loader.mock';
|
||||||
|
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
||||||
|
import { createSuccessfulRemoteDataObject$ } from '../../../../shared/remote-data.utils';
|
||||||
|
import { TruncatableService } from '../../../../shared/truncatable/truncatable.service';
|
||||||
|
import { TruncatePipe } from '../../../../shared/utils/truncate.pipe';
|
||||||
|
import { IIIFComponent } from './iiif.component';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { RelationshipService } from '../../../../core/data/relationship.service';
|
||||||
|
|
||||||
|
let comp: IIIFComponent;
|
||||||
|
let fixture: ComponentFixture<IIIFComponent>;
|
||||||
|
|
||||||
|
const mockItem: Item = Object.assign(new Item(), {
|
||||||
|
bundles: createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [])),
|
||||||
|
metadata: {
|
||||||
|
'dc.identifier.citation': [
|
||||||
|
{
|
||||||
|
language: 'en_US',
|
||||||
|
value: 'issue'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'dc.identifier.uri': [
|
||||||
|
{
|
||||||
|
language: 'en_US',
|
||||||
|
value: 'uri'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
,
|
||||||
|
'dc.identifier.other': [
|
||||||
|
{
|
||||||
|
language: 'en_US',
|
||||||
|
value: 'other'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('IIIFComponent', () => {
|
||||||
|
const mockBitstreamDataService = {
|
||||||
|
getThumbnailFor(item: Item): Observable<RemoteData<Bitstream>> {
|
||||||
|
return createSuccessfulRemoteDataObject$(new Bitstream());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
beforeEach(waitForAsync(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [TranslateModule.forRoot({
|
||||||
|
loader: {
|
||||||
|
provide: TranslateLoader,
|
||||||
|
useClass: TranslateLoaderMock
|
||||||
|
}
|
||||||
|
})],
|
||||||
|
declarations: [IIIFComponent, GenericItemPageFieldComponent, TruncatePipe],
|
||||||
|
providers: [
|
||||||
|
{ provide: ItemDataService, useValue: {} },
|
||||||
|
{ provide: TruncatableService, useValue: {} },
|
||||||
|
{ provide: RelationshipService, useValue: {} },
|
||||||
|
{ provide: ObjectCacheService, useValue: {} },
|
||||||
|
{ provide: UUIDService, useValue: {} },
|
||||||
|
{ provide: Store, useValue: {} },
|
||||||
|
{ provide: RemoteDataBuildService, useValue: {} },
|
||||||
|
{ provide: CommunityDataService, useValue: {} },
|
||||||
|
{ provide: HALEndpointService, useValue: {} },
|
||||||
|
{ provide: HttpClient, useValue: {} },
|
||||||
|
{ provide: DSOChangeAnalyzer, useValue: {} },
|
||||||
|
{ provide: NotificationsService, useValue: {} },
|
||||||
|
{ provide: DefaultChangeAnalyzer, useValue: {} },
|
||||||
|
{ provide: BitstreamDataService, useValue: mockBitstreamDataService },
|
||||||
|
],
|
||||||
|
|
||||||
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
}).overrideComponent(IIIFComponent, {
|
||||||
|
set: { changeDetection: ChangeDetectionStrategy.Default }
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(waitForAsync(() => {
|
||||||
|
fixture = TestBed.createComponent(IIIFComponent);
|
||||||
|
comp = fixture.componentInstance;
|
||||||
|
comp.object = mockItem;
|
||||||
|
fixture.detectChanges();
|
||||||
|
}));
|
||||||
|
it(`should set searchable attribute to false`, () => {
|
||||||
|
const miradorEl = fixture.debugElement.query(By.css('ds-mirador-viewer'));
|
||||||
|
expect(miradorEl.nativeElement.getAttribute('searchable')).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const key of Object.keys(mockItem.metadata)) {
|
||||||
|
it(`should be calling a component with metadata field ${key}`, () => {
|
||||||
|
const fields = fixture.debugElement.queryAll(By.css('.item-page-fields'));
|
||||||
|
expect(containsFieldInput(fields, key)).toBeTruthy();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function containsFieldInput(fields: DebugElement[], metadataKey: string): boolean {
|
||||||
|
for (const field of fields) {
|
||||||
|
const fieldComp = field.componentInstance;
|
||||||
|
if (isNotEmpty(fieldComp.fields)) {
|
||||||
|
if (fieldComp.fields.indexOf(metadataKey) > -1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
@@ -0,0 +1,24 @@
|
|||||||
|
import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||||
|
import { ViewMode } from '../../../../core/shared/view-mode.model';
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import {ItemComponent} from '../../../../+item-page/simple/item-types/shared/item.component';
|
||||||
|
|
||||||
|
@listableObjectComponent('IIIF', ViewMode.StandalonePage)
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-iiif',
|
||||||
|
styleUrls: ['./iiif.component.scss'],
|
||||||
|
templateUrl: './iiif.component.html'
|
||||||
|
})
|
||||||
|
|
||||||
|
export class IIIFComponent extends ItemComponent implements OnInit {
|
||||||
|
|
||||||
|
searchable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load iiif viewer in no search configuration.
|
||||||
|
*/
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.searchable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,3 @@
|
|||||||
|
<p class="full-text-op">{{'iiifviewer.fullscreen.notice' | translate}}</p>
|
||||||
|
<iframe title="Mirador Viewer" allowtransparency="true" [src]="iframeViewerUrl | async" id="mirador-viewer"></iframe>
|
||||||
|
|
@@ -0,0 +1,13 @@
|
|||||||
|
#mirador-viewer {
|
||||||
|
border: 1px solid #cccccc;
|
||||||
|
height: 660px;
|
||||||
|
width: 100%
|
||||||
|
}
|
||||||
|
.full-text-op {
|
||||||
|
text-align: right;
|
||||||
|
color: #999999;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
p.full-text-op {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
@@ -0,0 +1,94 @@
|
|||||||
|
import {ChangeDetectionStrategy, Component, Inject, Input, OnInit, PLATFORM_ID} from '@angular/core';
|
||||||
|
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
|
||||||
|
import { Item } from '../../../core/shared/item.model';
|
||||||
|
import { environment } from '../../../../environments/environment';
|
||||||
|
import { BitstreamDataService } from '../../../core/data/bitstream-data.service';
|
||||||
|
import { getFirstCompletedRemoteData } from '../../../core/shared/operators';
|
||||||
|
import { RemoteData } from '../../../core/data/remote-data';
|
||||||
|
import { PaginatedList } from '../../../core/data/paginated-list.model';
|
||||||
|
import { Bitstream } from '../../../core/shared/bitstream.model';
|
||||||
|
import { hasValue } from '../../../shared/empty.util';
|
||||||
|
import { Observable } from 'rxjs/internal/Observable';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
import {isPlatformBrowser} from '@angular/common';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-mirador-viewer',
|
||||||
|
styleUrls: ['./mirador-viewer.component.scss'],
|
||||||
|
templateUrl: './mirador-viewer.component.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
|
})
|
||||||
|
export class MiradorViewerComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input() item: Item;
|
||||||
|
|
||||||
|
@Input() query: string;
|
||||||
|
|
||||||
|
@Input() searchable: boolean;
|
||||||
|
|
||||||
|
iframeViewerUrl: Observable<SafeResourceUrl>;
|
||||||
|
|
||||||
|
multi = false;
|
||||||
|
|
||||||
|
notMobile = false;
|
||||||
|
|
||||||
|
constructor(private sanitizer: DomSanitizer,
|
||||||
|
private bitstreamDataService: BitstreamDataService,
|
||||||
|
@Inject(PLATFORM_ID) private platformId: any) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the url for the Mirador iframe. Adds parameters for the displaying the search panel, query results,
|
||||||
|
* or multi-page thumbnail navigation.
|
||||||
|
*/
|
||||||
|
setURL() {
|
||||||
|
// The path to the REST manifest endpoint.
|
||||||
|
const manifestApiEndpoint = encodeURIComponent(environment.rest.baseUrl + '/api/iiif/'
|
||||||
|
+ this.item.id + '/manifest');
|
||||||
|
// The Express path to Mirador viewer.
|
||||||
|
let viewerPath = '/iiif/mirador/index.html?manifest=' + manifestApiEndpoint;
|
||||||
|
if (this.searchable) {
|
||||||
|
// Tell the viewer add search to menu.
|
||||||
|
viewerPath += '&searchable=' + this.searchable;
|
||||||
|
}
|
||||||
|
if (this.query) {
|
||||||
|
// Tell the viewer to execute a search for the query term.
|
||||||
|
viewerPath += '&query=' + this.query;
|
||||||
|
}
|
||||||
|
if (this.multi) {
|
||||||
|
// Tell the viewer to add thumbnail navigation. If searchable, thumbnail navigation is added by default.
|
||||||
|
viewerPath += '&multi=' + this.multi;
|
||||||
|
}
|
||||||
|
if (this.notMobile) {
|
||||||
|
viewerPath += '¬Mobile=true';
|
||||||
|
}
|
||||||
|
// TODO: review whether the item.id should be sanitized. The query term should be (check mirador viewer).
|
||||||
|
return this.sanitizer.bypassSecurityTrustResourceUrl(viewerPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
/**
|
||||||
|
* Initializes the iframe url observable.
|
||||||
|
*/
|
||||||
|
if (isPlatformBrowser(this.platformId)) {
|
||||||
|
if (window.innerWidth > 768) {
|
||||||
|
this.notMobile = true;
|
||||||
|
}
|
||||||
|
this.iframeViewerUrl = this.bitstreamDataService
|
||||||
|
.findAllByItemAndBundleName(this.item, 'IIIF', {})
|
||||||
|
.pipe(
|
||||||
|
getFirstCompletedRemoteData(),
|
||||||
|
map((bitstreamsRD: RemoteData<PaginatedList<Bitstream>>) => {
|
||||||
|
if (hasValue(bitstreamsRD.payload)) {
|
||||||
|
if (bitstreamsRD.payload.totalElements > 2) {
|
||||||
|
/* IIIF bundle contains multiple images. The IIIF bundle also contains
|
||||||
|
* a single json file so multi is true only when count is 3 or more . */
|
||||||
|
this.multi = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.setURL();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -188,6 +188,7 @@ import { MissingTranslationHelper } from './translate/missing-translation.helper
|
|||||||
import { ItemVersionsNoticeComponent } from './item/item-versions/notice/item-versions-notice.component';
|
import { ItemVersionsNoticeComponent } from './item/item-versions/notice/item-versions-notice.component';
|
||||||
import { FileValidator } from './utils/require-file.validator';
|
import { FileValidator } from './utils/require-file.validator';
|
||||||
import { FileValueAccessorDirective } from './utils/file-value-accessor.directive';
|
import { FileValueAccessorDirective } from './utils/file-value-accessor.directive';
|
||||||
|
import { FileSectionComponent } from '../+item-page/simple/field-components/file-section/file-section.component';
|
||||||
import { ExistingRelationListElementComponent } from './form/builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component';
|
import { ExistingRelationListElementComponent } from './form/builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component';
|
||||||
import { ModifyItemOverviewComponent } from '../+item-page/edit-item-page/modify-item-overview/modify-item-overview.component';
|
import { ModifyItemOverviewComponent } from '../+item-page/edit-item-page/modify-item-overview/modify-item-overview.component';
|
||||||
import { ClaimedTaskActionsLoaderComponent } from './mydspace-actions/claimed-task/switcher/claimed-task-actions-loader.component';
|
import { ClaimedTaskActionsLoaderComponent } from './mydspace-actions/claimed-task/switcher/claimed-task-actions-loader.component';
|
||||||
@@ -322,6 +323,7 @@ const COMPONENTS = [
|
|||||||
DsDatePickerInlineComponent,
|
DsDatePickerInlineComponent,
|
||||||
DsSelectComponent,
|
DsSelectComponent,
|
||||||
ErrorComponent,
|
ErrorComponent,
|
||||||
|
FileSectionComponent,
|
||||||
FormComponent,
|
FormComponent,
|
||||||
LangSwitchComponent,
|
LangSwitchComponent,
|
||||||
LoadingComponent,
|
LoadingComponent,
|
||||||
|
@@ -1998,6 +1998,28 @@
|
|||||||
"journalvolume.page.volume": "Volume",
|
"journalvolume.page.volume": "Volume",
|
||||||
|
|
||||||
|
|
||||||
|
"iiifsearchable.listelement.badge": "Document Media",
|
||||||
|
|
||||||
|
"iiifsearchable.page.titleprefix": "Document: ",
|
||||||
|
|
||||||
|
"iiifsearchable.page.doi": "Permanent Link: ",
|
||||||
|
|
||||||
|
"iiifsearchable.page.issue": "Issue: ",
|
||||||
|
|
||||||
|
"iiifsearchable.page.description": "Description: ",
|
||||||
|
|
||||||
|
"iiifviewer.fullscreen.notice": "Use full screen for better viewing.",
|
||||||
|
|
||||||
|
"iiif.listelement.badge": "Image Media",
|
||||||
|
|
||||||
|
"iiif.page.titleprefix": "Image: ",
|
||||||
|
|
||||||
|
"iiif.page.doi": "Permanent Link: ",
|
||||||
|
|
||||||
|
"iiif.page.issue": "Issue: ",
|
||||||
|
|
||||||
|
"iiif.page.description": "Description: ",
|
||||||
|
|
||||||
|
|
||||||
"loading.bitstream": "Loading bitstream...",
|
"loading.bitstream": "Loading bitstream...",
|
||||||
|
|
||||||
|
166
src/mirador-viewer/index.js
Normal file
166
src/mirador-viewer/index.js
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
import Mirador from 'mirador/dist/es/src/index';
|
||||||
|
import miradorShareDialogPlugin from 'mirador-share-plugin/es/MiradorShareDialog';
|
||||||
|
import miradorSharePlugin from 'mirador-share-plugin/es/miradorSharePlugin';
|
||||||
|
import miradorDownloadPlugin from 'mirador-dl-plugin/es/miradorDownloadPlugin';
|
||||||
|
import miradorDownloadDialog from 'mirador-dl-plugin/es/MiradorDownloadDialog';
|
||||||
|
|
||||||
|
const params = new URLSearchParams(location.search);
|
||||||
|
const manifest = params.get('manifest');
|
||||||
|
const searchOption = params.get('searchable');
|
||||||
|
const query = params.get('query');
|
||||||
|
const multi = params.get('multi');
|
||||||
|
const notMobile = params.get('notMobile');
|
||||||
|
|
||||||
|
let windowSettings = {};
|
||||||
|
let sidbarPanel = 'info';
|
||||||
|
let defaultView = 'single';
|
||||||
|
let multipleItems = false;
|
||||||
|
let thumbNavigation = 'off';
|
||||||
|
|
||||||
|
windowSettings.manifestId = manifest;
|
||||||
|
|
||||||
|
(() => {
|
||||||
|
if (searchOption) {
|
||||||
|
defaultView = 'book';
|
||||||
|
sidbarPanel = 'search';
|
||||||
|
multipleItems = true;
|
||||||
|
if (notMobile) {
|
||||||
|
thumbNavigation = 'far-right';
|
||||||
|
}
|
||||||
|
if (query !== 'null') {
|
||||||
|
windowSettings.defaultSearchQuery = query;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(multi) {
|
||||||
|
multipleItems = multi;
|
||||||
|
if (notMobile) {
|
||||||
|
thumbNavigation = 'far-right';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
(Mirador.viewer(
|
||||||
|
{
|
||||||
|
id: 'mirador',
|
||||||
|
mainMenuSettings: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
|
thumbnailNavigation: {
|
||||||
|
defaultPosition: thumbNavigation, // Which position for the thumbnail navigation to be be displayed. Other possible values are "far-bottom" or "far-right"
|
||||||
|
displaySettings: true, // Display the settings for this in WindowTopMenu
|
||||||
|
height: 120, // height of entire ThumbnailNavigation area when position is "far-bottom"
|
||||||
|
width: 100, // width of one canvas (doubled for book view) in ThumbnailNavigation area when position is "far-right"
|
||||||
|
},
|
||||||
|
themes: {
|
||||||
|
light: {
|
||||||
|
palette: {
|
||||||
|
type: 'light',
|
||||||
|
primary: {
|
||||||
|
main: '#b03727',
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: '#b03727',
|
||||||
|
},
|
||||||
|
shades: { // Shades that can be used to offset color areas of the Workspace / Window
|
||||||
|
dark: '#eeeeee',
|
||||||
|
main: '#ffffff',
|
||||||
|
light: '#ffffff',
|
||||||
|
},
|
||||||
|
highlights: {
|
||||||
|
primary: '#ffff00',
|
||||||
|
secondary: '#00BFFF',
|
||||||
|
},
|
||||||
|
search: {
|
||||||
|
default: { fillStyle: '#00BFFF', globalAlpha: 0.3 },
|
||||||
|
hovered: { fillStyle: '#00FFFF', globalAlpha: 0.3 },
|
||||||
|
selected: { fillStyle: '#ff0900', globalAlpha: 0.3 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dark: {
|
||||||
|
palette: {
|
||||||
|
type: 'dark',
|
||||||
|
primary: {
|
||||||
|
main: '#2790b0',
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: '#eeeeee',
|
||||||
|
},
|
||||||
|
highlights: {
|
||||||
|
primary: '#ffff00',
|
||||||
|
secondary: '#00BFFF',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
selectedTheme: 'light',
|
||||||
|
data: [manifest],
|
||||||
|
windows: [
|
||||||
|
windowSettings
|
||||||
|
],
|
||||||
|
miradorSharePlugin: {
|
||||||
|
dragAndDropInfoLink: 'https://iiif.io',
|
||||||
|
embedOption: {
|
||||||
|
enabled: true,
|
||||||
|
embedUrlReplacePattern: [
|
||||||
|
/.*\.edu\/(\w+)\/iiif\/manifest/,
|
||||||
|
manifest
|
||||||
|
],
|
||||||
|
syncIframeDimensions: {
|
||||||
|
height: {param: 'maxheight'},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
shareLink: {
|
||||||
|
enabled: true,
|
||||||
|
manifestIdReplacePattern: [
|
||||||
|
/\/iiif\/manifest/,
|
||||||
|
'',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
miradorDownloadPlugin: {
|
||||||
|
restrictDownloadOnSizeDefinition: false
|
||||||
|
},
|
||||||
|
window: {
|
||||||
|
allowClose: false,
|
||||||
|
// sideBarOpenByDefault: false,
|
||||||
|
allowFullscreen: true,
|
||||||
|
allowMaximize: false,
|
||||||
|
defaultView: defaultView,
|
||||||
|
sideBarOpen: notMobile,
|
||||||
|
allowTopMenuButton: true,
|
||||||
|
defaultSidebarPanelWidth: 230,
|
||||||
|
switchCanvasOnSearch: true,
|
||||||
|
views: [
|
||||||
|
{ key: 'single', behaviors: ['individuals'] },
|
||||||
|
{ key: 'book', behaviors: ['paged'] },
|
||||||
|
{ key: 'scroll', behaviors: ['continuous'] },
|
||||||
|
{ key: 'gallery' },
|
||||||
|
],
|
||||||
|
panels: {
|
||||||
|
info: true,
|
||||||
|
attribution: false,
|
||||||
|
canvas: true,
|
||||||
|
search: searchOption,
|
||||||
|
layers: false,
|
||||||
|
},
|
||||||
|
sideBarPanel: sidbarPanel
|
||||||
|
},
|
||||||
|
workspace: {
|
||||||
|
allowNewWindows: false,
|
||||||
|
showZoomControls: true,
|
||||||
|
type: 'mosaic'
|
||||||
|
},
|
||||||
|
workspaceControlPanel: {
|
||||||
|
enabled: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[
|
||||||
|
miradorShareDialogPlugin,
|
||||||
|
miradorSharePlugin,
|
||||||
|
miradorDownloadDialog,
|
||||||
|
miradorDownloadPlugin
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)(manifest);
|
10
src/mirador-viewer/mirador.html
Normal file
10
src/mirador-viewer/mirador.html
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Mirador</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="mirador"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
28
webpack/webpack.mirador.config.ts
Normal file
28
webpack/webpack.mirador.config.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
mode: 'production',
|
||||||
|
entry: {
|
||||||
|
mirador: './src/mirador-viewer/index.js'
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
path: path.resolve(__dirname, '..' , 'dist/iiif/mirador'),
|
||||||
|
filename: '[name].js'
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.html$/i,
|
||||||
|
loader: 'html-loader',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
devServer: {
|
||||||
|
contentBase: '../dist/iiif/mirador',
|
||||||
|
},
|
||||||
|
plugins: [new HtmlWebpackPlugin({
|
||||||
|
filename: 'index.html',
|
||||||
|
template: './src/mirador-viewer/mirador.html'
|
||||||
|
})]
|
||||||
|
};
|
Reference in New Issue
Block a user