mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-05 13:02:54 +00:00
feat: add library account screens
This commit is contained in:
@@ -63,6 +63,7 @@ import {DebugDataCollectorService} from './modules/data/debug-data-collector.ser
|
||||
import {Browser} from './util/browser.factory';
|
||||
import {browserFactory} from './util/browser.factory';
|
||||
import {AuthModule} from './modules/auth/auth.module';
|
||||
import {LibraryModule} from './modules/library/library.module';
|
||||
|
||||
registerLocaleData(localeDe);
|
||||
|
||||
@@ -158,6 +159,7 @@ const providers: Provider[] = [
|
||||
EndSessionPageModule,
|
||||
IonicModule.forRoot(),
|
||||
FavoritesModule,
|
||||
LibraryModule,
|
||||
HttpClientModule,
|
||||
ProfilePageModule,
|
||||
FeedbackModule,
|
||||
|
||||
@@ -22,6 +22,8 @@ import {HttpClient} from '@angular/common/http';
|
||||
import {DataProvider} from '../data/data.provider';
|
||||
import {SCHebisSearchRoute} from './protocol/route';
|
||||
|
||||
const HEBIS_PREFIX = 'HEB';
|
||||
|
||||
/**
|
||||
* Generated class for the DataProvider provider.
|
||||
*
|
||||
@@ -72,10 +74,17 @@ export class HebisDataProvider extends DataProvider {
|
||||
* All results will be returned if no size is set in the request.
|
||||
*
|
||||
* @param searchRequest Search request
|
||||
* @param options Search options
|
||||
* @param options.addPrefix Add HeBIS prefix (useful when having only an ID, e.g. when using PAIA)
|
||||
*/
|
||||
async hebisSearch(
|
||||
searchRequest: SCHebisSearchRequest,
|
||||
options?: {addPrefix: boolean},
|
||||
): Promise<SCHebisSearchResponse> {
|
||||
if (options?.addPrefix) {
|
||||
searchRequest.query = [HEBIS_PREFIX, searchRequest.query].join('');
|
||||
}
|
||||
|
||||
let page: number | undefined = searchRequest.page;
|
||||
|
||||
if (typeof page === 'undefined') {
|
||||
|
||||
33
src/app/modules/library/account/account.page.html
Normal file
33
src/app/modules/library/account/account.page.html
Normal file
@@ -0,0 +1,33 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button></ion-back-button>
|
||||
<ion-menu-button></ion-menu-button>
|
||||
</ion-buttons>
|
||||
<ion-title>{{ 'library.account.title' | translate | titlecase }}</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<p *ngIf="name">
|
||||
{{ 'library.account.greeting' | translate | titlecase }}
|
||||
{{ name | firstLastName }}!
|
||||
{{ 'library.account.login.success' | translate }}
|
||||
</p>
|
||||
<ion-item [routerLink]="['profile']">
|
||||
<ion-icon name="person" slot="start"></ion-icon
|
||||
>{{ 'library.account.pages.profile.title' | translate | titlecase }}
|
||||
</ion-item>
|
||||
<ion-item [routerLink]="['holds-and-reservations']">
|
||||
<ion-icon name="library" slot="start"></ion-icon
|
||||
>{{ 'library.account.pages.holds.title' | translate | titlecase }}
|
||||
</ion-item>
|
||||
<ion-item [routerLink]="['checked-out']">
|
||||
<ion-icon name="book" slot="start"></ion-icon
|
||||
>{{ 'library.account.pages.checked_out.title' | translate | titlecase }}
|
||||
</ion-item>
|
||||
<ion-item [routerLink]="['fines']">
|
||||
<ion-icon name="cash-outline" slot="start"></ion-icon
|
||||
>{{ 'library.account.pages.fines.title' | translate | titlecase }}
|
||||
</ion-item>
|
||||
</ion-content>
|
||||
4
src/app/modules/library/account/account.page.scss
Normal file
4
src/app/modules/library/account/account.page.scss
Normal file
@@ -0,0 +1,4 @@
|
||||
ion-content {
|
||||
--padding-start: 8px;
|
||||
--padding-top: 8px;
|
||||
}
|
||||
22
src/app/modules/library/account/account.page.ts
Normal file
22
src/app/modules/library/account/account.page.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import {Component} from '@angular/core';
|
||||
import {LibraryAccountService} from './library-account.service';
|
||||
// import {Router} from '@angular/router';
|
||||
|
||||
@Component({
|
||||
templateUrl: './account.page.html',
|
||||
styleUrls: ['./account.page.scss'],
|
||||
})
|
||||
export class LibraryAccountPageComponent {
|
||||
name: string;
|
||||
|
||||
constructor(private readonly libraryAccountService: LibraryAccountService) {}
|
||||
|
||||
async ionViewWillEnter(): Promise<void> {
|
||||
try {
|
||||
const patron = await this.libraryAccountService.getProfile();
|
||||
this.name = patron.name;
|
||||
} catch {
|
||||
// this.router.navigate(['profile']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button></ion-back-button>
|
||||
<ion-menu-button></ion-menu-button>
|
||||
</ion-buttons>
|
||||
<ion-title>{{
|
||||
'library.account.pages.checked_out.title' | translate | titlecase
|
||||
}}</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<ng-container *ngIf="checkedOutItems">
|
||||
<stapps-paia-item
|
||||
*ngFor="let checkedOutItem of checkedOutItems"
|
||||
[item]="checkedOutItem"
|
||||
pageName="checked_out"
|
||||
>
|
||||
</stapps-paia-item>
|
||||
</ng-container>
|
||||
</ion-content>
|
||||
@@ -0,0 +1,23 @@
|
||||
import {Component} from '@angular/core';
|
||||
import {PAIADocument} from '../../types';
|
||||
import {LibraryAccountService} from '../library-account.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-checked-out',
|
||||
templateUrl: './checked-out-page.component.html',
|
||||
styleUrls: ['./checked-out-page.component.scss'],
|
||||
})
|
||||
export class CheckedOutPageComponent {
|
||||
checkedOutItems: PAIADocument[];
|
||||
|
||||
constructor(private readonly libraryAccountService: LibraryAccountService) {}
|
||||
|
||||
async ionViewWillEnter(): Promise<void> {
|
||||
try {
|
||||
this.checkedOutItems =
|
||||
await this.libraryAccountService.getCheckedOutItems();
|
||||
} catch {
|
||||
// TODO: error handling
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<!--
|
||||
~ Copyright (C) 2022 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/>.
|
||||
-->
|
||||
|
||||
<ion-card class="bold-header">
|
||||
<ion-card-header *ngIf="book">{{ book.name }}</ion-card-header>
|
||||
<ion-card-content>
|
||||
<ion-grid *ngFor="let property of additionalPropertiesToShow">
|
||||
<ion-row *ngIf="item[property]">
|
||||
<ion-col>
|
||||
{{
|
||||
'library.account.pages' +
|
||||
'.' +
|
||||
pageName +
|
||||
'.' +
|
||||
'labels' +
|
||||
'.' +
|
||||
property
|
||||
| translate
|
||||
| titlecase
|
||||
}}:</ion-col
|
||||
>
|
||||
<ion-col width-60 text-right>{{ item[property] }}</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
</ion-card-content>
|
||||
</ion-card>
|
||||
@@ -0,0 +1,14 @@
|
||||
/*!
|
||||
* Copyright (C) 2022 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/>.
|
||||
*/
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 {Component, Input} from '@angular/core';
|
||||
import {PAIADocument} from '../../../types';
|
||||
import {SCArticle, SCBook, SCPeriodical} from '@openstapps/core';
|
||||
import {LibraryAccountService} from '../../library-account.service';
|
||||
|
||||
@Component({
|
||||
selector: 'stapps-paia-item',
|
||||
templateUrl: './paiaitem.component.html',
|
||||
styleUrls: ['./paiaitem.component.scss'],
|
||||
})
|
||||
export class PAIAItemComponent {
|
||||
book?: SCBook | SCPeriodical | SCArticle;
|
||||
|
||||
private _item: PAIADocument;
|
||||
|
||||
additionalPropertiesToShow: (keyof PAIADocument)[] = [
|
||||
'about',
|
||||
'endtime',
|
||||
'label',
|
||||
];
|
||||
|
||||
@Input()
|
||||
set item(item: PAIADocument) {
|
||||
this._item = item;
|
||||
this.libraryAccountService
|
||||
.getDocumentFromHDS(item.edition as string)
|
||||
.then(book => {
|
||||
this.book = book;
|
||||
});
|
||||
}
|
||||
|
||||
get item() {
|
||||
return this._item;
|
||||
}
|
||||
|
||||
@Input()
|
||||
pageName: string;
|
||||
|
||||
constructor(private readonly libraryAccountService: LibraryAccountService) {}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button></ion-back-button>
|
||||
<ion-menu-button></ion-menu-button>
|
||||
</ion-buttons>
|
||||
<ion-title>{{
|
||||
'library.account.pages.fines.title' | translate | titlecase
|
||||
}}</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<ion-card *ngFor="let fine of fines" class="bold-header">
|
||||
<ion-card-header *ngIf="fine.about">{{ fine.about }}</ion-card-header>
|
||||
<ion-card-content>
|
||||
<ion-grid *ngFor="let property of additionalPropertiesToShow">
|
||||
<ion-row *ngIf="fine[property]">
|
||||
<ion-col>
|
||||
{{
|
||||
'library.account.pages.fines.labels' + '.' + property
|
||||
| translate
|
||||
| titlecase
|
||||
}}:</ion-col
|
||||
>
|
||||
<ion-col width-60 text-right>{{ fine[property] }}</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
</ion-card-content>
|
||||
</ion-card>
|
||||
<ion-grid *ngIf="amount">
|
||||
<ion-row *ngIf="amount">
|
||||
<ion-col>
|
||||
{{
|
||||
'library.account.pages.fines.labels.amount' | translate | titlecase
|
||||
}}:
|
||||
</ion-col>
|
||||
<ion-col>
|
||||
{{ amount }}
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
</ion-content>
|
||||
@@ -0,0 +1,46 @@
|
||||
import {Component} from '@angular/core';
|
||||
import {LibraryAccountService} from '../library-account.service';
|
||||
import {PAIAFee, PAIAFees} from '../../types';
|
||||
|
||||
@Component({
|
||||
selector: 'app-fines',
|
||||
templateUrl: './fines-page.component.html',
|
||||
styleUrls: ['./fines-page.component.scss'],
|
||||
})
|
||||
export class FinesPageComponent {
|
||||
amount: string | undefined;
|
||||
|
||||
additionalPropertiesToShow: (keyof PAIAFee)[] = [
|
||||
'item',
|
||||
'date',
|
||||
'feetype',
|
||||
'feeid',
|
||||
];
|
||||
|
||||
fines: PAIAFee[];
|
||||
|
||||
constructor(private readonly libraryAccountService: LibraryAccountService) {}
|
||||
|
||||
async ionViewWillEnter(): Promise<void> {
|
||||
let fees: PAIAFees;
|
||||
try {
|
||||
fees = await this.libraryAccountService.getFees();
|
||||
this.amount = fees.amount;
|
||||
this.fines = this.cleanUp(fees.fee);
|
||||
} catch {
|
||||
// TODO: error handling
|
||||
}
|
||||
}
|
||||
|
||||
private cleanUp(fines: PAIAFee[]): PAIAFee[] {
|
||||
for (const fine of fines) {
|
||||
for (const property in fine) {
|
||||
// remove properties with "null" included
|
||||
if (fine[<keyof PAIAFee>property]?.includes('null')) {
|
||||
delete fine.item;
|
||||
}
|
||||
}
|
||||
}
|
||||
return fines;
|
||||
}
|
||||
}
|
||||
10
src/app/modules/library/account/first-last-name.pipe.ts
Normal file
10
src/app/modules/library/account/first-last-name.pipe.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import {Pipe, PipeTransform} from '@angular/core';
|
||||
|
||||
@Pipe({
|
||||
name: 'firstLastName',
|
||||
})
|
||||
export class FirstLastNamePipe implements PipeTransform {
|
||||
transform(value: string): unknown {
|
||||
return value.split(', ').reverse().join(' ');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button></ion-back-button>
|
||||
<ion-menu-button></ion-menu-button>
|
||||
</ion-buttons>
|
||||
<ion-title>{{
|
||||
'library.account.pages.holds.title' | translate | titlecase
|
||||
}}</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<ng-container *ngIf="holds">
|
||||
<stapps-paia-item *ngFor="let hold of holds" [item]="hold" pageName="holds">
|
||||
</stapps-paia-item>
|
||||
</ng-container>
|
||||
</ion-content>
|
||||
@@ -0,0 +1,22 @@
|
||||
import {Component} from '@angular/core';
|
||||
import {LibraryAccountService} from '../library-account.service';
|
||||
import {PAIADocument} from '../../types';
|
||||
|
||||
@Component({
|
||||
selector: 'app-holds-and-reservations',
|
||||
templateUrl: './holds-and-reservations-page.component.html',
|
||||
styleUrls: ['./holds-and-reservations-page.component.scss'],
|
||||
})
|
||||
export class HoldsAndReservationsPageComponent {
|
||||
holds: PAIADocument[];
|
||||
|
||||
constructor(private readonly libraryAccountService: LibraryAccountService) {}
|
||||
|
||||
async ionViewWillEnter(): Promise<void> {
|
||||
try {
|
||||
this.holds = await this.libraryAccountService.getHoldsAndReservations();
|
||||
} catch {
|
||||
// TODO: error handling
|
||||
}
|
||||
}
|
||||
}
|
||||
100
src/app/modules/library/account/library-account.service.ts
Normal file
100
src/app/modules/library/account/library-account.service.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
// import {ConfigProvider} from '../../config/config.provider';
|
||||
import {PAIAAuthService} from '../../auth/paia/paia-auth.service';
|
||||
import {JQueryRequestor, Requestor} from '@openid/appauth';
|
||||
import {SCFeatureConfigurationExtern, SCMap} from '@openstapps/core';
|
||||
import {PAIADocumentStatus, PAIAFees, PAIAItems, PAIAPatron} from '../types';
|
||||
import {HebisDataProvider} from '../../hebis/hebis-data.provider';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class LibraryAccountService {
|
||||
// TODO: must come from backend (not that stable)
|
||||
private _config: SCMap<SCFeatureConfigurationExtern> = {
|
||||
profile: {
|
||||
url: 'https://hds.hebis.de:8443/core/{patron}',
|
||||
},
|
||||
items: {
|
||||
url: 'https://hds.hebis.de:8443/core/{patron}/items',
|
||||
},
|
||||
fees: {
|
||||
url: 'https://hds.hebis.de:8443/core/{patron}/fees',
|
||||
},
|
||||
};
|
||||
|
||||
constructor(
|
||||
protected requestor: Requestor = new JQueryRequestor(),
|
||||
private readonly paiaAuth: PAIAAuthService,
|
||||
private readonly hebisDataProvider: HebisDataProvider,
|
||||
) {}
|
||||
|
||||
get config() {
|
||||
return this._config;
|
||||
}
|
||||
|
||||
async getProfile() {
|
||||
return this.performRequest<PAIAPatron>(this.config.profile.url);
|
||||
}
|
||||
|
||||
async getItems() {
|
||||
return this.performRequest<PAIAItems>(this.config.items.url);
|
||||
}
|
||||
|
||||
async getFees() {
|
||||
return this.performRequest<PAIAFees>(this.config.fees.url);
|
||||
}
|
||||
|
||||
private async performRequest<T>(urlTemplate: string): Promise<T> {
|
||||
const token = await this.paiaAuth.getValidToken();
|
||||
const url = urlTemplate.replace('{patron}', token.patron);
|
||||
const settings: JQueryAjaxSettings = {
|
||||
url: url,
|
||||
dataType: 'json',
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Authorization': `Bearer: ${token.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
};
|
||||
|
||||
return this.requestor.xhr(settings);
|
||||
}
|
||||
|
||||
getRawId(input: string) {
|
||||
return input.split(':').pop();
|
||||
}
|
||||
|
||||
async getHoldsAndReservations() {
|
||||
return (await this.getItems()).doc.filter(document => {
|
||||
return [
|
||||
PAIADocumentStatus.Reserved,
|
||||
PAIADocumentStatus.Ordered,
|
||||
PAIADocumentStatus.Provided,
|
||||
].includes(Number(document.status));
|
||||
});
|
||||
}
|
||||
|
||||
async getCheckedOutItems() {
|
||||
return (await this.getItems()).doc.filter(document => {
|
||||
// return [PAIADocumentStatus.Held].includes(Number(document.status));
|
||||
// TODO: Put back the line above (demo purposes)
|
||||
return [PAIADocumentStatus.Rejected].includes(Number(document.status));
|
||||
});
|
||||
}
|
||||
|
||||
async getDocumentFromHDS(edition: string) {
|
||||
if (typeof edition === 'undefined') {
|
||||
return;
|
||||
}
|
||||
const response = await this.hebisDataProvider.hebisSearch(
|
||||
{
|
||||
query: this.getRawId(edition) as string,
|
||||
page: 0,
|
||||
},
|
||||
{addPrefix: true},
|
||||
);
|
||||
|
||||
return response.data[0];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button></ion-back-button>
|
||||
<ion-menu-button></ion-menu-button>
|
||||
</ion-buttons>
|
||||
<ion-title>{{
|
||||
'library.account.pages.profile.title' | translate | titlecase
|
||||
}}</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<ion-grid *ngIf="patron">
|
||||
<ng-container *ngFor="let property of propertiesToShow">
|
||||
<ion-row *ngIf="patron[property]">
|
||||
<ion-col>
|
||||
{{
|
||||
'library.account.pages.profile.labels' + '.' + property
|
||||
| translate
|
||||
| titlecase
|
||||
}}:
|
||||
</ion-col>
|
||||
<ion-col>
|
||||
{{ patron[property] }}
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ng-container>
|
||||
</ion-grid>
|
||||
</ion-content>
|
||||
@@ -0,0 +1,31 @@
|
||||
import {Component} from '@angular/core';
|
||||
import {LibraryAccountService} from '../library-account.service';
|
||||
import {PAIAPatron} from '../../types';
|
||||
|
||||
@Component({
|
||||
selector: 'app-profile',
|
||||
templateUrl: './profile-page.component.html',
|
||||
styleUrls: ['./profile-page.component.scss'],
|
||||
})
|
||||
export class ProfilePageComponent {
|
||||
patron: PAIAPatron;
|
||||
|
||||
propertiesToShow: (keyof PAIAPatron)[] = [
|
||||
'name',
|
||||
'email',
|
||||
'address',
|
||||
'expires',
|
||||
'note',
|
||||
];
|
||||
|
||||
constructor(private readonly libraryAccountService: LibraryAccountService) {}
|
||||
|
||||
async ionViewWillEnter(): Promise<void> {
|
||||
try {
|
||||
this.patron = await this.libraryAccountService.getProfile();
|
||||
console.log(this.patron);
|
||||
} catch {
|
||||
// TODO: error handling
|
||||
}
|
||||
}
|
||||
}
|
||||
51
src/app/modules/library/library.module.ts
Normal file
51
src/app/modules/library/library.module.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import {NgModule} from '@angular/core';
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
import {IonicModule} from '@ionic/angular';
|
||||
import {RouterModule, Routes} from '@angular/router';
|
||||
import {TranslateModule} from '@ngx-translate/core';
|
||||
import {LibraryAccountPageComponent} from './account/account.page';
|
||||
import {AuthRoutes} from '../auth/auth-routes';
|
||||
import {ProfilePageComponent} from './account/profile/profile-page.component';
|
||||
import {CheckedOutPageComponent} from './account/checked-out/checked-out-page.component';
|
||||
import {HoldsAndReservationsPageComponent} from './account/holds-and-reservations/holds-and-reservations-page.component';
|
||||
import {FinesPageComponent} from './account/fines/fines-page.component';
|
||||
import {PAIAItemComponent} from './account/elements/paia-item/paiaitem.component';
|
||||
import {FirstLastNamePipe} from './account/first-last-name.pipe';
|
||||
import {AuthGuardService} from '../auth/auth-guard.service';
|
||||
|
||||
const routes: AuthRoutes | Routes = [
|
||||
{
|
||||
path: 'library-account',
|
||||
component: LibraryAccountPageComponent,
|
||||
data: {authProvider: 'paia'},
|
||||
canActivate: [AuthGuardService],
|
||||
},
|
||||
{path: 'library-account/profile', component: ProfilePageComponent},
|
||||
{path: 'library-account/checked-out', component: CheckedOutPageComponent},
|
||||
{
|
||||
path: 'library-account/holds-and-reservations',
|
||||
component: HoldsAndReservationsPageComponent,
|
||||
},
|
||||
{path: 'library-account/fines', component: FinesPageComponent},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
RouterModule.forChild(routes),
|
||||
TranslateModule,
|
||||
],
|
||||
declarations: [
|
||||
LibraryAccountPageComponent,
|
||||
ProfilePageComponent,
|
||||
CheckedOutPageComponent,
|
||||
HoldsAndReservationsPageComponent,
|
||||
FinesPageComponent,
|
||||
PAIAItemComponent,
|
||||
FirstLastNamePipe,
|
||||
],
|
||||
})
|
||||
export class LibraryModule {}
|
||||
69
src/app/modules/library/types.ts
Normal file
69
src/app/modules/library/types.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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/>.
|
||||
*/
|
||||
|
||||
export interface PAIAPatron {
|
||||
name: string;
|
||||
email?: string;
|
||||
address?: string;
|
||||
expires?: string;
|
||||
status?: string;
|
||||
type?: string;
|
||||
note?: string;
|
||||
}
|
||||
|
||||
export interface PAIADocument {
|
||||
status: string;
|
||||
item?: string;
|
||||
edition?: string;
|
||||
about?: string;
|
||||
label?: string;
|
||||
queue?: string;
|
||||
renewals?: string;
|
||||
reminder?: string;
|
||||
endtime?: string;
|
||||
duedate?: string;
|
||||
cancancel?: boolean;
|
||||
canrenew?: boolean;
|
||||
// with locations
|
||||
condition?: unknown;
|
||||
}
|
||||
|
||||
export interface PAIAItems {
|
||||
doc: PAIADocument[];
|
||||
}
|
||||
|
||||
export interface PAIAFee {
|
||||
amount: string;
|
||||
date?: string;
|
||||
about?: string;
|
||||
item?: string;
|
||||
edition?: string;
|
||||
feetype?: string;
|
||||
feeid?: string;
|
||||
}
|
||||
|
||||
export interface PAIAFees {
|
||||
amount?: string;
|
||||
fee: PAIAFee[];
|
||||
}
|
||||
|
||||
export enum PAIADocumentStatus {
|
||||
NoRelation = 0,
|
||||
Reserved = 1,
|
||||
Ordered = 2,
|
||||
Held = 3,
|
||||
Provided = 4,
|
||||
Rejected = 5,
|
||||
}
|
||||
@@ -21,6 +21,21 @@ export class NavigationService {
|
||||
} catch (error) {
|
||||
this.logger.error(`error from loading menu entries: ${error}`);
|
||||
}
|
||||
|
||||
// TODO: move this menu item to the config (backend)
|
||||
menu[1].items.unshift({
|
||||
icon: 'library',
|
||||
route: '/library-account',
|
||||
title: 'library account',
|
||||
translations: {
|
||||
de: {
|
||||
title: 'Bibliothekskonto',
|
||||
},
|
||||
en: {
|
||||
title: 'Library account',
|
||||
},
|
||||
},
|
||||
});
|
||||
return menu;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,6 +169,61 @@
|
||||
"EMPTY_SEMESTER": "Keine Verzeichnisdaten für das ausgewählte Semester vorhanden"
|
||||
}
|
||||
},
|
||||
"library": {
|
||||
"account": {
|
||||
"title": "Bibliothekskonto",
|
||||
"greeting": "hallo",
|
||||
"login": {
|
||||
"success": "Du bist eingeloggt und kannst Dein Konto nutzen.",
|
||||
"error": "Du bist nicht eingeloggt oder deine Sitzung ist abgelaufen."
|
||||
},
|
||||
"pages": {
|
||||
"profile": {
|
||||
"title": "Deine persönlichen Daten",
|
||||
"labels": {
|
||||
"id": "Nutzer-ID",
|
||||
"name": "Name",
|
||||
"email": "E-Mail",
|
||||
"address": "Adresse",
|
||||
"expires": "Nutzungsberechtigung endet am",
|
||||
"status": "Status",
|
||||
"type": "Typ",
|
||||
"note": "Nachricht"
|
||||
}
|
||||
},
|
||||
"holds": {
|
||||
"title": "Bestellungen und Vormerkungen",
|
||||
"labels": {
|
||||
"title": "Titel",
|
||||
"about": "mehr Informationen",
|
||||
"label": "Label",
|
||||
"endtime": "voraussichtliche Verfügbarkeit"
|
||||
}
|
||||
},
|
||||
"checked_out": {
|
||||
"title": "checked out items",
|
||||
"labels": {
|
||||
"title": "Titel",
|
||||
"about": "mehr Informationen",
|
||||
"label": "Label",
|
||||
"endtime": "Leihfrist"
|
||||
}
|
||||
},
|
||||
"fines": {
|
||||
"title": "Gebühren",
|
||||
"labels": {
|
||||
"amount": "Betrag",
|
||||
"about": "Information",
|
||||
"date": "Datum",
|
||||
"item": "Artikel",
|
||||
"edition": "Ausgabe",
|
||||
"feetype": "Gebührenart",
|
||||
"feeid": "Gebühren ID"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"menu": {
|
||||
"context": {
|
||||
"title": "Kontext Menü",
|
||||
|
||||
@@ -169,6 +169,61 @@
|
||||
"EMPTY_SEMESTER": "No catalog data available for selected semester"
|
||||
}
|
||||
},
|
||||
"library": {
|
||||
"account": {
|
||||
"title": "library account",
|
||||
"greeting": "hello",
|
||||
"login": {
|
||||
"success": "You are logged-in and ready to access your account.",
|
||||
"error": "Not logged in or login expired."
|
||||
},
|
||||
"pages": {
|
||||
"profile": {
|
||||
"title": "library profile",
|
||||
"labels": {
|
||||
"id": "user ID",
|
||||
"name": "name",
|
||||
"email": "email",
|
||||
"address": "Address",
|
||||
"expires": "membership expires",
|
||||
"status": "status",
|
||||
"type": "type",
|
||||
"note": "note"
|
||||
}
|
||||
},
|
||||
"holds": {
|
||||
"title": "holds and reservations",
|
||||
"labels": {
|
||||
"title": "title",
|
||||
"about": "more information",
|
||||
"label": "label",
|
||||
"endtime": "Expected to be available"
|
||||
}
|
||||
},
|
||||
"checked_out": {
|
||||
"title": "checked out items",
|
||||
"labels": {
|
||||
"title": "title",
|
||||
"about": "more information",
|
||||
"label": "label",
|
||||
"endtime": "Loan period ends"
|
||||
}
|
||||
},
|
||||
"fines": {
|
||||
"title": "fines",
|
||||
"labels": {
|
||||
"amount": "amount",
|
||||
"about": "about",
|
||||
"date": "date",
|
||||
"item": "item",
|
||||
"edition": "edition",
|
||||
"feetype": "fee type",
|
||||
"feeid": "fee ID"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"menu": {
|
||||
"context": {
|
||||
"title": "context menu",
|
||||
|
||||
@@ -47,7 +47,6 @@ export const environment = {
|
||||
// TODO: Use Custom URL Scheme (ideally bundle ID from capacitor.config)
|
||||
redirect_url: `https://${appDomain}/auth/paia/callback`,
|
||||
scopes: '',
|
||||
// TODO: PAIA need to support PKCE, it will then work "out-of-the-box"
|
||||
pkce: true,
|
||||
} as IAuthConfig,
|
||||
},
|
||||
|
||||
@@ -82,3 +82,9 @@ ion-item, ion-card.compact {
|
||||
--width: fit-content;
|
||||
--max-width: 95%;
|
||||
}
|
||||
|
||||
ion-card.bold-header {
|
||||
ion-card-header {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user