LP1607922: Receiving items on page 2 of search results
[Evergreen.git] / Open-ILS / src / eg2 / src / app / staff / cat / vandelay / export.component.ts
1 import {Component, AfterViewInit, ViewChild, Renderer2, OnInit} from '@angular/core';
2 import {ActivatedRoute} from '@angular/router';
3 import {NgbPanelChangeEvent} from '@ng-bootstrap/ng-bootstrap';
4 import {HttpClient, HttpRequest, HttpEventType} from '@angular/common/http';
5 import {HttpResponse, HttpErrorResponse} from '@angular/common/http';
6 import {saveAs} from 'file-saver';
7 import {AuthService} from '@eg/core/auth.service';
8 import {ToastService} from '@eg/share/toast/toast.service';
9 import {ProgressInlineComponent} from '@eg/share/dialog/progress-inline.component';
10 import {VANDELAY_EXPORT_PATH} from './vandelay.service';
11 import {BasketService} from '@eg/share/catalog/basket.service';
12
13
14 @Component({
15   templateUrl: 'export.component.html'
16 })
17 export class ExportComponent implements AfterViewInit, OnInit {
18
19     recordSource: string;
20     fieldNumber: number;
21     selectedFile: File;
22     recordId: number;
23     bucketId: number;
24     recordType: string;
25     recordFormat: string;
26     recordEncoding: string;
27     includeHoldings: boolean;
28     isExporting: boolean;
29     exportingBasket: boolean;
30     basketRecords: number[];
31
32     @ViewChild('fileSelector') private fileSelector;
33     @ViewChild('exportProgress')
34         private exportProgress: ProgressInlineComponent;
35
36     constructor(
37         private renderer: Renderer2,
38         private route: ActivatedRoute,
39         private http: HttpClient,
40         private toast: ToastService,
41         private auth: AuthService,
42         private basket: BasketService
43     ) {
44         this.recordType = 'biblio';
45         this.recordFormat = 'USMARC';
46         this.recordEncoding = 'UTF-8';
47         this.includeHoldings = false;
48         this.basketRecords = [];
49     }
50
51     ngOnInit() {
52         const segments = this.route.snapshot.url.length;
53         if (segments > 0 &&
54             this.route.snapshot.url[segments - 1].path === 'basket') {
55                 this.exportingBasket = true;
56                 this.basket.getRecordIds().then(
57                     ids => this.basketRecords = ids
58                 );
59         }
60     }
61
62     ngAfterViewInit() {
63         if (this.exportingBasket) {
64             return; // no source to focus
65         }
66         this.renderer.selectRootElement('#csv-input').focus();
67     }
68
69     sourceChange($event: NgbPanelChangeEvent) {
70         this.recordSource = $event.panelId;
71
72         if (this.exportingBasket) {
73             return; // no source to focus
74         }
75
76         if ($event.nextState) { // panel opened
77
78             // give the panel a chance to render before focusing input
79             setTimeout(() => {
80                 this.renderer.selectRootElement(
81                     `#${this.recordSource}-input`).focus();
82             });
83         }
84     }
85
86     fileSelected($event) {
87        this.selectedFile = $event.target.files[0];
88     }
89
90     hasNeededData(): boolean {
91         return Boolean(
92             this.selectedFile ||
93             this.recordId     ||
94             this.bucketId     ||
95             (this.exportingBasket && this.basketRecords.length > 0)
96         );
97     }
98
99     exportRecords() {
100         this.isExporting = true;
101         this.exportProgress.update({value: 0});
102
103         const formData: FormData = new FormData();
104
105         formData.append('ses', this.auth.token());
106         formData.append('rectype', this.recordType);
107         formData.append('encoding', this.recordEncoding);
108         formData.append('format', this.recordFormat);
109
110         if (this.includeHoldings) {
111             formData.append('holdings', '1');
112         }
113
114         if (this.exportingBasket) {
115             this.basketRecords.forEach(id => formData.append('id', '' + id));
116
117         } else {
118
119             switch (this.recordSource) {
120
121                 case 'csv':
122                     formData.append('idcolumn', '' + this.fieldNumber);
123                     formData.append('idfile',
124                         this.selectedFile, this.selectedFile.name);
125                     break;
126
127                 case 'record-id':
128                     formData.append('id', '' + this.recordId);
129                     break;
130
131                 case 'bucket-id':
132                     formData.append('containerid', '' + this.bucketId);
133                     break;
134             }
135         }
136
137         this.sendExportRequest(formData);
138     }
139
140     sendExportRequest(formData: FormData) {
141
142         const fileName = `export.${this.recordType}.` +
143             `${this.recordEncoding}.${this.recordFormat}`;
144
145         const req = new HttpRequest('POST', VANDELAY_EXPORT_PATH,
146             formData, {reportProgress: true, responseType: 'text'});
147
148         this.http.request(req).subscribe(
149             evt => {
150                 console.debug(evt);
151                 if (evt.type === HttpEventType.DownloadProgress) {
152                     // File size not reported by server in advance.
153                     this.exportProgress.update({value: evt.loaded});
154
155                 } else if (evt instanceof HttpResponse) {
156
157                     saveAs(new Blob([evt.body as Blob],
158                         {type: 'application/octet-stream'}), fileName);
159
160                     this.isExporting = false;
161                 }
162             },
163
164             (err: HttpErrorResponse) => {
165                 console.error(err);
166                 this.toast.danger(err.error);
167                 this.isExporting = false;
168             }
169         );
170     }
171 }
172