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, User} 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 {HelperFunctions} from "../../openaireLibrary/utils/HelperFunctions.class";
16
import {UserManagementService} from "../../openaireLibrary/services/user-management.service";
17

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

    
52
  constructor (private route: ActivatedRoute,
53
               private _communitiesService: CommunitiesService,
54
               private _subscribeService: SubscribeService,
55
               private userManagementService: UserManagementService) {
56
    this.errorCodes = new ErrorCodes();
57
    this.errorMessages = new ErrorMessagesComponent();
58
    this.searchUtils.status = this.errorCodes.LOADING;
59
  }
60

    
61
  public ngOnInit() {
62
    this.route.data
63
        .subscribe((data: { envSpecific: EnvProperties }) => {
64
          this.properties = data.envSpecific;
65
          this.piwikSiteId = this.properties.piwikSiteId;
66
          this.baseUrl = data.envSpecific.searchLinkToCommunities;
67
        });
68
    this.sub =  this.route.queryParams.subscribe(params => {
69
      this.searchPage.resultsPerPage = 10;
70
      this.searchUtils.keyword = (params['keyword']?params['keyword']:'');
71
      this.searchUtils.page = (params['page'] === undefined) ? 1: + params['page'];
72
      this.searchUtils.sortBy = (params['sortBy'] === undefined)? '' : params['sortBy'];
73
      this.searchUtils.size = (params['size'] === undefined) ? this.searchPage.resultsPerPage: +params['size'];
74
      this.searchPage.searchUtils = this.searchUtils;
75
      if(this.searchUtils.size != 5 && this.searchUtils.size != 10 && this.searchUtils.size != 20 && this.searchUtils.size != 50) {
76
        this.searchUtils.size = this.searchPage.resultsPerPage;
77
      }
78
      if(this.searchUtils.sortBy && this.searchUtils.sortBy != "creationdate,descending" && this.searchUtils.sortBy != "creationdate,ascending") {
79
        this.searchUtils.sortBy = "";
80
      }
81
      this.searchPage.refineFields = this.refineFields;
82
      let queryParams = this.searchPage.getQueryParamsFromUrl(params);
83
      if(typeof document !== 'undefined') {
84
        this.userManagementService.getUserInfo().subscribe(user => {
85
          this.user = user;
86
          this.initCommunities(queryParams);
87
        });
88
      } else  {
89
        this.initCommunities(queryParams);
90
      }
91
    });
92
  }
93

    
94
  public ngOnDestroy() {
95
    if(this.sub){
96
      this.sub.unsubscribe();
97
    }
98
    if(this.subResults){
99
      this.subResults.unsubscribe();
100
    }
101
  }
102

    
103
  /**
104
   * Initialize communities from Communities APIs
105
   *
106
   * @param params
107
   */
108
  private initCommunities(params: Map<string, string>) {
109
    this.subResults = this._communitiesService.getCommunitiesState().subscribe(
110
        data => {
111
          if(!data){
112
            return;
113
          }
114
          for(let i = 0; i < data.length; i++) {
115
            this.totalResults[i] = data[i];
116
            this.totalResults[i].isManager = false;
117
            this.totalResults[i].isSubscribed = false;
118
            if(this.user) {
119
              this.totalResults[i].isManager = this.isCommunityManager(this.totalResults[i]);
120
            }
121
          }
122
          if(this.user) {
123
            this._subscribeService.getCommunitiesSubscribedTo(this.properties/*, this.user.email*/).subscribe(
124
              res => {
125
                for (let i = 0; i < this.totalResults.length; i++) {
126
                  this.totalResults[i].isSubscribed = (res.indexOf(this.totalResults[i].communityId) != -1);
127
                }
128
                this._getResults(params);
129
              }
130
            );
131
          }
132
          else {
133
            this._getResults(params);
134
          }
135
        },
136
        err => {
137
          this.handleError('Error getting communities', err);
138
          this.searchUtils.status = this.errorMessages.getErrorCode(err.status);
139
          this.disableForms = false;
140
          HelperFunctions.scroll();
141
        }
142
      );
143
  }
144

    
145

    
146
  /**
147
   * Get all communities from Communities API and apply permission access validator,
148
   * keyword searching, filter, paging and sorting.
149
   *
150
   * @param params, status
151
   * @private
152
   */
