/* * Copyright (C) 2023 StApps * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, version 3. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ import {Injectable} from '@angular/core'; import {DaiaAvailabilityResponse, DaiaHolding, DaiaService} from './protocol/response'; import {StorageProvider} from '../storage/storage.provider'; import {HttpClient, HttpHeaders} from '@angular/common/http'; import {ConfigProvider} from '../config/config.provider'; import {SCFeatureConfiguration} from '@openstapps/core'; import {NGXLogger} from 'ngx-logger'; import {TranslateService} from '@ngx-translate/core'; /** * Generated class for the DataProvider provider. * * See https://angular.io/guide/dependency-injection for more info on providers * and Angular DI. */ @Injectable({ providedIn: 'root', }) export class DaiaDataProvider { /** * TODO */ storageProvider: StorageProvider; httpClient: HttpClient; daiaServiceUrl?: string; hebisProxyUrl?: string; clientHeaders = new HttpHeaders(); /** * TODO * * @param storageProvider TODO * @param httpClient TODO * @param configProvider TODO * @param logger TODO * @param translateService TODO */ constructor( storageProvider: StorageProvider, httpClient: HttpClient, private configProvider: ConfigProvider, private readonly logger: NGXLogger, private translateService: TranslateService, ) { this.storageProvider = storageProvider; this.httpClient = httpClient; this.clientHeaders = this.clientHeaders.set('Content-Type', 'application/json'); } async getAvailability(id: string): Promise { if (typeof this.daiaServiceUrl === 'undefined') { try { const features = this.configProvider.getValue('features') as SCFeatureConfiguration; if (features.extern?.daia?.url) { this.daiaServiceUrl = features.extern?.daia?.url; } else { this.logger.error('Daia service url undefined'); return undefined; } if (features.extern?.hebisProxy?.url) { this.hebisProxyUrl = features.extern?.hebisProxy?.url; } else { this.logger.error('HeBIS proxy url undefined'); return undefined; } } catch (error) { this.logger.error(error); return undefined; } } return new Promise(resolve => this.httpClient .get(this.daiaServiceUrl as string, { params: {id, lang: this.translateService.currentLang}, }) .subscribe( (response: DaiaAvailabilityResponse) => { const holdings: DaiaHolding[] = []; if (response && Array.isArray(response.document)) { response.document.map(document => { Array.isArray(document.item) && document.item.map(element => { try { const { department: {id: departmentId, content: departmentLabel, href: departmentLink} = { id: 'noDep', content: '', href: '', }, label, about, available, storage, chronology, unavailable, } = element; const holdingStatus = this.holdingHasStatus(available || []) ? this.getHoldingStatus(available || [], unavailable || []) : undefined; const dueDate = holdingStatus === 'checked_out' ? (unavailable.find(item => item.service === 'loan') as DaiaService).expected : undefined; holdings.push({ id: element.id, department: { id: departmentId, content: departmentLabel, href: departmentLink, }, signature: label, status: holdingStatus, dueDate: dueDate, online: Array.isArray(available) && typeof available.find(item => item.service === 'remote') !== 'undefined', available: (Array.isArray(available) && available.find(item => ['openaccess', 'loan', 'presentation'].includes(item.service), )) || undefined, unavailable: (Array.isArray(unavailable) && unavailable.find(item => item.service === 'loan')) || undefined, storage, about, holdings: chronology?.about, open: (Array.isArray(available) && available.some(item => item.service === 'openaccess')) || undefined, }); } catch { // No element available } }); }); } resolve(holdings); }, error => { // handle "availability info not found" separately from the problems with getting the info if (error.status === 404) resolve([]); // eslint-disable-next-line unicorn/no-useless-undefined resolve(undefined); }, ), ); } getHoldingLink(holding: DaiaHolding, open = false) { if (typeof this.hebisProxyUrl === 'undefined') { this.logger.error('HeBIS proxy url undefined'); return; } const resourceLink = holding.available?.href; return open ? resourceLink : `${this.hebisProxyUrl}${encodeURIComponent(resourceLink as string)}`; } holdingHasStatus(available: DaiaService[]): boolean { return !available.some(item => item.service === 'remote'); } getHoldingStatus(available: DaiaService[], unavailable: DaiaService[]): DaiaHolding['status'] { const loan: {available: number; unavailable: number} = { available: available.findIndex(item => item.service === 'loan'), unavailable: unavailable.findIndex(item => item.service === 'loan'), }; const presentation: {available: number; unavailable: number} = { available: available.findIndex(item => item.service === 'presentation'), unavailable: unavailable.findIndex(item => item.service === 'presentation'), }; if (loan.unavailable !== -1 && typeof unavailable[loan.unavailable].expected !== 'undefined') { return 'checked_out'; } if ( loan.unavailable !== -1 && unavailable[loan.unavailable].limitations?.some(limitation => ['OnBuy', 'JustReturned'].includes(limitation.id), ) ) return 'not_yet_available'; if ( loan.unavailable !== -1 && unavailable[loan.unavailable].limitations?.some(limitation => ['CopyIsMissing', 'Canceled'].includes(limitation.id), ) ) return 'not_available'; if ( (loan.unavailable !== -1 && unavailable[loan.unavailable].limitations?.some(limitation => ['OnlyInHouse'].includes(limitation.id), )) || (loan.available !== -1 && available[loan.available].limitations?.some(limitation => ['ExternalLoan'].includes(limitation.id), )) || (loan.available === -1 && presentation.available !== -1 && presentation.unavailable === -1) ) return 'library_only'; if (loan.available !== -1) return 'available'; return 'unknown'; } }