Project

General

Profile

1
import {Component, Input}                 from '@angular/core';
2
import {ViewChild}                from '@angular/core';
3
import {ViewEncapsulation}  from '@angular/core';
4
import {OnInit, AfterViewInit}            from '@angular/core';
5
import {Location}                         from '@angular/common';
6
import {ActivatedRoute, Router}                   from '@angular/router';
7
import {Title, Meta}                      from '@angular/platform-browser';
8
import {Subject}                       from 'rxjs';
9
import {DataTableDirective }              from 'angular-datatables';
10
import {EnvProperties}                    from '../../utils/properties/env-properties';
11
import {Filter, Value}                    from './searchHelperClasses.class';
12
import {SearchFields}       from '../../utils/properties/searchFields';
13
import {SearchCustomFilter, SearchUtilsClass} from './searchUtils.class';
14
import {StringUtils}                 from '../../utils/string-utils.class';
15
import {ModalLoading}                     from '../../utils/modal/loading.component';
16
import {SearchFilterModalComponent}       from './searchFilterModal.component';
17
import {ErrorCodes}                       from '../../utils/properties/errorCodes';
18
import {PiwikService}                     from '../../utils/piwik/piwik.service';
19
import { SEOService } from '../../sharedComponents/SEO/SEO.service';
20
import {HelperService} from "../../utils/helper/helper.service";
21

    
22
@Component({
23
    selector: 'search-page-table',
24
    templateUrl:'searchPageTableView.component.html',
25
    styles: [`
26
      #dpTable_info, #dpTable_paginate,  #dpTable_length,  #dpTable_filter{
27
        display: none;
28
      }
29

    
30
      `],
31
      encapsulation: ViewEncapsulation.None // this used in order styles to work
32

    
33
  })
