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 {ActivatedRoute} from "@angular/router"; import {AdvancedField, 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 {StringUtils} from "../../openaireLibrary/utils/string-utils.class"; import {HelperFunctions} from "../../openaireLibrary/utils/HelperFunctions.class"; import {UserManagementService} from "../../openaireLibrary/services/user-management.service"; import {Breadcrumb} from "../../openaireLibrary/utils/breadcrumbs/breadcrumbs.component"; import {NewSearchPageComponent} from "../../openaireLibrary/searchPages/searchUtils/newSearchPage.component"; import {properties} from "../../../environments/environment"; import {Subscriber} from "rxjs"; @Component({ selector: 'search-communities', template: ` ` }) export class SearchCommunitiesComponent { public piwikSiteId = null; private errorCodes: ErrorCodes; private errorMessages: ErrorMessagesComponent; public results: CommunityInfo[] = []; public totalResults: CommunityInfo[] = []; public subscriptions = []; public filters = []; public searchFields: SearchFields = new SearchFields(); public searchUtils: SearchUtilsClass = new SearchUtilsClass(); public selectedFields: AdvancedField[] = []; public disableForms: boolean = false; public baseUrl: string = null; public fieldIds: string[] = ["q"]; public refineFields: string[] = this.searchFields.COMMUNITIES_SEARCH_FIELDS; public fieldIdsMap = { ["q"]: { name: "All fields", type: "keyword", param: "q", operator: "op", equalityOperator: "=", filterType: null } }; public keyword = ""; public searchLink; public showType = false; public breadcrumbs: Breadcrumb[] = [{name: 'home', route: '/'}, {name: 'communities'}]; properties: EnvProperties; @ViewChild(NewSearchPageComponent, { static: true }) searchPage: NewSearchPageComponent; private user: User; private userFilterLoaded: boolean = false; constructor(private route: ActivatedRoute, private _communitiesService: CommunitiesService, private userManagementService: UserManagementService) { this.errorCodes = new ErrorCodes(); this.errorMessages = new ErrorMessagesComponent(); this.searchUtils.status = this.errorCodes.LOADING; } public ngOnInit() { var firstLoad = true; this.properties = properties; this.piwikSiteId = this.properties.piwikSiteId; this.baseUrl = this.properties.searchLinkToCommunities; this.subscriptions.push(this.route.queryParams.subscribe(params => { this.searchPage.resultsPerPage = 10; this.keyword = (params['fv0'] ? params['fv0'] : ''); this.keyword = StringUtils.URIDecode(this.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.searchUtils.baseUrl = this.baseUrl; 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; this.searchLink = this.properties.searchLinkToCommunities; this.selectedFields = []; this.searchPage.prepareSearchPage(this.fieldIds, this.selectedFields, this.refineFields, [], this.fieldIdsMap, null, params, "community", null); let queryParams = params;//this.searchPage.getQueryParamsFromUrl(params); if (typeof document !== 'undefined') { this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => { this.user = user; this.initCommunities(queryParams); })); } else { this.initCommunities(queryParams); } })); } ngOnDestroy() { this.subscriptions.forEach(subscription => { if (subscription instanceof Subscriber) { subscription.unsubscribe(); } }); } /** * Initialize communities from Communities APIs * * @param params */ private initCommunities(params) { this.subscriptions.push(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]); this.totalResults[i].isSubscribed = Session.isSubscribedTo('community', this.totalResults[i].communityId, this.user); } } if (this.user) { 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; } )); } /** * Get all communities from Communities API and apply permission access validator, * keyword searching, filter, paging and sorting. * * @param params, status * @private */ private _getResults(params) { this.searchUtils.status = this.errorCodes.LOADING; this.disableForms = true; this.results = this.totalResults; 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.keyword && this.keyword != '') { this.searchForKeywords(); } this.checkFilters(params); this.sort(); this.searchUtils.totalResults = this.results.length; this.filters = this.searchPage.prepareFiltersToShow(this.filters, this.searchUtils.totalResults); 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; } } } /** * 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.keyword.split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/, -1); for (let i = 0; i < this.results.length; i++) { for (let keyword of keywords) { keyword = keyword.toLowerCase(); if (keyword != '' && (StringUtils.containsWord(this.results[i].title, keyword) || StringUtils.containsWord(this.results[i].shortTitle, keyword) || StringUtils.containsWord(this.results[i].communityId, keyword) || StringUtils.containsWord(this.results[i].description, 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) { 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): CommunityInfo[] { let results: CommunityInfo[] = []; let values: string[] = []; if (params[filterId]) { values = (StringUtils.URIDecode(params[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.isPortalAdministrator(this.user) || Session.isCommunityCurator(this.user) || Session.isManager('community', community.communityId, this.user); } /** * 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"]); this.userFilterLoaded = true; } 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, filterType: "checkbox" }; filters.push(filter); } return filters; } private handleError(message: string, error) { console.error('Communities Search Page: ' + message, error); } }