Project

General

Profile

1
import {Component, ViewChild} from "@angular/core";
2
import {SearchUtilsClass} from "../../openaireLibrary/searchPages/searchUtils/searchUtils.class";
3
import {ErrorMessagesComponent} from "../../openaireLibrary/utils/errorMessages.component";
4
import {ErrorCodes} from "../../openaireLibrary/utils/properties/errorCodes";
5
import {EnvProperties} from "../../openaireLibrary/utils/properties/env-properties";
6
import {SearchPageComponent} from "../../openaireLibrary/searchPages/searchUtils/searchPage.component";
7
import {ActivatedRoute} from "@angular/router";
8
import {Filter, Value} from "../../openaireLibrary/searchPages/searchUtils/searchHelperClasses.class";
9
import {SearchFields} from "../../openaireLibrary/utils/properties/searchFields";
10
import {CommunitiesService} from "../../openaireLibrary/connect/communities/communities.service";
11
import {Session} from "../../openaireLibrary/login/utils/helper.class";
12
import {CommunityInfo} from "../../openaireLibrary/connect/community/communityInfo";
13
import {SubscribeService} from "../../openaireLibrary/utils/subscribe/subscribe.service";
14
import {StringUtils} from "../../openaireLibrary/utils/string-utils.class";
15
import {PiwikService} from "../../openaireLibrary/utils/piwik/piwik.service";
16
import {HelperFunctions} from "../../openaireLibrary/utils/HelperFunctions.class";
17

    
18
@Component({
19
  selector: 'search-communities',
20
  template: `
21
      <search-page pageTitle="OpenAIRE-Connect | Search Communities"
22
                   [hasPrefix]=false searchFormClass="communitiesSearchForm"
23
                   formPlaceholderText="Search for Research Communities and Initiatives"
24
                   type="communities" entityType="community" [filters]="filters"
25
                   [results]="results" [searchUtils]="searchUtils"
26
                   [showResultCount]=true [baseUrl]="baseUrl"
27
                   [disableForms]="disableForms"
28
                   [lastIndex]=false [sort]=true>
29
      </search-page>
30
  `
31
})
32
export class SearchCommunitiesComponent {
33
  public piwiksub: any;
34
  private errorCodes: ErrorCodes;
35
  private errorMessages: ErrorMessagesComponent;
36
  public results: CommunityInfo[] = [];
37
  public totalResults: CommunityInfo[] = [];
38
  public sub: any; public subResults: any;
39
  public filters = [];
40
  public searchFields:SearchFields = new SearchFields();
41
  public searchUtils:SearchUtilsClass = new SearchUtilsClass();
42
  public disableForms: boolean = false;
43
  public baseUrl: string = null;
44
  public refineFields: string[] =  this.searchFields.COMMUNITIES_SEARCH_FIELDS;
45
  properties:EnvProperties;
46
  @ViewChild (SearchPageComponent) searchPage : SearchPageComponent ;
47

    
48
  constructor (private route: ActivatedRoute,
49
               private _communitiesService: CommunitiesService,
50
               private _subscribeService: SubscribeService,
51
               private _piwikService: PiwikService) {
52
    this.errorCodes = new ErrorCodes();
53
    this.errorMessages = new ErrorMessagesComponent();
54
    this.searchUtils.status = this.errorCodes.LOADING;
55
  }
56

    
57
  public ngOnInit() {
58
    this.route.data
59
        .subscribe((data: { envSpecific: EnvProperties }) => {
60
          this.properties = data.envSpecific;
61
          this.baseUrl = data.envSpecific.searchLinkToCommunities;
62
          if(this.properties.enablePiwikTrack && (typeof document !== 'undefined')){
63
            this.piwiksub = this._piwikService.trackView(this.properties, "OpenAIRE Connect|Search Communities", this.properties.piwikSiteId).subscribe();
64
          }
65
        });
66
    this.sub =  this.route.queryParams.subscribe(params => {
67
      this.searchPage.resultsPerPage = 5;
68
      this.searchUtils.keyword = (params['keyword']?params['keyword']:'');
69
      this.searchUtils.page = (params['page'] === undefined) ? 1: + params['page'];
70
      this.searchUtils.sortBy = (params['sortBy'] === undefined)? '' : params['sortBy'];
71
      this.searchUtils.size = (params['size'] === undefined) ? this.searchPage.resultsPerPage: + params['size'];
72
      if(this.searchUtils.size != 5 && this.searchUtils.size != 10 && this.searchUtils.size != 20 && this.searchUtils.size != 50) {
73
        this.searchUtils.size = this.searchPage.resultsPerPage;
74
      }
75
      if(this.searchUtils.sortBy && this.searchUtils.sortBy != "creationdate,descending" && this.searchUtils.sortBy != "creationdate,ascending") {
76
        this.searchUtils.sortBy = "";
77
      }
78
      this.searchPage.refineFields = this.refineFields;
79
      let queryParams = this.searchPage.getQueryParamsFromUrl(params);
80
      this.filters = this.createFilters();
81

    
82
      this.initCommunities(queryParams);
83
    });
84
  }
85

    
86
  public ngOnDestroy() {
87
    if(this.sub){
88
      this.sub.unsubscribe();
89
    }
90
    if(this.subResults){
91
      this.subResults.unsubscribe();
92
    }
93
  }
94

    
95
  /**
96
   * Initialize communities from Communities APIs
97
   *
98
   * @param params
99
   */
100
  private initCommunities(params: Map<string, string>) {
101
    this.subResults = this._communitiesService.getCommunitiesState().subscribe(
102
        data => {
103
          for(let i = 0; i < data.length; i++) {
104
            this.totalResults[i] = data[i];
105
            this.totalResults[i].isManager = false;
106
            this.totalResults[i].isSubscribed = false;
107
            // For Test do not delete them.
108
            //this.results[i].description = "EGI is a federated e-Infrastructure set up to provide advanced computing services for research and innovation.EGI is a federated e-Infrastructure set up to provide advanced computing services for research and innovation.EGI is a federated e-Infrastructure set up to provide advanced computing services for research and innovation."
109
            //this.results[i].date = new Date(new Date(2012, 0, 1).getTime() + Math.random() * (new Date().getTime() - new Date(2012, 0, 1).getTime()));
110
            if(Session.isLoggedIn()) {
111
              this.totalResults[i].isManager = this.isCommunityManager(this.totalResults[i]);
112
            }
113
          }
114
          if(Session.isLoggedIn()) {
115
            this._subscribeService.getCommunitiesSubscribedTo(Session.getUserEmail(), this.properties["adminToolsAPIURL"]).subscribe(
116
              res => {
117
                for (let i = 0; i < this.totalResults.length; i++) {
118
                  this.totalResults[i].isSubscribed = (res.indexOf(this.totalResults[i].communityId) != -1);
119
                }
120
                this._getResults(params);
121
              }
122
            );
123
          }
124
          else {
125
            this._getResults(params);
126
          }
127
        },
128
        err => {
129
          this.handleError('Error getting communities', err);
130
          this.searchUtils.status = this.errorMessages.getErrorCode(err.status);
131
          this.disableForms = false;
132
          HelperFunctions.scroll();
133
        }
134
      );
135
  }
136

    
137

    
138
  /**
139
   * Get all communities from Communities API and apply permission access validator,
140
   * keyword searching, filter, paging and sorting.
141
   *
142
   * @param params, status
143
   * @private
144
   */
145
  private _getResults(params: Map<string, string>){
146
    this.searchUtils.status = this.errorCodes.LOADING;
147
    this.disableForms = true;
148
    this.results = this.totalResults;
149
    this.searchUtils.totalResults = 0;
150
    this.applyParams(params);
151
  }
152

    
153
  /**
154
   * Return the communities in which user has permission to view or manage.
155
   */
156
  private showCommunities() {
157
    let ret: CommunityInfo[] = [];
158
    for(let result of this.results) {
159
      if (result.status == 'hidden') {
160
        continue;
161
      } else if (result.status == "manager") {
162
        let mail = Session.getUserEmail();
163
        if (mail == null) { // no user
164
          continue;
165
        } else if (Session.isCommunityCurator() || Session.isPortalAdministrator()) {
166
          ret.push(result);
167
        } else if (result.managers.indexOf(mail) != -1) {
168
          ret.push(result);
169
        }
170
        continue;
171
      }
172
      ret.push(result);
173
    }
174
    this.results = ret;
175
  }
176

    
177
  /**
178
   * Apply permission access validator,
179
   * keyword searching, filter, paging and sorting.
180
   *
181
   * @param params
182
   * @param status
183
   */
184
  public applyParams(params: Map<string, string>) {
185
    this.showCommunities();
186
    if(this.searchUtils.keyword && this.searchUtils.keyword != '') {
187
      this.searchForKeywords();
188
    }
189
    this.checkFilters(params);
190
    this.sort();
191
    this.searchUtils.totalResults = this.results.length;
192
    this.searchPage.checkSelectedFilters(this.filters);
193
    this.searchPage.updateBaseUrlWithParameters(this.filters);
194
    this.results = this.results.slice((this.searchUtils.page-1)*this.searchUtils.size, (this.searchUtils.page*this.searchUtils.size));
195
    this.searchUtils.status = this.errorCodes.DONE;
196
    if(this.searchUtils.totalResults == 0 ){
197
      this.searchUtils.status = this.errorCodes.NONE;
198
    }
199
    this.disableForms = false;
200
    if(this.searchUtils.status == this.errorCodes.DONE) {
201
      // Page out of limit!!!
202
      let totalPages:any = this.searchUtils.totalResults/(this.searchUtils.size);
203
      if(!(Number.isInteger(totalPages))) {
204
        totalPages = (parseInt(totalPages, 10) + 1);
205
      }
206
      if(totalPages < this.searchUtils.page) {
207
        this.searchUtils.totalResults = 0;
208
        this.searchUtils.status = this.errorCodes.OUT_OF_BOUND;
209
      }
210
    }
211
    HelperFunctions.scroll();
212
  }
213

    
214

    
215
  /**
216
   * Parse the given keywords into array and check if any of the requirements field of a community includes
217
   * one of the given words.
218
   */
219
  private searchForKeywords() {
220
      let ret: CommunityInfo[] = [];
221
      let keywords: string[] = this.searchUtils.keyword.split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/,-1);
222
      for(let i = 0; i < this.results.length; i++) {
223
          for(let keyword of keywords) {
224
            keyword = keyword.toLowerCase();
225
            if (keyword != '' && (this.results[i].title.toLowerCase().includes(keyword) || this.results[i].shortTitle.toLowerCase().includes(keyword) ||
226
                this.results[i].communityId.toLowerCase().includes(keyword) || this.results[i].description.toLowerCase().includes(keyword))) {
227
                ret.push(this.results[i]);
228
                break;
229
            }
230
          }
231
      }
232
      this.results = ret;
233
  }
