diff --git a/searchPages/searchResearchResults.component.ts b/searchPages/searchResearchResults.component.ts index b29f0a0a..a0b28c98 100644 --- a/searchPages/searchResearchResults.component.ts +++ b/searchPages/searchResearchResults.component.ts @@ -13,6 +13,7 @@ import {NewSearchPageComponent} from "./searchUtils/newSearchPage.component"; @Component({ selector: 'search-research-results', template: ` + {{resultType}} { @@ -113,7 +114,6 @@ export class SearchResearchResultsComponent { refine = false; } - firstLoad = false; let page = (params['page'] === undefined) ? 1 : +params['page']; this.searchUtils.page = (page <= 0) ? 1 : page; @@ -127,8 +127,10 @@ export class SearchResearchResultsComponent { } this.selectedFields = []; - this.searchPage.prepareSearchPage(this.fieldIds, this.selectedFields, this.refineFields, this.fieldIdsMap,this.customFilter,params); - this._getResults(this.searchPage.getSearchAPIQueryForAdvancedSearhFields(), this.searchUtils.page, this.searchUtils.size, this.searchUtils.sortBy, refine, this.searchPage.getSearchAPIQueryForRefineFields(params)); + this.searchPage.prepareSearchPage(this.fieldIds, this.selectedFields, this.refineFields, this.fieldIdsMap,this.customFilter,params, this.resultType); + this._getResults(this.searchPage.getSearchAPIQueryForAdvancedSearhFields(), this.searchUtils.page, this.searchUtils.size, this.searchUtils.sortBy, refine, this.searchPage.getSearchAPIQueryForRefineFields(params, firstLoad)); + firstLoad = false; + }); } @@ -156,7 +158,7 @@ export class SearchResearchResultsComponent { this.results = []; this.searchUtils.totalResults = 0; // TODO update the following method to get more than one types - this._searchResearchResultsService.advancedSearch(this.resultType, parameters, page, size, sortBy, this.properties, (refine) ? this.searchPage.getRefineFieldsQuery() : null, this.searchPage.getFields(), refineFieldsFilterQuery).subscribe( + this._searchResearchResultsService.advancedSearchResults(this.resultType, parameters, page, size, sortBy, this.properties, (refine) ? this.searchPage.getRefineFieldsQuery() : null, this.searchPage.getFields(), refineFieldsFilterQuery).subscribe( data => { this.searchUtils.totalResults = data[0]; this.results = data[1]; @@ -223,6 +225,8 @@ export class SearchResearchResultsComponent { return "software"; } else if (entityType == "other") { return (full ? ("other research product" + (plural ? "s" : "")) : "other"); + } else if (entityType == "result") { + return (full ? ("research outcome" + (plural ? "s" : "")) : "result"); } } } diff --git a/searchPages/searchResearchResults.module.ts b/searchPages/searchResearchResults.module.ts index 2a89cb89..89c59fe7 100644 --- a/searchPages/searchResearchResults.module.ts +++ b/searchPages/searchResearchResults.module.ts @@ -1,6 +1,6 @@ -import { NgModule} from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule } from '@angular/forms'; +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; import {SearchResearchResultsServiceModule} from '../services/searchResearchResultsService.module'; import {FreeGuard} from '../login/freeGuard.guard'; diff --git a/searchPages/searchUtils/advancedSearchForm.component.html b/searchPages/searchUtils/advancedSearchForm.component.html index 83000295..aa98103a 100644 --- a/searchPages/searchUtils/advancedSearchForm.component.html +++ b/searchPages/searchUtils/advancedSearchForm.component.html @@ -1,4 +1,5 @@ -
+
{{pageTitle}} @@ -10,6 +11,9 @@ + @@ -68,18 +72,18 @@
Search for: - - - - - - - + + + + + + @@ -113,13 +117,16 @@ - + diff --git a/searchPages/searchUtils/advancedSearchForm.component.ts b/searchPages/searchUtils/advancedSearchForm.component.ts index f49e53b9..6b30e238 100644 --- a/searchPages/searchUtils/advancedSearchForm.component.ts +++ b/searchPages/searchUtils/advancedSearchForm.component.ts @@ -1,7 +1,7 @@ import {Component, EventEmitter, Input, Output} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; -import {AdvancedField} from '../searchUtils/searchHelperClasses.class'; +import {AdvancedField, Filter} from '../searchUtils/searchHelperClasses.class'; import {SearchFields} from '../../utils/properties/searchFields'; import {Dates} from '../../utils/string-utils.class'; import {EnvProperties} from '../../utils/properties/env-properties'; @@ -23,7 +23,8 @@ export class AdvancedSearchFormComponent { @Input() formPlaceholderText = "Type Keywords..."; @Input() pageTitle; @Output() queryChange = new EventEmitter(); - + @Input() @Output() resultTypes; + @Input() quickFilter:{filter: Filter, selected:boolean, filterId:string, value:string}; validDateFrom: boolean = true; validDateTo: boolean = true; @@ -31,10 +32,12 @@ export class AdvancedSearchFormComponent { newFieldName:string; fieldList:{[id:string]:any[]} = {}; public searchFields:SearchFields = new SearchFields(); -properties:EnvProperties; + properties:EnvProperties; public operators: {name:string, id:string}[] = this.searchFields.ADVANCED_SEARCH_OPERATORS; - constructor (private route: ActivatedRoute) { - } + + constructor (private route: ActivatedRoute) { + + } ngOnInit() { this.route.data @@ -53,6 +56,7 @@ properties:EnvProperties; this.queryChanged(); } queryChanged() { + console.log("Q CHanged!") this.validDateFrom = true; this.validDateTo = true; @@ -72,7 +76,6 @@ properties:EnvProperties; }); if(this.validDateFrom && this.validDateTo) { - //console.info("emit"); this.queryChange.emit({ diff --git a/searchPages/searchUtils/advancedSearchForm.module.ts b/searchPages/searchUtils/advancedSearchForm.module.ts index 92728b29..1b7a5a34 100644 --- a/searchPages/searchUtils/advancedSearchForm.module.ts +++ b/searchPages/searchUtils/advancedSearchForm.module.ts @@ -1,18 +1,19 @@ -import { NgModule} from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule } from '@angular/forms'; -import { RouterModule } from '@angular/router'; +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {RouterModule} from '@angular/router'; -import{AdvancedSearchFormComponent} from './advancedSearchForm.component'; +import {AdvancedSearchFormComponent} from './advancedSearchForm.component'; import {EntitiesAutocompleteModule} from '../../utils/entitiesAutoComplete/entitiesAutoComplete.module'; import {StaticAutocompleteModule} from '../../utils/staticAutoComplete/staticAutoComplete.module'; import {DateFilterModule} from './dateFilter.module'; -import{SearchFormModule} from './searchForm.module'; +import {SearchFormModule} from './searchForm.module'; +import {QuickSelectionsModule} from "./quick-selections.module"; @NgModule({ imports: [ - CommonModule, FormsModule, RouterModule, EntitiesAutocompleteModule, StaticAutocompleteModule, DateFilterModule, SearchFormModule + CommonModule, FormsModule, RouterModule, EntitiesAutocompleteModule, StaticAutocompleteModule, DateFilterModule, SearchFormModule, QuickSelectionsModule ], declarations: [ AdvancedSearchFormComponent, diff --git a/searchPages/searchUtils/newSearchPage.component.html b/searchPages/searchUtils/newSearchPage.component.html index f242ce72..b5679533 100644 --- a/searchPages/searchUtils/newSearchPage.component.html +++ b/searchPages/searchUtils/newSearchPage.component.html @@ -10,13 +10,14 @@ [(fieldIds)]="fieldIds" [(fieldIdsMap)]="fieldIdsMap" [(selectedFields)]="selectedFields" - (queryChange)="queryChanged($event)" + (queryChange)="queryChanged()" [isDisabled]="disableForms" [simpleSearchLink]="simpleSearchLink" [advancedSearchLink]="advancedSearchLink" [advancedSearchLinkParameters] ="this.routerHelper.createQueryParams(this.parameterNames, this.parameterValues)" [pageTitle]=pageTitle [simpleView]="simpleView" [formPlaceholderText]="formPlaceholderText" + [(resultTypes)]="resultTypes" [quickFilter]="quickFilter" > @@ -45,14 +46,13 @@
- + - - + - -1) { @@ -297,11 +301,23 @@ export class NewSearchPageComponent { } } + } else if (this.quickFilter.filterId == filter.filterId && this.quickFilter.selected) { + for (let filterValue of filter.values) { + if (filterValue.id == this.quickFilter.value) { + filterValue.selected = true; + filter.countSelectedValues++; + } else { + filterValue.selected = false; + } + } } else { for (let filterValue of filter.values) { filterValue.selected = false; } } + if (filter.filterId == this.quickFilter.filterId) { + this.quickFilter.filter = filter; + } } this.filterFilterValues(this.filters); return filters; @@ -345,7 +361,7 @@ export class NewSearchPageComponent { return filters; } - public countSelectedFilters(filters:Filter[]): number { + public countSelectedFilters(filters: Filter[]): number { this.selectedFilters = 0; for (let filter of filters) { if (filter.countSelectedValues > 0) { @@ -368,6 +384,9 @@ export class NewSearchPageComponent { if (value.selected == true) { value.selected = false; } + if (this.quickFilter && this.quickFilter.filterId == filter.filterId) { + this.removeValueFromQuickFilter(); + } this.goTo(1); } @@ -386,7 +405,26 @@ export class NewSearchPageComponent { } filterChanged($event) { + if (this.quickFilter) { + this.removeValueFromQuickFilter(); + } this.goTo(1); + + } + + /** + * if there is a change in the values of the quick filter, this function has to be run, to also update the quickFilter + */ + removeValueFromQuickFilter() { + if (this.quickFilter.filter.countSelectedValues == 0) { + this.quickFilter.selected = false; + } else { + let isQuickEnabled = false; + for (let filterValue of this.quickFilter.filter.values) { + isQuickEnabled = (filterValue.name == this.quickFilter.value) + } + this.quickFilter.selected = (isQuickEnabled && this.quickFilter.filter.countSelectedValues == 1); + } } // for loading @@ -511,7 +549,7 @@ export class NewSearchPageComponent { * Create Search API query based on the filters of refine fields * @param URLparams */ - getSearchAPIQueryForRefineFields(URLparams) { + getSearchAPIQueryForRefineFields(URLparams, firstLoad: boolean) { var allFqs = ""; for (var i = 0; i < this.refineFields.length; i++) { @@ -539,6 +577,33 @@ export class NewSearchPageComponent { allFqs += "&fq=" + StringUtils.URIEncode(this.customFilter.queryFieldName + " exact " + StringUtils.quote((this.customFilter.valueId))); } + if (this.quickFilter) { + if ((this.entityType == "result" && firstLoad && URLparams[this.quickFilter.filterId] == undefined && (URLparams["qf"] == undefined || URLparams["qf"] == "true")) + || ((this.entityType == "result" && URLparams[this.quickFilter.filterId] != undefined && StringUtils.URIDecode(URLparams[this.quickFilter.filterId]).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/, -1).indexOf(StringUtils.quote(this.quickFilter.value)) != -1))) { + this.quickFilter.selected = true; + } else { + this.quickFilter.selected = false; + } + if (this.entityType == "result" && firstLoad && URLparams[this.quickFilter.filterId] == undefined && (URLparams["qf"] == undefined || URLparams["qf"] == "true")) { + allFqs += "&fq=resultbestaccessright exact " + StringUtils.quote(this.quickFilter.value); + } + } + + if (this.entityType == "result") { + if (URLparams["type"]) { + for (let type of URLparams["type"].split(",")) { + allFqs += "&type=" + type; + } + } + } else if (this.entityType == "publication") { + allFqs += "&type=publications"; + } else if (this.entityType == "dataset") { + allFqs += "&type=datasets"; + } else if (this.entityType == "software") { + allFqs += "&type=software"; + } else if (this.entityType == "other") { + allFqs += "&type=other"; + } // var keyword = URLparams['keyword']; // var doiQuery = ""; // var keywordQuery = ""; @@ -576,9 +641,7 @@ export class NewSearchPageComponent { // } // } //TODO add DOI? - // console.log(this.parameterNames) - // console.log(this.parameterValues) - return allFqs; + return allFqs; } @@ -588,7 +651,7 @@ export class NewSearchPageComponent { * @param filters either query filters or filters defined by the URL parameters * @param includePage */ - buildPageURLParameters(filters:Filter[],includePage: boolean) { + buildPageURLParameters(filters: Filter[], includePage: boolean) { this.parameterNames.splice(0, this.parameterNames.length); this.parameterValues.splice(0, this.parameterValues.length); var fields: { [key: string]: { values: string[], operators: string[] } } = {}; @@ -653,6 +716,30 @@ export class NewSearchPageComponent { this.parameterValues.push(this.searchUtils.keyword); } + if (this.resultTypes && this.entityType == "result") { + let values = []; + if (this.resultTypes.publication) { + values.push("publications"); + } + if (this.resultTypes.dataset) { + values.push("datasets"); + } + if (this.resultTypes.software) { + values.push("software"); + } + if (this.resultTypes.other) { + values.push("other"); + } + if (values.length > 0) { + this.parameterNames.push("type"); + this.parameterValues.push(values.join(",")); + } + if(this.quickFilter) { + this.parameterNames.push("qf"); + this.parameterValues.push("" + this.quickFilter.selected); + } + } + // if (this.searchUtils.size != this.resultsPerPage) { // // allLimits += ((allLimits.length == 0) ? '?' : '&') + 'size=' + this.searchUtils.size; // this.parameterNames.push("size"); @@ -695,11 +782,46 @@ export class NewSearchPageComponent { filters.push(filter) } } - // console.log("Empty Filters"); - // console.log(filters); - this.URLCreatedFilters = filters; - // return filters; + if (this.quickFilter) { + if (this.entityType == "result" && (URLparams[this.quickFilter.filterId] == undefined) && (URLparams["qf"] == undefined || URLparams["qf"] == "true")) { + let filter = new Filter(); + filter.title = fields.getFieldName(this.quickFilter.filterId, "publication"); + filter.filterId = this.quickFilter.filterId; + filter.originalFilterId = this.quickFilter.filterId; + filter.values = []; + let v: Value = new Value(); + v.name = this.quickFilter.value; + v.id = this.quickFilter.value; + v.selected = true; + filter.values.push(v); + filter.countSelectedValues = 1; + filters.push(filter) + } + } + if (this.entityType == "result") { + this.resultTypes = null; + this.resultTypes = { + + }; + + if (URLparams["type"]) { + + this.resultTypes['publication'] = (URLparams["type"].split(",").indexOf("publications") != -1); + this.resultTypes['dataset'] = (URLparams["type"].split(",").indexOf("datasets") != -1); + this.resultTypes['software'] = (URLparams["type"].split(",").indexOf("software") != -1); + this.resultTypes['other'] = (URLparams["type"].split(",").indexOf("other") != -1); + + } else { + this.resultTypes['publication'] = true; + this.resultTypes['dataset'] = true; + this.resultTypes['software'] = true; + this.resultTypes['other'] = true; + } + + } + + this.URLCreatedFilters = filters; } /** @@ -708,11 +830,11 @@ export class NewSearchPageComponent { * Count the checked * @param filters */ - public prepareFiltersToShow(filters:Filter[]):Filter[]{ + public prepareFiltersToShow(filters: Filter[]): Filter[] { if (this.URLCreatedFilters.length > 0 && this.searchUtils.totalResults == 0) { this.showUnknownFilters = true; this.filters = this.URLCreatedFilters; - } else if (this.searchUtils.totalResults != 0 ) { + } else if (this.searchUtils.totalResults != 0) { this.showUnknownFilters = false; this.filters = filters; } @@ -731,13 +853,14 @@ export class NewSearchPageComponent { * @param customFilter * @param params */ - prepareSearchPage(fieldIds, selectedFields, refineFields,fieldIdsMap, customFilter, params){ - this.fieldIds = fieldIds; - this.selectedFields = selectedFields; - this.refineFields = refineFields; - this.fieldIdsMap = fieldIdsMap; - this.customFilter = customFilter; - this.getRefineFiltersFromURL(params); - this.createAdvancedSearchSelectedFiltersFromURLParameters(params); -} + prepareSearchPage(fieldIds, selectedFields, refineFields, fieldIdsMap, customFilter, params, entityType) { + this.entityType = entityType; + this.fieldIds = fieldIds; + this.selectedFields = selectedFields; + this.refineFields = refineFields; + this.fieldIdsMap = fieldIdsMap; + this.customFilter = customFilter; + this.getRefineFiltersFromURL(params); + this.createAdvancedSearchSelectedFiltersFromURLParameters(params); + } } diff --git a/searchPages/searchUtils/quick-selections.component.ts b/searchPages/searchUtils/quick-selections.component.ts new file mode 100644 index 00000000..bf8ab697 --- /dev/null +++ b/searchPages/searchUtils/quick-selections.component.ts @@ -0,0 +1,119 @@ +import {Component, EventEmitter, Input, OnChanges, Output, SimpleChanges} from '@angular/core'; +import {FormBuilder, FormGroup} from "@angular/forms"; +import {Filter} from "./searchHelperClasses.class"; + +@Component({ + selector: 'quick-selections', + template: ` +
+
+ + {{quickFilter.value}} + +
+ + Publications + Research Data + Software + Other Research outcomes + +
+ ` +}) + +export class QuickSelectionsComponent implements OnChanges { + @Input() resultTypes; + @Output() typeChange = new EventEmitter(); + @Input() isDisabled; + @Input() quickFilter: { filter: Filter, selected: boolean, filterId: string, value: string }; + @Input() QFselected: boolean; + control: FormGroup; + initialized = false; + + constructor(private _fb: FormBuilder) { + + this.control = this._fb.group({ + publication: true, + dataset: true, + software: true, + other: true, + QFselected: true + }); + + } + + changed(typeChanged: boolean = true) { + if (!this.initialized && this.isDisabled) { + this.initialized = true; + return; + } + let value = this.control.getRawValue(); + this.resultTypes.publication = value.publication; + this.resultTypes.dataset = value.dataset; + this.resultTypes.software = value.software; + this.resultTypes.other = value.other; + // this.resultTypes.open = value.open; + if (typeChanged && this.resultTypes && !this.resultTypes.publication && !this.resultTypes.dataset && !this.resultTypes.software && !this.resultTypes.other) { + this.resultTypes.publication = true; + this.resultTypes.dataset = true; + this.resultTypes.software = true; + this.resultTypes.other = true; + this.setFormValues(); + } + this.typeChange.emit({}); + } + + quickFilterChanged() { + let value = this.control.getRawValue(); + this.quickFilter.selected = value.QFselected; + if (value.QFselected) { + for (let filterValue of this.quickFilter.filter.values) { + filterValue.selected = (filterValue.name == this.quickFilter.value) + } + this.quickFilter.filter.countSelectedValues = 1; + } else { + for (let filterValue of this.quickFilter.filter.values) { + filterValue.selected = false; + } + this.quickFilter.filter.countSelectedValues = 0; + } + this.typeChange.emit({}); + } + + ngOnInit() { + if (this.resultTypes) { + this.setFormValues(); + } + } + + ngOnChanges(changes: SimpleChanges): void { + if (changes.isDisabled) { + if (changes.isDisabled.currentValue == true) { + this.control.disable(); + } else if (changes.isDisabled.currentValue == false) { + this.control.enable(); + } + } + + if (changes.QFselected) { + let value = this.control.getRawValue(); + if (changes.QFselected.currentValue != value.QFselected) { + this.setFormValues(); + } + + } + } + + setFormValues() { + this.control.setValue({ + publication: this.resultTypes.publication, + dataset: this.resultTypes.dataset, + software: this.resultTypes.software, + other: this.resultTypes.software, + QFselected: this.QFselected + }); + } + + +} diff --git a/searchPages/searchUtils/quick-selections.module.ts b/searchPages/searchUtils/quick-selections.module.ts new file mode 100644 index 00000000..f75af1c7 --- /dev/null +++ b/searchPages/searchUtils/quick-selections.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule, ReactiveFormsModule} from '@angular/forms'; +import {RouterModule} from '@angular/router'; +import {ShowAuthorsModule} from "../../utils/authors/showAuthors.module"; +import {QuickSelectionsComponent} from "./quick-selections.component"; +import {MatCheckboxModule, MatSlideToggleModule} from "@angular/material"; + +@NgModule({ + imports: [ + CommonModule, FormsModule, + RouterModule, ShowAuthorsModule, MatCheckboxModule, ReactiveFormsModule, MatSlideToggleModule + ], + declarations: [ + QuickSelectionsComponent, + ], + providers:[ + ], + exports: [ + QuickSelectionsComponent + ] +}) +export class QuickSelectionsModule { } diff --git a/searchPages/searchUtils/selectAllContentTabs.component.ts b/searchPages/searchUtils/selectAllContentTabs.component.ts new file mode 100644 index 00000000..759bc7b0 --- /dev/null +++ b/searchPages/searchUtils/selectAllContentTabs.component.ts @@ -0,0 +1,33 @@ +import {Component, Input} from '@angular/core'; +import {SearchResult} from '../../utils/entities/searchResult'; +import {ErrorCodes} from '../../utils/properties/errorCodes'; +import {RouterHelper} from '../../utils/routerHelper.class'; + +@Component({ + selector: 'select-content-tabs', + template: ` + + ` + }) + +export class SelectAllContentTabsComponent { + @Input() searchAll: boolean; + @Input() status: number; + @Input() type: string; + @Input() urlParam: string; + @Input() showLoading: boolean = false; + @Input() showOrganizations: boolean = true; + + public errorCodes:ErrorCodes = new ErrorCodes(); + public routerHelper:RouterHelper = new RouterHelper(); + public errorMessage: string = "No results found"; + constructor () { + + } + + ngOnInit() {} + + public quote(params: string):string { + return '"'+params+'"'; + } +} diff --git a/services/searchResearchResults.service.ts b/services/searchResearchResults.service.ts index 2471dc85..113b7e69 100644 --- a/services/searchResearchResults.service.ts +++ b/services/searchResearchResults.service.ts @@ -105,6 +105,28 @@ export class SearchResearchResultsService { return this.http.get((properties.useCache)? (properties.cacheUrl+encodeURIComponent(url)): url) .pipe(map(res => [res['meta'].total, this.parseResults(resultType, res['results'], properties),RefineResultsUtils.parse(res['refineResults'],refineFields, "publication")])); } + advancedSearchResults (resultType:string, params: string, page: number, size: number, sortBy: string, properties:EnvProperties, refineParams:string=null, refineFields:string[] =null, refineQuery:string = null ):any { + let url = properties.searchAPIURLLAst+"results/?format=json"; + if(params!= null && params != '' ) { + url +="&query=(" + params + ")"; + } + if(refineParams!= null && refineParams != '' ) { + url += refineParams; + } + if(sortBy) { + let sortOptions = sortBy.split(","); + url += "sortBy "+sortOptions[0]+"/sort."+sortOptions[1]+" "; + } + if(refineQuery) { + url += "&" + refineQuery; + } + + url += "&page="+(page-1)+"&size="+size; + // url += "&format=json"; + + return this.http.get((properties.useCache)? (properties.cacheUrl+encodeURIComponent(url)): url) + .pipe(map(res => [res['meta'].total, this.parseResults(resultType, res['results'], properties),RefineResultsUtils.parse(res['refineResults'],refineFields, "publication")])); + } searchResultForEntity (resultType:string, params: string, page: number, size: number, properties:EnvProperties):any { let link = properties.searchAPIURLLAst;