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
import {Breadcrumb} from "../../utils/breadcrumbs/breadcrumbs.component";
22

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

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

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

    
65
  public isPiwikEnabled;
66

    
67

    
68
  @ViewChild (SearchFilterModalComponent) searchFilterModal : SearchFilterModalComponent ;
69
  public currentFilter: Filter;
70
  public errorCodes:ErrorCodes = new ErrorCodes();
71
  piwiksub: any;
72
  dtOptions: DataTables.Settings = {};
73
  showTable = false; filteringAdded = false;
74
  @ViewChild(DataTableDirective) datatableElement: DataTableDirective;
75
  dtTrigger: Subject<any> = new Subject(); //necessary
76
  properties:EnvProperties;
77
  url = null;
78
  public pageContents = null;
79
  @Input() customFilter: SearchCustomFilter = null;
80
  @Input() enableEntitySelection: boolean = false;
81
  @Input() includeOnlyResultsAndFilter:boolean = false;
82
  @Input() showBreadcrumb:boolean = false;
83
  breadcrumbs:Breadcrumb[] = [];
84

    
85
  constructor (private route: ActivatedRoute,
86
               private router: Router,
87
               private location: Location,
88
               private _meta: Meta,
89
               private _title: Title,
90
               private _piwikService:PiwikService,
91
             private seoService: SEOService,
92
               private helper: HelperService) { }
93

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

    
120

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

    
141
            return true;
142
          }
143
          // console.info("filter false (keyword:"+this.searchUtils.keyword+")");
144

    
145
          return false;
146
        });
147
      }catch(e){
148
        console.error("An error occured in ngAfterViewInit of SearchPageTableViewComponent ", e)
149
    }
150

    
151
    }
152

    
153

    
154
  totalPages(): number {
155
      let totalPages:any = this.searchUtils.totalResults/(this.searchUtils.size);
156
      if(!(Number.isInteger(totalPages))) {
157
          totalPages = (parseInt(totalPages, 10) + 1);
158
      }
159
      return totalPages;
160
  }
161

    
162
  toggleModal($event) {
163
    this.currentFilter = $event.value;
164
    this.searchFilterModal.open();
165

    
166
  }
167

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

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

    
201
    this.filters = filters;
202
       for(var i=0; i< filters.length ; i++){
203
            var filter:Filter = filters[i];
204
            filter.countSelectedValues = 0;
205

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

    
223
        return filters;
224
  }
225

    
226
  /*
227
  *
228
  */
229
  private createUrlParameters(filters:Filter[], includePage:boolean){
230
    var allLimits="";//location.search.slice(1);
231
    this.parameterNames.splice(0,this.parameterNames.length);
232
    this.parameterValues.splice(0,this.parameterValues.length);
233

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

    
256
    return allLimits;
257
  }
258

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

    
289
  private removeFilter(value:Value,filter:Filter){
290
    filter.countSelectedValues--;
291
    if(value.selected == true){
292
      value.selected = false;
293
     }
294
    this.goTo(1);
295
  }
296
  goTo(page:number = 1){
297

    
298
    this.searchUtils.page=page;
299
   var table = $('#dpTable').DataTable();
300

    
301
   table.page( page - 1  ).draw( false );
302

    
303
   // Object { page: 0, pages: 3, start: 0, end: 10, length: 10, recordsTotal: 28, recordsDisplay: 21, serverSide: false }
304
   var info = table.page.info();
305
   this.searchUtils.totalResults = info.recordsDisplay;
306

    
307
    var urlParameters = this.createUrlParameters(this.filters,true);
308
    this.location.go(location.pathname,urlParameters);
309
  }
310

    
311
  filterChanged($event){
312
       this.goTo(1);
313
  }
314
  keywordChanged($event) {
315
       this.searchUtils.keyword = $event.value;
316
       this.goTo(1);
317
  }
318

    
319
  sizeChanged($event) {
320
    this.searchUtils.size = $event.value;
321
    var table = $('#dpTable').DataTable();
322
    table.page.len( this.searchUtils.size ).draw();
323
    this.goTo(1);
324
  }
325
/*
326
	downloadClicked($event) {
327
		if($event.value == true) {
328
		    var queryParameters = this.createSearchQueryParameters(this.filters);
329

    
330
		    this.downloadClick.emit({
331
		        value: queryParameters
332
		    });
333
		}
334
	}
335
*/
336

    
337

    
338
  getSelectedValues(filter):any{
339
    var selected = [];
340
    if(filter.countSelectedValues >0){
341
      for (var i=0; i < filter.values.length; i++){
342
        if(filter.values[i].selected){
343
          selected.push(filter.values[i]);
344
        }
345
      }
346
    }
347
    return selected;
348

    
349
  }
350
  /*
351
  Trigger a table draw in order to get the initial filtering
352
  */
353
  triggerInitialLoad(){
354
      setTimeout(function(){
355
        var table = $('#dpTable').DataTable();
356
        table.page( 0  ).draw( false );
357

    
358
      }, 500);
359
  }