234

    
235
  /**
236
   * Check the current results if they satisfy the values of each filter category and
237
   * update the number of possible results in each value.
238
   *
239
   * @param params
240
   */
241
  private checkFilters(params: Map<string, string>) {
242
    let typeResults: CommunityInfo[] = this.applyFilter('type', params);
243
    let statusResults: CommunityInfo[] = this.results;
244
    let roleResults: CommunityInfo[] = this.results;
245
    if(Session.isLoggedIn()) {
246
      statusResults = this.applyFilter('status', params);
247
      roleResults = this.applyFilter('role', params);
248
      this.resetFilterNumbers('status');
249
      this.updateFilterNumbers(typeResults.filter(value => {
250
        return roleResults.includes(value);
251
      }), 'status');
252
      this.resetFilterNumbers('role');
253
      this.updateFilterNumbers(statusResults.filter(value => {
254
        return typeResults.includes(value);
255
      }), 'role');
256
    }
257
    this.resetFilterNumbers('type');
258
    this.updateFilterNumbers(statusResults.filter(value => {
259
      return roleResults.includes(value);
260
    }), 'type');
261
    this.results = statusResults.filter(value => {
262
      return typeResults.includes(value);
263
    })
264
    this.results = this.results.filter(value => {
265
      return roleResults.includes(value);
266
    });
267
  }
