evt-polymorphic-models.ts 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import { HttpClient } from '@angular/common/http';
  2. import { BehaviorSubject, Observable } from 'rxjs';
  3. import { distinctUntilChanged, filter, map, switchMap } from 'rxjs/operators';
  4. import { AppConfig } from '../app.config';
  5. import { isUrl } from '../utils/js-utils';
  6. import { Surface, ViewerDataType, XMLImagesValues } from './evt-models';
  7. export interface OsdTileSource {
  8. type?: string;
  9. '@context'?: string;
  10. '@id'?: string;
  11. profile?: [];
  12. protocol?: string;
  13. url?: string;
  14. height: string;
  15. width: string;
  16. }
  17. export type ViewerDataInput = string | XMLImagesValues[];
  18. interface ViewerSource {
  19. getDataType(key: string, data?: Surface[]): ViewerDataType;
  20. getSource(source: ViewerDataType): ViewerDataInput;
  21. getTileSource(change: BehaviorSubject<ViewerDataInput>, http?: HttpClient): Observable<OsdTileSource[]>;
  22. }
  23. type ViewerConstructors<T> = {
  24. [K in keyof T]: new () => T[K];
  25. };
  26. class ViewerController<T extends Record<string, ViewerSource>> {
  27. private factories: T;
  28. constructor(classes: ViewerConstructors<T>) {
  29. this.factories = Object.fromEntries(
  30. Object.entries(classes).map(
  31. ([key, value]) => ([key, new value()]),
  32. ),
  33. ) as T;
  34. }
  35. getSource<K extends keyof T>(source: ViewerDataType, type: string | K): ReturnType<T[K]['getSource']> {
  36. return this.factories[type].getSource(source) as ReturnType<T[K]['getSource']>;
  37. }
  38. getTileSource<K extends keyof T>(change: BehaviorSubject<ViewerDataInput>, type: string | K, http?: HttpClient): ReturnType<T[K]['getTileSource']> {
  39. return this.factories[type].getTileSource(change, http) as ReturnType<T[K]['getTileSource']>;
  40. }
  41. getDataType<K extends keyof T>(type: string, data?: Surface[]): ReturnType<T[K]['getDataType']> {
  42. return this.factories[type].getDataType(type, data) as ReturnType<T[K]['getDataType']>;
  43. }
  44. }
  45. class ManifestSource {
  46. getDataType(key: string): ViewerDataType {
  47. return {
  48. type: key,
  49. value: {
  50. manifestURL: AppConfig.evtSettings.files.editionImagesSource[key].value,
  51. },
  52. };
  53. }
  54. getSource(source: ViewerDataType): string {
  55. return source.value.manifestURL;
  56. }
  57. getTileSource(change: BehaviorSubject<string>, http: HttpClient): Observable<OsdTileSource[]> {
  58. return (
  59. change
  60. .pipe(
  61. filter((url) => !!url),
  62. distinctUntilChanged(),
  63. switchMap((url) => http.get<{ sequences: Partial<Array<{ canvases }>> }>(url)),
  64. map((manifest) => manifest // get the resource fields in the manifest json structure
  65. .sequences.map((seq) => seq.canvases.map((canv) => canv.images).reduce((x, y) => x.concat(y), []))
  66. .reduce((x, y) => x.concat(y), []).map((res) => res.resource)
  67. .map(this.buildTileSource),
  68. ),
  69. )
  70. );
  71. }
  72. buildTileSource(manifestResource) {
  73. return {
  74. '@context': manifestResource.service['@context'],
  75. '@id': manifestResource.service['@id'],
  76. profile: [manifestResource.service['@profile']],
  77. protocol: 'http://iiif.io/api/image',
  78. height: manifestResource.height,
  79. width: manifestResource.width,
  80. };
  81. }
  82. }
  83. class XMLSource {
  84. getDataType(key: string, data: Surface[]): ViewerDataType {
  85. const localImagesFolder = AppConfig.evtSettings.files.imagesFolderUrl;
  86. const xmlImages: XMLImagesValues[] = data.map(s =>
  87. s[AppConfig.evtSettings.files.editionImagesSource[key].value]
  88. ? {
  89. url: isUrl(s.corresp) ? s.corresp : localImagesFolder + s.corresp,
  90. } : {
  91. width: s[key][0].width,
  92. height: s[key][0].height,
  93. url: isUrl(s[key][0].url) ? s[key][0].url : localImagesFolder + s[key][0].url,
  94. });
  95. return { type: key, value: { xmlImages } };
  96. }
  97. getSource(source: ViewerDataType): XMLImagesValues[] {
  98. return source.value.xmlImages;
  99. }
  100. getTileSource(change: BehaviorSubject<XMLImagesValues[]>): Observable<OsdTileSource[]> {
  101. return (
  102. change
  103. .pipe(
  104. map((value) => value.map(this.buildTileSource)),
  105. )
  106. );
  107. }
  108. buildTileSource(resource) {
  109. return {
  110. type: 'image',
  111. url: resource.url,
  112. width: resource.width,
  113. height: resource.height,
  114. };
  115. }
  116. }
  117. const ViewerModels = Object.freeze({
  118. manifest: ManifestSource,
  119. graphics: XMLSource,
  120. default: XMLSource,
  121. });
  122. export const ViewerSource = new ViewerController(ViewerModels);