153
  private _getResults(params: Map<string, string>){
154
    this.searchUtils.status = this.errorCodes.LOADING;
155
    this.disableForms = true;
156
    this.results = this.totalResults;
157
    if(this.filters.length === 0) {
158
      this.filters = this.createFilters();
159
    }
160
    this.searchUtils.totalResults = 0;
161
    this.applyParams(params);
162
  }
163

    
164
  /**
165
   * Return the communities in which user has permission to view or manage.
166
   */
167
  private showCommunities() {
168
    let ret: CommunityInfo[] = [];
169
    for(let result of this.results) {
170
      if (result.status == 'hidden') {
171
        continue;
172
      } else if (result.status == "manager") {
173
        let mail = (this.user)?this.user.email:null;
174
        if (mail == null) { // no user
175
          continue;
176
        } else if (Session.isCommunityCurator(this.user) || Session.isPortalAdministrator(this.user)) {
177
          ret.push(result);
178
        } else if (result.managers.indexOf(mail) != -1) {
179
          ret.push(result);
180
        }
181
        continue;
182
      }
183
      ret.push(result);
184
    }
185
    this.results = ret;
186
  }
187

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

    
225

    
226
  /**
227
   * Parse the given keywords into array and check if any of the requirements field of a community includes
228
   * one of the given words.
229
   */
230
  private searchForKeywords() {
231
      let ret: CommunityInfo[] = [];
232
      let keywords: string[] = this.searchUtils.keyword.split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/,-1);
233
      for(let i = 0; i < this.results.length; i++) {
234
          for(let keyword of keywords) {
235
            keyword = keyword.toLowerCase();
236
            if (keyword != '' && (this.results[i].title.toLowerCase().includes(keyword) || this.results[i].shortTitle.toLowerCase().includes(keyword) ||
237
                this.results[i].communityId.toLowerCase().includes(keyword) || this.results[i].description.toLowerCase().includes(keyword))) {
238
                ret.push(this.results[i]);
239
                break;
240
            }
241
          }
242
      }
243
      this.results = ret;
244
  }
245

    
246
  /**
247
   * Check the current results if they satisfy the values of each filter category and
248
   * update the number of possible results in each value.
249
   *
250
   * @param params
251
   */
252
  private checkFilters(params: Map<string, string>) {
253
    let typeResults: CommunityInfo[] = this.applyFilter('type', params);
254
    let statusResults: CommunityInfo[] = this.results;
255
    let roleResults: CommunityInfo[] = this.results;
256
    if(this.user) {
257
      statusResults = this.applyFilter('status', params);
258
      roleResults = this.applyFilter('role', params);
259
      this.resetFilterNumbers('status');
260
      this.updateFilterNumbers(typeResults.filter(value => {
261
        return roleResults.includes(value);
262
      }), 'status');
263
      this.resetFilterNumbers('role');
264
      this.updateFilterNumbers(statusResults.filter(value => {
265
        return typeResults.includes(value);
266
      }), 'role');
267
    }
268
    this.resetFilterNumbers('type');
269
    this.updateFilterNumbers(statusResults.filter(value => {
270
      return roleResults.includes(value);
271
    }), 'type');
272
    this.results = statusResults.filter(value => {
273
      return typeResults.includes(value);
274
    })
275
    this.results = this.results.filter(value => {
276
      return roleResults.includes(value);
277
    });
278
  }
279

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

    
346
    /**
347
     * Reset the values of filter with id filterId with zero.
348
     *
349
     * @param filterId
350
     */
351
  private resetFilterNumbers(filterId: string) {
352
    for (let i = 0; i < this.filters.length; i++) {
353
      if(this.filters[i].filterId == filterId) {
354
        for (let j = 0; j < this.filters[i].values.length; j++) {
355
          this.filters[i].values[j].number = 0;
356
        }
357
        break;
358
      }
359
    }
360
  }
361

    
362
    /**
363
     * Update the values of filter with id filterId based on
364
     * results.
365
     *
366
     * @param results
367
     * @param filterId
368
     */
