diff --git a/src/app/searchPages/communities/searchCommunities.component.ts b/src/app/searchPages/communities/searchCommunities.component.ts index 272c745..c54633c 100644 --- a/src/app/searchPages/communities/searchCommunities.component.ts +++ b/src/app/searchPages/communities/searchCommunities.component.ts @@ -57,15 +57,21 @@ export class SearchCommunitiesComponent { 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.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; - this.searchPage.resultsPerPage = 5; let queryParams = this.searchPage.getQueryParamsFromUrl(params); this.filters = this.createFilters(); - this._getResults(queryParams, this.searchUtils.page, this.searchUtils.size); + this._getResults(queryParams); }); } @@ -79,7 +85,10 @@ export class SearchCommunitiesComponent { } - private showCommunities(): SearchResult[]{ + /** + * 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') { @@ -97,10 +106,17 @@ export class SearchCommunitiesComponent { } ret.push(result); } - return ret; + this.results = ret; } - private _getResults(params: Map, page: number, size: number){ + /** + * 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 = []; @@ -111,6 +127,7 @@ export class SearchCommunitiesComponent { for(let i = 0; i < data.length; i++) { this.results[i] = new SearchResult(); this.results[i].community = data[i]; + //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); } @@ -119,18 +136,32 @@ export class SearchCommunitiesComponent { for(let i = 0; i < res.length; i++) { this.results[i].isSubscribed = res[i]; } - this.results = this.showCommunities(); - this.results = this.checkFilters(params); - this.updateFilterNumbers(this.results); + 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((page-1)*size, (page*size)); + 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; + } + } }, err => { this.handleError('Error getting if user is subscribed', err); @@ -149,8 +180,34 @@ export class SearchCommunitiesComponent { ); } + /** + * 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 ret: SearchResult[] = []; + let typeResults: SearchResult[] = []; + let statusResults: SearchResult[] = []; let types: string[] = []; let statuses: string[] = []; if(params.get('type') != undefined) { @@ -161,89 +218,149 @@ export class SearchCommunitiesComponent { } for(let i = 0; i < this.results.length; i++) { if (types.length == 0) { - ret.push(this.results[i]); + typeResults.push(this.results[i]); } else { for (let type of types) { if (this.results[i].community.type == type.replace(/["']/g, "")) { - ret.push(this.results[i]); + typeResults.push(this.results[i]); + break; } } } } - if(ret.length > 0) { - this.results = ret; - ret = []; - } + this.resetFilterNumbers('status'); + this.updateFilterNumbers(typeResults, 'status'); for(let i = 0; i < this.results.length; i++) { if( statuses.length == 0) { - ret.push(this.results[i]); + statusResults.push(this.results[i]); } else { for (let status of statuses) { if(status.replace(/["']/g, "") == 'subscribed') { if(this.results[i].isSubscribed) { - ret.push(this.results[i]); + statusResults.push(this.results[i]); + break; } - break; } else if(status.replace(/["']/g, "") == 'nonsubscribed') { if(!this.results[i].isSubscribed) { - ret.push(this.results[i]); + statusResults.push(this.results[i]); + break; } - break; } else if(status.replace(/["']/g, "") == 'managing') { if (this.results[i].isManager) { - ret.push(this.results[i]); + statusResults.push(this.results[i]); + break; } - break; } } } } - return ret; + this.resetFilterNumbers('type'); + this.updateFilterNumbers(statusResults, 'type'); + this.results = statusResults.filter(value => { + return typeResults.includes(value); + }); } - private updateFilterNumbers(results: SearchResult[]) { + /** + * 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++) { - let filter: Filter = this.filters[i]; - for (let j = 0; j < filter.values.length; j++) { - let value: Value = filter.values[j]; - value.number = 0; + 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++) { - let community: CommunityInfo = results[k].community; for (let i = 0; i < this.filters.length; i++) { - let filter: Filter = this.filters[i]; - for (let j = 0; j < filter.values.length; j++) { - let value: Value = filter.values[j]; - if(filter.filterId == 'type') { - if(community.type == value.id) { - value.number++; + 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(filter.filterId == 'status') { - if(results[k].isSubscribed){ - filter.values[0].number++; - } - else { - filter.values[1].number++; - } - if(results[k].isManager) { - filter.values[2].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 (results[k].isManager) { + this.filters[i].values[2].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, this.searchUtils.page, this.searchUtils.size); + this._getResults($event.params); } + /** + * Create Search Communities filters. + * + */ private createFilters(): Filter[] { let filter_names=["Type"]; let filter_ids=["type"]; @@ -265,7 +382,7 @@ export class SearchCommunitiesComponent { 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:j, selected:false}; + 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 };