Files
openstapps/src/app/modules/hebis/daia-data.provider.ts
2023-01-13 18:14:05 +00:00

235 lines
8.2 KiB
TypeScript

/*
* 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 <https://www.gnu.org/licenses/>.
*/
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<DaiaHolding[] | undefined> {
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<DaiaAvailabilityResponse>(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';
}
}