34
export class SearchPageTableViewComponent  implements OnInit, AfterViewInit {
35
  @Input() piwikSiteId = null;
36
  @Input() hasPrefix: boolean = true;
37
  @Input() pageTitle = "";
38
  @Input() results;
39
  @Input() filters = [];
40
  @Input() columnNames = [];
41
  @Input() type:string = "";
42
  @Input() entityType: string = "";
43
  @Input() searchUtils:SearchUtilsClass;// = new SearchUtilsClass();
44
  //@Output() downloadClick = new EventEmitter();
45
  @Input() showResultCount:boolean = true;
46
  @Input() showRefine:boolean = true;
47
  @Input() refineFields = [];
48
  //@Input() csvParams: string;
49
  //@Input() csvPath: string;
50
  @Input() openaireLink: string;
51
  @Input() searchViewLink: string;
52
  @Input() disableForms: boolean = false;
53
  @Input() enableSearchView: boolean = true;
54
  @Input() searchFormClass: string = "searchForm";
55
  @Input() formPlaceholderText = "Type Keywords...";
56
  @Input() mapUrl: string = "";
57
  @Input() mapTooltipType: string ="content providers";
58
  @ViewChild (ModalLoading) loading : ModalLoading ;
59
  private searchFieldsHelper:SearchFields = new SearchFields();
60
  private queryParameters: Map<string, string>  = new Map<string,string>();
61
  public parameterNames:string[] =[];
62
  public parameterValues:string[] =[];
63

    
64
  public isPiwikEnabled;
65

    
66

    
67
  @ViewChild (SearchFilterModalComponent) searchFilterModal : SearchFilterModalComponent ;
68
  public currentFilter: Filter;
69
  public errorCodes:ErrorCodes = new ErrorCodes();
70
  piwiksub: any;
71
  dtOptions: DataTables.Settings = {};
72
  showTable = false; filteringAdded = false;
73
  @ViewChild(DataTableDirective) datatableElement: DataTableDirective;
74
  dtTrigger: Subject<any> = new Subject(); //necessary
75
  properties:EnvProperties;
76
  url = null;
77
  public pageContents = null;
78
  @Input() customFilter: SearchCustomFilter = null;
79
  @Input() enableEntitySelection: boolean = false;
80
  constructor (private route: ActivatedRoute,
81
               private router: Router,
82
               private location: Location,
83
               private _meta: Meta,
84
               private _title: Title,
85
               private _piwikService:PiwikService,
86
             private seoService: SEOService,
87
               private helper: HelperService) { }
88

    
89
  ngOnInit() {
90
    this.route.data
91
      .subscribe((data: { envSpecific: EnvProperties }) => {
92
        this.properties = data.envSpecific;
93
        this.getPageContents();
94
        this.isPiwikEnabled = data.envSpecific.enablePiwikTrack;
95
        if(typeof window !== 'undefined') {
96
          this.updateUrl(data.envSpecific.baseLink+location.pathname);
97
          this.url =data.envSpecific.baseLink+location.pathname;
98
        }
99
        if(typeof document !== 'undefined' && this.isPiwikEnabled){
100
          this.piwiksub = this._piwikService.trackView(data.envSpecific, this.pageTitle, this.piwikSiteId).subscribe();
101
        }
102
      });
103
        this.dtOptions = {
104
          "paging": true,
105
          "searching": false,
106
          "lengthChange": false,
107
          "pageLength": this.searchUtils.size
108
        };
109
        this.updateTitle(this.pageTitle);
110
        var description = "Openaire, search, repositories, open access, type, content provider, funder, project, " + this.type + "," +this.pageTitle;
111
        this.updateDescription(description);
112
        this.seoService.createLinkForCanonicalURL(this.properties.baseLink+this.router.url,false);
113

    
114

    
115
   }
116
  ngOnDestroy() {
117
     if(this.piwiksub){
118
        this.piwiksub.unsubscribe();
119
      }
120
      try{
121
        $.fn['dataTable'].ext.search.pop();
122
      }catch(e){
123
        console.error("An error occured in ngOnDestroy of SearchPageTableViewComponent ", e)
124
    }
125
  }
126
    ngAfterViewInit(): void {
127
      try{
128
       $.fn['dataTable'].ext.search.push((settings, data, dataIndex) => {
129
//console.info(dataIndex+": "+data);
130
//console.info(this.results);
131
          //if (this.filterData(this.results[dataIndex], this.searchUtils.keyword, this.filters)) {
132
          if(this.filterAll(this.results[dataIndex], this.searchUtils.keyword.toLowerCase(),this.filters)) {
133
            // console.info("filter true (keyword:"+this.searchUtils.keyword+")");
134

    
135
            return true;
136
          }
137
          // console.info("filter false (keyword:"+this.searchUtils.keyword+")");
138

    
139
          return false;
140
        });
141
      }catch(e){
142
        console.error("An error occured in ngAfterViewInit of SearchPageTableViewComponent ", e)
143
    }
144

    
145
    }
146

    
147

    
148
  totalPages(): number {
149
      let totalPages:any = this.searchUtils.totalResults/(this.searchUtils.size);
150
      if(!(Number.isInteger(totalPages))) {
151
          totalPages = (parseInt(totalPages, 10) + 1);
152
      }
153
      return totalPages;
154
  }
155

    
156
  toggleModal($event) {
157
    this.currentFilter = $event.value;
158
    this.searchFilterModal.open();
159

    
160
  }
161

    
162
  updateDescription(description:string) {
163
    this._meta.updateTag({content:description},"name='description'");
164
    this._meta.updateTag({content:description},"property='og:description'");
165
  }
166
  updateTitle(title:string) {
167
    var _prefix: string = "";
168
    if(this.hasPrefix) {
169
      _prefix = "OpenAIRE | ";
170
    }
171
    var _title = _prefix + ((title.length> 50 ) ?title.substring(0,50):title);
172
    this._title.setTitle(_title);
173
    this._meta.updateTag({content:_title},"property='og:title'");
174
  }
175
  updateUrl(url:string) {
176
    this._meta.updateTag({content:url},"property='og:url'");
177
  }
178

    
179
public getParametersFromUrl(params) {
180
  for(var i=0; i< this.refineFields.length ; i++) {
181
    var filterId =  this.refineFields[i];
182
    if(params[filterId] != undefined) {
183
      if(this.queryParameters == undefined){
184
        this.queryParameters = new Map<string,string>();
185
      }
186
      this.queryParameters[filterId]=decodeURIComponent(params[filterId]);
187
    }
188
  }
189
}
190
 /*
191
 * Mark as check the new filters that are selected, when you get them from search
192
 */
193
  public checkSelectedFilters(filters:Filter[]){
194

    
195
    this.filters = filters;
196
       for(var i=0; i< filters.length ; i++){
197
            var filter:Filter = filters[i];
198
            filter.countSelectedValues = 0;
199

    
200
              if(this.queryParameters[filter.filterId] != undefined) {
201
                let values = (decodeURIComponent(this.queryParameters[filter.filterId])).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/,-1);
202
                     for(let filterValue of filter.values) {
203
                       if(values.indexOf(StringUtils.quote(filterValue.id)) > -1) {
204
                            filterValue.selected = true;
205
                            filter.countSelectedValues++;
206
                         }else{
207
                           filterValue.selected = false;
208
                         }
209
                    }
210
            }else{
211
              for(let filterValue of filter.values) {
212
                 filterValue.selected = false;
213
              }
214
            }
215
        }
216

    
217
        return filters;
218
  }