369
  private updateFilterNumbers(results: CommunityInfo[], filterId: string) {
370
    for(let k = 0; k < results.length; k++) {
371
      for (let i = 0; i < this.filters.length; i++) {
372
        if(this.filters[i].filterId == filterId) {
373
            if (this.filters[i].filterId == 'type') {
374
                for (let j = 0; j < this.filters[i].values.length; j++) {
375
                    if (results[k].type == this.filters[i].values[j].id) {
376
                        this.filters[i].values[j].number++;
377
                    }
378
                }
379
            }
380
            else if (this.filters[i].filterId == 'status') {
381
                if (results[k].isSubscribed) {
382
                    this.filters[i].values[0].number++;
383
                } else {
384
                    this.filters[i].values[1].number++;
385
                }
386
            }
387
            else if (this.filters[i].filterId == 'role') {
388
                if (results[k].isManager) {
389
                  this.filters[i].values[0].number++;
390
                }
391
            }
392
            break;
393
        }
394
      }
395
    }
396
  }
397

    
398
    /**
399
     * Sorting results based on sortBy.
400
     */
401
  private sort() {
402
    if(this.searchUtils.sortBy == '') {
403
      this.results.sort((left, right): number => {
404
        if (left.title > right.title) {
405
          return 1;
406
        } else if (left.title < right.title) {
407
          return -1;
408
        } else {
409
          return 0;
410
        }
411
      })
412
    } else if(this.searchUtils.sortBy == 'creationdate,descending') {
413
      this.results.sort((left, right): number => {
414
        if (!right.date || left.date > right.date) {
415
          return -1;
416
        } else if (!left.date || left.date < right.date) {
417
          return 1;
418
        } else {
419
          return 0;
420
        }
421
      })
422
    } else if(this.searchUtils.sortBy == 'creationdate,ascending') {
423
      this.results.sort((left, right): number => {
424
        if (!right.date || left.date > right.date) {
425
          return 1;
426
        } else if (!left.date || left.date < right.date) {
427
          return -1;
428
        } else {
429
          return 0;
430
        }
431
      })
432
    }
433
  }
434

    
435

    
436
  private isCommunityManager(community: CommunityInfo): boolean {
437
    return Session.isCommunityCurator(this.user) || community.managers.indexOf(this.user.email) != -1;
438
  }
439

    
440
    /**
441
     * Create Search Communities filters.
442
     *
443
     */
444
  private createFilters(): Filter[] {
445
    let filter_names = [];
446
    let filter_ids = [];
447
    let searchFields = new SearchFields();
448
    let filter_original_ids = searchFields.COMMUNITIES_SEARCH_FIELDS;
449
    let value_names = [];
450
    let value_original_ids=[];
451
    this.showType = this.results.filter(community => community.type === 'ri').length > 0;
452
    if(this.showType) {
453
      filter_names.push("Type");
454
      filter_ids.push("type");
455
      value_names.push([ "Research Communities", "Research Initiatives" ]);
456
      value_original_ids.push(["community","ri"]);
457
    } else {
458
      filter_original_ids = searchFields.COMMUNITIES_SEARCH_FIELDS.splice(0, 1);
459
    }
460
    if(this.user) {
461
      filter_names.push("Status");
462
      filter_ids.push("status");
463
      value_names.push([ "Subscribed", "Non-subscribed"]);
464
      value_original_ids.push(["subscribed", "nonsubscribed"]);
465
      filter_names.push("Role");
466
      filter_ids.push("role");
467
      value_names.push([ "Manager"]);
468
      value_original_ids.push(["manager"]);
469
    }
470
    let filters: Filter[] = [];
471
    for(let  i =0 ; i < filter_names.length; i++){
472
      let values: Value[] = [];
473
      for(let j =0 ; j < value_names[i].length; j++){
474
        let value: Value = {name: value_names[i][j], id: value_original_ids[i][j], number:0, selected:false};
475
        values.push(value);
476
      }
477
      let filter: Filter = {title: filter_names[i], filterId: filter_ids[i], originalFilterId:  filter_original_ids[i], values : values, countSelectedValues:0, "filterOperator": 'or', valueIsExact: true , filterType: "checkbox"};
478
      filters.push(filter);
479
    }
480
    return filters;
481
  }
482

    
483
  private handleError(message: string, error) {
484
    console.error('Communities Search Page: ' + message, error);
485
  }
486

    
487
}
(2-2/3)