import {Component, ElementRef, ViewChild} from "@angular/core"; import {SearchUtilsClass} from "../../openaireLibrary/searchPages/searchUtils/searchUtils.class"; import {ErrorMessagesComponent} from "../../openaireLibrary/utils/errorMessages.component"; import {ErrorCodes} from "../../openaireLibrary/utils/properties/errorCodes"; import {EnvProperties} from "../../openaireLibrary/utils/properties/env-properties"; import {SearchPageComponent} from "../../openaireLibrary/searchPages/searchUtils/searchPage.component"; import {ActivatedRoute} from "@angular/router"; import {Filter, Value} from "../../openaireLibrary/searchPages/searchUtils/searchHelperClasses.class"; import {SearchFields} from "../../openaireLibrary/utils/properties/searchFields"; import {CommunitiesService} from "../../openaireLibrary/connect/communities/communities.service"; import {Session} from "../../openaireLibrary/login/utils/helper.class"; import {CommunityInfo} from "../../openaireLibrary/connect/community/communityInfo"; import {SearchResult} from "../../openaireLibrary/utils/entities/searchResult"; import {SubscribeService} from "../../openaireLibrary/utils/subscribe/subscribe.service"; import {Observable} from "rxjs"; import {StringUtils} from "../../openaireLibrary/utils/string-utils.class"; @Component({ selector: 'search-communities', template: ` ` }) export class SearchCommunitiesComponent { private errorCodes: ErrorCodes; private errorMessages: ErrorMessagesComponent; public results: SearchResult[] = []; public sub: any; public subResults: any; public filters = []; public searchFields:SearchFields = new SearchFields(); public searchUtils:SearchUtilsClass = new SearchUtilsClass(); public disableForms: boolean = false; public baseUrl: string = null; public refineFields: string[] = this.searchFields.COMMUNITIES_SEARCH_FIELDS; properties:EnvProperties; @ViewChild (SearchPageComponent) searchPage : SearchPageComponent ; constructor (private route: ActivatedRoute, private _communitiesService: CommunitiesService, private _subscribeService: SubscribeService, private element: ElementRef) { this.errorCodes = new ErrorCodes(); this.errorMessages = new ErrorMessagesComponent(); this.searchUtils.status = this.errorCodes.LOADING; } public ngOnInit() { this.route.data .subscribe((data: { envSpecific: EnvProperties }) => { this.properties = data.envSpecific; this.baseUrl = data.envSpecific.searchLinkToCommunities; }); this.sub = this.route.queryParams.subscribe(params => { this.searchPage.resultsPerPage = 5; this.searchUtils.keyword = (params['keyword']?params['keyword']:''); this.searchUtils.page = (params['page'] === undefined) ? 1: + params['page']; this.searchUtils.sortBy = (params['sortBy'] === undefined)? '' : params['sortBy']; this.searchUtils.size = (params['size'] === undefined) ? this.searchPage.resultsPerPage: + params['size']; if(this.searchUtils.size != 5 && this.searchUtils.size != 10 && this.searchUtils.size != 20 && this.searchUtils.size != 50) { this.searchUtils.size = this.searchPage.resultsPerPage; } if(this.searchUtils.sortBy && this.searchUtils.sortBy != "creationdate,descending" && this.searchUtils.sortBy != "creationdate,ascending") { this.searchUtils.sortBy = ""; } this.searchPage.refineFields = this.refineFields; let queryParams = this.searchPage.getQueryParamsFromUrl(params); this.filters = this.createFilters(); this._getResults(queryParams); }); } public ngOnDestroy() { if(this.sub){ this.sub.unsubscribe(); } if(this.subResults){ this.subResults.unsubscribe(); } } /** * Return the communities in which user has permission to view or manage. */ private showCommunities() { let ret: SearchResult[] = []; for(let result of this.results) { if (result.community.status == 'hidden') { continue; } else if (result.community.status == "manager") { let mail = Session.getUserEmail(); if (mail == null) { // no user continue; } else if (Session.isCommunityCurator() || Session.isPortalAdministrator()) { ret.push(result); } else if (result.community.managers.indexOf(mail) != -1) { ret.push(result); } continue; } ret.push(result); } this.results = ret; } /** * Get all communities from Communities API and apply permission access validator, * if a keyword is included, filter, paging and sorting. * * @param params * @private */ private _getResults(params: Map){ this.searchUtils.status = this.errorCodes.LOADING; this.disableForms = true; this.results = []; this.searchUtils.totalResults = 0; this.subResults = this._communitiesService.getCommunities(this.properties, this.properties.communitiesAPI).subscribe( data => { let observables: Observable[] = []; for(let i = 0; i < data.length; i++) { this.results[i] = new SearchResult(); this.results[i].community = data[i]; // For Test do not delete them. //this.results[i].community.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." //this.results[i].community.date = new Date(new Date(2012, 0, 1).getTime() + Math.random() * (new Date().getTime() - new Date(2012, 0, 1).getTime())); observables.push(this._subscribeService.isSubscribedToCommunity(this.results[i].community.communityId, Session.getUserEmail(), this.properties["adminToolsAPIURL"])); this.results[i].isManager = this.isCommunityManager(this.results[i].community); } Observable.forkJoin(observables).subscribe( res => { for(let i = 0; i < res.length; i++) { this.results[i].isSubscribed = res[i]; } this.showCommunities(); if(this.searchUtils.keyword && this.searchUtils.keyword != '') { this.searchForKeywords(); } this.checkFilters(params); this.sort(); this.searchUtils.totalResults = this.results.length; this.searchPage.checkSelectedFilters(this.filters); this.searchPage.updateBaseUrlWithParameters(this.filters); this.results = this.results.slice((this.searchUtils.page-1)*this.searchUtils.size, (this.searchUtils.page*this.searchUtils.size)); this.searchUtils.status = this.errorCodes.DONE; if(this.searchUtils.totalResults == 0 ){ this.searchUtils.status = this.errorCodes.NONE; } this.disableForms = false; if(this.searchUtils.status == this.errorCodes.DONE) { // Page out of limit!!! let totalPages:any = this.searchUtils.totalResults/(this.searchUtils.size); if(!(Number.isInteger(totalPages))) { totalPages = (parseInt(totalPages, 10) + 1); } if(totalPages < this.searchUtils.page) { this.searchUtils.totalResults = 0; this.searchUtils.status = this.errorCodes.OUT_OF_BOUND; } } this.scroll(); }, err => { this.handleError('Error getting if user is subscribed', err); this.searchUtils.status = this.errorMessages.getErrorCode(err.status); this.disableForms = false; this.scroll(); } ); }, err => { //console.log(err); this.handleError('Error getting communities', err); this.searchUtils.status = this.errorMessages.getErrorCode(err.status); this.disableForms = false; this.scroll(); } ); } /** * Parse the given keywords into array and check if any of the requirements field of a community includes * one of the given words. */ private searchForKeywords() { let ret: SearchResult[] = []; let keywords: string[] = this.searchUtils.keyword.split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/,-1); for(let i = 0; i < this.results.length; i++) { for(let keyword of keywords) { if (keyword != '' && (this.results[i].community.title.includes(keyword) || this.results[i].community.shortTitle.includes(keyword) || this.results[i].community.communityId.includes(keyword) || this.results[i].community.description.includes(keyword))) { ret.push(this.results[i]); break; } } } this.results = ret; } /** * Check the current results if they satisfy the values of each filter category and * update the number of possible results in each value. * * @param params */ private checkFilters(params: Map) { let typeResults: SearchResult[] = []; let statusResults: SearchResult[] = []; let roleResults: SearchResult[] = []; let types: string[] = []; let statuses: string[] = []; let roles: string[] = []; if(params.get('type') != undefined) { types = (StringUtils.URIDecode(params.get('type'))).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/,-1); } if(params.get('status') != undefined) { statuses = (StringUtils.URIDecode(params.get('status'))).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/,-1); } if(params.get('role') != undefined) { roles = (StringUtils.URIDecode(params.get('role'))).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/,-1); } for(let i = 0; i < this.results.length; i++) { if (types.length == 0) { typeResults.push(this.results[i]); } else { for (let type of types) { if (this.results[i].community.type == type.replace(/["']/g, "")) { typeResults.push(this.results[i]); break; } } } } for(let i = 0; i < this.results.length; i++) { if( statuses.length == 0) { statusResults.push(this.results[i]); } else { for (let status of statuses) { if(status.replace(/["']/g, "") == 'subscribed') { if(this.results[i].isSubscribed) { statusResults.push(this.results[i]); break; } } else if(status.replace(/["']/g, "") == 'nonsubscribed') { if(!this.results[i].isSubscribed) { statusResults.push(this.results[i]); break; } } else if(status.replace(/["']/g, "") == 'managing') { if (this.results[i].isManager) { statusResults.push(this.results[i]); break; } } } } } for(let i = 0; i < this.results.length; i++) { if (roles.length == 0) { roleResults.push(this.results[i]); } else { for (let role of roles) { if(role.replace(/["']/g, "") == 'manager') { if (this.results[i].isManager) { roleResults.push(this.results[i]); break; } } } } } this.resetFilterNumbers('status'); this.updateFilterNumbers(typeResults.filter(value => { return roleResults.includes(value); }), 'status'); this.resetFilterNumbers('type'); this.updateFilterNumbers(statusResults.filter(value => { return roleResults.includes(value); }), 'type'); this.resetFilterNumbers('role'); this.updateFilterNumbers(statusResults.filter(value => { return typeResults.includes(value); }), 'role'); this.results = statusResults.filter(value => { return typeResults.includes(value); }) this.results = this.results.filter(value => { return roleResults.includes(value); }); } /** * Reset the values of filter with id filterId with zero. * * @param filterId */ private resetFilterNumbers(filterId: string) { for (let i = 0; i < this.filters.length; i++) { if(this.filters[i].filterId == filterId) { for (let j = 0; j < this.filters[i].values.length; j++) { this.filters[i].values[j].number = 0; } break; } } } /** * Update the values of filter with id filterId based on * results. * * @param results * @param filterId */ private updateFilterNumbers(results: SearchResult[], filterId: string) { for(let k = 0; k < results.length; k++) { for (let i = 0; i < this.filters.length; i++) { if(this.filters[i].filterId == filterId) { if (this.filters[i].filterId == 'type') { for (let j = 0; j < this.filters[i].values.length; j++) { if (results[k].community.type == this.filters[i].values[j].id) { this.filters[i].values[j].number++; } } } if (this.filters[i].filterId == 'status') { if (results[k].isSubscribed) { this.filters[i].values[0].number++; } else { this.filters[i].values[1].number++; } } if (this.filters[i].filterId == 'role') { if (results[k].isManager) { this.filters[i].values[0].number++; } } break; } } } } /** * Sorting results based on sortBy. */ private sort() { if(this.searchUtils.sortBy == '') { this.results.sort((left, right): number => { if (left.community.title > right.community.title) { return 1; } else if (left.community.title < right.community.title) { return -1; } else { return 0; } }) } else if(this.searchUtils.sortBy == 'creationdate,descending') { this.results.sort((left, right): number => { if (!right.community.date || left.community.date > right.community.date) { return -1; } else if (!left.community.date || left.community.date < right.community.date) { return 1; } else { return 0; } }) } else if(this.searchUtils.sortBy == 'creationdate,ascending') { this.results.sort((left, right): number => { if (!right.community.date || left.community.date > right.community.date) { return 1; } else if (!left.community.date || left.community.date < right.community.date) { return -1; } else { return 0; } }) } } private isCommunityManager(community: CommunityInfo): boolean { return Session.isCommunityCurator() || community.managers.indexOf(Session.getUserEmail()) != -1; } public queryChanged($event) { this._getResults($event.params); } /** * Create Search Communities filters. * */ private createFilters(): Filter[] { let filter_names=["Type"]; let filter_ids=["type"]; let searchFields = new SearchFields(); let filter_original_ids = searchFields.COMMUNITIES_SEARCH_FIELDS; let value_names = [ [ "Research Communities", "Research Initiatives" ] ]; let value_original_ids=[ ["community","ri"] ]; if(Session.isLoggedIn()) { filter_names[1] = "Status"; filter_ids[1] = "status"; value_names[1] = [ "Subscribed", "Non-subscribed"]; value_original_ids[1] = ["subscribed", "nonsubscribed"]; filter_names[2] = "Role"; filter_ids[2] = "role"; value_names[2] = [ "Manager" ]; value_original_ids[2] = ["manager"]; } let filters: Filter[] = []; for(let i =0 ; i < filter_names.length; i++){ let values: Value[] = []; for(let j =0 ; j < value_names[i].length; j++){ let value: Value = {name: value_names[i][j], id: value_original_ids[i][j], number:0, selected:false}; values.push(value); } let filter: Filter = {title: filter_names[i], filterId: filter_ids[i], originalFilterId: filter_original_ids[i], values : values, countSelectedValues:0, "filterOperator": 'or', valueIsExact: true }; filters.push(filter); } return filters; } private handleError(message: string, error) { console.error('Communities Search Page: ' + message, error); } public scroll() { if (typeof document !== 'undefined') { this.element.nativeElement.scrollIntoView(); } } }