import {Component, 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, User} from "../../openaireLibrary/login/utils/helper.class"; import {CommunityInfo} from "../../openaireLibrary/connect/community/communityInfo"; import {SubscribeService} from "../../openaireLibrary/utils/subscribe/subscribe.service"; import {StringUtils} from "../../openaireLibrary/utils/string-utils.class"; import {HelperFunctions} from "../../openaireLibrary/utils/HelperFunctions.class"; import {UserManagementService} from "../../openaireLibrary/services/user-management.service"; import {url} from "inspector"; @Component({ selector: 'search-communities', template: ` ` }) export class SearchCommunitiesComponent { public piwikSiteId = null; private errorCodes: ErrorCodes; private errorMessages: ErrorMessagesComponent; public results: CommunityInfo[] = []; public totalResults: CommunityInfo[] = []; 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; public showType = false; properties:EnvProperties; @ViewChild (SearchPageComponent) searchPage : SearchPageComponent ; private user: User; constructor (private route: ActivatedRoute, private _communitiesService: CommunitiesService, private _subscribeService: SubscribeService, private userManagementService: UserManagementService) { 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.piwikSiteId = this.properties.piwikSiteId; this.baseUrl = data.envSpecific.searchLinkToCommunities; }); this.sub = this.route.queryParams.subscribe(params => { this.searchPage.resultsPerPage = 10; 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']; this.searchPage.searchUtils = this.searchUtils; 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); if(typeof document !== 'undefined') { this.userManagementService.getUserInfo(this.properties.userInfoUrl).subscribe(user => { this.user = user; this.initCommunities(queryParams); }); } else { this.initCommunities(queryParams); } }); } public ngOnDestroy() { if(this.sub){ this.sub.unsubscribe(); } if(this.subResults){ this.subResults.unsubscribe(); } } /** * Initialize communities from Communities APIs * * @param params */ private initCommunities(params: Map) { this.subResults = this._communitiesService.getCommunitiesState().subscribe( data => { if(!data){ return; } for(let i = 0; i < data.length; i++) { this.totalResults[i] = data[i]; this.totalResults[i].isManager = false; this.totalResults[i].isSubscribed = false; if(this.user) { this.totalResults[i].isManager = this.isCommunityManager(this.totalResults[i]); } } if(this.user) { this._subscribeService.getCommunitiesSubscribedTo(this.properties, this.user.email).subscribe( res => { for (let i = 0; i < this.totalResults.length; i++) { this.totalResults[i].isSubscribed = (res.indexOf(this.totalResults[i].communityId) != -1); } this._getResults(params); } ); } else { this._getResults(params); } }, err => { this.handleError('Error getting communities', err); this.searchUtils.status = this.errorMessages.getErrorCode(err.status); this.disableForms = false; HelperFunctions.scroll(); } ); } /** * Get all communities from Communities API and apply permission access validator, * keyword searching, filter, paging and sorting. * * @param params, status * @private */ private _getResults(params: Map){ this.searchUtils.status = this.errorCodes.LOADING; this.disableForms = true; this.results = this.totalResults; if(this.filters.length === 0) { this.filters = this.createFilters(); } this.searchUtils.totalResults = 0; this.applyParams(params); } /** * Return the communities in which user has permission to view or manage. */ private showCommunities() { let ret: CommunityInfo[] = []; for(let result of this.results) { if (result.status == 'hidden') { continue; } else if (result.status == "manager") { let mail = (this.user)?this.user.email:null; if (mail == null) { // no user continue; } else if (Session.isCommunityCurator(this.user) || Session.isPortalAdministrator(this.user)) { ret.push(result); } else if (result.managers.indexOf(mail) != -1) { ret.push(result); } continue; } ret.push(result); } this.results = ret; } /** * Apply permission access validator, * keyword searching, filter, paging and sorting. * * @param params * @param status */ public applyParams(params: Map) { 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; } } HelperFunctions.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: CommunityInfo[] = []; let keywords: string[] = this.searchUtils.keyword.split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/,-1); for(let i = 0; i < this.results.length; i++) { for(let keyword of keywords) { keyword = keyword.toLowerCase(); if (keyword != '' && (this.results[i].title.toLowerCase().includes(keyword) || this.results[i].shortTitle.toLowerCase().includes(keyword) || this.results[i].communityId.toLowerCase().includes(keyword) || this.results[i].description.toLowerCase().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: CommunityInfo[] = this.applyFilter('type', params); let statusResults: CommunityInfo[] = this.results; let roleResults: CommunityInfo[] = this.results; if(this.user) { statusResults = this.applyFilter('status', params); roleResults = this.applyFilter('role', params); this.resetFilterNumbers('status'); this.updateFilterNumbers(typeResults.filter(value => { return roleResults.includes(value); }), 'status'); this.resetFilterNumbers('role'); this.updateFilterNumbers(statusResults.filter(value => { return typeResults.includes(value); }), 'role'); } this.resetFilterNumbers('type'); this.updateFilterNumbers(statusResults.filter(value => { return roleResults.includes(value); }), 'type'); this.results = statusResults.filter(value => { return typeResults.includes(value); }) this.results = this.results.filter(value => { return roleResults.includes(value); }); } /** * Apply filter with filterId and return the results * * @param filterId * @param params */ private applyFilter(filterId: string, params: Map): CommunityInfo[] { let results:CommunityInfo[] = []; let values: string[] = []; if(params.get(filterId) != undefined) { values = (StringUtils.URIDecode(params.get(filterId))).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/,-1); } if(filterId == 'type') { for (let i = 0; i < this.results.length; i++) { if (values.length == 0) { results.push(this.results[i]); } else { for (let value of values) { if (this.results[i].type == value.replace(/["']/g, "")) { results.push(this.results[i]); break; } } } } } else if(filterId == 'status') { for (let i = 0; i < this.results.length; i++) { if (values.length == 0) { results.push(this.results[i]); } else { for (let value of values) { if (value.replace(/["']/g, "") == 'subscribed') { if (this.results[i].isSubscribed) { results.push(this.results[i]); break; } } else if (value.replace(/["']/g, "") == 'nonsubscribed') { if (!this.results[i].isSubscribed) { results.push(this.results[i]); break; } } } } } } else if(filterId == 'role') { for (let i = 0; i < this.results.length; i++) { if (values.length == 0) { results.push(this.results[i]); } else { for (let value of values) { if (value.replace(/["']/g, "") == 'manager') { if (this.results[i].isManager) { results.push(this.results[i]); break; } } } } } } return results; } /** * 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: CommunityInfo[], 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].type == this.filters[i].values[j].id) { this.filters[i].values[j].number++; } } } else if (this.filters[i].filterId == 'status') { if (results[k].isSubscribed) { this.filters[i].values[0].number++; } else { this.filters[i].values[1].number++; } } else 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.title > right.title) { return 1; } else if (left.title < right.title) { return -1; } else { return 0; } }) } else if(this.searchUtils.sortBy == 'creationdate,descending') { this.results.sort((left, right): number => { if (!right.date || left.date > right.date) { return -1; } else if (!left.date || left.date < right.date) { return 1; } else { return 0; } }) } else if(this.searchUtils.sortBy == 'creationdate,ascending') { this.results.sort((left, right): number => { if (!right.date || left.date > right.date) { return 1; } else if (!left.date || left.date < right.date) { return -1; } else { return 0; } }) } } private isCommunityManager(community: CommunityInfo): boolean { return Session.isCommunityCurator(this.user) || community.managers.indexOf(this.user.email) != -1; } /** * Create Search Communities filters. * */ private createFilters(): Filter[] { let filter_names = []; let filter_ids = []; let searchFields = new SearchFields(); let filter_original_ids = searchFields.COMMUNITIES_SEARCH_FIELDS; let value_names = []; let value_original_ids=[]; this.showType = this.results.filter(community => community.type === 'ri').length > 0; if(this.showType) { filter_names.push("Type"); filter_ids.push("type"); value_names.push([ "Research Communities", "Research Initiatives" ]); value_original_ids.push(["community","ri"]); } else { filter_original_ids = searchFields.COMMUNITIES_SEARCH_FIELDS.splice(0, 1); } if(this.user) { filter_names.push("Status"); filter_ids.push("status"); value_names.push([ "Subscribed", "Non-subscribed"]); value_original_ids.push(["subscribed", "nonsubscribed"]); filter_names.push("Role"); filter_ids.push("role"); value_names.push([ "Manager"]); value_original_ids.push(["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 , valueIsUnique: false}; filters.push(filter); } return filters; } private handleError(message: string, error) { console.error('Communities Search Page: ' + message, error); } }