219

    
220
  /*
221
  *
222
  */
223
  private createUrlParameters(filters:Filter[], includePage:boolean){
224
    var allLimits="";//location.search.slice(1);
225
    this.parameterNames.splice(0,this.parameterNames.length);
226
    this.parameterValues.splice(0,this.parameterValues.length);
227

    
228
    for (let filter of filters){
229
      var filterLimits="";
230
      if(filter.countSelectedValues > 0){
231
        for (let value of filter.values){
232
          if(value.selected == true){
233
            filterLimits+=((filterLimits.length == 0)?'':',') +'"'+ StringUtils.URIEncode(value.id)+'"';
234
           }
235
        }
236
        this.queryParameters[filter.filterId]=filterLimits;
237
        if(filterLimits.length > 0){
238
          this.parameterNames.push(filter.filterId);
239
          this.parameterValues.push(filterLimits);
240
        }
241
        allLimits+=(allLimits.length==0?"?":"&")+((filterLimits.length == 0 )?'':filter.filterId + '='+ filterLimits) ;
242
      }
243
    }
244
    if(this.searchUtils.keyword.length > 0 ){
245
       allLimits+=(allLimits.length==0?"?":"&")+'fv0=' + this.searchUtils.keyword;
246
      this.parameterNames.push("fv0");
247
      this.parameterValues.push(this.searchUtils.keyword);
248
     }
249

    
250
    return allLimits;
251
  }
252

    
253
  public isFiltered(){
254
    var filtered=false;
255
    for (let filter of this.filters){
256
       if(filter.countSelectedValues > 0){
257
           filtered = true;
258
           break;
259
       }
260
     }
261
    if(this.searchUtils.keyword.length > 0 ){
262
      filtered = true;
263
    }
264
    return filtered;
265
  }
266
  private clearKeywords(){
267
    if(this.searchUtils.keyword.length > 0 ){
268
      this.searchUtils.keyword ='';
269
    }
270
    this.goTo(1);
271
  }
272
  private clearFilters(){
273
    for (var i =0 ; i <  this.filters.length; i++) {
274
         for (var j=0; j <  this.filters[i].values.length; j++) {
275
          if(this.filters[i].values[j].selected) {
276
            this.filters[i].values[j].selected = false;
277
          }
278
         }
279
        this.filters[i].countSelectedValues = 0;
280
    }
281
  }
282

    
283
  private removeFilter(value:Value,filter:Filter){
284
    filter.countSelectedValues--;
285
    if(value.selected == true){
286
      value.selected = false;
287
     }
288
    this.goTo(1);
289
  }
290
  goTo(page:number = 1){
291

    
292
    this.searchUtils.page=page;
293
   var table = $('#dpTable').DataTable();
294

    
295
   table.page( page - 1  ).draw( false );
296

    
297
   // Object { page: 0, pages: 3, start: 0, end: 10, length: 10, recordsTotal: 28, recordsDisplay: 21, serverSide: false }
298
   var info = table.page.info();
299
   this.searchUtils.totalResults = info.recordsDisplay;
300

    
301
    var urlParameters = this.createUrlParameters(this.filters,true);
302
    this.location.go(location.pathname,urlParameters);
303
  }
