Progress OpenSearch. Pending solving onFilter issue with active filters

This commit is contained in:
Porras-Bernardez 2024-06-13 17:01:14 +02:00
parent da430d6142
commit d135ab2d50
11 changed files with 109 additions and 82 deletions

View File

@ -20,6 +20,9 @@ const get = <T>(url: string, queryParams?: any): Observable<T> => {
// Function to make a POST request using Axios wrapped in an Observable // Function to make a POST request using Axios wrapped in an Observable
const post = <T>(url: string, body: any, queryParams?: any): Observable<T> => { const post = <T>(url: string, body: any, queryParams?: any): Observable<T> => {
// Use defer to create an Observable that makes the Axios POST request when subscribed to // Use defer to create an Observable that makes the Axios POST request when subscribed to
// console.log(body);
// console.log(queryParams);
return defer(() => axiosInstance.post<T>(url, body, { return defer(() => axiosInstance.post<T>(url, body, {
params: queryParams, params: queryParams,
headers: { headers: {

View File

@ -20,6 +20,7 @@ export default class FacetCategory extends Vue {
filterName!: string; filterName!: string;
get alias(): string { get alias(): string {
console.log("filterName:", this.filterName);
return this.filterName == "datatype" ? "doctype" : this.filterName; return this.filterName == "datatype" ? "doctype" : this.filterName;
} }
@ -53,6 +54,7 @@ export default class FacetCategory extends Vue {
@Emit("filter") @Emit("filter")
activateItem(filterItem: FacetItem): FacetItem { activateItem(filterItem: FacetItem): FacetItem {
// console.log(filterItem);
filterItem.category = this.alias; filterItem.category = this.alias;
filterItem.active = true; filterItem.active = true;
// this.$emit("filter", filterItem); // this.$emit("filter", filterItem);

View File

@ -8,6 +8,9 @@
<!-- e.g.language --> <!-- e.g.language -->
<ul class="filter-items list-unstyled" v-bind:class="{ limited: facetItems.length > 1 && collapsed }"> <ul class="filter-items list-unstyled" v-bind:class="{ limited: facetItems.length > 1 && collapsed }">
<li v-for="(item, index) in facetItems" v-bind:key="index" class="list-group-item titlecase"> <li v-for="(item, index) in facetItems" v-bind:key="index" class="list-group-item titlecase">
{{ item.active }}
{{ item.val }}
{{ item.count }} //
<!-- <span :class="item.Active ? 'disabled' : ''" @click.prevent="activateItem(item)">{{ item.val }} ({{ item.count }}) </span> --> <!-- <span :class="item.Active ? 'disabled' : ''" @click.prevent="activateItem(item)">{{ item.val }} ({{ item.count }}) </span> -->
<span v-bind:class="item.active ? 'disabled' : ''" @click.prevent="activateItem(item)">{{ item.val }} ({{ item.count }}) </span> <span v-bind:class="item.active ? 'disabled' : ''" @click.prevent="activateItem(item)">{{ item.val }} ({{ item.count }}) </span>
</li> </li>

View File

@ -210,7 +210,7 @@ export default class VsInput extends Vue {
// Handler for search input change // Handler for search input change
searchChanged(): void { searchChanged(): void {
console.log("Search changed!"); // console.log("Search changed!");
this.selectedIndex = -1; this.selectedIndex = -1;
// Let's warn the parent that a change was made // Let's warn the parent that a change was made
// this.$emit("input", this.display); // this.$emit("input", this.display);
@ -224,7 +224,7 @@ export default class VsInput extends Vue {
// Perform the search request // Perform the search request
private resourceSearch() { private resourceSearch() {
console.log("resourceSearch"); // console.log("resourceSearch");
if (!this.display) { if (!this.display) {
this.results = []; this.results = [];
return; return;
@ -252,14 +252,11 @@ export default class VsInput extends Vue {
this.highlights = highlights; // Store highlights this.highlights = highlights; // Store highlights
// console.log(datasets); // console.log(datasets);
// this.$emit("search", this.display);
// this.loading = false;
} }
// Handle errors from the search request // Handle errors from the search request
private errorHandler(err: string): void { private errorHandler(err: string): void {
this.error = err; this.error = err;
// this.loading = false;
} }
/** /**
@ -321,18 +318,14 @@ export default class VsInput extends Vue {
@Emit("search-change") @Emit("search-change")
private select(obj: Suggestion): Suggestion { private select(obj: Suggestion): Suggestion {
// if (!obj) { console.log("select:");
// return; this.value = obj;
// }
console.log("select");
this.value = obj; //(obj["title_output"]) ? obj["title_output"] : obj.id
console.log(obj); console.log(obj);
this.display = obj.value; // this.formatDisplay(obj) this.display = obj.value;
// this.selectedDisplay = this.display;
this.close(); this.close();
// this.$emit("update", this.value);
return this.value; return this.value;
} }
@ -355,12 +348,7 @@ export default class VsInput extends Vue {
if (!this.value) { if (!this.value) {
this.clear(); this.clear();
} }
// if (this.selectedDisplay !== this.display && this.value) {
// this.display = this.selectedDisplay;
// }
this.results = []; this.results = [];
this.error = ""; this.error = "";
//this.removeEventListener()
// this.$emit("close");
} }
} }

View File

@ -23,13 +23,15 @@ export default class VsResult extends Vue {
.join("."); .join(".");
} }
private convert(unixtimestamp: number): string { // private convert(unixtimestamp: number): string { // SOLR
private convert(unixtimestamp: string): string { // OpenSearch
// Unixtimestamp // Unixtimestamp
// var unixtimestamp = document.getElementById('timestamp').value; // var unixtimestamp = document.getElementById('timestamp').value;
// Months array // Months array
const months_arr = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; const months_arr = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
// Convert timestamp to milliseconds // Convert timestamp to milliseconds
const date = new Date(unixtimestamp * 1000); // const date = new Date(unixtimestamp * 1000); // SOLR
const date = new Date(Number(unixtimestamp) * 1000); // OpenSearch
// Year // Year
const year = date.getFullYear(); const year = date.getFullYear();
// Month // Month

View File

@ -20,7 +20,8 @@
{{ convert(document.server_date_published) + ":&nbsp;" }} {{ convert(document.server_date_published) + ":&nbsp;" }}
</span> </span>
<span class="text"> <span class="text">
{{ document.abstract_output }} <!-- {{ document.abstract_output }} -->
{{ document.abstract[0] }}
<span class="ellipsis">...</span> <span class="ellipsis">...</span>
<span class="fill"></span> <span class="fill"></span>
</span> </span>

View File

@ -82,7 +82,7 @@ export class Suggestion {
export enum SearchType { export enum SearchType {
Title = "title", Title = "title",
Author = "author", Author = "author",
Subject = "subject" Subject = "subjects" // ** !! The field has this name in OpenSearch!!
} }
export class DbDataset { export class DbDataset {

View File

@ -26,6 +26,7 @@ export interface ResponseContent {
docs: Array<Dataset>; docs: Array<Dataset>;
} }
//Used
export class FacetResults { export class FacetResults {
[key: string]: Array<FacetItem>; [key: string]: Array<FacetItem>;
} }
@ -39,6 +40,7 @@ export interface FacetInstance {
[key: string]: Array<FacetItem>; [key: string]: Array<FacetItem>;
} }
//Used
export class FacetItem { export class FacetItem {
val: string; val: string;
count: number; count: number;

View File

@ -146,8 +146,10 @@ class DatasetService {
const lowercaseTerm = typeof suggestion === 'string' ? suggestion.toLowerCase() : suggestion.value.toLowerCase(); const lowercaseTerm = typeof suggestion === 'string' ? suggestion.toLowerCase() : suggestion.value.toLowerCase();
console.log("facetedsearchOPEN > suggestion entered:"); // console.log("facetedsearchOPEN > suggestion entered:");
console.log(suggestion); // console.log(suggestion);
// console.log("typeof:", typeof suggestion);
/** /**
* The query construction depends on whether the suggestion is a string or a Suggestion object. */ * The query construction depends on whether the suggestion is a string or a Suggestion object. */
@ -169,7 +171,7 @@ class DatasetService {
// When suggestion is a suggestion object // When suggestion is a suggestion object
: { : {
match: { match: {
[suggestion.type.toLowerCase()]: { [suggestion.type]: {
query: suggestion.value, query: suggestion.value,
operator: 'and' // all the terms in the query must be present in the field operator: 'and' // all the terms in the query must be present in the field
} }
@ -219,7 +221,7 @@ class DatasetService {
// // })) // // }))
// ); // );
const stations = api.post<OpenSearchResponse>(base, body); const stations = api.post<OpenSearchResponse>(base, body);
return stations; return stations;
} }

View File

@ -59,7 +59,7 @@ export default class DatasetDetailComponent extends Vue {
} }
onSearch(suggestion: Suggestion | string): void { onSearch(suggestion: Suggestion | string): void {
console.log("onSearch"); console.log("onSearch (dataset-detail.component)");
const host = window.location.host; const host = window.location.host;
const parts = host.split("."); const parts = host.split(".");

View File

@ -68,6 +68,8 @@ export default class SearchViewComponent extends Vue {
// Computed property to get search term as string // Computed property to get search term as string
get stringSearchTerm(): string { get stringSearchTerm(): string {
// console.log("stringSearchTerm:", this.searchTerm);
if (typeof this.searchTerm === "string") { if (typeof this.searchTerm === "string") {
return this.searchTerm; return this.searchTerm;
} else if (this.searchTerm instanceof Suggestion) { } else if (this.searchTerm instanceof Suggestion) {
@ -147,13 +149,24 @@ export default class SearchViewComponent extends Vue {
// Handle the search results // Handle the search results
private dataHandlerOPEN(res: OpenSearchResponse, filterItem?: FacetItem): void { private dataHandlerOPEN(res: OpenSearchResponse, filterItem?: FacetItem): void {
// console.log("dataHandlerOPEN (datasets, highlights):");
// console.log(datasets);
// console.log(highlights);
this.results = res.hits.hits.map(hit => hit._source); this.results = res.hits.hits.map(hit => hit._source);
this.numFound = res.hits.total.value; this.numFound = res.hits.total.value;
// console.log("dataHandlerOPEN (results, numFound):");
// console.log(this.results);
// console.log(this.numFound);
// console.log(res.hits.hits);
// console.log(res.hits.total.value);
// for (const key in this.results) {
// if (Object.prototype.hasOwnProperty.call(this.results, key)) {
// const element = this.results[key];
// // console.log(element.abstract[0]);
// // console.log(element.language);
// console.log(element.server_date_published);
// }
// }
this.pagination.total = res.hits.total.value; this.pagination.total = res.hits.total.value;
this.pagination.perPage = 10; this.pagination.perPage = 10;
this.pagination.data = this.results; this.pagination.data = this.results;
@ -178,9 +191,9 @@ export default class SearchViewComponent extends Vue {
// Method to handle search response // Method to handle search response
private dataHandler(res: SolrResponse, filterItem?: FacetItem): void { private dataHandler(res: SolrResponse, filterItem?: FacetItem): void {
console.log("dataHandlerSOLR (docs, numFound):"); // console.log("dataHandlerSOLR (docs, numFound):");
console.log(res.response.docs); // console.log(res.response.docs);
console.log(res.response.numFound); // console.log(res.response.numFound);
// Update results // Update results
this.results = res.response.docs; this.results = res.response.docs;
@ -242,6 +255,8 @@ export default class SearchViewComponent extends Vue {
// Method to handle pagination // Method to handle pagination
onMenuClick(page: number) { onMenuClick(page: number) {
console.log("onMenuClick");
this.pagination.currentPage = page; this.pagination.currentPage = page;
const start = page * this.pagination.perPage - this.pagination.perPage; const start = page * this.pagination.perPage - this.pagination.perPage;
@ -259,14 +274,19 @@ export default class SearchViewComponent extends Vue {
// Method to handle facet filtering // Method to handle facet filtering
onFilter(facetItem: FacetItem): void { onFilter(facetItem: FacetItem): void {
console.log("onFilter");
// Reset current page // Reset current page
this.pagination.currentPage = 1; this.pagination.currentPage = 1;
// console.log(facetItem.val); console.log(facetItem.val);
console.log(facetItem.category);
// if (!this.activeFilterCategories.hasOwnProperty(facetItem.category)) { // if (!this.activeFilterCategories.hasOwnProperty(facetItem.category)) {
// Check if filter item already exists // Check if filter item already exists
if (!Object.prototype.hasOwnProperty.call(this.activeFilterCategories, facetItem.category)) { if (!Object.prototype.hasOwnProperty.call(this.activeFilterCategories, facetItem.category)) {
this.activeFilterCategories[facetItem.category] = new Array<string>(); this.activeFilterCategories[facetItem.category] = new Array<string>();
console.log(this.activeFilterCategories);
} }
// if (!this.activeFilterCategories[facetItem.category].some((e) => e === facetItem.val)) { // if (!this.activeFilterCategories[facetItem.category].some((e) => e === facetItem.val)) {
@ -279,6 +299,7 @@ export default class SearchViewComponent extends Vue {
// (res: SolrResponse) => this.dataHandler(res, facetItem), // (res: SolrResponse) => this.dataHandler(res, facetItem),
// (error: string) => this.errorHandler(error), // (error: string) => this.errorHandler(error),
// ); // );
console.log(this.activeFilterCategories);
DatasetService.facetedSearchOPEN(this.searchTerm, this.activeFilterCategories, this.open.core, this.open.host, undefined).subscribe({ DatasetService.facetedSearchOPEN(this.searchTerm, this.activeFilterCategories, this.open.core, this.open.host, undefined).subscribe({
next: (res: OpenSearchResponse) => this.dataHandlerOPEN(res, facetItem), next: (res: OpenSearchResponse) => this.dataHandlerOPEN(res, facetItem),
error: (error: string) => this.errorHandler(error), error: (error: string) => this.errorHandler(error),
@ -286,60 +307,63 @@ export default class SearchViewComponent extends Vue {
} }
} }
// // Method to clear facet category filter // // // Method to clear facet category filter
onClearFacetCategory(categoryName: string): void { // onClearFacetCategory(categoryName: string): void {
delete this.activeFilterCategories[categoryName]; // console.log("onClearFacetCategory");
// delete this.activeFilterCategories[categoryName];
// Trigger new search with updated filter // // Trigger new search with updated filter
DatasetService.facetedSearch(this.searchTerm, this.activeFilterCategories, this.solr.core, this.solr.host, undefined).subscribe({ // DatasetService.facetedSearch(this.searchTerm, this.activeFilterCategories, this.solr.core, this.solr.host, undefined).subscribe({
next: (res: SolrResponse) => { // next: (res: SolrResponse) => {
this.results = res.response.docs; // this.results = res.response.docs;
this.numFound = res.response.numFound; // this.numFound = res.response.numFound;
// pagination // // pagination
this.pagination["total"] = res.response.numFound; // this.pagination["total"] = res.response.numFound;
this.pagination["perPage"] = res.responseHeader.params.rows as number; // this.pagination["perPage"] = res.responseHeader.params.rows as number;
this.pagination["currentPage"] = 1; // this.pagination["currentPage"] = 1;
this.pagination["data"] = res.response.docs; // this.pagination["data"] = res.response.docs;
const facet_fields: FacetFields = res.facets; // const facet_fields: FacetFields = res.facets;
let prop: keyof typeof facet_fields; // let prop: keyof typeof facet_fields;
for (prop in facet_fields) { // for (prop in facet_fields) {
const facetCategory: FacetInstance = facet_fields[prop]; // const facetCategory: FacetInstance = facet_fields[prop];
if (facetCategory.buckets) { // if (facetCategory.buckets) {
const facetItems: Array<FacetItem> = facetCategory.buckets; // const facetItems: Array<FacetItem> = facetCategory.buckets;
const facetValues = facetItems.map((facetItem) => { // const facetValues = facetItems.map((facetItem) => {
let rObj: FacetItem; // let rObj: FacetItem;
if (this.facets[prop]?.some((e) => e.val === facetItem.val)) { // if (this.facets[prop]?.some((e) => e.val === facetItem.val)) {
// console.log(facetValue + " is included") // // console.log(facetValue + " is included")
// Update existing facet item with new count // // Update existing facet item with new count
const indexOfFacetValue = this.facets[prop].findIndex((i) => i.val === facetItem.val); // const indexOfFacetValue = this.facets[prop].findIndex((i) => i.val === facetItem.val);
// console.log(indexOfFacetValue); // // console.log(indexOfFacetValue);
rObj = this.facets[prop][indexOfFacetValue]; // rObj = this.facets[prop][indexOfFacetValue];
rObj.count = facetItem.count; // rObj.count = facetItem.count;
// rObj = new FacetItem(val, count); // // rObj = new FacetItem(val, count);
// if facet ccategory is reactivated category, deactivate all filter items // // if facet ccategory is reactivated category, deactivate all filter items
if (prop == categoryName) { // if (prop == categoryName) {
rObj.active = false; // rObj.active = false;
} // }
} else { // } else {
// Create new facet item // // Create new facet item
rObj = new FacetItem(facetItem.val, facetItem.count); // rObj = new FacetItem(facetItem.val, facetItem.count);
} // }
return rObj; // return rObj;
}); // });
this.facets[prop] = facetValues; // this.facets[prop] = facetValues;
} // }
} // }
}, // },
error: (error: string) => this.errorHandler(error), // error: (error: string) => this.errorHandler(error),
complete: () => console.log("clear facet category completed"), // complete: () => console.log("clear facet category completed"),
}); // });
} // }
// Method to clear facet category filter // Method to clear facet category filter
onClearFacetCategoryOPEN(categoryName: string): void { onClearFacetCategoryOPEN(categoryName: string): void {
console.log("onClearFacetCategory");
delete this.activeFilterCategories[categoryName]; delete this.activeFilterCategories[categoryName];
// Trigger new search with updated filter // Trigger new search with updated filter