360

    
361
/*
362
Transform initial - not filtered results to get the filtered number
363
*/
364
    transform(results, searchUtils:SearchUtilsClass = null  ): any {
365
      if(searchUtils!=null) {
366
        this.searchUtils = searchUtils;
367
      }
368
      if(results.length > 0) {
369
        var errorCodes:ErrorCodes = new ErrorCodes();
370
        this.searchUtils.status = errorCodes.LOADING;
371

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

    
374
        let oldTotal = this.searchUtils.totalResults;
375
        //console.info(result);
376
        this.searchUtils.totalResults = result.length;
377

    
378
        var errorCodes:ErrorCodes = new ErrorCodes();
379
        this.searchUtils.status = errorCodes.DONE;
380
        if(this.searchUtils.totalResults == 0 ){
381
          //this.searchUtils.status = errorCodes.NONE;
382
        }
383

    
384
        // if(oldTotal != this.searchUtils.totalResults) {
385
        //   args[3].detectChanges();
386
        // }
387
         return result;
388
      }
389
       return [];
390
    }
391

    
392
    filterAll(row: any, query: string, filters:Filter[]) {
393
      let returnValue: boolean = false;
394

    
395
      if(query) {
396
        if(row.title && row.title.name.toLowerCase().indexOf(query) > -1) {
397
          returnValue = true;
398
        }
399

    
400
        if(row.type && row.type.toLowerCase().indexOf(query) > -1) {
401
          returnValue = true;
402
        }
403

    
404
        if(row.countries && row.countries.length > 0) {
405
          for(let country of row.countries) {
406
            if(country.toLowerCase().indexOf(query) > -1) {
407
              returnValue = true;
408
              break;
409
            }
410
          }
411
        }
412

    
413
        if(row.compatibility && row.compatibility.toLowerCase().indexOf(query) > -1) {
414
          returnValue = true;
415
        }
416

    
417
        if(row.organizations && row.organizations.length > 0) {
418
          for(let organization of row.organizations) {
419
            if(organization.name.toLowerCase().indexOf(query) > -1) {
420
              returnValue = true;
421
              break;
422
            }
423
          }
424
        }
425

    
426
        if(row.name && row.name.toLowerCase().indexOf(query) > -1) {
427
          returnValue = true;
428
        }
429

    
430
        if(row.acronym && row.acronym.toLowerCase().indexOf(query) > -1) {
431
          returnValue = true;
432
        }
433

    
434
        if(row.grantId && row.grantId.toLowerCase().indexOf(query) > -1) {
435
          returnValue = true;
436
        }
437

    
438
        if(row.funder && row.funder.toLowerCase().indexOf(query) > -1) {
439
          returnValue = true;
440
        }
441

    
442
        if(!returnValue) {
443
          return false;
444
        }
445
      }
446

    
447
      for (let filter of filters){
448
        if(filter.countSelectedValues > 0){
449
          for (let value of filter.values){
450
            if(value.selected == true){
451

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

    
478
                returnValue = true;
479
                if(filter.filterOperator == "or") {
480
                  break;
481
                }
482
              } else {
483
                  if(filter.filterOperator == "and") {
484
                    return false;
485
                  }
486
                  returnValue = false;
487
              }
488
            }
489
          }
490
          if(!returnValue) {
491
            return false;
492
          }
493
        }
494
      }
495

    
496
      return true;
497
    }
498
    filterQuery(data, query){
499
      if(data.toLowerCase().indexOf(query.toLowerCase()) > -1){
500
        return true;
501
      }else{
502
        return false;
503
      }
504
    }
505
    filterData(row: any, query: string, filters:Filter[]) {
506

    
507

    
508
      let returnValue: boolean = false;
509

    
510
      if(query) {
511
        for(var i=0; i <this.columnNames.length; i++){
512
          var r= this.filterQuery(row[i], query);
513
          // console.log(query+" "+ row+" "+r);
514
          if(r) {
515
            returnValue = true;
516
            break;
517
          }
518
        }
519

    
520
        if(!returnValue) {
521
          return false;
522
        }
523
      }
524

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

    
543
              //if(row[field].trim() == value.name.trim()) {
544
              if((filter.valueIsExact && (row[field].trim() == value.name.trim()))
545
                || (!filter.valueIsExact && (row[field].includes(value.name)))){
546
                returnValue = true;
547
                if(filter.filterOperator == "or") {
548
                  break;
549
                }
550
              } else {
551
                  if(filter.filterOperator == "and") {
552
                    return false;
553
                  }
554
                  returnValue = false;
555
              }
556
            }
557
          }
558
          if(!returnValue) {
559
            return false;
560
          }
561
        }
562
      }
563

    
564
      return true;
565
    }
566

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

    
582
      this.pageContents = contents;
583
    })
584
  }
585
}
(41-41/55)