--- /dev/null
+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 {}
--- /dev/null
+
+<eg-staff-banner i18n-bannerText bannerText="Holds Pull List"></eg-staff-banner>
+
+<eg-holds-grid
+ persistKey="circ.holds.pull_list"
+ printTemplate="hold_pull_list"
+ [enablePreFetch]="true"
+ [hidePickupLibFilter]="true"
+ [pullListOrg]="targetOrg()">
+</eg-holds-grid>
+
--- /dev/null
+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();
+ }
+}
+
--- /dev/null
+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 {}
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)],
<span class="material-icons" aria-hidden="true">pin_drop</span>
<span i18n>Capture Holds</span>
</a>
- <a class="dropdown-item" href="/eg/staff/circ/holds/pull">
+ <a class="dropdown-item" routerLink="/staff/circ/holds/pull-list">
<span class="material-icons" aria-hidden="true">view_list</span>
<span i18n>Pull List for Hold Requests</span>
</a>
<ng-container *ngIf="mode == 'list' && initComplete()">
+ <h3 i18n>Holds Count: {{holdsCount}}</h3>
+
<div class="row" *ngIf="!hidePickupLibFilter">
<div class="col-lg-4">
<div class="input-group">
</div>
</div>
+ <div class="row" *ngIf="pullListOrg">
+ <div class="col-lg-4 mb-2">
+ <div class="input-group">
+ <div class="input-group-prepend">
+ <div class="input-group-text" i18n>View Pull List For:</div>
+ </div>
+ <eg-org-select [initialOrgId]="pullListOrg"
+ (onChange)="pullListOrgChanged($event)">
+ </eg-org-select>
+ </div>
+ </div>
+ </div>
+
<eg-grid #holdsGrid [dataSource]="gridDataSource" [sortable]="true"
[useLocalSort]="enablePreFetch" [cellTextGenerator]="cellTextGenerator"
[showFields]="showFields"
[multiSortable]="true" [persistKey]="persistKey"
(onRowActivate)="showDetail($event)">
- <eg-grid-toolbar-checkbox (onChange)="preFetchHolds($event)" *ngIf="!hopeless"
+ <eg-grid-toolbar-button *ngIf="pullListOrg"
+ (onClick)="printHolds()" i18n-label label="Print Full List">
+ </eg-grid-toolbar-button>
+
+ <eg-grid-toolbar-checkbox
+ (onChange)="preFetchHolds($event)" *ngIf="!hopeless && preFetchSetting"
[initialValue]="enablePreFetch" i18n-label label="Pre-Fetch All Holds">
</eg-grid-toolbar-checkbox>
@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;
// 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:
this.holdsGrid.reload();
}
+ pullListOrgChanged(org: IdlObject) {
+ this.pullListOrg = org.id();
+ this.holdsGrid.reload();
+ }
+
preFetchHolds(apply: boolean) {
this.enablePreFetch = apply;
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'] = {
fetchHolds(pager: Pager, sort: any[]): Observable<any> {
// We need at least one filter.
- if (!this._recordId && !this.pickupLib && !this._userId) {
+ if (!this._recordId && !this.pickupLib && !this._userId && !this.pullListOrg) {
return of([]);
}
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;
'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.
+-%]
+<div>
+ <style>
+ #holds-pull-list-table td {
+ padding: 5px;
+ border: 1px solid rgba(0,0,0,.05);
+ }
+ </style>
+ <table id="holds-pull-list-table">
+ <thead>
+ <tr>
+ <th>Type</th>
+ <th>Title</th>
+ <th>Author</th>
+ <th>Shelf Location</th>
+ <th>Call Number</th>
+ <th>Barcode/Part</th>
+ </tr>
+ </thead>
+ <tbody>
+ [% FOR hold IN holds %]
+ <tr>
+ <td>[% hold.hold_type %]</td>
+ <td style="width: 30%">[% hold.title %]</td>
+ <td style="width: 25%">[% hold.author %]</td>
+ <td>[% hold.acpl_name %]</td>
+ <td>[% hold.cn_full_label %]</td>
+ <td>[% hold.cp_barcode %][% IF hold.p_label %]/[% hold.p_label %][% END %]</td>
+ </tr>
+ [% END %]
+ </tbody>
+ </table>
+</div>
+$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 (
--- /dev/null
+
+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.
+-%]
+<div>
+ <style>
+ #holds-pull-list-table td {
+ padding: 5px;
+ border: 1px solid rgba(0,0,0,.05);
+ }
+ </style>
+ <table id="holds-pull-list-table">
+ <thead>
+ <tr>
+ <th>Type</th>
+ <th>Title</th>
+ <th>Author</th>
+ <th>Shelf Location</th>
+ <th>Call Number</th>
+ <th>Barcode/Part</th>
+ </tr>
+ </thead>
+ <tbody>
+ [% FOR hold IN holds %]
+ <tr>
+ <td>[% hold.hold_type %]</td>
+ <td style="width: 30%">[% hold.title %]</td>
+ <td style="width: 25%">[% hold.author %]</td>
+ <td>[% hold.acpl_name %]</td>
+ <td>[% hold.cn_full_label %]</td>
+ <td>[% hold.cp_barcode %][% IF hold.p_label %]/[% hold.p_label %][% END %]</td>
+ </tr>
+ [% END %]
+ </tbody>
+ </table>
+</div>
+$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;
+
</a>
</li>
<li>
- <a href="./circ/holds/pull" target="_self">
+ <a href="/eg2/staff/circ/holds/pull-list">
<span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>
[% l('Pull List for Hold Requests') %]
</a>