]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/eg2/src/app/staff/acq/lineitem/lineitem-list.component.html
LP#1357037: add sorting option to Angular line item lists
[Evergreen.git] / Open-ILS / src / eg2 / src / app / staff / acq / lineitem / lineitem-list.component.html
1
2 <!-- BATCH ACTIONS -->
3 <eg-acq-cancel-dialog #cancelDialog></eg-acq-cancel-dialog>
4
5 <div class="row mt-3" *ngIf="poId || picklistId">
6   <div class="col-lg-1">
7     <div ngbDropdown>
8       <button class="btn btn-info btn-sm" ngbDropdownToggle i18n>Actions</button>
9       <div ngbDropdownMenu>
10         <a ngbDropdownItem routerLink="../brief-record"
11           queryParamsHandling="merge" i18n>Add Brief Record</a>
12         <button ngbDropdownItem (click)="deleteLineitems()" 
13           [disabled]="!canDeleteLis()" i18n>Delete Selected Lineitems</button>
14         <div class="dropdown-divider"></div>
15         <h6 class="dropdown-header" i18n>Selection List Actions</h6>
16         <button ngbDropdownItem (click)="createPo()" 
17           [disabled]="!picklistId" i18n>Create Purchase Order from Selected Lineitems</button>
18         <button ngbDropdownItem (click)="createPo(true)"
19           [disabled]="!picklistId" i18n>Create Purchase Order from All Lineitems</button>
20         <div class="dropdown-divider"></div>
21         <h6 class="dropdown-header" i18n>Purchase Order Actions</h6>
22         <button ngbDropdownItem (click)="receiveSelected()" 
23           [disabled]="!poId" i18n>Mark Selected Lineitems as Received</button>
24         <button ngbDropdownItem (click)="unReceiveSelected()" 
25           [disabled]="!poId" i18n>Un-Receive Selected Lineitems</button>
26         <button ngbDropdownItem (click)="cancelSelected()" 
27           [disabled]="!poId" i18n>Cancel Selected Lineitems</button>
28       </div>
29     </div>
30   </div>
31   <div class="col-lg-5">
32     <input type="text" class="form-control" [(ngModel)]="batchNote"
33       placeholder="New Line Item Note..." i18n-placeholder/>
34   </div>
35   <div class="col-lg-4 form-inline">
36     <div class="form-check mr-2">
37       <input class="form-check-input" type="checkbox"
38         id="vendor-public" [(ngModel)]="noteIsPublic">
39       <label class="form-check-label" for="vendor-public">
40         Note is vendor-public
41       </label>
42     </div>
43     <button class="btn btn-outline-dark" (click)="applyBatchNote()"
44       [disabled]="!selectedIds().length" i18n>
45       Apply To Selected
46     </button>
47   </div>
48 </div>
49
50 <div *ngIf="batchFailure" class="row mt-2 p-2">
51   <div class="col-lg-12 p-2 border border-danger label-with-material-icon" i18n>
52     <span class="material-icons text-danger pr-2">report</span>
53     Batch operation failed: 
54     {{batchFailure.textcode}} {{batchFailure.desc}}
55
56     <a class="ml-auto" href="javascript:;" 
57       (click)="batchFailure = null" title="Close" i18n-title>
58       <span class="material-icons text-danger">close</span>
59     </a>
60   </div>
61 </div>
62
63 <!-- NAVIGATION / EXPANDY -->
64
65 <div *ngIf="poId || picklistId"
66   class="row mt-3 mb-1 border border-info rounded toolbar">
67   <div class="col-lg-12 d-flex">
68     <div class="d-flex justify-content-center flex-column h-100">
69       <div class="form-check">
70         <input class="form-check-input" id='toggle-page-cbox'
71           [(ngModel)]="batchSelectPage" (change)="toggleSelectAll(false)" type="checkbox"/>
72         <label class="form-check-label" for='toggle-page-cbox' i18n>Items In Page</label>
73       </div>
74     </div>
75
76     <div class="d-flex justify-content-center flex-column h-100 ml-3">
77       <div class="form-check">
78         <input class="form-check-input" id='toggle-all-cbox'
79           [(ngModel)]="batchSelectAll" (change)="toggleSelectAll(true)" type="checkbox"/>
80         <label class="form-check-label" for='toggle-all-cbox' i18n>All Items</label>
81       </div>
82     </div>
83
84     <div class="d-flex ml-3 justify-content-center flex-column h-100">
85       <span class="font-italic" style="font-size:90%" i18n>
86         {{selectedIds().length}} Selected
87       </span>
88     </div>
89
90     <div class="d-flex ml-3 justify-content-center flex-column h-100">
91       <button type="button" (click)="toggleFilterSort()"
92         class="btn btn-sm btn-outline-dark mr-1">
93         <span *ngIf="showFilterSort"  i18n>Hide Filter &amp; Sort Options</span>
94         <span *ngIf="!showFilterSort" i18n>Show Filter &amp; Sort Options</span>
95       </button>
96     </div>
97
98     <div class="flex-1"></div>
99
100     <div class="btn-toolbar">
101       <button type="button" (click)="toggleExpandAll()"
102         class="btn btn-sm btn-outline-dark mr-1">
103         <span title="Expand All" i18n-title *ngIf="!expandAll"
104           class="material-icons mat-icon-in-button">unfold_more</span>
105         <span title="Collapse All" i18n-title *ngIf="expandAll"
106           class="material-icons mat-icon-in-button">unfold_less</span>
107       </button>
108       <button [disabled]="pager.isFirstPage()" type="button"
109         class="btn btn-sm btn-outline-dark mr-1" (click)="pager.toFirst(); goToPage()">
110         <span title="First Page" i18n-title
111           class="material-icons mat-icon-in-button">first_page</span>
112       </button>
113       <button [disabled]="pager.isFirstPage()" type="button"
114         class="btn btn-sm btn-outline-dark mr-1" (click)="pager.decrement(); goToPage()">
115         <span title="Previous Page" i18n-title
116             class="material-icons mat-icon-in-button">keyboard_arrow_left</span>
117       </button>
118       <button [disabled]="pager.isLastPage()" type="button"
119         class="btn btn-sm btn-outline-dark mr-1" (click)="pager.increment(); goToPage()">
120         <span title="Next Page" i18n-title
121           class="material-icons mat-icon-in-button">keyboard_arrow_right</span>
122       </button>
123       <div ngbDropdown class="mr-1" placement="bottom-right">
124         <button ngbDropdownToggle class="btn btn-outline-dark text-button">
125           <span title="Select Row Count" i18n-title i18n>
126             Rows {{pager.limit}}
127           </span>
128         </button>
129         <div class="dropdown-menu" ngbDropdownMenu>
130           <a class="dropdown-item" (click)="pageSizeChange(count)"
131             *ngFor="let count of [5, 10, 25, 50, 100, 500, 1000, 10000]">
132             <span class="ml-2">{{count}}</span>
133           </a>
134         </div>
135       </div>
136     </div><!-- buttons -->
137   </div>
138   <div [hidden]="!showFilterSort">
139     <div class="col-lg-12 d-flex">
140       <div class="d-flex justify-content-center flex-column h-100">
141         <div class="form-group form-inline">
142           <label for="sort-order-select" class="form-check-label mr-1">Sort by:</label>
143           <select name="sort-order-select" id="sort-order-select"
144             [ngModel]="sortOrder" (ngModelChange)="sortOrderChange($event)"
145             class="form-control">
146             <option value="li_id_asc" i18n>Lineitem ID Ascending</option>
147             <option value="li_id_desc" i18n>Lineitem ID Descending</option>
148             <option value="title_asc" i18n>Title Ascending</option>
149             <option value="title_desc" i18n>Title Descending</option>
150             <option value="author_asc" i18n>Author Ascending</option>
151             <option value="author_desc" i18n>Author Descending</option>
152             <option value="publisher_asc" i18n>Publisher Ascending</option>
153             <option value="publisher_desc" i18n>Publisher Descending</option>
154             <option value="order_ident_asc" i18n>Order Identifier Ascending</option>
155             <option value="order_ident_desc" i18n>Order Identifier Descending</option>
156           </select>
157         </div>
158       </div>
159     </div>
160   </div>
161 </div>
162
163 <!-- LINEITEM LIST -->
164
165 <ng-container *ngIf="pageOfLineitems.length === 0 && !loading">
166   <div class="row mt-2">
167     <div class="col-lg-6 offset-lg-3 alert alert-warning" i18n>
168       No items to display.
169     </div>
170   </div>
171 </ng-container>
172
173 <ng-container *ngFor="let li of pageOfLineitems">
174   <div class="row mt-2 border-bottom pt-2 pb-2 li-state-{{li.state()}}">
175     <div class="col-lg-12 d-flex">
176       <div class="jacket-wrapper">
177         <ng-container *ngIf="jacketIdent(li)">
178           <a href="/opac/extras/ac/jacket/large/{{jacketIdent(li)}}">
179             <img class="jacket"
180               src='/opac/extras/ac/jacket/small/{{jacketIdent(li)}}'/>
181           </a>
182         </ng-container>
183         <ng-container *ngIf="!jacketIdent(li)"><img class="jacket"/></ng-container>
184       </div>
185
186       <div class="ml-2 flex-1"> <!-- lineitem summary info -->
187         <div class="row">
188           <div class="col-lg-12">
189             <input type="checkbox" [(ngModel)]="selected[li.id()]"/>
190             <a class="ml-2" queryParamsHandling="merge" [id]="li.id()"
191               routerLink="./lineitem/{{li.id()}}/detail">
192               {{displayAttr(li, 'title')}}
193             </a>
194           </div>
195         </div>
196         <div class="row">
197           <div class="col-lg-12">
198             <span class="pr-1">{{displayAttr(li, 'author')}}</span>
199             <span class="pr-1">{{displayAttr(li, 'isbn')}}</span>
200             <span class="pr-1">{{displayAttr(li, 'issn')}}</span>
201             <span class="pr-1">{{displayAttr(li, 'edition')}}</span>
202             <span class="pr-1">{{displayAttr(li, 'pubdate')}}</span>
203             <span class="pr-1">{{displayAttr(li, 'publisher')}}</span>
204             <span class="pr-1">{{li.source_label()}}</span>
205           </div>
206         </div>
207         <div class="row" *ngIf="li.purchase_order()">
208           <div class="col-lg-12">
209             <eg-lineitem-order-summary [li]="li"></eg-lineitem-order-summary>
210           </div>
211         </div>
212         <div class="row">
213           <div class="col-lg-12">
214             <span title="Lineitem ID" i18n-title i18n># {{li.id()}}</span>
215             <span class="ml-1 mr-1" i18n> | </span>
216             <span title="Existing Item Count" i18n-title i18n
217               [ngClass]="{'text-danger font-weight-bold': existingCopyCounts[li.id()] > 0}">
218               {{existingCopyCounts[li.id()]}}</span>
219             <span class="ml-1 mr-1" i18n> | </span>
220             <a class="label-with-material-icon" title="Items" i18n-title
221               routerLink="./lineitem/{{li.id()}}/items" queryParamsHandling="merge">
222               <span class="material-icons small mr-1">shopping_basket</span>
223               <span i18n>Items ({{li.lineitem_details().length}})</span>
224             </a>
225             <span class="ml-1 mr-1" i18n> | </span>
226             <a class="label-with-material-icon" title="Expand" i18n-title
227               href="javascript:;" (click)="toggleShowExpand(li.id())">
228               <ng-container *ngIf="showExpandFor != li.id()">
229                 <span class="material-icons small mr-1">unfold_more</span>
230                 <span i18n>Expand</span>
231               </ng-container>
232               <ng-container *ngIf="showExpandFor == li.id()">
233                 <span class="material-icons small mr-1">unfold_less</span>
234                 <span i18n>Collapse</span>
235               </ng-container>
236             </a>
237             <span class="ml-1 mr-1" i18n> | </span>
238             <a class="label-with-material-icon" title="Notes" i18n-title
239               href="javascript:;" (click)="toggleShowNotes(li.id())">
240               <span class="material-icons small mr-1">event_note</span>
241               <span i18n>Notes ({{li.lineitem_notes().length}})</span>
242               <span *ngIf="liHasAlerts(li)" class="text-danger material-icons"
243                 title="Has Alerts" i18n-title>flag</span>
244             </a>
245             <ng-container *ngIf="li.eg_bib_id()">
246               <span class="ml-1 mr-1" i18n> | </span>
247               <a class="label-with-material-icon mr-2"
248                 routerLink="/staff/catalog/record/{{li.eg_bib_id()}}">
249                 <span class="material-icons small mr-1">library_books</span>
250                 <span i18n>Catalog</span>
251               </a>
252             </ng-container>
253
254             <!-- TODO link to catalog -->
255
256             <span class="ml-1 mr-1" i18n> | </span>
257             <a class="label-with-material-icon"
258               routerLink="lineitem/{{li.id()}}/worksheet/">
259               <span class="material-icons small mr-1">create</span>
260               <span i18n>Worksheet</span>
261             </a>
262             <ng-container *ngIf="!picklistId && li.picklist() && li.picklist().name()">
263               <span class="ml-1 mr-1" i18n> | </span>
264               <a class="label-with-material-icon"
265                 title="Selection List" i18n-title 
266                 routerLink="/staff/acq/picklist/{{li.picklist().id()}}">
267                 <span class="material-icons small mr-1">widgets</span>
268                 <span i18n>{{li.picklist().name()}}</span>
269               </a>
270             </ng-container>
271             <ng-container *ngIf="!poId && li.purchase_order()">
272               <span class="ml-1 mr-1" i18n> | </span>
273               <a class="label-with-material-icon"
274                 title="Purchase Order" i18n-title
275                 routerLink="/staff/acq/po/{{li.purchase_order().id()}}">
276                 <span class="material-icons small mr-1">center_focus_weak</span>
277                 <span i18n>{{li.purchase_order().id()}}</span>
278               </a>
279             </ng-container>
280
281             <!-- TODO patron requests -->
282
283             <span class="ml-1 mr-1" i18n> | </span>
284             <a class="label-with-material-icon"
285               [queryParams]="{f: 'jub:id', val1: li.id()}"
286               routerLink="/staff/acq/search/invoices">
287               <span class="material-icons small mr-1">list</span>
288               <span i18n>Invoice(s)</span>
289             </a>
290
291             <!-- TODO: claim policy -->
292
293             <ng-container *ngIf="li.provider()">
294               <span class="ml-1 mr-1" i18n> | </span>
295               <a class="label-with-material-icon"
296                 title="Selection List" i18n-title 
297                 routerLink="/staff/acq/provider/{{li.provider().id()}}/details">
298                 <span class="material-icons small mr-1">store</span>
299                 <span i18n>{{li.provider().name()}}</span>
300               </a>
301             </ng-container>
302
303             <!-- TODO import queue -->
304
305           </div>
306         </div>
307       </div>
308
309       <!-- actions along the right -->
310       <div class="d-flex flex-column justify-content-end">
311         <div class="row">
312           <div class="col-lg-12 d-flex">
313           <div class="flex-1"> </div>
314             <!-- w-auto allows the input group to stick to the right 
315                  as the status label grows -->
316             <div class="input-group w-auto">
317               <div class="input-group-prepend">
318                 <span *ngIf="identOptions(li).length > 1" class="text-danger mr-1"
319                   i18n-title title="Multiple Order Identifier Options" i18n>
320                   ({{identOptions(li).length}})
321                 </span>
322                 <div ngbDropdown>
323                   <button class="btn btn-outline-dark btn-sm" ngbDropdownToggle 
324                     title="Order Identifier Type" i18n-title [disabled]="!canEditIdent(li)"
325                     [ngClass]="{'btn-warning': !selectedIdent(li)}">
326                     <ng-container *ngIf="orderIdentTypes[li.id()]=='isbn'" i18n>ISBN</ng-container>
327                     <ng-container *ngIf="orderIdentTypes[li.id()]=='upc'" i18n>UPC</ng-container>
328                     <ng-container *ngIf="orderIdentTypes[li.id()]=='issn'" i18n>ISSN</ng-container>
329                   </button>
330                   <div ngbDropdownMenu>
331                     <button class="btn-sm" ngbDropdownItem
332                       (click)="orderIdentTypes[li.id()]='isbn'" i18n>ISBN</button>
333                     <button class="btn-sm" ngbDropdownItem
334                       (click)="orderIdentTypes[li.id()]='upc'" i18n>UPC</button>
335                     <button class="btn-sm" ngbDropdownItem
336                       (click)="orderIdentTypes[li.id()]='issn'" i18n>ISSN</button>
337                   </div>
338                 </div>
339               </div>
340               <eg-combobox [entries]="identOptions(li)" [smallFormControl]="true"
341                 placeholder="Order Identifer..." i18n-placeholder
342                 [disabled]="!canEditIdent(li)"
343                 [allowFreeText]="true" [selectedId]="selectedIdent(li)"
344                 (onChange)="orderIdentChanged(li, $event)">
345               </eg-combobox>
346             </div>
347           </div>
348         </div>
349         <div class="row mt-2">
350           <div class="col-lg-12 d-flex">
351             <div class="flex-1"></div>
352             <div class="mr-2">
353               <ng-container [ngSwitch]="li.state()">    
354                 <div i18n 
355                   class="p-1 text-dark border border-dark bg-light rounded-lg" 
356                   *ngSwitchCase="'new'">New</div>
357                 <div i18n 
358                   class="p-1 text-dark border border-dark bg-light rounded-lg" 
359                   *ngSwitchCase="'selector-ready'">Selector-Ready</div>
360                 <div i18n 
361                   class="p-1 text-dark border border-dark bg-light rounded-lg" 
362                   *ngSwitchCase="'order-ready'">Order-Ready</div>
363                 <div i18n 
364                   class="p-1 text-dark border border-dark bg-light rounded-lg" 
365                   *ngSwitchCase="'approved'">Approved</div>
366                 <div i18n 
367                   class="p-1 text-dark border border-dark bg-light rounded-lg" 
368                   *ngSwitchCase="'pending-order'">Pending-Order</div>
369                 <div i18n 
370                   class="p-1 text-primary border border-primary bg-light rounded-lg" 
371                   *ngSwitchCase="'on-order'">On-Order</div>
372                 <div i18n 
373                   class="p-1 text-success border border-success bg-light rounded-lg" 
374                   *ngSwitchCase="'received'">Received</div>
375                 <div i18n 
376                   class="p-1 text-danger border border-danger bg-light rounded-lg" 
377                   *ngSwitchCase="'cancelled'">Canceled</div>
378               </ng-container>
379             </div>
380             <div class="mr-2">
381               <div ngbDropdown>
382                 <button class="btn btn-info btn-sm" ngbDropdownToggle i18n>Actions</button>
383                 <div ngbDropdownMenu>
384                   <button ngbDropdownItem [disabled]="li.state() != 'on-order'"
385                     (click)="markReceived([li.id()])" i18n>Mark Received</button>
386                   <button ngbDropdownItem [disabled]="li.state() != 'received'"
387                     (click)="markUnReceived([li.id()])" i18n>Mark Un-Received</button>
388                   <button ngbDropdownItem [disabled]="!liHasRealCopies(li)"
389                     (click)="editHoldings(li)" i18n>Holdings Maintenance</button>
390                   <a ngbDropdownItem routerLink="lineitem/{{li.id()}}/history"
391                     queryParamsHandling="merge" i18n>View History</a>
392                 </div>
393               </div>
394             </div>
395             <div>
396               <input type="text" class="form-control-sm medium"
397                 [ngClass]="{'border border-danger text-danger': !liPriceIsValid(li)}"
398                 placeholder='Price...' i18n-placeholder
399                 (change)="liPriceChange(li)" [ngModel]="li.estimated_unit_price()"
400                 (ngModelChange)="li.estimated_unit_price($event)"/>
401             </div>
402           </div>
403         </div>
404       </div>
405     </div>
406   </div>
407
408   <div class="row" *ngIf="showNotesFor == li.id()">
409     <div class="col-lg-10 offset-lg-1 p-2 mt-2">
410       <eg-lineitem-notes [lineitem]="li" (closeRequested)="showNotesFor = null">
411       </eg-lineitem-notes>
412     </div>
413   </div>
414   <div class="row" *ngIf="showExpandFor == li.id() || expandAll">
415     <div class="col-lg-10 offset-lg-1 p-2 mt-2 shadow">
416
417       <!-- Note the flex values are set so they also match the layout
418            of the list of copies in the copies component. -->
419       <div class="div d-flex font-weight-bold">
420         <div class="flex-1 p-1" i18n>Owning Branch</div>  
421         <div class="flex-1 p-1" i18n>Copy Location</div>
422         <div class="flex-1 p-1" i18n>Collection Code</div>
423         <div class="flex-1 p-1" i18n>Fund</div>
424         <div class="flex-1 p-1" i18n>Circ Modifier</div>
425         <div class="flex-1 p-1" i18n>Callnumber</div>
426         <div class="flex-1 p-1" i18n>Barcode</div>
427       </div>
428       <div class="batch-copy-row" *ngFor="let copy of li.lineitem_details()">
429         <eg-lineitem-copy-attrs [embedded]="true" [copy]="copy">
430         </eg-lineitem-copy-attrs>
431       </div>
432     </div>
433   </div>
434 </ng-container>
435
436 <div class="row" *ngIf="loading">
437   <div class="offset-lg-3 col-lg-6">
438     <eg-progress-inline *ngIf="loading"></eg-progress-inline>
439   </div>
440 </div>
441