+<eg-progress-dialog #progressDialog></eg-progress-dialog>
+
<eg-prompt-dialog #nonCatCount
promptType="number"
i18n-dialogTitle dialogTitle="Non-Cat Checkout"
</div>
<input type="text" class="form-control" id="barcode-input"
[placeholder]="checkoutNoncat ? '' : 'Barcode...'" i18n-placeholder
- [disabled]="checkoutNoncat != null"
+ [(ngModel)]="checkoutBarcode" [disabled]="checkoutNoncat != null"
i18n-aria-label aria-label="Barcode Input"/>
<div class="input-group-append">
<button class="btn btn-outline-dark" (click)="checkout()" i18n>Submit</button>
</div>
</div>
</div>
+
+<ng-template #titleTemplate let-r="row">
+ <ng-container *ngIf="r.record">
+ <a routerLink="/staff/catalog/record/{{r.record.id()}}">{{r.title}}</a>
+ </ng-container>
+ <ng-container *ngIf="!r.record">{{r.title}}</ng-container>
+</ng-template>
+
+<div class="row">
+ <div class="col-lg-12">
+ <eg-grid #checkoutsGrid [dataSource]="gridDataSource" [sortable]="true"
+ [useLocalSort]="true" [cellTextGenerator]="cellTextGenerator"
+ persistKey="circ.patron.checkout">
+ <eg-grid-column path="index" [index]="true"
+ label="Row Index" i18n-label [hidden]="true"></eg-grid-column>
+ <eg-grid-column path="circ.id" label="Circ ID" i18n-label></eg-grid-column>
+ <eg-grid-column path="title" label="Title" i18n-label
+ [cellTemplate]="titleTemplate"></eg-grid-column>
+ </eg-grid>
+ </div>
+</div>
+
+
+
+
import {Component, OnInit, AfterViewInit, Input, ViewChild} from '@angular/core';
import {Router, ActivatedRoute, ParamMap} from '@angular/router';
-import {Observable, empty, of} from 'rxjs';
+import {Observable, empty, of, from} from 'rxjs';
import {tap, switchMap} from 'rxjs/operators';
import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
import {IdlObject} from '@eg/core/idl.service';
import {PatronManagerService} from './patron.service';
import {CheckoutParams, CheckoutResult, CircService} from '@eg/staff/share/circ/circ.service';
import {PromptDialogComponent} from '@eg/share/dialog/prompt.component';
+import {GridDataSource, GridColumn, GridCellTextGenerator} from '@eg/share/grid/grid';
+import {GridComponent} from '@eg/share/grid/grid.component';
+import {Pager} from '@eg/share/util/pager';
+
+interface CircGridEntry {
+ title?: string;
+ circ?: IdlObject;
+ copyAlertCount: number;
+}
@Component({
templateUrl: 'checkout.component.html',
maxNoncats = 99; // Matches AngJS version
checkoutNoncat: IdlObject = null;
+ checkoutBarcode = '';
+ checkouts: CircGridEntry[] = [];
+ gridDataSource: GridDataSource = new GridDataSource();
+ cellTextGenerator: GridCellTextGenerator;
@ViewChild('nonCatCount') nonCatCount: PromptDialogComponent;
+ @ViewChild('checkoutsGrid') checkoutsGrid: GridComponent;
constructor(
private org: OrgService,
ngOnInit() {
this.circ.getNonCatTypes();
+
+ this.gridDataSource.getRows = (pager: Pager, sort: any[]) => {
+ return from(this.checkouts);
+ };
+
+ this.cellTextGenerator = {
+ title: row => row.title
+ };
}
ngAfterViewInit() {
+ this.focusInput();
+ }
+
+ focusInput() {
const input = document.getElementById('barcode-input');
if (input) { input.focus(); }
}
params.noncat_type = this.checkoutNoncat.id();
return params;
});
+ } else if (this.checkoutBarcode) {
+ params.copy_barcode = this.checkoutBarcode;
+ return Promise.resolve(params);
}
- return null;
+ return Promise.resolve(null);
}
checkout() {
this.collectParams()
.then((params: CheckoutParams) => {
- if (!params) { return null; }
- return this.circ.checkout(params);
+ if (params) {
+ return this.circ.checkout(params);
+ }
})
.then((result: CheckoutResult) => {
- if (!result) { return null; }
-
- // Reset the form
- this.checkoutNoncat = null;
+ if (result) {
+ if (result.success) {
+ this.gridifyResult(result);
+ this.resetForm();
+ }
+ }
});
}
+ resetForm() {
+ this.checkoutBarcode = '';
+ this.checkoutNoncat = null;
+ this.focusInput();
+ }
+
+ gridifyResult(result: CheckoutResult) {
+ const entry: CircGridEntry = {
+ circ: result.circ,
+ copyAlertCount: 0 // TODO
+ };
+
+ if (this.checkoutNoncat) {
+ entry.title = this.checkoutNoncat.name();
+ } else if (result.record) {
+ entry.title = result.record.title();
+ }
+
+ this.checkouts.unshift(entry);
+ this.checkoutsGrid.reload();
+ }
+
noncatPrompt(): Observable<number> {
return this.nonCatCount.open()
.pipe(switchMap(count => {
import {AudioService} from '@eg/share/util/audio.service';
+// API parameter options
export interface CheckoutParams {
patron_id: number;
+ copy_id?: number;
+ copy_barcode?: string;
noncat?: boolean;
noncat_type?: number;
noncat_count?: number;
+ noop?: boolean;
}
export interface CheckoutResult {
+ index: number;
+ params: CheckoutParams,
+ success: boolean;
circ?: IdlObject;
+ record?: IdlObject;
}
@Injectable()
export class CircService {
+ static resultIndex = 0;
nonCatTypes: IdlObject[] = null;
'open-ils.circ',
'open-ils.circ.checkout.full',
this.auth.token(), params
- ).toPromise().then(result => this.processCheckoutResult(result))
+ ).toPromise().then(result => this.processCheckoutResult(params, result))
}
- processCheckoutResult(response: any): Promise<CheckoutResult> {
+ processCheckoutResult(
+ params: CheckoutParams, response: any): Promise<CheckoutResult> {
+
console.debug('checkout resturned', response);
if (Array.isArray(response)) { response = response[0]; }
}
const result: CheckoutResult = {
+ index: CircService.resultIndex++,
+ params: params,
+ success: true,
circ: payload.circ
};