304

    
305
  filterChanged($event){
306
       this.goTo(1);
307
  }
308
  keywordChanged($event) {
309
       this.searchUtils.keyword = $event.value;
310
       this.goTo(1);
311
  }
312

    
313
  sizeChanged($event) {
314
    this.searchUtils.size = $event.value;
315
    var table = $('#dpTable').DataTable();
316
    table.page.len( this.searchUtils.size ).draw();
317
    this.goTo(1);
318
  }
319
/*
320
	downloadClicked($event) {
321
		if($event.value == true) {
322
		    var queryParameters = this.createSearchQueryParameters(this.filters);
323

    
324
		    this.downloadClick.emit({
325
		        value: queryParameters
326
		    });
327
		}
328
	}
329
*/
330

    
331

    
332
  getSelectedValues(filter):any{
333
    var selected = [];
334
    if(filter.countSelectedValues >0){
335
      for (var i=0; i < filter.values.length; i++){
336
        if(filter.values[i].selected){
337
          selected.push(filter.values[i]);
338
        }
339
      }
340
    }
341
    return selected;
342

    
343
  }
344
  /*
345
  Trigger a table draw in order to get the initial filtering
346
  */
347
  triggerInitialLoad(){
348
      setTimeout(function(){
349
        var table = $('#dpTable').DataTable();
350
        table.page( 0  ).draw( false );
351

    
352
      }, 500);
353
  }
354

    
355
/*
356
Transform initial - not filtered results to get the filtered number
357
*/
358
    transform(results, searchUtils:SearchUtilsClass = null  ): any {
359
      if(searchUtils!=null) {
360
        this.searchUtils = searchUtils;
361
      }
362
      if(results.length > 0) {
363
        var errorCodes:ErrorCodes = new ErrorCodes();
364
        this.searchUtils.status = errorCodes.LOADING;
365

    
366
        var result = results.filter(row=>this.filterAll(row, this.searchUtils.keyword.toLowerCase(),this.filters));
367

    
368
        let oldTotal = this.searchUtils.totalResults;
369
        //console.info(result);
370
        this.searchUtils.totalResults = result.length;
371

    
372
        var errorCodes:ErrorCodes = new ErrorCodes();
373
        this.searchUtils.status = errorCodes.DONE;
374
        if(this.searchUtils.totalResults == 0 ){
375
          //this.searchUtils.status = errorCodes.NONE;
376
        }
377

    
378
        // if(oldTotal != this.searchUtils.totalResults) {
379
        //   args[3].detectChanges();
380
        // }
381
         return result;
382
      }
383
       return [];
384
    }
385

    
386
    filterAll(row: any, query: string, filters:Filter[]) {
387
      let returnValue: boolean = false;
388

    
389
      if(query) {
390
        if(row.title && row.title.name.toLowerCase().indexOf(query) > -1) {
391
          returnValue = true;
392
        }
393

    
394
        if(row.type && row.type.toLowerCase().indexOf(query) > -1) {
395
          returnValue = true;
396
        }
397

    
398
        if(row.countries && row.countries.length > 0) {
399
          for(let country of row.countries) {
400
            if(country.toLowerCase().indexOf(query) > -1) {
401
              returnValue = true;
402
              break;
403
            }
404
          }
405
        }
406

    
407
        if(row.compatibility && row.compatibility.toLowerCase().indexOf(query) > -1) {
408
          returnValue = true;
409
        }
410

    
411
        if(row.organizations && row.organizations.length > 0) {
412
          for(let organization of row.organizations) {
413
            if(organization.name.toLowerCase().indexOf(query) > -1) {
414
              returnValue = true;
415
              break;
416
            }
417
          }
418
        }
419

    
420
        if(row.name && row.name.toLowerCase().indexOf(query) > -1) {
421
          returnValue = true;
422
        }
423

    
424
        if(row.acronym && row.acronym.toLowerCase().indexOf(query) > -1) {
425
          returnValue = true;
426
        }
427

    
428
        if(row.grantId && row.grantId.toLowerCase().indexOf(query) > -1) {
429
          returnValue = true;
430
        }
431

    
432
        if(row.funder && row.funder.toLowerCase().indexOf(query) > -1) {
433
          returnValue = true;
434
        }
435

    
436
        if(!returnValue) {
437
          return false;
438
        }
439
      }
440

    
441
      for (let filter of filters){
442
        if(filter.countSelectedValues > 0){
443
          for (let value of filter.values){
444
            if(value.selected == true){
445

    
446
              // make it generic in future commit
447
              let field:string = "";
448
              /*
449
              let index: number = -1;
450
              for(let i=0; i<this.columnNames.length; i++) {
451
                if(filter.title == this.columnNames[i]) {
452
                  index = i;
453
                }
454
              }
455
              */
456
              if(filter.title == "Type") {
457
                field = "type";
458
              } else if(filter.title == "Compatibility") {
459
                field = "compatibility";
460
              } else if(filter.title == "Funder") {
461
                field = "funder";
462
              } else if(filter.title == "Country") {
463
                field = "countries";
464
              }
465
              //console.info(row);
466
//console.info("|"+row[field]+"|"+"   "+"|"+value.name+"|");
467
              //if(row[field] == value.name) {
468
              if(row[field] &&
469
                ((filter.valueIsExact && (row[field].trim() == value.name.trim()))
470
                || (!filter.valueIsExact && (row[field].includes(value.name))))){
471

    
472
                returnValue = true;
473
                if(filter.filterOperator == "or") {
474
                  break;
475
                }
476
              } else {
477
                  if(filter.filterOperator == "and") {
478
                    return false;
479
                  }
480
                  returnValue = false;
481
              }
482
            }
483
          }
484
          if(!returnValue) {
485
            return false;
486
          }
487
        }
488
      }
489

    
490
      return true;
491
    }
