-EXPORT
+<h2 i18n>Export Records</h2>
+
+<div class="common-form striped-even form-validated">
+ <div class="row">
+ <div class="col-lg-6">
+ <div class="row"><label>Select a Record Source</label></div>
+ <ngb-accordion [closeOthers]="true" activeIds="csv"
+ (panelChange)="sourceChange($event)">
+ <ngb-panel id="csv" title="CSV File">
+ <ng-template ngbPanelContent>
+ <div class="row">
+ <div class="col-lg-6">
+ <label i18n>Use Field Number</label>
+ </div>
+ <div class="col-lg-6">
+ <input type="number" class="form-control"
+ [(ngModel)]="fieldNumber"
+ i18n-placeholder placeholder="Starts at 0..."/>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-lg-6">
+ <label i18n>From CSV file</label>
+ </div>
+ <div class="col-lg-6">
+ <input #fileSelector (change)="fileSelected($event)"
+ class="form-control" type="file"/>
+ </div>
+ </div>
+ </ng-template>
+ </ngb-panel>
+ <ngb-panel id="record-id" title="Record ID">
+ <ng-template ngbPanelContent>
+ <div class="row">
+ <div class="col-lg-6">
+ <label i18n>Record ID</label>
+ </div>
+ <div class="col-lg-6">
+ <input type="number" class="form-control" [(ngModel)]="recordId"/>
+ </div>
+ </div>
+ </ng-template>
+ </ngb-panel>
+ <ngb-panel id="bucket-id" title="Bucket">
+ <ng-template ngbPanelContent>
+ <div class="row">
+ <div class="col-lg-6">
+ <label i18n>Bucket ID</label>
+ </div>
+ <div class="col-lg-6">
+ <input type="number" class="form-control" [(ngModel)]="bucketId"/>
+ </div>
+ </div>
+ </ng-template>
+ </ngb-panel>
+ </ngb-accordion>
+ </div><!-- col -->
+ <div class="col-lg-6">
+ <div class="row">
+ <div class="col-lg-6">
+ <label i18n>Record Type</label>
+ </div>
+ <div class="col-lg-6">
+ <select class="form-control" [(ngModel)]="recordType">
+ <option i18n value="biblio">Bibliographic Records</option>
+ <option i18n value="authority">Authority Records</option>
+ </select>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-lg-6">
+ <label i18n>Record Format</label>
+ </div>
+ <div class="col-lg-6">
+ <select class="form-control" [(ngModel)]="recordFormat">
+ <option i18n value="USMARC">MARC21</option>
+ <option i18n value="UNIMARC">UNIMARC</option>
+ <option i18n value="XML">MARC XML</option>
+ <option i18n value="BRE">Evergreen Record Entry</option>
+ </select>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-lg-6">
+ <label i18n>Record Encoding</label>
+ </div>
+ <div class="col-lg-6">
+ <select class="form-control" [(ngModel)]="recordEncoding">
+ <option i18n value="UTF-8">UTF-8</option>
+ <option i18n value="MARC8">MARC8</option>
+ </select>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-lg-6">
+ <label i18n>Include holdings in Bibliographic Records</label>
+ </div>
+ <div class="col-lg-6">
+ <input class="form-check-input" type="checkbox" [(ngModel)]="includeHoldings">
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-lg-10 offset-lg-1">
+ <button class="btn btn-success btn-lg btn-block font-weight-bold"
+ [disabled]="isExporting || !hasNeededData()"
+ (click)="exportRecords()" i18n>Export</button>
+ </div>
+ </div>
+ <div class="row" [hidden]="!isExporting">
+ <div class="col-lg-10 offset-lg-1">
+ <eg-progress-inline #exportProgress></eg-progress-inline>
+ </div>
+ </div>
+ </div><!-- left col -->
+ </div><!-- row -->
+</div>
+
-import {Component, OnInit} from '@angular/core';
+import {Component, OnInit, ViewChild} from '@angular/core';
+import {NgbPanelChangeEvent} from '@ng-bootstrap/ng-bootstrap';
+import {HttpClient, HttpRequest, HttpEventType} from '@angular/common/http';
+import {HttpResponse, HttpErrorResponse} from '@angular/common/http';
+import {saveAs} from 'file-saver/FileSaver';
+import {AuthService} from '@eg/core/auth.service';
+import {ToastService} from '@eg/share/toast/toast.service';
+import {ProgressInlineComponent} from '@eg/share/dialog/progress-inline.component';
+import {VandelayService, VANDELAY_EXPORT_PATH} from './vandelay.service';
+
@Component({
templateUrl: 'export.component.html'
})
export class ExportComponent implements OnInit {
- constructor() {}
+ recordSource: string;
+ fieldNumber: number;
+ selectedFile: File;
+ recordId: number;
+ bucketId: number;
+ recordType: string;
+ recordFormat: string;
+ recordEncoding: string;
+ includeHoldings: boolean;
+ isExporting: boolean;
+
+ @ViewChild('fileSelector') private fileSelector;
+ @ViewChild('exportProgress')
+ private exportProgress: ProgressInlineComponent;
+
+ constructor(
+ private http: HttpClient,
+ private toast: ToastService,
+ private auth: AuthService
+ ) {
+ this.recordType = 'biblio';
+ this.recordFormat = 'USMARC';
+ this.recordEncoding = 'UTF-8';
+ this.includeHoldings = false;
+ }
ngOnInit() {
}
+ sourceChange($event: NgbPanelChangeEvent) {
+ this.recordSource = $event.panelId;
+ }
+
+ fileSelected($event) {
+ this.selectedFile = $event.target.files[0];
+ }
+
+ hasNeededData(): boolean {
+ return Boolean(
+ this.selectedFile || this.recordId || this.bucketId
+ );
+ }
+
+ exportRecords() {
+ this.isExporting = true;
+ this.exportProgress.update({value: 0});
+
+ const formData: FormData = new FormData();
+
+ formData.append('ses', this.auth.token());
+ formData.append('rectype', this.recordType);
+ formData.append('encoding', this.recordEncoding);
+ formData.append('format', this.recordFormat);
+
+ if (this.includeHoldings) {
+ formData.append('holdings', '1');
+ }
+
+ switch (this.recordSource) {
+
+ case 'csv':
+ formData.append('idcolumn', ''+this.fieldNumber);
+ formData.append('idfile',
+ this.selectedFile, this.selectedFile.name);
+ break;
+
+ case 'record-id':
+ formData.append('id', ''+this.recordId);
+ break;
+
+ case 'bucket-id':
+ formData.append('containerid', ''+this.bucketId);
+ break;
+ }
+
+ this.sendExportRequest(formData);
+ }
+
+ sendExportRequest(formData: FormData) {
+
+ const fileName = `export.${this.recordType}.` +
+ `${this.recordEncoding}.${this.recordFormat}`;
+
+ const req = new HttpRequest('POST', VANDELAY_EXPORT_PATH,
+ formData, {reportProgress: true, responseType: 'text'});
+
+ this.http.request(req).subscribe(
+ evt => {
+ console.log(evt);
+ if (evt.type === HttpEventType.DownloadProgress) {
+ // File size not reported by server in advance.
+ this.exportProgress.update({value: evt.loaded});
+
+ } else if (evt instanceof HttpResponse) {
+
+ saveAs(new Blob([evt.body],
+ {type: 'application/octet-stream'}), fileName);
+
+ this.isExporting = false;
+ }
+ },
+
+ (err: HttpErrorResponse) => {
+ console.error(err);
+ this.toast.danger(err.error);
+ this.isExporting = false;
+ }
+ );
+ }
}
+++ /dev/null
-
-
-.import-form {
- margin-right: 10px;
- margin-left: 10px;
- font-size: 95%;
-}
-
-.import-form .row {
- margin: 5px;
- padding: 3px;
-}
-
-.import-form .row:nth-child(even) {
- background-color: rgba(0,0,0,.03);
- border-top: 1px solid rgba(0,0,0,.125);
- border-bottom: 1px solid rgba(0,0,0,.125);
-}
-
-.import-form label {
- font-weight: bold;
-}
-
-.import-form input[type="checkbox"] {
- /* BS adds a negative left margin */
- margin-left: 0px;
-}
</div>
</div>
-<div class="import-form form-validated">
- <h2 i18n>MARC File Upload</h2>
+<h2 i18n>MARC File Upload</h2>
+<div class="common-form striped-odd form-validated ml-3 mr-3">
<div class="row">
<div class="col-lg-3">
<label i18n>Record Type</label>
}
@Component({
- templateUrl: 'import.component.html',
- styleUrls: ['import.component.css']
+ templateUrl: 'import.component.html'
})
export class ImportComponent implements OnInit, AfterViewInit, OnDestroy {
(err: HttpErrorResponse) => {
console.error(err);
- this.toast.danger(err.error.error);
+ this.toast.danger(err.error);
}
)).toPromise();
}
-<!--
-Do we need this? I think it's fairly obvious what page we're on and
-it takes up a good bit of vertical space which is needed by the large
-import form.
-<eg-staff-banner bannerText="MARC Record Import/Export" i18n-bannerText>
-</eg-staff-banner>
--->
<ul class="nav nav-pills nav-fill pb-4">
<li class="nav-item">
- <a class="nav-link disabled" [ngClass]="{active: tab=='export'}"
+ <a class="nav-link" [ngClass]="{active: tab=='export'}"
routerLink="/staff/cat/vandelay/export" i18n>Export</a>
</li>
<li class="nav-item">
</li>
</ul>
+<!-- load nav-specific page -->
<router-outlet></router-outlet>