From 26e587b6eb55822b45331c2345b1b434c8afd1f9 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Fri, 12 Mar 2021 17:50:40 -0500 Subject: [PATCH] LP1919465 Holds pull list Angular / Wide Holds API Port Ports the holds pull list to Angular and takes advantage of the new Wide Holds API. Includes seed data for grid preferences and a new holds pull list (server) print template. The UI displays the total holds count and includes a org unit selector. It pre-fetches all holds, partly to display the full count, but also based on the assumption that a pull list will typically be used all or none. Signed-off-by: Bill Erickson Signed-off-by: Jennifer Weston Signed-off-by: Chris Sharp --- .../src/app/staff/circ/holds/holds.module.ts | 28 +++++++ .../staff/circ/holds/pull-list.component.html | 11 +++ .../staff/circ/holds/pull-list.component.ts | 30 ++++++++ .../app/staff/circ/holds/routing.module.ts | 15 ++++ .../eg2/src/app/staff/circ/routing.module.ts | 23 +++--- .../src/eg2/src/app/staff/nav.component.html | 2 +- .../app/staff/share/holds/grid.component.html | 22 +++++- .../app/staff/share/holds/grid.component.ts | 51 +++++++++--- Open-ILS/src/sql/Pg/950.data.seed-values.sql | 69 +++++++++++++++++ .../XXXX.data.pull-list-print-template.sql | 77 +++++++++++++++++++ Open-ILS/src/templates/staff/navbar.tt2 | 2 +- 11 files changed, 308 insertions(+), 22 deletions(-) create mode 100644 Open-ILS/src/eg2/src/app/staff/circ/holds/holds.module.ts create mode 100644 Open-ILS/src/eg2/src/app/staff/circ/holds/pull-list.component.html create mode 100644 Open-ILS/src/eg2/src/app/staff/circ/holds/pull-list.component.ts create mode 100644 Open-ILS/src/eg2/src/app/staff/circ/holds/routing.module.ts create mode 100644 Open-ILS/src/sql/Pg/upgrade/XXXX.data.pull-list-print-template.sql diff --git a/Open-ILS/src/eg2/src/app/staff/circ/holds/holds.module.ts b/Open-ILS/src/eg2/src/app/staff/circ/holds/holds.module.ts new file mode 100644 index 0000000000..5526c365be --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/circ/holds/holds.module.ts @@ -0,0 +1,28 @@ +import {NgModule} from '@angular/core'; +import {FmRecordEditorModule} from '@eg/share/fm-editor/fm-editor.module'; +import {StaffCommonModule} from '@eg/staff/common.module'; +import {HoldsModule} from '@eg/staff/share/holds/holds.module'; +import {HoldingsModule} from '@eg/staff/share/holdings/holdings.module'; +import {BookingModule} from '@eg/staff/share/booking/booking.module'; +import {PatronModule} from '@eg/staff/share/patron/patron.module'; +import {HoldsUiRoutingModule} from './routing.module'; +import {HoldsPullListComponent} from './pull-list.component'; + +@NgModule({ + declarations: [ + HoldsPullListComponent + ], + imports: [ + StaffCommonModule, + FmRecordEditorModule, + HoldsModule, + HoldingsModule, + BookingModule, + PatronModule, + HoldsUiRoutingModule + ], + providers: [ + ] +}) + +export class HoldsUiModule {} diff --git a/Open-ILS/src/eg2/src/app/staff/circ/holds/pull-list.component.html b/Open-ILS/src/eg2/src/app/staff/circ/holds/pull-list.component.html new file mode 100644 index 0000000000..263463a5bd --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/circ/holds/pull-list.component.html @@ -0,0 +1,11 @@ + + + + + + diff --git a/Open-ILS/src/eg2/src/app/staff/circ/holds/pull-list.component.ts b/Open-ILS/src/eg2/src/app/staff/circ/holds/pull-list.component.ts new file mode 100644 index 0000000000..ee3e696584 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/circ/holds/pull-list.component.ts @@ -0,0 +1,30 @@ +import {Component, OnInit, Input, ViewChild, HostListener} from '@angular/core'; +import {NgbTabset, NgbTabChangeEvent} from '@ng-bootstrap/ng-bootstrap'; +import {Router, ActivatedRoute, ParamMap} from '@angular/router'; +import {PcrudService} from '@eg/core/pcrud.service'; +import {IdlObject} from '@eg/core/idl.service'; +import {AuthService} from '@eg/core/auth.service'; +import {StoreService} from '@eg/core/store.service'; + +@Component({ + selector: 'eg-holds-pull-list', + templateUrl: 'pull-list.component.html' +}) +export class HoldsPullListComponent implements OnInit { + + constructor( + private router: Router, + private route: ActivatedRoute, + private pcrud: PcrudService, + private auth: AuthService, + private store: StoreService + ) {} + + ngOnInit() { + } + + targetOrg(): number { + return this.auth.user().ws_ou(); + } +} + diff --git a/Open-ILS/src/eg2/src/app/staff/circ/holds/routing.module.ts b/Open-ILS/src/eg2/src/app/staff/circ/holds/routing.module.ts new file mode 100644 index 0000000000..960eaee76a --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/circ/holds/routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule, Routes} from '@angular/router'; +import {HoldsPullListComponent} from './pull-list.component'; + +const routes: Routes = [{ + path: 'pull-list', + component: HoldsPullListComponent +}]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) + +export class HoldsUiRoutingModule {} diff --git a/Open-ILS/src/eg2/src/app/staff/circ/routing.module.ts b/Open-ILS/src/eg2/src/app/staff/circ/routing.module.ts index 49cd79aa96..0e94cc5066 100644 --- a/Open-ILS/src/eg2/src/app/staff/circ/routing.module.ts +++ b/Open-ILS/src/eg2/src/app/staff/circ/routing.module.ts @@ -1,16 +1,19 @@ import {NgModule} from '@angular/core'; import {RouterModule, Routes} from '@angular/router'; -const routes: Routes = [ - { path: 'patron', - loadChildren: () => - import('./patron/routing.module').then(m => m.CircPatronRoutingModule) - }, - { path: 'item', - loadChildren: () => - import('./item/routing.module').then(m => m.CircItemRoutingModule) - } -]; +const routes: Routes = [{ + path: 'patron', + loadChildren: () => + import('./patron/routing.module').then(m => m.CircPatronRoutingModule) +}, { + path: 'item', + loadChildren: () => + import('./item/routing.module').then(m => m.CircItemRoutingModule) +}, { + path: 'holds', + loadChildren: () => + import('./holds/holds.module').then(m => m.HoldsUiModule) +}]; @NgModule({ imports: [RouterModule.forChild(routes)], 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 bd57834dbd..6040ccf465 100644 --- a/Open-ILS/src/eg2/src/app/staff/nav.component.html +++ b/Open-ILS/src/eg2/src/app/staff/nav.component.html @@ -61,7 +61,7 @@ Capture Holds - + Pull List for Hold Requests diff --git a/Open-ILS/src/eg2/src/app/staff/share/holds/grid.component.html b/Open-ILS/src/eg2/src/app/staff/share/holds/grid.component.html index f0dce3558c..524868c2b0 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/holds/grid.component.html +++ b/Open-ILS/src/eg2/src/app/staff/share/holds/grid.component.html @@ -33,6 +33,8 @@ +

Holds Count: {{holdsCount}}

+
@@ -46,13 +48,31 @@
+
+
+
+
+
View Pull List For:
+
+ + +
+
+
+ - + + + diff --git a/Open-ILS/src/eg2/src/app/staff/share/holds/grid.component.ts b/Open-ILS/src/eg2/src/app/staff/share/holds/grid.component.ts index 3a95b05139..06247c10bf 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/holds/grid.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/share/holds/grid.component.ts @@ -33,6 +33,9 @@ export class HoldsGridComponent implements OnInit { @Input() initialPickupLib: number | IdlObject; @Input() hidePickupLibFilter: boolean; + // Setting a value here puts us into "pull list" mode. + @Input() pullListOrg: number; + // If true, only retrieve holds with a Hopeless Date // and enable related Actions @Input() hopeless: boolean; @@ -47,7 +50,7 @@ export class HoldsGridComponent implements OnInit { // If set, all holds are fetched on grid load and sorting/paging all // happens in the client. If false, sorting and paging occur on // the server. - enablePreFetch: boolean; + @Input() enablePreFetch: boolean; // How to sort when no sort parameters have been applied // via grid controls. This uses the eg-grid sort format: @@ -200,6 +203,11 @@ export class HoldsGridComponent implements OnInit { this.holdsGrid.reload(); } + pullListOrgChanged(org: IdlObject) { + this.pullListOrg = org.id(); + this.holdsGrid.reload(); + } + preFetchHolds(apply: boolean) { this.enablePreFetch = apply; @@ -215,13 +223,32 @@ export class HoldsGridComponent implements OnInit { applyFilters(): any { - const filters: any = { - is_staff_request: true, - fulfillment_time: this._showFulfilledSince ? - this._showFulfilledSince.toISOString() : null, - cancel_time: this._showCanceledSince ? - this._showCanceledSince.toISOString() : null, - }; + const filters: any = {}; + + if (this.pullListOrg) { + filters.cancel_time = null; + filters.capture_time = null; + filters.frozen = 'f'; + + // There are aliases for these (cp_status, cp_circ_lib), + // but the API complains when I use them. + filters['cp.status'] = [0, 7]; + filters['cp.circ_lib'] = this.pullListOrg; + + return filters; + } + + if (this._showFulfilledSince) { + filters.fulfillment_time = this._showFulfilledSince.toISOString(); + } else { + filters.fulfillment_time = null; + } + + if (this._showCanceledSince) { + filters.cancel_time = this._showCanceledSince.toISOString(); + } else { + filters.cancel_time = null; + } if (this.hopeless) { filters['hopeless_holds'] = { @@ -263,7 +290,7 @@ export class HoldsGridComponent implements OnInit { fetchHolds(pager: Pager, sort: any[]): Observable { // We need at least one filter. - if (!this._recordId && !this.pickupLib && !this._userId) { + if (!this._recordId && !this.pickupLib && !this._userId && !this.pullListOrg) { return of([]); } @@ -276,6 +303,12 @@ export class HoldsGridComponent implements OnInit { subObj[obj.name] = {dir: obj.dir, nulls: 'last'}; orderBy.push(subObj); }); + } else if (this.pullListOrg) { + orderBy.push( + {copy_location_order_position: {dir: 'asc', nulls: 'last'}}, + {acpl_name: {dir: 'asc', nulls: 'last'}}, + {cn_label_sortkey: {dir: 'asc'}} + ); } const limit = this.enablePreFetch ? null : pager.limit; 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 143584f91a..305f0e14bc 100644 --- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql +++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql @@ -21912,6 +21912,75 @@ VALUES 'coust', 'description'), 'array' ); +-- NOTE: If the template ID requires changing, beware it appears in +-- 3 places below. + +INSERT INTO config.print_template + (id, name, locale, active, owner, label, template) +VALUES ( + 4, 'hold_pull_list', 'en-US', TRUE, + (SELECT id FROM actor.org_unit WHERE parent_ou IS NULL), + oils_i18n_gettext(4, 'Hold Pull List ', 'cpt', 'label'), + '' +); + +UPDATE config.print_template SET template = +$TEMPLATE$ +[%- + USE date; + SET holds = template_data; + # template_data is an arry of wide_hold hashes. +-%] +
+ + + + + + + + + + + + + + [% FOR hold IN holds %] + + + + + + + + + [% END %] + +
TypeTitleAuthorShelf LocationCall NumberBarcode/Part
[% hold.hold_type %][% hold.title %][% hold.author %][% hold.acpl_name %][% hold.cn_full_label %][% hold.cp_barcode %][% IF hold.p_label %]/[% hold.p_label %][% END %]
+
+$TEMPLATE$ WHERE id = 4; + +INSERT INTO config.workstation_setting_type (name, grp, datatype, label) +VALUES ( + 'eg.grid.circ.holds.pull_list', 'gui', 'object', + oils_i18n_gettext( + 'circ.holds.pull_list', + 'Hold Pull List Grid Settings', + 'cwst', 'label' + ) +), ( + 'circ.holds.pull_list.prefetch', 'gui', 'bool', + oils_i18n_gettext( + 'circ.holds.pull_list.prefetch', + 'Hold Pull List Prefetch Preference', + 'cwst', 'label' + ) +); INSERT INTO config.workstation_setting_type (name, grp, datatype, label) VALUES ( diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.data.pull-list-print-template.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.data.pull-list-print-template.sql new file mode 100644 index 0000000000..6b1c71c0d9 --- /dev/null +++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.data.pull-list-print-template.sql @@ -0,0 +1,77 @@ + +BEGIN; + +-- SELECT evergreen.upgrade_deps_block_check('TODO', :eg_version); + +-- NOTE: If the template ID requires changing, beware it appears in +-- 3 places below. + +INSERT INTO config.print_template + (id, name, locale, active, owner, label, template) +VALUES ( + 4, 'hold_pull_list', 'en-US', TRUE, + (SELECT id FROM actor.org_unit WHERE parent_ou IS NULL), + oils_i18n_gettext(4, 'Hold Pull List ', 'cpt', 'label'), + '' +); + +UPDATE config.print_template SET template = +$TEMPLATE$ +[%- + USE date; + SET holds = template_data; + # template_data is an arry of wide_hold hashes. +-%] +
+ + + + + + + + + + + + + + [% FOR hold IN holds %] + + + + + + + + + [% END %] + +
TypeTitleAuthorShelf LocationCall NumberBarcode/Part
[% hold.hold_type %][% hold.title %][% hold.author %][% hold.acpl_name %][% hold.cn_full_label %][% hold.cp_barcode %][% IF hold.p_label %]/[% hold.p_label %][% END %]
+
+$TEMPLATE$ WHERE id = 4; + +INSERT INTO config.workstation_setting_type (name, grp, datatype, label) +VALUES ( + 'eg.grid.circ.holds.pull_list', 'gui', 'object', + oils_i18n_gettext( + 'circ.holds.pull_list', + 'Hold Pull List Grid Settings', + 'cwst', 'label' + ) +), ( + 'circ.holds.pull_list.prefetch', 'gui', 'bool', + oils_i18n_gettext( + 'circ.holds.pull_list.prefetch', + 'Hold Pull List Prefetch Preference', + 'cwst', 'label' + ) +); + +COMMIT; + diff --git a/Open-ILS/src/templates/staff/navbar.tt2 b/Open-ILS/src/templates/staff/navbar.tt2 index 5daf52d401..bb0409a524 100644 --- a/Open-ILS/src/templates/staff/navbar.tt2 +++ b/Open-ILS/src/templates/staff/navbar.tt2 @@ -110,7 +110,7 @@
  • - + [% l('Pull List for Hold Requests') %] -- 2.43.2