492
    filterQuery(data, query){
493
      if(data.toLowerCase().indexOf(query.toLowerCase()) > -1){
494
        return true;
495
      }else{
496
        return false;
497
      }
498
    }
499
    filterData(row: any, query: string, filters:Filter[]) {
500

    
501

    
502
      let returnValue: boolean = false;
503

    
504
      if(query) {
505
        for(var i=0; i <this.columnNames.length; i++){
506
          var r= this.filterQuery(row[i], query);
507
          // console.log(query+" "+ row+" "+r);
508
          if(r) {
509
            returnValue = true;
510
            break;
511
          }
512
        }
513

    
514
        if(!returnValue) {
515
          return false;
516
        }
517
      }
518

    
519
      for (let filter of filters){
520
        if(filter.countSelectedValues > 0){
521
          for (let value of filter.values){
522
            if(value.selected == true){
523
              let field = 1;
524
              /*if(filter.title == "Type") {
525
                field = 1;
526
              } else if(filter.title == "Compatibility Level") {
527
                field = 4;
528
              } else if(filter.title == "Funder") {
529
                field = 3
530
              }*/
531
              for(let i=0; i<this.columnNames.length; i++) {
532
                if(filter.title == this.columnNames[i]) {
533
                  field = i;
534
                }
535
              }
536

    
537
              //if(row[field].trim() == value.name.trim()) {
538
              if((filter.valueIsExact && (row[field].trim() == value.name.trim()))
539
                || (!filter.valueIsExact && (row[field].includes(value.name)))){
540
                returnValue = true;
541
                if(filter.filterOperator == "or") {
542
                  break;
543
                }
544
              } else {
545
                  if(filter.filterOperator == "and") {
546
                    return false;
547
                  }
548
                  returnValue = false;
549
              }
550
            }
551
          }
552
          if(!returnValue) {
553
            return false;
554
          }
555
        }
556
      }
557

    
558
      return true;
559
    }
560

    
561
    public encode(param: string): string {
562
      return StringUtils.URIEncode(param);
563
    }
564
    public countFilters():number{
565
      var filters=0;
566
      for (let filter of this.filters){
567
         if(filter.countSelectedValues > 0){
568
             filters+=filter.countSelectedValues;
569
         }
570
       }
571
      return filters;
572
    }
573
  private getPageContents() {
574
    this.helper.getPageHelpContents(this.properties,  (this.customFilter) ? this.customFilter.valueId : null, this.router.url).subscribe(contents => {
575

    
576
      this.pageContents = contents;
577
    })
578
  }
579
}
(41-41/55)