Project

General

Profile

1
import {Component, Input, ViewChild} from '@angular/core';
2
import {SearchCrossrefService} from '../../claim-utils/service/searchCrossref.service';
3
import {SearchDataciteService} from '../../claim-utils/service/searchDatacite.service';
4

    
5
import {ModalLoading} from '../../../utils/modal/loading.component';
6
import {Dates, DOI} from '../../../utils/string-utils.class';
7
import {EnvProperties} from '../../../utils/properties/env-properties';
8

    
9
declare var UIkit: any;
10

    
11

    
12
@Component({
13
  selector: 'bulk-claim',
14
  template: `
15
    <div class="uk-animation uk-text-center" style=" ">
16
      <form class=" ">
17

    
18
        <div class="uk-grid">
19
          <div class="uk-width-expand">
20
            <!--div class="uk-text-lead">Upload a DOI csv file <helper  div="link-result-bulk" tooltip=true ></helper></div>
21
            <label for="exampleInputFile">Select a file: </label-->
22
            <div class="js-upload" uk-form-custom>
23
              <input id="exampleInputFile" class="uk-width-medium" type="file" (change)="fileChangeEvent($event)"/>
24
              <span class="uk-link">Upload a DOI's CSV file </span>
25
              <!--button class="uk-button  portal-button" type="button" tabindex="-1" [class.disabled]="!enableUpload" ><span class="uk-margin-small-right uk-icon"  >
26
              <svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <polyline fill="none" stroke="#000" points="5 8 9.5 3.5 14 8 "></polyline> <rect x="3" y="17" width="13" height="1"></rect>
27
               <line fill="none" stroke="#000" x1="9.5" y1="15" x2="9.5" y2="4"></line></svg></span> Select</button-->
28
              <!--helper  div="link-result-bulk" tooltip=true ></helper-->
29
            </div>
30

    
31

    
32
            <div *ngIf="showReport" uk-alert class="uk-alert uk-alert-primary" role="alert">
33
              <a class="uk-alert-close" uk-close></a>
34
              <div>Uploaded file contains {{allIds.length}} {{((allIds.length == 1) ? 'DOI' : 'DOIs')}}.
35
                <span
36
                  *ngIf="allIds.length > 0">{{foundIds.length}} {{((foundIds.length == 1) ? 'result was' : 'results were')}} succefully  fetched from CrossRef and Datacite.</span>
37
              </div>
38
              <div
39
                *ngIf="duplicateIds.length > 0">{{duplicateIds.length | number}} duplicate DOIs in {{((duplicateIds.length == 1) ? 'line' : 'lines')}} {{duplicateIdsRow}}.
40
              </div>
41
              <div *ngIf="notFoundIds.length > 0">Couldn't be found:
42
                <ul class="">
43
                  <li *ngFor="let id of notFoundIds; let i = index">"{{id}}" in line {{notFoundIdsRow[i]}}</li>
44
                </ul>
45
              </div>
46
              <div *ngIf="noValidIds.length > 0">No valid DOIs:
47
                <ul class="">
48
                  <li *ngFor="let id of noValidIds; let i = index">"{{id}}" in line {{noValidIdsRow[i]}}</li>
49
                </ul>
50
              </div>
51
              <div
52
                *ngIf="allIds.length == 0 || foundIds.length == 0"> Please make sure that the uploaded file, is a csv file with the proper format.
53
              </div>
54

    
55
            </div>
56
            <div *ngIf="errorMessage.length > 0 " class="uk-alert uk-alert-danger" role="alert">{{errorMessage}}</div>
57
            <modal-loading
58
              [message]="'Uploading, reading your documet and fetching results. Please give us a moment..'"></modal-loading>
59
          </div>
60
          <!--helper  div="link-result-bulk" ></helper-->
61
        </div>
62
      </form>
63

    
64

    
65
    </div>
66
  `
67

    
68
})
69
export class BulkClaimComponent {
70
  filesToUpload: Array<File>;
71
  source: string = "crossref";
72
  type: string = "publication";
73
  @Input() public select: boolean = true;
74
  @Input() public results;
75
  @Input() public properties: EnvProperties;
76

    
77
  allIds: string[] = [];
78
  foundIds: string[] = [];
79
  duplicateIds: string[] = [];
80
  duplicateIdsRow: number[] = [];
81
  notFoundIds: string[] = [];
82
  notFoundIdsRow: number[] = [];
83
  noValidIds: string[] = [];
84
  noValidIdsRow: number[] = [];
85
  showReport: boolean = false;
86
  @ViewChild(ModalLoading) loading: ModalLoading;
87
  errorMessage = "";
88
  enableUpload: boolean = true;
89
  @Input() localStoragePrefix: string = "";
90
  exceedsLimit = false;
91
  limit = 150;
92

    
93
  constructor(private _searchCrossrefService: SearchCrossrefService, private _searchDataciteService: SearchDataciteService) {
94
    this.filesToUpload = [];
95
  }
96

    
97
  ngOnInit() {
98
  }
99

    
100
  upload() {
101
    this.enableUpload = false;
102
    this.showReport = false;
103
    this.errorMessage = "";
104
    if (this.filesToUpload.length == 0) {
105
      this.errorMessage = "There is no selected file to upload.";
106
      return;
107
    } else {
108
      if (this.filesToUpload[0].name.indexOf(".csv") == -1 || this.filesToUpload[0].type != "text/csv") {
109
        this.errorMessage = "No valid file type. The required type is CSV";
110
        return;
111
      }
112
    }
113
    this.loading.open();
114

    
115
    this.makeFileRequest(this.properties.uploadService, [], this.filesToUpload).then((result) => {
116
      const rows = (result as any).split('\n');  // I have used space, you can use any thing.
117
      this.exceedsLimit = false;
118
      let invalid_rows = 0;
119
      this.duplicateIds = [];
120
      this.allIds = [];
121
      this.foundIds = [];
122
      this.noValidIds = [];
123
      this.results.slice(0, this.results.length);
124
      this.notFoundIds = [];
125

    
126
      if (rows.length + this.results.length > this.limit) {
127
        this.exceedsLimit = true;
128
        UIkit.notification({
129
          message: 'Your basket exceeds the number of allowed results (150)',
130
          status: 'warning',
131
          timeout: 1500,
132
          pos: 'top-center'
133
        });
134

    
135
      }
136
      for (let i = 0; i < ((rows.length > this.limit - this.results.length) ? (this.limit - this.results.length) : rows.length); i++) {
137
        if (rows[i] && rows[i] != null) {
138
          const values = rows[i].split(',');
139

    
140
          const id = BulkClaimComponent.removeDoubleQuotes(values[0]);
141
          if (DOI.isValidDOI(id)) {
142
            let accessMode = (values[1] != undefined) ? BulkClaimComponent.removeDoubleQuotes(values[1]) : "OPEN";
143
            accessMode = (BulkClaimComponent.validateAccessMode(accessMode) ? accessMode : "OPEN");
144
            let embargoDate = (values[2] != undefined) ? BulkClaimComponent.removeDoubleQuotes(values[2]) : Dates.getDateToday();
145
            embargoDate = (Dates.isValidDate(embargoDate) ? embargoDate : Dates.getDateToday());
146
            if (this.allIds.indexOf(id) > -1) {
147
              this.duplicateIds.push(id);
148
              this.duplicateIdsRow.push(i + 1);
149
            } else {
150
              this.allIds.push(id);
151
              this.fetchResult(id, accessMode, embargoDate, i + 1);
152
            }
153
          } else {
154
            this.noValidIds.push(id);
155
            this.noValidIdsRow.push(i + 1);
156
          }
157
        } else {
158
          invalid_rows++;
159
        }
160

    
161
      }
162
      if (rows.length == 0 || rows.length == invalid_rows || rows.length == (invalid_rows + this.noValidIds.length) || this.limit == this.results.length) {
163
        this.endOfFetching();
164
      }
165

    
166
    }, (error) => {
167
      this.enableUpload = true;
168
      console.log(error);
169
      this.loading.close();
170
      //this.errorMessage = "An error occured while uploading...";
171
      BulkClaimComponent.handleError("Error uploading file", error);
172
    });
173
  }
174

    
175
  private static removeDoubleQuotes(value) {
176
    if (value.indexOf('"') == 0) {
177
      value = value.substring(1, value.length);
178
    }
179
    const index = +value.indexOf('"');
180
    if (index == (value.length - 1) || index == (value.length - 2)) {
181
      value = value.substring(0, index);
182
    }
183
    return value;
184
  }
185

    
186
  private static validateAccessMode(value) {
187
    const accessModes = ["OPEN", "CLOSED", "EMBARGO"];
188
    return accessModes.indexOf(value) > -1;
189
  }
190

    
191
  fileChangeEvent(fileInput: any) {
192
    this.filesToUpload = <Array<File>>fileInput.target.files;
193
    this.upload();
194
  }
195

    
196
  makeFileRequest(url: string, params: Array<string>, files: Array<File>) {
197
    return new Promise((resolve, reject) => {
198
      const formData: any = new FormData();
199
      const xhr = new XMLHttpRequest();
200
      for (let i = 0; i < files.length; i++) {
201
        formData.append("uploads[]", files[i], files[i].name);
202
      }
203
      xhr.onreadystatechange = function () {
204
        if (xhr.readyState == 4) {
205
          if (xhr.status == 200) {
206
            resolve(xhr.response);
207
          } else {
208
            reject(xhr.response);
209
          }
210
        }
211
      }
212
      xhr.open("POST", url, true);
213
      xhr.send(formData);
214
    });
215
  }
216

    
217
  fetchResult(id: string, accessMode: string, date: string, row: number) {
218
    this._searchCrossrefService.searchCrossrefByDOIs([id], this.properties.searchCrossrefAPIURL, true).subscribe(
219
      data => {
220

    
221
        const result = data[1][0];
222
        if (data[1].length > 0) {
223
          this.foundIds.push(id);
224
          result["embargoEndDate"] = date;
225
          this.results.push(result);
226
          this.endOfFetching();
227
        } else {
228
          this.searchInDatacite(id, accessMode, date, row);
229
          // this.notFoundIds.push(id);
230
        }
231
      },
232
      err => {
233
        //console.log(err);
234
        BulkClaimComponent.handleError("Error getting crossref by DOIs: " + id, err);
235
        this.notFoundIds.push(id);
236
        this.notFoundIdsRow.push(row);
237
        this.endOfFetching();
238
      }
239
    );
240
  }
241

    
242
  searchInDatacite(id: string, accessMode: string, date: string, row: number) {
243
    this._searchDataciteService.getDataciteResultByDOI(id, this.properties, true).subscribe(
244
      items => {
245

    
246
        if (items[1].length > 0) {
247
          var result = items[1][0];
248

    
249
          this.foundIds.push(id);
250
          result["embargoEndDate"] = date;
251
          this.results.push(result);
252
        } else {
253
          this.notFoundIds.push(id);
254
          this.notFoundIdsRow.push(row);
255
        }
256
        this.endOfFetching();
257
      },
258
      err => {
259
        //console.log(err);
260
        BulkClaimComponent.handleError("Error getting datacite resultentityI: " + id, err);
261
        this.notFoundIds.push(id);
262
        this.notFoundIdsRow.push(row);
263
        this.endOfFetching();
264
      }
265
    );
266
  }
267

    
268
  endOfFetching() {
269
    if (this.limit == this.results.length) {
270
      this.enableUpload = true;
271
      this.loading.close();
272
      return;
273
    }
274
    if (this.allIds.length == this.foundIds.length + this.notFoundIds.length) {
275
      this.showReport = true;
276
      this.enableUpload = true;
277
      this.loading.close();
278
      if (this.results != null) {
279
        localStorage.setItem(this.localStoragePrefix, JSON.stringify(this.results));
280
      }
281
    }
282

    
283
  }
284

    
285
  private static handleError(message: string, error) {
286
    console.error("Bulk Claim (component): " + message, error);
287
  }
288
}
(1-1/2)