From cd9c5fb25b788794225abe61cf6182ebc9ffd209 Mon Sep 17 00:00:00 2001 From: Jane Sandberg Date: Sat, 30 Mar 2019 13:19:29 -0700 Subject: [PATCH] LP1816475: Improving booking return, adding validation Signed-off-by: Jane Sandberg --- Open-ILS/src/eg2/src/app/core/format.service.ts | 8 +- .../datetime-select/datetime-select.component.html | 5 ++ .../datetime-select/datetime-select.component.ts | 10 ++- .../app/share/fm-editor/fm-editor.component.html | 3 +- .../src/app/share/fm-editor/fm-editor.component.ts | 18 +++++ .../src/app/staff/booking/pickup.component.html | 12 +-- .../eg2/src/app/staff/booking/pickup.component.ts | 60 +-------------- .../staff/booking/reservations-grid.component.html | 6 +- .../staff/booking/reservations-grid.component.ts | 85 ++++++++++++++++++++-- .../src/app/staff/booking/return.component.html | 14 ++-- .../eg2/src/app/staff/booking/return.component.ts | 61 +++++++++++++--- .../eg2/src/app/staff/booking/routing.module.ts | 6 +- Open-ILS/src/eg2/src/app/staff/nav.component.html | 2 +- Open-ILS/src/sql/Pg/950.data.seed-values.sql | 6 ++ .../upgrade/XXXX.data.booking-sticky-settings.sql | 6 ++ Open-ILS/src/templates/staff/circ/patron/index.tt2 | 2 +- Open-ILS/src/templates/staff/navbar.tt2 | 2 +- 17 files changed, 200 insertions(+), 106 deletions(-) diff --git a/Open-ILS/src/eg2/src/app/core/format.service.ts b/Open-ILS/src/eg2/src/app/core/format.service.ts index fddbed2b9a..28085e3b79 100644 --- a/Open-ILS/src/eg2/src/app/core/format.service.ts +++ b/Open-ILS/src/eg2/src/app/core/format.service.ts @@ -146,13 +146,15 @@ export class FormatService { momentizeDateString(date: string, timezone: string): Moment { const parseableFormat = this.makeFormatParseable(this.dateFormat); - if (parseableFormat.length) {return Moment(date, parseableFormat, timezone)}; - return Moment(date, timezone); + if (parseableFormat.length) { return Moment.tz(date, parseableFormat, timezone); } + // TODO: The following fallback returns the date at midnight UTC, + // rather than midnight in the local TZ + return Moment.tz(date, timezone); } momentizeDateTimeString(datetime: string, timezone: string): Moment { const parseableFormat = this.makeFormatParseable(this.dateTimeFormat); - if (parseableFormat.length) {return Moment(datetime, parseableFormat, timezone)}; + if (parseableFormat.length) { return Moment(datetime, parseableFormat, timezone); } return Moment(datetime, timezone); } diff --git a/Open-ILS/src/eg2/src/app/share/datetime-select/datetime-select.component.html b/Open-ILS/src/eg2/src/app/share/datetime-select/datetime-select.component.html index 4848dede11..891079a4e7 100644 --- a/Open-ILS/src/eg2/src/app/share/datetime-select/datetime-select.component.html +++ b/Open-ILS/src/eg2/src/app/share/datetime-select/datetime-select.component.html @@ -1,3 +1,4 @@ +error
+
+ error + {{validatorError}} +
(); + @Output() onChangeAsMoment = new EventEmitter(); stringVersion: any; // Used internally on internal input timeModel: NgbTimeStruct; @@ -70,10 +72,10 @@ export class DateTimeSelectComponent implements OnInit { } if (newDate && !isNaN(newDate)) { - console.log('newDate'); // Set component view value - this.stringVersion = this.format.transform({value: newDate, datatype: 'timestamp', datePlusTime: true}); + this.stringVersion = this.format.transform({value: newDate, datatype: 'timestamp', datePlusTime: true}); // Update form passed in view value + this.onChangeAsMoment.emit(newDate); this.onChangeAsIso.emit(newDate.toISOString()); } } diff --git a/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.html b/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.html index 747ac14cee..583bef0eab 100644 --- a/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.html +++ b/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.html @@ -50,7 +50,8 @@ [showTZ]="timezone" [timezone]="timezone" domId="{{idPrefix}}-{{field.name}}" - (onChangeAsIso)="record[field.name]($event)" + (onChangeAsMoment)="record[field.name]($event)" + [validatorError]="field.validatorError" [readOnly]="field.readOnly" initialIso="{{record[field.name]()}}"> diff --git a/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.ts b/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.ts index 789895cac5..1b13d8c5ee 100644 --- a/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.ts +++ b/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.ts @@ -59,6 +59,13 @@ export interface FmFieldOptions { // This supersedes all other isRequired specifiers. isRequiredOverride?: (field: string, record: IdlObject) => boolean; + // If this function is defined, the function will be called + // when fields change their values, to check if users are entering + // valid values, and delivering an error message if not. + // + // Currently only implemented for the datetime-select widget + validator?: (field: string, value: any, record: IdlObject) => string; + // Directly apply the readonly status of the field. // This only has an affect if the value is true. isReadonly?: boolean; @@ -324,6 +331,16 @@ export class FmRecordEditorComponent || fieldOptions.isReadonly === true || this.readonlyFieldsList.includes(field.name); + if (fieldOptions.validator) { + field.validator = fieldOptions.validator; + } else { + field.validator = (fieldName: string, value: any, record: IdlObject) => { return ''; } + } + + field.validate = (fieldName: string, value: any, record: IdlObject) => { + field.validatorError = field.validator(fieldName, value, record); } + + if (fieldOptions.isRequiredOverride) { field.isRequired = () => { return fieldOptions.isRequiredOverride(field.name, this.record); @@ -526,5 +543,6 @@ export class FmRecordEditorComponent // datatype == text / interval / editable-pkey return 'text'; } + } diff --git a/Open-ILS/src/eg2/src/app/staff/booking/pickup.component.html b/Open-ILS/src/eg2/src/app/staff/booking/pickup.component.html index 34b236f838..5073d79c3e 100644 --- a/Open-ILS/src/eg2/src/app/staff/booking/pickup.component.html +++ b/Open-ILS/src/eg2/src/app/staff/booking/pickup.component.html @@ -18,17 +18,7 @@
- - - - - - - - - +

Already picked up

diff --git a/Open-ILS/src/eg2/src/app/staff/booking/pickup.component.ts b/Open-ILS/src/eg2/src/app/staff/booking/pickup.component.ts index 57b54b1418..610b2b7d13 100644 --- a/Open-ILS/src/eg2/src/app/staff/booking/pickup.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/booking/pickup.component.ts @@ -1,5 +1,4 @@ import { Component, Input, OnInit, ViewChild } from '@angular/core'; -import { GridDataSource } from '@eg/share/grid/grid'; import { Pager } from '@eg/share/util/pager'; import {PatronService} from '@eg/staff/share/patron.service'; import {PcrudService} from '@eg/core/pcrud.service'; @@ -8,7 +7,6 @@ import {IdlObject} from '@eg/core/idl.service'; import {NetService} from '@eg/core/net.service'; import {Observable} from 'rxjs'; import {single, tap} from 'rxjs/operators'; -import {GridComponent} from '@eg/share/grid/grid.component'; import {ReservationsGridComponent} from './reservations-grid.component'; import {Router, ActivatedRoute, ParamMap} from '@angular/router'; import {ServerStoreService} from '@eg/core/server-store.service'; @@ -24,13 +22,10 @@ export class PickupComponent implements OnInit { patronId: number; retrievePatron: () => void; - @ViewChild('readyGrid') readyGrid: GridComponent; + @ViewChild('readyGrid') readyGrid: ReservationsGridComponent; @ViewChild('pickedUpGrid') pickedUpGrid: ReservationsGridComponent; - public readySource: GridDataSource; noSelectedRows: (rows: IdlObject[]) => boolean; - pickupSelected: (reservations: IdlObject[]) => void; - pickup: (reservation: IdlObject) => Observable; onlyShowCaptured = true; handleShowCapturedChange: () => void; @@ -42,7 +37,7 @@ export class PickupComponent implements OnInit { private patron: PatronService, private route: ActivatedRoute, private router: Router, - private store: ServerStoreService, + private store: ServerStoreService, private toast: ToastService ) { } @@ -60,36 +55,12 @@ export class PickupComponent implements OnInit { }).subscribe( (resp) => { this.patronBarcode = resp.card().barcode(); - this.readyGrid.reload(); + this.readyGrid.reloadGrid(); this.pickedUpGrid.reloadGrid(); }, (err) => { console.debug(err); } ); }); - this.readySource = new GridDataSource(); - this.readySource.getRows = (pager: Pager, sort: any[]) => { - const orderBy: any = {}; - let where = { - 'usr' : this.patronId, - 'pickup_time' : null, - 'start_time' : {'!=': null}, - 'cancel_time' : null - }; - if (this.onlyShowCaptured) { - where['capture_time'] = {'!=': null}; - } - - return this.pcrud.search('bresv', where, { - order_by: orderBy, - limit: pager.limit, - offset: pager.offset, - flesh: 1, - flesh_fields: {'bresv' : [ - 'usr', 'capture_staff', 'target_resource', 'target_resource_type', 'current_resource', 'request_lib', 'pickup_lib' - ] } - }); - - }; this.retrievePatron = () => { if (this.patronBarcode) { this.patron.bcSearch(this.patronBarcode).pipe(single()).subscribe( @@ -98,36 +69,13 @@ export class PickupComponent implements OnInit { ); } }; - this.noSelectedRows = (rows: IdlObject[]) => (rows.length === 0); - - this.pickupSelected = (reservations: IdlObject[]) => { - const pickupOne = (thing: IdlObject) => { - if (!thing) { return; } - this.pickup(thing).subscribe( - () => pickupOne(reservations.shift())); - }; - pickupOne(reservations.shift()); - }; - this.pickup = (reservation: IdlObject) => { - return this.net.request( - 'open-ils.circ', - 'open-ils.circ.reservation.pickup', - this.auth.token(), - {'patron_barcode': this.patronBarcode, 'reservation': reservation}) - .pipe(tap( - (success) => { - this.readyGrid.reload(); - this.pickedUpGrid.reloadGrid(); }, - (error) => { console.debug(error); } - )); - }; this.store.getItem('eg.booking.pickup.ready.only_show_captured').then(onlyCaptured => { if (onlyCaptured != null) { this.onlyShowCaptured = onlyCaptured; } }); this.handleShowCapturedChange = () => { this.onlyShowCaptured = !this.onlyShowCaptured; - this.readyGrid.reload(); + this.readyGrid.reloadGrid(); this.store.setItem('eg.booking.pickup.ready.only_show_captured', this.onlyShowCaptured); }; diff --git a/Open-ILS/src/eg2/src/app/staff/booking/reservations-grid.component.html b/Open-ILS/src/eg2/src/app/staff/booking/reservations-grid.component.html index f2ed3ba116..9fd3187bee 100644 --- a/Open-ILS/src/eg2/src/app/staff/booking/reservations-grid.component.html +++ b/Open-ILS/src/eg2/src/app/staff/booking/reservations-grid.component.html @@ -1,14 +1,15 @@ + - + @@ -39,6 +40,7 @@ idlClass="bresv" datetimeFields="start_time,end_time" hiddenFields="xact_finish,cancel_time,booking_interval" + [fieldOptions]="{start_time:{validator:startTimeShouldBeFuture}}" [readonlyFields]="listReadOnlyFields()"> (); gridSource: GridDataSource; patronBarcode: string; @@ -43,6 +46,8 @@ export class ReservationsGridComponent implements OnInit { @ViewChild('noTimezoneSetDialog') noTimezoneSetDialog: NoTimezoneSetComponent; editSelected: (rows: IdlObject[]) => void; + pickupSelected: (rows: IdlObject[]) => void; + pickupResource: (rows: IdlObject) => Observable; returnSelected: (rows: IdlObject[]) => void; returnResource: (rows: IdlObject) => Observable; cancelSelected: (rows: IdlObject[]) => void; @@ -52,12 +57,17 @@ export class ReservationsGridComponent implements OnInit { filterByCurrentResourceBarcode: () => void; listReadOnlyFields: () => string; + startTimeShouldBeFuture: (fieldName: string, value: Moment, record: IdlObject) => string; + + handleRowActivate: (row: IdlObject) => void; + reloadGrid: () => void; noSelectedRows: (rows: IdlObject[]) => boolean; notOnePatronSelected: (rows: IdlObject[]) => boolean; notOneResourceSelected: (rows: IdlObject[]) => boolean; cancelNotAppropriate: (rows: IdlObject[]) => boolean; + pickupNotAppropriate: (rows: IdlObject[]) => boolean; returnNotAppropriate: (rows: IdlObject[]) => boolean; constructor( @@ -79,6 +89,7 @@ export class ReservationsGridComponent implements OnInit { this.noTimezoneSetDialog.open(); } + this.gridSource = new GridDataSource(); this.gridSource.getRows = (pager: Pager, sort: any[]) => { @@ -92,8 +103,15 @@ export class ReservationsGridComponent implements OnInit { if (this.resource) { where['current_resource'] = this.resource; } + if (this.onlyCaptured) { + where['capture_time'] = {'!=': null}; + } + if (this.status) { - if ('pickedUp' === this.status) { + if ('pickupReady' === this.status) { + where['pickup_time'] = null; + where['start_time'] = {'!=': null}; + } else if ('pickedUp' === this.status || 'returnReady' === this.status) { where['pickup_time'] = {'!=': null}; where['return_time'] = null; } else if ('returnedToday' === this.status) { @@ -112,7 +130,7 @@ export class ReservationsGridComponent implements OnInit { 'usr', 'capture_staff', 'target_resource', 'target_resource_type', 'current_resource', 'request_lib', 'pickup_lib' ], 'au': ['card'] } }).pipe(tap((row) => { - this.org.settings('lib.timezone', row['pickup_lib']()).then((tz) => {row['timezone'] = tz['lib.timezone']}); + this.org.settings('lib.timezone', row['pickup_lib']()).then((tz) => {row['timezone'] = tz['lib.timezone'];}); })); }; @@ -155,9 +173,12 @@ export class ReservationsGridComponent implements OnInit { this.notOnePatronSelected = (rows: IdlObject[]) => (new Set(rows.map(row => row.usr().id())).size !== 1); this.notOneResourceSelected = (rows: IdlObject[]) => (new Set(rows.map(row => row.current_resource().id())).size !== 1); this.cancelNotAppropriate = (rows: IdlObject[]) => (this.noSelectedRows(rows) || ('pickedUp' === this.status)); + this.pickupNotAppropriate = (rows: IdlObject[]) => (this.noSelectedRows(rows) || ('pickupReady' !== this.status)); this.returnNotAppropriate = (rows: IdlObject[]) => { if (this.noSelectedRows(rows)) { return true; + } else if (this.status && ('pickupReady' === this.status)) { + return true; } else { rows.forEach(row => { if ((null == row.pickup_time()) || row.return_time()) { return true; } @@ -168,6 +189,15 @@ export class ReservationsGridComponent implements OnInit { this.reloadGrid = () => { this.grid.reload(); }; + this.pickupSelected = (reservations: IdlObject[]) => { + const pickupOne = (thing: IdlObject) => { + if (!thing) { return; } + this.pickupResource(thing).subscribe( + () => pickupOne(reservations.shift())); + }; + pickupOne(reservations.shift()); + }; + this.returnSelected = (reservations: IdlObject[]) => { const returnOne = (thing: IdlObject) => { if (!thing) { return; } @@ -177,6 +207,20 @@ export class ReservationsGridComponent implements OnInit { returnOne(reservations.shift()); }; + this.pickupResource = (reservation: IdlObject) => { + return this.net.request( + 'open-ils.circ', + 'open-ils.circ.reservation.pickup', + this.auth.token(), + {'patron_barcode': reservation.usr().card().barcode(), 'reservation': reservation}) + .pipe(tap( + (success) => { + this.onPickup.emit(reservation); + this.grid.reload(); }, + (error) => { console.debug(error); } + )); + }; + this.returnResource = (reservation: IdlObject) => { return this.net.request( 'open-ils.circ', @@ -188,12 +232,37 @@ export class ReservationsGridComponent implements OnInit { (error) => { console.debug(error); } )); }; + this.listReadOnlyFields = () => { - let list = "usr,xact_start,request_time,capture_time,pickup_time,return_time,capture_staff,target_resource_type,current_resource,target_resource,unrecovered,request_library,pickup_library,fine_interval,fine_amount,max_fine"; - if (this.status) { list = list + ",start_time"; } - if ('returnedToday' === this.status) { list = list + ",end_time"; } + let list = 'usr,xact_start,request_time,capture_time,pickup_time,return_time,capture_staff,target_resource_type,' + + 'current_resource,target_resource,unrecovered,request_library,pickup_library,fine_interval,fine_amount,max_fine'; + if (this.status && ('pickupReady' !== this.status)) { list = list + ',start_time'; } + if (this.status && ('returnedToday' === this.status)) { list = list + ',end_time'; } return list; - } + }; + + this.startTimeShouldBeFuture = (fieldName: string, value: Moment, record: IdlObject) => { + if (Moment(value) < Moment()) { + return 'Start time must be in the future'; + } + return ''; + }; + + this.handleRowActivate = (row: IdlObject) => { + if (this.status) { + if ('returnReady' === this.status) { + this.returnResource(row).subscribe(); + } else if ('pickupReady' === this.status) { + this.pickupResource(row).subscribe(); + } else if ('returnedToday' === this.status) { + this.toast.warning('Cannot edit this reservation'); + } else { + this.showEditDialog(row); + } + } else { + this.showEditDialog(row); + } + }; } showEditDialog(idlThing: IdlObject) { diff --git a/Open-ILS/src/eg2/src/app/staff/booking/return.component.html b/Open-ILS/src/eg2/src/app/staff/booking/return.component.html index 1743504155..0e20a91e1b 100644 --- a/Open-ILS/src/eg2/src/app/staff/booking/return.component.html +++ b/Open-ILS/src/eg2/src/app/staff/booking/return.component.html @@ -3,8 +3,8 @@ - - + +
@@ -18,14 +18,14 @@

Ready for return

- +

Returned today

- +
- +
@@ -35,10 +35,10 @@

Ready for return

- +

Returned today

- +
diff --git a/Open-ILS/src/eg2/src/app/staff/booking/return.component.ts b/Open-ILS/src/eg2/src/app/staff/booking/return.component.ts index 20d8b3549d..b00a672a63 100644 --- a/Open-ILS/src/eg2/src/app/staff/booking/return.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/booking/return.component.ts @@ -1,4 +1,8 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, ViewChild } from '@angular/core'; +import {Router, ActivatedRoute, ParamMap} from '@angular/router'; +import { NgbTabChangeEvent } from '@ng-bootstrap/ng-bootstrap'; +import {Observable} from 'rxjs'; +import {single} from 'rxjs/operators'; import { GridDataSource } from '@eg/share/grid/grid'; import { Pager } from '@eg/share/util/pager'; import {PatronService} from '@eg/staff/share/patron.service'; @@ -6,8 +10,9 @@ import {PcrudService} from '@eg/core/pcrud.service'; import {AuthService} from '@eg/core/auth.service'; import {IdlObject} from '@eg/core/idl.service'; import {NetService} from '@eg/core/net.service'; -import {Observable} from 'rxjs'; -import {single} from 'rxjs/operators'; +import {ReservationsGridComponent} from './reservations-grid.component'; +import {ServerStoreService} from '@eg/core/server-store.service'; +import {ToastService} from '@eg/share/toast/toast.service'; @Component({ @@ -20,27 +25,61 @@ export class ReturnComponent implements OnInit { patronId: number; retrievePatronByBarcode: () => void; retrievePatronByResource: () => void; + selectedTab: 'patron' | 'resource' = 'patron'; noSelectedRows: (rows: IdlObject[]) => boolean; - resetEverything: () => void; + handleTabChange: ($event: NgbTabChangeEvent) => void; + @ViewChild('patronReady') patronReady: ReservationsGridComponent; + @ViewChild('patronReturned') patronReturned: ReservationsGridComponent; + @ViewChild('resourceReady') resourceReady: ReservationsGridComponent; + @ViewChild('resourceReturned') resourceReturned: ReservationsGridComponent; constructor( private auth: AuthService, private net: NetService, private pcrud: PcrudService, - private patron: PatronService + private patron: PatronService, + private route: ActivatedRoute, + private router: Router, + private store: ServerStoreService, + private toast: ToastService ) { } ngOnInit() { + this.route.paramMap.subscribe((params: ParamMap) => { + this.patronId = +params.get('patron_id'); + if (this.patronId) { + this.pcrud.search('au', { + 'id': this.patronId, + }, { + limit: 1, + flesh: 1, + flesh_fields: {'au': ['card']} + }).subscribe( + (resp) => { + this.patronBarcode = resp.card().barcode(); + this.patronReady.reloadGrid(); + this.patronReturned.reloadGrid(); + }, (err) => { console.debug(err); } + ); + } else { + this.store.getItem('eg.booking.return.tab').then(tab => { + if (tab) { this.selectedTab = tab; } + }); + } + }); + this.retrievePatronByBarcode = () => { if (this.patronBarcode) { this.patron.bcSearch(this.patronBarcode).pipe(single()).subscribe( - resp => { this.patronId = resp[0]['id']; } + resp => { this.router.navigate(['/staff', 'booking', 'return', 'by_patron', resp[0].id]); }, + err => { this.toast.danger('No patron found with this barcode'); }, ); } }; + this.retrievePatronByResource = () => { if (this.resourceBarcode) { this.pcrud.search('brsrc', {'barcode': this.resourceBarcode}, { @@ -50,15 +89,19 @@ export class ReturnComponent implements OnInit { flesh_fields: {'brsrc': ['curr_rsrcs']}, select: {'curr_rsrcs': {'return_time': null, 'pickup_time': {'!=': null}}} }).subscribe((resp) => { - if (resp.curr_rsrcs().usr()) { - this.patronId = resp.curr_rsrcs().usr(); + if (resp.curr_rsrcs()[0].usr()) { + this.patronId = resp.curr_rsrcs()[0].usr(); + this.resourceReady.reloadGrid(); + this.resourceReturned.reloadGrid(); } }); } }; this.noSelectedRows = (rows: IdlObject[]) => (rows.length === 0); - this.resetEverything = () => { + this.handleTabChange = ($event) => { + this.store.setItem('eg.booking.return.tab', $event.nextId); + this.router.navigate(['/staff', 'booking', 'return']); this.resourceBarcode = null; this.patronBarcode = null; this.patronId = null; diff --git a/Open-ILS/src/eg2/src/app/staff/booking/routing.module.ts b/Open-ILS/src/eg2/src/app/staff/booking/routing.module.ts index b50d26ca7c..a13375e31c 100644 --- a/Open-ILS/src/eg2/src/app/staff/booking/routing.module.ts +++ b/Open-ILS/src/eg2/src/app/staff/booking/routing.module.ts @@ -26,8 +26,10 @@ const routes: Routes = [{ component: PullListComponent }, { path: 'return', - component: ReturnComponent - }, + children: [ + {path: '', component: ReturnComponent}, + {path: 'by_patron/:patron_id', component: ReturnComponent}, + ]}, ]; @NgModule({ diff --git a/Open-ILS/src/eg2/src/app/staff/nav.component.html b/Open-ILS/src/eg2/src/app/staff/nav.component.html index 0aa6dae9dd..0fab3aa5e9 100644 --- a/Open-ILS/src/eg2/src/app/staff/nav.component.html +++ b/Open-ILS/src/eg2/src/app/staff/nav.component.html @@ -298,7 +298,7 @@ trending_up Pick Up Reservations - + trending_down Return Reservations diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql index 02fd4d3bba..147fa93c09 100644 --- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql +++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql @@ -19921,6 +19921,12 @@ VALUES ( 'Sticky setting for filter tab in Manage Reservations', 'cwst', 'label') ), ( + 'eg.booking.return.tab', 'gui', 'string', + oils_i18n_gettext( + 'booking.return.tab', + 'Sticky setting for tab in Booking Return', + 'cwst', 'label') +), ( 'eg.booking.pickup.ready.only_show_captured', 'gui', 'bool', oils_i18n_gettext( 'booking.pickup.ready.only_show_captured', diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.data.booking-sticky-settings.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.data.booking-sticky-settings.sql index 2741f17372..47555f4168 100644 --- a/Open-ILS/src/sql/Pg/upgrade/XXXX.data.booking-sticky-settings.sql +++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.data.booking-sticky-settings.sql @@ -26,6 +26,12 @@ VALUES ( 'Sticky setting for filter tab in Manage Reservations', 'cwst', 'label') ), ( + 'eg.booking.return.tab', 'gui', 'string', + oils_i18n_gettext( + 'booking.return.tab', + 'Sticky setting for tab in Booking Return', + 'cwst', 'label') +), ( 'eg.booking.pickup.ready.only_show_captured', 'gui', 'bool', oils_i18n_gettext( 'booking.pickup.ready.only_show_captured', diff --git a/Open-ILS/src/templates/staff/circ/patron/index.tt2 b/Open-ILS/src/templates/staff/circ/patron/index.tt2 index e151ede31b..50b9494272 100644 --- a/Open-ILS/src/templates/staff/circ/patron/index.tt2 +++ b/Open-ILS/src/templates/staff/circ/patron/index.tt2 @@ -224,7 +224,7 @@ angular.module('egCoreMod').run(['egStrings', function(s) {
  • - + [% l('Booking: Return Reservations') %]
  • diff --git a/Open-ILS/src/templates/staff/navbar.tt2 b/Open-ILS/src/templates/staff/navbar.tt2 index 2e839b05c1..7ed79f1f7b 100644 --- a/Open-ILS/src/templates/staff/navbar.tt2 +++ b/Open-ILS/src/templates/staff/navbar.tt2 @@ -456,7 +456,7 @@
  • - + [% l('Return Reservations') %] -- 2.11.0