From: Bill Erickson Date: Tue, 19 Feb 2019 16:04:15 +0000 (-0500) Subject: LP1806087 Catalog holds display WIP X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=5ae37c297ba99a16ffe3784051c73faac8725d16;p=working%2FEvergreen.git LP1806087 Catalog holds display WIP Signed-off-by: Bill Erickson --- diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/catalog.module.ts b/Open-ILS/src/eg2/src/app/staff/catalog/catalog.module.ts index cc30f6cc1d..d159437822 100644 --- a/Open-ILS/src/eg2/src/app/staff/catalog/catalog.module.ts +++ b/Open-ILS/src/eg2/src/app/staff/catalog/catalog.module.ts @@ -2,6 +2,7 @@ import {NgModule} from '@angular/core'; import {StaffCommonModule} from '@eg/staff/common.module'; import {CatalogCommonModule} from '@eg/share/catalog/catalog-common.module'; import {CatalogRoutingModule} from './routing.module'; +import {HoldsGridModule} from '@eg/staff/share/holds-grid/holds-grid.module'; import {CatalogComponent} from './catalog.component'; import {SearchFormComponent} from './search-form.component'; import {ResultsComponent} from './result/results.component'; @@ -21,7 +22,6 @@ import {PartsComponent} from './record/parts.component'; import {PartMergeDialogComponent} from './record/part-merge-dialog.component'; import {BrowseComponent} from './browse.component'; import {BrowseResultsComponent} from './browse/results.component'; -import {HoldsComponent} from './record/holds.component'; @NgModule({ declarations: [ @@ -41,12 +41,12 @@ import {HoldsComponent} from './record/holds.component'; PartMergeDialogComponent, BrowseComponent, BrowseResultsComponent, - HoldsComponent ], imports: [ StaffCommonModule, CatalogCommonModule, - CatalogRoutingModule + CatalogRoutingModule, + HoldsGridModule ], providers: [ StaffCatalogService, diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/record/holds.component.html b/Open-ILS/src/eg2/src/app/staff/catalog/record/holds.component.html deleted file mode 100644 index 59867a052c..0000000000 --- a/Open-ILS/src/eg2/src/app/staff/catalog/record/holds.component.html +++ /dev/null @@ -1,227 +0,0 @@ - - - - -
- -
-
-
-
-
Pickup Library
-
- - -
-
-
- - - - - - - - - - - {{cp_barcode}} - - - - - - - - - - - - - - - - {{hold.title}} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/record/holds.component.ts b/Open-ILS/src/eg2/src/app/staff/catalog/record/holds.component.ts deleted file mode 100644 index 5c281b6380..0000000000 --- a/Open-ILS/src/eg2/src/app/staff/catalog/record/holds.component.ts +++ /dev/null @@ -1,121 +0,0 @@ -import {Component, OnInit, Input, ViewChild} from '@angular/core'; -import {Observable, Observer, of} from 'rxjs'; -import {map, filter} from 'rxjs/operators'; -import {IdlObject} from '@eg/core/idl.service'; -import {NetService} from '@eg/core/net.service'; -import {OrgService} from '@eg/core/org.service'; -import {AuthService} from '@eg/core/auth.service'; -import {StaffCatalogService} from '../catalog.service'; -import {Pager} from '@eg/share/util/pager'; -import {GridDataSource} from '@eg/share/grid/grid'; -import {GridComponent} from '@eg/share/grid/grid.component'; -import {ProgressDialogComponent} from '@eg/share/dialog/progress.component'; - -@Component({ - selector: 'eg-catalog-holds', - templateUrl: 'holds.component.html' -}) -export class HoldsComponent implements OnInit { - - recId: number; - initDone = false; - gridDataSource: GridDataSource; - pickupLib: IdlObject; - holdsCount: number; - @ViewChild('holdsGrid') private holdsGrid: GridComponent; - @ViewChild('progressDialog') private progressDialog: ProgressDialogComponent; - - @Input() set recordId(id: number) { - this.recId = id; - // Only force new data collection when recordId() - // is invoked after ngInit() has already run. - if (this.initDone) { - this.holdsGrid.reload(); - } - } - - constructor( - private net: NetService, - private org: OrgService, - private auth: AuthService, - private staffCat: StaffCatalogService, - ) { - this.gridDataSource = new GridDataSource(); - } - - ngOnInit() { - this.initDone = true; - this.pickupLib = this.staffCat.searchContext.searchOrg; - - this.gridDataSource.getRows = (pager: Pager, sort: any[]) => { - // sorting not currently supported - return this.fetchHolds(pager, sort); - }; - } - - pickupLibChanged(org: IdlObject) { - this.pickupLib = org; - this.holdsGrid.reload(); - } - - fetchHolds(pager: Pager, sort: any[]): Observable { - if (!this.recId) { return of([]); } - - const orgs = this.org.descendants(this.pickupLib, true); - - const restrictions = { - is_staff_request: true, - fulfillment_time: null, - cancel_time: null, - record_id: this.recId, - pickup_lib: orgs - }; - - const orderBy: any = []; - sort.forEach(obj => { - const subObj: any = {}; - subObj[obj.name] = {dir: obj.dir, nulls: 'last'}; - orderBy.push(subObj); - }); - - let observer: Observer; - const observable = new Observable(obs => observer = obs); - - this.progressDialog.open(); - this.progressDialog.update({value: 0, max: 1}); - let first = true; - let loadCount = 0; - this.net.request( - 'open-ils.circ', - 'open-ils.circ.hold.wide_hash.stream', - this.auth.token(), restrictions, orderBy, pager.limit, pager.offset - ).subscribe( - holdData => { - - if (first) { // First response is the hold count. - this.holdsCount = Number(holdData); - first = false; - - } else { // Subsequent responses are hold data blobs - - this.progressDialog.update( - {value: ++loadCount, max: this.holdsCount}); - - observer.next(holdData); - } - }, - err => { - this.progressDialog.close(); - observer.error(err); - }, - () => { - this.progressDialog.close(); - observer.complete(); - } - ); - - return observable; - } -} - - diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/record/record.component.html b/Open-ILS/src/eg2/src/app/staff/catalog/record/record.component.html index 5f3bf73a8a..68689443d7 100644 --- a/Open-ILS/src/eg2/src/app/staff/catalog/record/record.component.html +++ b/Open-ILS/src/eg2/src/app/staff/catalog/record/record.component.html @@ -42,7 +42,9 @@ - + diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/record/record.component.ts b/Open-ILS/src/eg2/src/app/staff/catalog/record/record.component.ts index 6c935ffdcf..a0ee5c1a7e 100644 --- a/Open-ILS/src/eg2/src/app/staff/catalog/record/record.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/catalog/record/record.component.ts @@ -127,6 +127,13 @@ export class RecordComponent implements OnInit { this.bib.fleshBibUsers([summary.record]); }); } + + currentSearchOrg(): IdlObject { + if (this.staffCat && this.staffCat.searchContext) { + return this.staffCat.searchContext.searchOrg; + } + return null; + } } diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/search-form.component.ts b/Open-ILS/src/eg2/src/app/staff/catalog/search-form.component.ts index ed35231d05..785e69e682 100644 --- a/Open-ILS/src/eg2/src/app/staff/catalog/search-form.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/catalog/search-form.component.ts @@ -100,9 +100,10 @@ export class SearchFormComponent implements OnInit, AfterViewInit { try { // TODO: sometime the selector is not available in the DOM // until even later (even with setTimeouts). Need to fix this. - // Note the error is thrown selectRootElement(). + // Note the error is thrown from selectRootElement(), not the + // call to .focus() on a null reference. this.renderer.selectRootElement(selector).focus(); - } catch(E) {} + } catch (E) {} } /** diff --git a/Open-ILS/src/eg2/src/app/staff/share/holds-grid/holds-grid.component.html b/Open-ILS/src/eg2/src/app/staff/share/holds-grid/holds-grid.component.html new file mode 100644 index 0000000000..59867a052c --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/share/holds-grid/holds-grid.component.html @@ -0,0 +1,227 @@ + + + + +
+ +
+
+
+
+
Pickup Library
+
+ + +
+
+
+ + + + + + + + + + + {{cp_barcode}} + + + + + + + + + + + + + + + + {{hold.title}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/Open-ILS/src/eg2/src/app/staff/share/holds-grid/holds-grid.component.ts b/Open-ILS/src/eg2/src/app/staff/share/holds-grid/holds-grid.component.ts new file mode 100644 index 0000000000..1b840e8e7d --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/share/holds-grid/holds-grid.component.ts @@ -0,0 +1,177 @@ +import {Component, OnInit, Input, ViewChild} from '@angular/core'; +import {Observable, Observer, of} from 'rxjs'; +import {map, filter} from 'rxjs/operators'; +import {IdlObject} from '@eg/core/idl.service'; +import {NetService} from '@eg/core/net.service'; +import {OrgService} from '@eg/core/org.service'; +import {AuthService} from '@eg/core/auth.service'; +import {Pager} from '@eg/share/util/pager'; +import {GridDataSource} from '@eg/share/grid/grid'; +import {GridComponent} from '@eg/share/grid/grid.component'; +import {ProgressDialogComponent} from '@eg/share/dialog/progress.component'; + +@Component({ + selector: 'eg-holds-grid', + templateUrl: 'holds-grid.component.html' +}) +export class HoldsGridComponent implements OnInit { + + // If either are set/true, the pickup lib selector will display + @Input() initialPickupLib: number | IdlObject; + + // How to sort when no sort parameters have been applied + // via grid controls. This uses the eg-grid sort format: + // [{name: fname, dir: 'asc'}, {name: fname2, dir: 'desc'}] + @Input() defaultSort: any[]; + + initDone = false; + pickupLib: IdlObject; + holdsCount: number; + gridDataSource: GridDataSource; + @ViewChild('holdsGrid') private holdsGrid: GridComponent; + @ViewChild('progressDialog') + private progressDialog: ProgressDialogComponent; + + // Bib record ID. + _recordId: number; + @Input() set recordId(id: number) { + this._recordId = id; + if (this.initDone) { // reload on update + this.holdsGrid.reload(); + } + } + + _userId: number; + @Input() set userId(id: number) { + this._userId = id; + if (this.initDone) { + this.holdsGrid.reload(); + } + } + + // Include holds canceled on or after the provided date. + // If no value is passed, canceled holds are not displayed. + _showCanceledSince: Date; + @Input() set showCanceledSince(show: Date) { + this._showCanceledSince = show; + if (this.initDone) { // reload on update + this.holdsGrid.reload(); + } + } + + // Include holds fulfilled on or after hte provided date. + // If no value is passed, fulfilled holds are not displayed. + _showFulfilledSince: Date; + @Input() set showFulfilledSince(show: Date) { + this._showFulfilledSince = show; + if (this.initDone) { // reload on update + this.holdsGrid.reload(); + } + } + + constructor( + private net: NetService, + private org: OrgService, + private auth: AuthService, + ) { + this.gridDataSource = new GridDataSource(); + } + + ngOnInit() { + this.initDone = true; + this.pickupLib = this.org.get(this.initialPickupLib); + + this.gridDataSource.getRows = (pager: Pager, sort: any[]) => { + + if (this.defaultSort && sort.length === 0) { + // Only use initial sort if sorting has not been modified + // by the grid's own sort controls. + sort = this.defaultSort; + } + + // sorting not currently supported + return this.fetchHolds(pager, sort); + }; + } + + pickupLibChanged(org: IdlObject) { + this.pickupLib = org; + this.holdsGrid.reload(); + } + + fetchHolds(pager: Pager, sort: any[]): Observable { + + // We need at least one filter. + if (!this._recordId && !this.pickupLib && !this._userId) { + return of([]); + } + + const restrictions: any = { + is_staff_request: true, + fulfillment_time: this._showFulfilledSince ? + this._showFulfilledSince.toISOString() : null, + cancel_time: this._showCanceledSince ? + this._showCanceledSince.toISOString() : null, + }; + + if (this.pickupLib) { + restrictions.pickup_lib = + this.org.descendants(this.pickupLib, true); + } + + if (this._recordId) { + restrictions.record_id = this._recordId; + } + + if (this._userId) { + restrictions.usr_id = this._userId; + } + + const orderBy: any = []; + sort.forEach(obj => { + const subObj: any = {}; + subObj[obj.name] = {dir: obj.dir, nulls: 'last'}; + orderBy.push(subObj); + }); + + let observer: Observer; + const observable = new Observable(obs => observer = obs); + + this.progressDialog.open(); + this.progressDialog.update({value: 0, max: 1}); + let first = true; + let loadCount = 0; + this.net.request( + 'open-ils.circ', + 'open-ils.circ.hold.wide_hash.stream', + this.auth.token(), restrictions, orderBy, pager.limit, pager.offset + ).subscribe( + holdData => { + + if (first) { // First response is the hold count. + this.holdsCount = Number(holdData); + first = false; + + } else { // Subsequent responses are hold data blobs + + this.progressDialog.update( + {value: ++loadCount, max: this.holdsCount}); + + observer.next(holdData); + } + }, + err => { + this.progressDialog.close(); + observer.error(err); + }, + () => { + this.progressDialog.close(); + observer.complete(); + } + ); + + return observable; + } +} + + diff --git a/Open-ILS/src/eg2/src/app/staff/share/holds-grid/holds-grid.module.ts b/Open-ILS/src/eg2/src/app/staff/share/holds-grid/holds-grid.module.ts new file mode 100644 index 0000000000..13647291f2 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/share/holds-grid/holds-grid.module.ts @@ -0,0 +1,19 @@ +import {NgModule} from '@angular/core'; +import {StaffCommonModule} from '@eg/staff/common.module'; +import {HoldsGridComponent} from './holds-grid.component'; + +@NgModule({ + declarations: [ + HoldsGridComponent + ], + imports: [ + StaffCommonModule + ], + exports: [ + HoldsGridComponent + ], + providers: [ + ] +}) + +export class HoldsGridModule {}