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
import {url} from "inspector";
18

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

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

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

    
91
  public ngOnDestroy() {
92
    if(this.sub){
93
      this.sub.unsubscribe();
94
    }
95
    if(this.subResults){
96
      this.subResults.unsubscribe();
97
    }
98
  }
99

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

    
142

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

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

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

    
222

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

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

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

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

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

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

    
432

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

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

    
480
  private handleError(message: string, error) {
481
    console.error('Communities Search Page: ' + message, error);
482
  }
483

    
484
}
(2-2/3)