268

    
269
  /**
270
   * Apply filter with filterId and return the results
271
   *
272
   * @param filterId
273
   * @param params
274
   */
275
  private applyFilter(filterId: string, params: Map<string, string>): CommunityInfo[] {
276
    let results:CommunityInfo[] = [];
277
    let values: string[] = [];
278
    if(params.get(filterId) != undefined) {
279
      values = (StringUtils.URIDecode(params.get(filterId))).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/,-1);
280
    }
281
    if(filterId == 'type') {
282
      for (let i = 0; i < this.results.length; i++) {
283
        if (values.length == 0) {
284
          results.push(this.results[i]);
285
        } else {
286
          for (let value of values) {
287
            if (this.results[i].type == value.replace(/["']/g, "")) {
288
              results.push(this.results[i]);
289
              break;
290
            }
291
          }
292
        }
293
      }
294
    }
295
    else if(filterId == 'status') {
296
      for (let i = 0; i < this.results.length; i++) {
297
        if (values.length == 0) {
298
          results.push(this.results[i]);
299
        } else {
300
          for (let value of values) {
301
            if (value.replace(/["']/g, "") == 'subscribed') {
302
              if (this.results[i].isSubscribed) {
303
                results.push(this.results[i]);
304
                break;
305
              }
306
            } else if (value.replace(/["']/g, "") == 'nonsubscribed') {
307
              if (!this.results[i].isSubscribed) {
308
                results.push(this.results[i]);
309
                break;
310
              }
311
            }
312
          }
313
        }
314
      }
315
    }
316
    else if(filterId == 'role') {
317
      for (let i = 0; i < this.results.length; i++) {
318
        if (values.length == 0) {
319
          results.push(this.results[i]);
320
        } else {
321
          for (let value of values) {
322
            if (value.replace(/["']/g, "") == 'manager') {
323
              if (this.results[i].isManager) {
324
                results.push(this.results[i]);
325
                break;
326
              }
327
            }
328
          }
329
        }
330
      }
331
    }
332
    return results;
333
  }
334

    
335
    /**
336
     * Reset the values of filter with id filterId with zero.
337
     *
338
     * @param filterId
339
     */
340
  private resetFilterNumbers(filterId: string) {
341
    for (let i = 0; i < this.filters.length; i++) {
342
      if(this.filters[i].filterId == filterId) {
343
        for (let j = 0; j < this.filters[i].values.length; j++) {
344
          this.filters[i].values[j].number = 0;
345
        }
346
        break;
347
      }
348
    }
349
  }
350

    
351
    /**
352
     * Update the values of filter with id filterId based on
353
     * results.
354
     *
355
     * @param results
356
     * @param filterId
357
     */
358
  private updateFilterNumbers(results: CommunityInfo[], filterId: string) {
359
    for(let k = 0; k < results.length; k++) {
360
      for (let i = 0; i < this.filters.length; i++) {
361
        if(this.filters[i].filterId == filterId) {
362
            if (this.filters[i].filterId == 'type') {
363
                for (let j = 0; j < this.filters[i].values.length; j++) {
364
                    if (results[k].type == this.filters[i].values[j].id) {
365
                        this.filters[i].values[j].number++;
366
                    }
367
                }
368
            }
369
            else if (this.filters[i].filterId == 'status') {
370
                if (results[k].isSubscribed) {
371
                    this.filters[i].values[0].number++;
372
                } else {
373
                    this.filters[i].values[1].number++;
374
                }
375
            }
376
            else if (this.filters[i].filterId == 'role') {
377
                if (results[k].isManager) {
378
                  this.filters[i].values[0].number++;
379
                }
380
            }
381
            break;
382
        }
383
      }
384
    }
385
  }
386

    
387
    /**
388
     * Sorting results based on sortBy.
389
     */
390
  private sort() {
391
    if(this.searchUtils.sortBy == '') {
392
      this.results.sort((left, right): number => {
393
        if (left.title > right.title) {
394
          return 1;
395
        } else if (left.title < right.title) {
396
          return -1;
397
        } else {
398
          return 0;
399
        }
400
      })
401
    } else if(this.searchUtils.sortBy == 'creationdate,descending') {
402
      this.results.sort((left, right): number => {
403
        if (!right.date || left.date > right.date) {
404
          return -1;
405
        } else if (!left.date || left.date < right.date) {
406
          return 1;
407
        } else {
408
          return 0;
409
        }
410
      })
411
    } else if(this.searchUtils.sortBy == 'creationdate,ascending') {
412
      this.results.sort((left, right): number => {
413
        if (!right.date || left.date > right.date) {
414
          return 1;
415
        } else if (!left.date || left.date < right.date) {
416
          return -1;
417
        } else {
418
          return 0;
419
        }
420
      })
421
    }
422
  }
423

    
424

    
425
  private isCommunityManager(community: CommunityInfo): boolean {
426
    return Session.isCommunityCurator() || community.managers.indexOf(Session.getUserEmail()) != -1;
427
  }
428

    
429
    /**
430
     * Create Search Communities filters.
431
     *
432
     */
433
  private createFilters(): Filter[] {
434
    let filter_names=["Type"];
435
    let filter_ids=["type"];
436
    let searchFields = new SearchFields();
437
    let filter_original_ids = searchFields.COMMUNITIES_SEARCH_FIELDS;
438
    let value_names = [
439
      [ "Research Communities", "Research Initiatives" ]
440
    ];
441
    let value_original_ids=[
442
      ["community","ri"]
443
    ];
444
    if(Session.isLoggedIn()) {
445
      filter_names[1] = "Status";
446
      filter_ids[1] = "status";
447
      value_names[1] = [ "Subscribed", "Non-subscribed"];
448
      value_original_ids[1] = ["subscribed", "nonsubscribed"];
449
      filter_names[2] = "Role";
450
      filter_ids[2] = "role";
451
      value_names[2] = [ "Manager" ];
452
      value_original_ids[2] = ["manager"];
453
    }
454
    let filters: Filter[] = [];
455
    for(let  i =0 ; i < filter_names.length; i++){
456
      let values: Value[] = [];
457
      for(let j =0 ; j < value_names[i].length; j++){
458
        let value: Value = {name: value_names[i][j], id: value_original_ids[i][j], number:0, selected:false};
459
        values.push(value);
460
      }
461
      let filter: Filter = {title: filter_names[i], filterId: filter_ids[i], originalFilterId:  filter_original_ids[i], values : values, countSelectedValues:0, "filterOperator": 'or', valueIsExact: true };
462
      filters.push(filter);
463
    }
464
    return filters;
465
  }
466

    
467
  private handleError(message: string, error) {
468
    console.error('Communities Search Page: ' + message, error);
469
  }
470

    
471
}
(2-2/3)