From 12679aec2257f855f76764d8658b283abac75db4 Mon Sep 17 00:00:00 2001 From: Olli Mannevaara Date: Wed, 22 Nov 2023 16:25:48 +0200 Subject: [PATCH] New filters: publicationType, international, articleType, jufo --- .../publications2.component.html | 88 ++++ .../publications2/publications2.component.ts | 90 +++- .../portal/services/publication2.service.ts | 453 +++++++++++++++++- .../pagination/pagination.component.ts | 2 - 4 files changed, 619 insertions(+), 14 deletions(-) diff --git a/src/app/portal/components/results/publications2/publications2.component.html b/src/app/portal/components/results/publications2/publications2.component.html index 81bfffbea..3dd9fbb4b 100644 --- a/src/app/portal/components/results/publications2/publications2.component.html +++ b/src/app/portal/components/results/publications2/publications2.component.html @@ -127,6 +127,94 @@

Julkaisut - {{total$ | async}}

+ +
+ +
+

Peer Reviewed

+ +
+ {{peerReviewedAdditions$ | async | json}} +
+
+ + +
+ +
+
+ + + + + + + + +
+
+ + +
+ +
+
+

International Publication

+ + + + + + + + +
+
+ + +
+ +
+
+

Article Type

+ + + + + + + + +
+
+ + +
+ +
+

Jufo

