mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-20 08:33:11 +00:00
235 lines
8.2 KiB
TypeScript
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';
|
|
}
|
|
}
|