diff --git a/frontend/app/src/app/modules/library/account/account.page.ts b/frontend/app/src/app/modules/library/account/account.page.ts index 93d9d0db..efa35da5 100644 --- a/frontend/app/src/app/modules/library/account/account.page.ts +++ b/frontend/app/src/app/modules/library/account/account.page.ts @@ -11,7 +11,7 @@ export class LibraryAccountPageComponent { constructor(private readonly libraryAccountService: LibraryAccountService) {} async ionViewWillEnter(): Promise { - const patron = await this.libraryAccountService.getProfile(); + const patron = await this.libraryAccountService.getPatron(); this.name = patron?.name; } } diff --git a/frontend/app/src/app/modules/library/account/checked-out/checked-out-page.component.ts b/frontend/app/src/app/modules/library/account/checked-out/checked-out-page.component.ts index 0c1a756b..0756b9a2 100644 --- a/frontend/app/src/app/modules/library/account/checked-out/checked-out-page.component.ts +++ b/frontend/app/src/app/modules/library/account/checked-out/checked-out-page.component.ts @@ -39,6 +39,8 @@ export class CheckedOutPageComponent { async fetchItems() { try { + // Prepare patron (status) for the items + await this.libraryAccountService.getPatron(); this.checkedOutItems = undefined; this.checkedOutItems = await this.libraryAccountService.getFilteredItems([PAIADocumentStatus.Held]); } catch { diff --git a/frontend/app/src/app/modules/library/account/checked-out/checked-out-page.html b/frontend/app/src/app/modules/library/account/checked-out/checked-out-page.html index 04d0b9c6..446e946c 100644 --- a/frontend/app/src/app/modules/library/account/checked-out/checked-out-page.html +++ b/frontend/app/src/app/modules/library/account/checked-out/checked-out-page.html @@ -27,7 +27,7 @@ @for (checkedOutItem of checkedOutItems; track checkedOutItem) { diff --git a/frontend/app/src/app/modules/library/account/elements/paia-item/paiaitem.component.ts b/frontend/app/src/app/modules/library/account/elements/paia-item/paiaitem.component.ts index e08546e6..c44aac2d 100644 --- a/frontend/app/src/app/modules/library/account/elements/paia-item/paiaitem.component.ts +++ b/frontend/app/src/app/modules/library/account/elements/paia-item/paiaitem.component.ts @@ -14,7 +14,8 @@ */ import {Component, EventEmitter, Input, Output} from '@angular/core'; -import {DocumentAction, PAIADocument} from '../../../types'; +import {DocumentAction, PAIADocument, PAIADocumentStatus} from '../../../types'; +import {LibraryAccountService} from '../../library-account.service'; @Component({ selector: 'stapps-paia-item', @@ -22,7 +23,21 @@ import {DocumentAction, PAIADocument} from '../../../types'; styleUrls: ['./paiaitem.scss'], }) export class PAIAItemComponent { - @Input() item: PAIADocument; + private _item: PAIADocument; + + renewable: boolean; + + constructor(private readonly libraryAccountService: LibraryAccountService) {} + + @Input() + set item(value: PAIADocument) { + this._item = value; + void this.setRenewable(); + } + + get item(): PAIADocument { + return this._item; + } @Input() propertiesToShow: (keyof PAIADocument)[]; @@ -36,4 +51,9 @@ export class PAIAItemComponent { async onClick(action: DocumentAction['action']) { this.documentAction.emit({doc: this.item, action}); } + + private async setRenewable() { + const isActive = await this.libraryAccountService.isActivePatron(); + this.renewable = isActive && Number(this.item.status) === PAIADocumentStatus.Held; + } } diff --git a/frontend/app/src/app/modules/library/account/elements/paia-item/paiaitem.html b/frontend/app/src/app/modules/library/account/elements/paia-item/paiaitem.html index 178711d1..f98bccd7 100644 --- a/frontend/app/src/app/modules/library/account/elements/paia-item/paiaitem.html +++ b/frontend/app/src/app/modules/library/account/elements/paia-item/paiaitem.html @@ -23,7 +23,7 @@ @if (item[property]) {

{{ 'library.account.pages' + '.' + listName + '.' + 'labels' + '.' + property | translate }}: - @if (!['endtime', 'duedate'].includes(property)) { + @if (!['starttime', 'duedate'].includes(property)) { {{ item[property] }} } @else { {{ $any(item[property]) | amDateFormat: 'll' }} @@ -40,7 +40,7 @@ - @if (item.canrenew) { + @if (renewable && item.canrenew) { {{ 'library.account.actions.renew.header' | translate }} diff --git a/frontend/app/src/app/modules/library/account/holds/holds-page.component.ts b/frontend/app/src/app/modules/library/account/holds/holds-page.component.ts index 0a0f2f2f..1c34e81d 100644 --- a/frontend/app/src/app/modules/library/account/holds/holds-page.component.ts +++ b/frontend/app/src/app/modules/library/account/holds/holds-page.component.ts @@ -45,6 +45,8 @@ export class HoldsPageComponent { ? [PAIADocumentStatus.Reserved] : [PAIADocumentStatus.Ordered, PAIADocumentStatus.Provided]; try { + // Prepare patron (status) for the items + await this.libraryAccountService.getPatron(); this.paiaDocuments = await this.libraryAccountService.getFilteredItems(itemsStatus); } catch { await this.libraryAccountService.handleError(); diff --git a/frontend/app/src/app/modules/library/account/holds/holds-page.html b/frontend/app/src/app/modules/library/account/holds/holds-page.html index 9e2fce72..f3d91764 100644 --- a/frontend/app/src/app/modules/library/account/holds/holds-page.html +++ b/frontend/app/src/app/modules/library/account/holds/holds-page.html @@ -58,7 +58,7 @@ @for (hold of paiaDocuments; track hold) { diff --git a/frontend/app/src/app/modules/library/account/library-account.service.ts b/frontend/app/src/app/modules/library/account/library-account.service.ts index f3d81d14..b316f039 100644 --- a/frontend/app/src/app/modules/library/account/library-account.service.ts +++ b/frontend/app/src/app/modules/library/account/library-account.service.ts @@ -20,7 +20,15 @@ import { SCFeatureConfiguration, SCFeatureConfigurationExtern, } from '@openstapps/core'; -import {DocumentAction, PAIADocument, PAIADocumentStatus, PAIAFees, PAIAItems, PAIAPatron} from '../types'; +import { + DocumentAction, + PAIADocument, + PAIADocumentStatus, + PAIAFees, + PAIAItems, + PAIAPatron, + PAIAPatronStatus, +} from '../types'; import {HebisDataProvider} from '../../hebis/hebis-data.provider'; import {PAIATokenResponse} from '../../auth/paia/paia-token-response'; import {AuthHelperService} from '../../auth/auth-helper.service'; @@ -43,6 +51,11 @@ export class LibraryAccountService { */ authType: SCAuthorizationProviderType; + /** + * Account (Patron) status + */ + private status?: PAIAPatronStatus; + constructor( protected requestor: Requestor = new JQueryRequestor(), private readonly hebisDataProvider: HebisDataProvider, @@ -60,12 +73,23 @@ export class LibraryAccountService { this.authType = config.authProvider as SCAuthorizationProviderType; } - async getProfile() { - const patron = ((await this.getValidToken()) as PAIATokenResponse).patron; - return { + async getPatron() { + const patronId = ((await this.getValidToken()) as PAIATokenResponse).patron; + const patron = { ...(await this.performRequest(`${this.baseUrl}/{patron}`)), - id: patron, + id: patronId, } as PAIAPatron; + // Refresh the status + this.status = Number(patron.status); + return patron; + } + + async getPatronStatus() { + return this.status ?? (this.status = Number((await this.getPatron()).status) as PAIAPatronStatus); + } + + async isActivePatron() { + return (await this.getPatronStatus()) === PAIAPatronStatus.Active; } async getItems() { diff --git a/frontend/app/src/app/modules/library/account/profile/profile-page.component.ts b/frontend/app/src/app/modules/library/account/profile/profile-page.component.ts index d3772aca..a2a57abb 100644 --- a/frontend/app/src/app/modules/library/account/profile/profile-page.component.ts +++ b/frontend/app/src/app/modules/library/account/profile/profile-page.component.ts @@ -25,15 +25,19 @@ import {PAIAPatron} from '../../types'; export class ProfilePageComponent { patron?: PAIAPatron; - propertiesToShow: (keyof PAIAPatron)[] = ['id', 'name', 'email', 'address', 'expires', 'note']; + propertiesToShow: (keyof PAIAPatron)[] = ['id', 'name', 'email', 'address', 'expires']; constructor(private readonly libraryAccountService: LibraryAccountService) {} async ionViewWillEnter(): Promise { try { - this.patron = await this.libraryAccountService.getProfile(); + this.patron = await this.libraryAccountService.getPatron(); } catch { await this.libraryAccountService.handleError(); } } + + isUnlimitedExpiry(date = ''): boolean { + return new Date(date).getFullYear() === 9999; + } } diff --git a/frontend/app/src/app/modules/library/account/profile/profile-page.html b/frontend/app/src/app/modules/library/account/profile/profile-page.html index 375ce7be..5a69eaed 100644 --- a/frontend/app/src/app/modules/library/account/profile/profile-page.html +++ b/frontend/app/src/app/modules/library/account/profile/profile-page.html @@ -36,11 +36,11 @@ @if (!['expires'].includes(property)) { {{ patron[property] }} } @else { - @if (patron[property] === '9999-12-31') { + @if (isUnlimitedExpiry(patron['expires'])) { {{ 'library.account.pages.profile.values.unlimited' | translate }} } @else { {{ 'library.account.pages.profile.values.expires' | translate }}: {{ - patron[property] | amDateFormat: 'll' + patron['expires'] | amDateFormat: 'll' }} } } diff --git a/frontend/app/src/app/modules/library/types.ts b/frontend/app/src/app/modules/library/types.ts index dcdf33a7..15e119e1 100644 --- a/frontend/app/src/app/modules/library/types.ts +++ b/frontend/app/src/app/modules/library/types.ts @@ -19,11 +19,19 @@ export interface PAIAPatron { email?: string; address?: string; expires?: string; - status?: string; + status?: PAIAPatronStatus; type?: string; note?: string; } +export enum PAIAPatronStatus { + Active = 0, + Inactive = 1, + InactiveExpired = 2, + InactiveOutstandingFees = 3, + InactiveExpiredOutstandingFees = 4, +} + /* * Document representing a library item received from the HeBIS PAIA service * TODO: would be good to standardize the items of HeBIS PAIA to match the official PAIA documentation @@ -39,7 +47,7 @@ export interface PAIADocument { queue?: string; renewals?: string; reminder?: string; - endtime?: string; + starttime?: string; duedate?: string; cancancel?: boolean; canrenew?: boolean; diff --git a/frontend/app/src/assets/i18n/de.json b/frontend/app/src/assets/i18n/de.json index 08d7db92..e5972956 100644 --- a/frontend/app/src/assets/i18n/de.json +++ b/frontend/app/src/assets/i18n/de.json @@ -336,8 +336,10 @@ "title": "Titel", "about": "Mehr Informationen", "label": "Signatur", + "starttime": "Übermittelt am", "endtime": "Abzuholen bis", - "storage": "Abholbereit" + "storage": "Abholtheke", + "queue": "Position in der Warteschlange" }, "holds": "Bestellungen", "reservations": "Vormerkungen" @@ -348,7 +350,7 @@ "title": "Titel", "about": "Mehr Informationen", "label": "Signatur", - "endtime": "Leihfristende", + "duedate": "Leihfristende", "renewals": "Verlängerungen" } }, diff --git a/frontend/app/src/assets/i18n/en.json b/frontend/app/src/assets/i18n/en.json index 0591313f..6f3c9c37 100644 --- a/frontend/app/src/assets/i18n/en.json +++ b/frontend/app/src/assets/i18n/en.json @@ -336,8 +336,10 @@ "title": "Title", "about": "More information", "label": "Shelfmark", + "starttime": "Submitted at", "endtime": "Available for pickup until", - "storage": "Available for pickup" + "storage": "Pick-up counter", + "queue": "Position in the queue" }, "holds": "orders", "reservations": "reservations" @@ -348,7 +350,7 @@ "title": "Title", "about": "More information", "label": "Label", - "endtime": "Due date", + "duedate": "Due date", "renewals": "Renewals" } }, diff --git a/frontend/app/src/environments/environment.production.ts b/frontend/app/src/environments/environment.production.ts index f5c55261..21d32569 100644 --- a/frontend/app/src/environments/environment.production.ts +++ b/frontend/app/src/environments/environment.production.ts @@ -21,7 +21,7 @@ export const environment = { backend_url: 'https://mobile.server.uni-frankfurt.de', app_host: 'mobile.app.uni-frankfurt.de', custom_url_scheme: 'de.anyschool.app', - backend_version: '3.1.0', + backend_version: '3.3.0', production: true, }; diff --git a/frontend/app/src/environments/environment.ts b/frontend/app/src/environments/environment.ts index d112dcef..37144be1 100644 --- a/frontend/app/src/environments/environment.ts +++ b/frontend/app/src/environments/environment.ts @@ -21,7 +21,7 @@ export const environment = { backend_url: 'https://mobile.server.uni-frankfurt.de', app_host: 'mobile.app.uni-frankfurt.de', custom_url_scheme: 'de.anyschool.app', - backend_version: '3.1.0', + backend_version: '3.3.0', production: false, };