+ + + + + + + +
diff --git a/src/app/portal/components/results/publications2/publications2.component.ts b/src/app/portal/components/results/publications2/publications2.component.ts index a90e4fc88..0a5aac7c7 100644 --- a/src/app/portal/components/results/publications2/publications2.component.ts +++ b/src/app/portal/components/results/publications2/publications2.component.ts @@ -5,13 +5,19 @@ import { ActivatedRoute, Router } from '@angular/router'; import { FormsModule } from '@angular/forms'; import { AsyncPipe, JsonPipe, NgForOf, NgIf } from '@angular/common'; import { + getArticleTypeCodeAdditions, + getInternationalPublicationAdditions, getJufoClassCodeAdditions, getLanguageCodeAdditions, - getOrganizationAdditions, getPublicationAudienceAdditions, getPublicationFormatAdditions, + getOrganizationAdditions, + getParentPublicationTypeAdditions, + getPeerReviewedAdditions, + getPublicationAudienceAdditions, + getPublicationFormatAdditions, getYearAdditions, HighlightedPublication, Publication2Service } from '@portal/services/publication2.service'; -import { map, take } from 'rxjs/operators'; +import { map, take, tap } from 'rxjs/operators'; import { SharedModule } from '@shared/shared.module'; import { SearchBar2Component } from '@portal/search-bar2/search-bar2.component'; import { NgArrayPipesModule } from 'ngx-pipes'; @@ -122,6 +128,86 @@ export class Publications2Component implements OnDestroy { }))) ); + peerReviewedAdditions$ = this.aggregations$.pipe( + map(aggs => getPeerReviewedAdditions(aggs).map((bucket: any) => ({ id: bucket.key, count: bucket.doc_count })) ?? []), + map(aggs => aggs.sort((a, b) => b.count - a.count)) + ); + + // getParentPublicationTypeAdditions + // getInternationalPublicationAdditions + // getArticleTypeCodeAdditions + // getJufoClassCodeAdditions + + parentPublicationTypeAdditions$ = this.aggregations$.pipe( + map(aggs => getParentPublicationTypeAdditions(aggs).map((bucket: any) => ({ id: bucket.key, count: bucket.doc_count })) ?? []), + map(aggs => aggs.sort((a, b) => b.count - a.count)) + ); + + internationalPublicationAdditions$ = this.aggregations$.pipe( + map(aggs => getInternationalPublicationAdditions(aggs).map((bucket: any) => ({ id: bucket.key.toString(), count: bucket.doc_count })) ?? []), + map(aggs => aggs.sort((a, b) => b.count - a.count)) + ); + + internationalPublicationNames$ = this.publications2Service.getInternationalPublicationNames(); + + internationalPublicationFilters$ = combineLatest([this.internationalPublicationAdditions$, this.internationalPublicationNames$, this.searchParams$.pipe(map(params => params.international ?? []))]).pipe( + map(([internationalPublicationAdditions, internationalPublicationNames, enabledFilters]) => internationalPublicationAdditions.map(internationalPublicationAddition => ({ + id: internationalPublicationAddition.id, + count: internationalPublicationAddition.count, + name: internationalPublicationNames[internationalPublicationAddition.id], + enabled: enabledFilters.includes(internationalPublicationAddition.id) + }))) + ); + + articleTypeCodeAdditions$ = this.aggregations$.pipe( + map(aggs => getArticleTypeCodeAdditions(aggs).map((bucket: any) => ({ id: bucket.key.toString(), count: bucket.doc_count })) ?? []), + map(aggs => aggs.sort((a, b) => b.count - a.count)) + ); + + articleTypeCodeNames$ = this.publications2Service.getArticleTypeCodeNames(); + + articleTypeCodeFilters$ = combineLatest([this.articleTypeCodeAdditions$, this.articleTypeCodeNames$, this.searchParams$.pipe(map(params => params.articleType ?? []))]).pipe( + map(([articleTypeCodeAdditions, articleTypeCodeNames, enabledFilters]) => articleTypeCodeAdditions.map(articleTypeCodeAddition => ({ + id: articleTypeCodeAddition.id, + count: articleTypeCodeAddition.count, + name: articleTypeCodeNames[articleTypeCodeAddition.id], + enabled: enabledFilters.includes(articleTypeCodeAddition.id) + }))) + ); + + jufoClassCodeAdditions$ = this.aggregations$.pipe( + map(aggs => getJufoClassCodeAdditions(aggs).map((bucket: any) => ({ id: bucket.key.toString(), count: bucket.doc_count })) ?? []), + map(aggs => aggs.sort((a, b) => b.count - a.count)) + ); + + jufoClassCodeFilters$ = combineLatest([this.jufoClassCodeAdditions$, this.searchParams$.pipe(map(params => params.jufo ?? []))]).pipe( + map(([jufoClassCodeAdditions, enabledFilters]) => jufoClassCodeAdditions.map(jufoClassCodeAddition => ({ + id: jufoClassCodeAddition.id, + count: jufoClassCodeAddition.count, + name: jufoClassCodeAddition.id, + enabled: enabledFilters.includes(jufoClassCodeAddition.id) + }))) + ); + + // getParentPublicationTypeNames + // getInternationalPublicationNames + // getArticleTypeCodeNames + + parentPublicationTypeNames$ = this.publications2Service.getParentPublicationTypeNames(); + + // TODO these give just ids and not names + // internationalPublicationNames$ = this.publications2Service.getInternationalPublicationNames(); + // articleTypeCodeNames$ = this.publications2Service.getArticleTypeCodeNames(); + + parentPublicationTypeFilters$ = combineLatest([this.parentPublicationTypeAdditions$, this.parentPublicationTypeNames$, this.searchParams$.pipe(map(params => params.parentPublicationType ?? []))]).pipe( + map(([parentPublicationTypeAdditions, parentPublicationTypeNames, enabledFilters]) => parentPublicationTypeAdditions.map(parentPublicationTypeAddition => ({ + id: parentPublicationTypeAddition.id, + count: parentPublicationTypeAddition.count, + name: parentPublicationTypeNames[parentPublicationTypeAddition.id], + enabled: enabledFilters.includes(parentPublicationTypeAddition.id) + }))) + ); + /* TODO localization solution */ public sectorName = { 1: "Yliopisto", diff --git a/src/app/portal/services/publication2.service.ts b/src/app/portal/services/publication2.service.ts index 3b8c03855..3c1e866d4 100644 --- a/src/app/portal/services/publication2.service.ts +++ b/src/app/portal/services/publication2.service.ts @@ -1,6 +1,6 @@ import { inject, Injectable, LOCALE_ID, OnInit, SecurityContext } from '@angular/core'; // import { object, Output, parse, string } from 'valibot'; -import { BehaviorSubject, forkJoin, Observable, shareReplay } from 'rxjs'; +import { BehaviorSubject, forkJoin, Observable, of, shareReplay } from 'rxjs'; import { HttpClient } from '@angular/common/http'; import { map, switchMap, take, tap } from 'rxjs/operators'; import { ActivatedRoute } from '@angular/router'; @@ -42,6 +42,13 @@ type SearchParams = { language?: string[], format?: string[], audience?: string[], + peerReviewed?: string[], + + // new terms + parentPublicationType?: string[], + international?: string[], + articleType?: string[], + jufo?: string[], // placeholders publicationTypeCode?: string[], @@ -123,7 +130,13 @@ export class Publication2Service { ...termsForOrganization(searchParams), ...termsForLanguageCode(searchParams), ...termsForPublicationFormat(searchParams), - ...termsForPublicationAudience(searchParams) + ...termsForPublicationAudience(searchParams), + ...termsForPeerReviewed(searchParams), + // Add new terms + ...termsForParentPublicationType(searchParams), + ...termsForInternationalPublication(searchParams), + ...termsForArticleTypeCode(searchParams), + ...termsForJufoClassCode(searchParams) ] } } @@ -146,7 +159,13 @@ export class Publication2Service { ...additionsFromOrganization(searchParams), ...additionsFromLanguageCode(searchParams), ...additionsFromPublicationFormat(searchParams), - ...additionsFromPublicationAudience(searchParams) + ...additionsFromPublicationAudience(searchParams), + ...additionsFromPeerReviewed(searchParams), + // Add new terms + ...additionsFromParentPublicationType(searchParams), + ...additionsFromInternationalPublication(searchParams), + ...additionsFromArticleTypeCode(searchParams), + ...additionsFromJufoClassCode(searchParams) } }); } @@ -315,6 +334,66 @@ export class Publication2Service { shareReplay({ bufferSize: 1, refCount: true }) ); } + +// getParentPublicationTypeNames +// getInternationalPublicationNames +// getArticleTypeCodeNames + + + getParentPublicationTypeNames()/*: Observable>*/ { + const body = { + "size": 0, + "aggs": { + "composite_pairs": { + "composite": { + "size": 1000, + "sources": [ + { "id": { "terms": { "field": "parentPublicationType.id.keyword" } } }, + { "nameFiParentPublicationType": { "terms": { "field": "parentPublicationType.nameFiParentPublicationType.keyword" } } } + ] + } + } + } + } + + type ParentPublicationTypeAggregation = { + aggregations: { + composite_pairs: { + buckets: Array<{ + key: { + id: string; + nameFiParentPublicationType: string; + }; + doc_count: number; + }>; + }; + }; + }; + + const response$ = this.http.post('https://researchfi-api-qa.rahtiapp.fi/portalapi/publication/_search?', body); + + return response$.pipe( + map((res) => res.aggregations.composite_pairs.buckets.map((bucket) => [bucket.key.id, bucket.key.nameFiParentPublicationType])), // TODO localized path needed + map(pairs => Object.fromEntries(pairs)), + shareReplay({ bufferSize: 1, refCount: true }) + ); + } + + getInternationalPublicationNames(): Observable> { + return of({ + "0": "Kotimainen julkaisu", // TODO use localize`` + "1": "Kansainvälinen julkaisu" // TODO use localize`` + }); + } + + getArticleTypeCodeNames(): Observable> { + return of({ + "0": "Lehti", // TODO use localize`` + "1": "Kokoomateos", // TODO use localize`` + "2": "Konferenssi", // TODO use localize`` + "3": "Verkkoalusta" // TODO use localize`` + }); + } } function matchingTerms(searchParams: SearchParams) { @@ -401,6 +480,100 @@ function termsForPublicationAudience(searchParams: SearchParams) { return []; } +/* Peer reviewed +"terms": { + "field": "peerReviewed.id.keyword", + "size": 100 +} +*/ +function termsForPeerReviewed(searchParams: SearchParams) { + if (searchParams.peerReviewed) { + return [{ + terms: { + "peerReviewed.id.keyword": searchParams.peerReviewed + } + }]; + } + return []; +} + +/* Parent Publication Type +{ + "size": 0, + "aggs": { + "parentPublicationType": { + "terms": { + "field": "parentPublicationType.id.keyword", + "size": 100 + } + } + } +} +*/ +function termsForParentPublicationType(searchParams: SearchParams) { + if (searchParams.parentPublicationType) { + return [{ + terms: { + "parentPublicationType.id.keyword": searchParams.parentPublicationType + } + }]; + } + return []; +} + +/* International Publication +"terms": { + "field": "internationalPublication", + "size": 100 +} +*/ +function termsForInternationalPublication(searchParams: SearchParams) { + if (searchParams.international) { + return [{ + terms: { + "internationalPublication": searchParams.international + } + }]; + } + return []; +} + +/* +"terms": { + "field": "articleTypeCode", + "size": 100 +} +*/ +function termsForArticleTypeCode(searchParams: SearchParams) { + if (searchParams.articleType) { + return [{ + terms: { + "articleTypeCode": searchParams.articleType + } + }]; + } + return []; +} + +/* +"jufoClassCode": { + "terms": { + "field": "jufoClassCode.keyword", + "size": 100 + } +} +*/ +function termsForJufoClassCode(searchParams: SearchParams) { + if (searchParams.jufo) { + return [{ + terms: { + "jufoClassCode.keyword": searchParams.jufo + } + }]; + } + return []; +} + function additionsFromYear(searchParams: SearchParams) { return { "all_data_except_publicationYear": { @@ -416,7 +589,13 @@ function additionsFromYear(searchParams: SearchParams) { ...termsForStatusCode(searchParams), ...termsForLanguageCode(searchParams), ...termsForPublicationFormat(searchParams), - ...termsForPublicationAudience(searchParams) + ...termsForPublicationAudience(searchParams), + ...termsForPeerReviewed(searchParams), + // Add new terms + ...termsForParentPublicationType(searchParams), + ...termsForInternationalPublication(searchParams), + ...termsForArticleTypeCode(searchParams), + ...termsForJufoClassCode(searchParams) ] } }, @@ -462,7 +641,13 @@ function additionsFromTypeCode(searchParams: SearchParams) { ...termsForOrganization(searchParams), ...termsForLanguageCode(searchParams), ...termsForPublicationFormat(searchParams), - ...termsForPublicationAudience(searchParams) + ...termsForPublicationAudience(searchParams), + ...termsForPeerReviewed(searchParams), + // Add new terms + ...termsForParentPublicationType(searchParams), + ...termsForInternationalPublication(searchParams), + ...termsForArticleTypeCode(searchParams), + ...termsForJufoClassCode(searchParams) ] } }, @@ -494,7 +679,13 @@ function additionsFromStatusCode(searchParams: SearchParams) { ...termsForOrganization(searchParams), ...termsForLanguageCode(searchParams), ...termsForPublicationFormat(searchParams), - ...termsForPublicationAudience(searchParams) + ...termsForPublicationAudience(searchParams), + ...termsForPeerReviewed(searchParams), + // Add new terms + ...termsForParentPublicationType(searchParams), + ...termsForInternationalPublication(searchParams), + ...termsForArticleTypeCode(searchParams), + ...termsForJufoClassCode(searchParams) ] } }, @@ -526,7 +717,13 @@ function additionsFromLanguageCode(searchParams: SearchParams) { ...termsForStatusCode(searchParams), ...termsForOrganization(searchParams), ...termsForPublicationFormat(searchParams), - ...termsForPublicationAudience(searchParams) + ...termsForPublicationAudience(searchParams), + ...termsForPeerReviewed(searchParams), + // Add new terms + ...termsForParentPublicationType(searchParams), + ...termsForInternationalPublication(searchParams), + ...termsForArticleTypeCode(searchParams), + ...termsForJufoClassCode(searchParams) ] } }, @@ -558,7 +755,13 @@ function additionsFromPublicationFormat(searchParams: SearchParams) { ...termsForStatusCode(searchParams), ...termsForOrganization(searchParams), ...termsForLanguageCode(searchParams), - ...termsForPublicationAudience(searchParams) + ...termsForPublicationAudience(searchParams), + ...termsForPeerReviewed(searchParams), + // Add new terms + ...termsForParentPublicationType(searchParams), + ...termsForInternationalPublication(searchParams), + ...termsForArticleTypeCode(searchParams), + ...termsForJufoClassCode(searchParams) ] } }, @@ -591,7 +794,13 @@ function additionsFromPublicationAudience(searchParams: SearchParams) { ...termsForStatusCode(searchParams), ...termsForOrganization(searchParams), ...termsForLanguageCode(searchParams), - ...termsForPublicationFormat(searchParams) + ...termsForPublicationFormat(searchParams), + ...termsForPeerReviewed(searchParams), + // Add new terms + ...termsForParentPublicationType(searchParams), + ...termsForInternationalPublication(searchParams), + ...termsForArticleTypeCode(searchParams), + ...termsForJufoClassCode(searchParams) ] } }, @@ -608,6 +817,201 @@ function additionsFromPublicationAudience(searchParams: SearchParams) { }; } +function additionsFromPeerReviewed(searchParams: SearchParams) { + return { + "all_data_except_peerReviewed": { + "global": {}, + "aggregations": { + "filtered_except_peerReviewed": { + "filter": { + "bool": { + "must": [ + matchingTerms(searchParams), + ...termsForYear(searchParams), + ...termsForTypeCode(searchParams), + ...termsForStatusCode(searchParams), + ...termsForOrganization(searchParams), + ...termsForLanguageCode(searchParams), + ...termsForPublicationFormat(searchParams), + ...termsForPublicationAudience(searchParams), + // Add new terms + ...termsForParentPublicationType(searchParams), + ...termsForInternationalPublication(searchParams), + ...termsForArticleTypeCode(searchParams), + ...termsForJufoClassCode(searchParams) + ] + } + }, + "aggregations": { + "all_peerReviewed": { + "terms": { + "field": "peerReviewed.id.keyword", + "size": 100 + } + } + } + } + } + } + }; +} + +function additionsFromParentPublicationType(searchParams: SearchParams) { + return { + "all_data_except_parentPublicationType": { + "global": {}, + "aggregations": { + "filtered_except_parentPublicationType": { + "filter": { + "bool": { + "must": [ + matchingTerms(searchParams), + ...termsForYear(searchParams), + ...termsForTypeCode(searchParams), + ...termsForStatusCode(searchParams), + ...termsForOrganization(searchParams), + ...termsForLanguageCode(searchParams), + ...termsForPublicationFormat(searchParams), + ...termsForPublicationAudience(searchParams), + ...termsForPeerReviewed(searchParams), + // Add new terms + ...termsForInternationalPublication(searchParams), + ...termsForArticleTypeCode(searchParams), + ...termsForJufoClassCode(searchParams) + ] + } + }, + "aggregations": { + "all_parentPublicationTypes": { + "terms": { + "field": "parentPublicationType.id.keyword", + "size": 100 + } + } + } + } + } + } + } +} + +function additionsFromInternationalPublication(searchParams: SearchParams) { + return { + "all_data_except_internationalPublication": { + "global": {}, + "aggregations": { + "filtered_except_internationalPublication": { + "filter": { + "bool": { + "must": [ + matchingTerms(searchParams), + ...termsForYear(searchParams), + ...termsForTypeCode(searchParams), + ...termsForStatusCode(searchParams), + ...termsForOrganization(searchParams), + ...termsForLanguageCode(searchParams), + ...termsForPublicationFormat(searchParams), + ...termsForPublicationAudience(searchParams), + ...termsForPeerReviewed(searchParams), + // Add new terms + ...termsForParentPublicationType(searchParams), + ...termsForArticleTypeCode(searchParams), + ...termsForJufoClassCode(searchParams) + ] + } + }, + "aggregations": { + "all_internationalPublications": { + "terms": { + "field": "internationalPublication", + "size": 100 + } + } + } + } + } + } + } +} + +function additionsFromArticleTypeCode(searchParams: SearchParams) { +return { + "all_data_except_articleTypeCode": { + "global": {}, + "aggregations": { + "filtered_except_articleTypeCode": { + "filter": { + "bool": { + "must": [ + matchingTerms(searchParams), + ...termsForYear(searchParams), + ...termsForTypeCode(searchParams), + ...termsForStatusCode(searchParams), + ...termsForOrganization(searchParams), + ...termsForLanguageCode(searchParams), + ...termsForPublicationFormat(searchParams), + ...termsForPublicationAudience(searchParams), + ...termsForPeerReviewed(searchParams), + // Add new terms + ...termsForParentPublicationType(searchParams), + ...termsForInternationalPublication(searchParams), + ...termsForJufoClassCode(searchParams) + ] + } + }, + "aggregations": { + "all_articleTypeCodes": { + "terms": { + "field": "articleTypeCode", + "size": 100 + } + } + } + } + } + } + } +} + +function additionsFromJufoClassCode(searchParams: SearchParams) { + return { + "all_data_except_jufoClassCode": { + "global": {}, + "aggregations": { + "filtered_except_jufoClassCode": { + "filter": { + "bool": { + "must": [ + matchingTerms(searchParams), + ...termsForYear(searchParams), + ...termsForTypeCode(searchParams), + ...termsForStatusCode(searchParams), + ...termsForOrganization(searchParams), + ...termsForLanguageCode(searchParams), + ...termsForPublicationFormat(searchParams), + ...termsForPublicationAudience(searchParams), + ...termsForPeerReviewed(searchParams), + // Add new terms + ...termsForParentPublicationType(searchParams), + ...termsForInternationalPublication(searchParams), + ...termsForArticleTypeCode(searchParams) + ] + } + }, + "aggregations": { + "all_jufoClassCodes": { + "terms": { + "field": "jufoClassCode.keyword", + "size": 100 + } + } + } + } + } + } + } +} + type OrganizationAggregation = { all_data_except_organizationId: { filtered_except_organizationId: { @@ -666,7 +1070,16 @@ function additionsFromOrganization(searchParams: SearchParams) { ...termsForYear(searchParams), ...termsForTypeCode(searchParams), ...termsForStatusCode(searchParams), - ...termsForLanguageCode(searchParams) + ...termsForLanguageCode(searchParams), + // ? + ...termsForPublicationFormat(searchParams), + ...termsForPublicationAudience(searchParams), + ...termsForPeerReviewed(searchParams), + // Add new terms + ...termsForParentPublicationType(searchParams), + ...termsForInternationalPublication(searchParams), + ...termsForArticleTypeCode(searchParams), + ...termsForJufoClassCode(searchParams) ] } }, @@ -740,3 +1153,23 @@ export function getPublicationFormatAdditions(aggregations: any) { export function getPublicationAudienceAdditions(aggregations: any) { return aggregations.all_data_except_publicationAudience?.filtered_except_publicationAudience.all_publicationAudiences.buckets ?? []; } + +export function getPeerReviewedAdditions(aggregations: any) { + return aggregations.all_data_except_peerReviewed?.filtered_except_peerReviewed.all_peerReviewed.buckets ?? []; +} + +export function getParentPublicationTypeAdditions(aggregations: any) { + return aggregations.all_data_except_parentPublicationType?.filtered_except_parentPublicationType.all_parentPublicationTypes.buckets ?? []; +} + +export function getInternationalPublicationAdditions(aggregations: any) { + return aggregations.all_data_except_internationalPublication?.filtered_except_internationalPublication.all_internationalPublications.buckets ?? []; +} + +export function getArticleTypeCodeAdditions(aggregations: any) { + return aggregations.all_data_except_articleTypeCode?.filtered_except_articleTypeCode.all_articleTypeCodes.buckets ?? []; +} + +export function getJufoClassCodeAdditions(aggregations: any) { + return aggregations.all_data_except_jufoClassCode?.filtered_except_jufoClassCode.all_jufoClassCodes.buckets ?? []; +} diff --git a/src/app/shared/components/pagination/pagination.component.ts b/src/app/shared/components/pagination/pagination.component.ts index 182ad63bb..978d9d3a4 100644 --- a/src/app/shared/components/pagination/pagination.component.ts +++ b/src/app/shared/components/pagination/pagination.component.ts @@ -88,8 +88,6 @@ function countTotalPages(totalDocuments, pageSize): number { } function generatePages(currentPage: number, range: 5 | 9, results: number, pageSize: number): number[] { - console.log(currentPage, range, results, pageSize); - let output: number[] = []; const maxPage = countTotalPages(results, pageSize); const i = currentPage;