430 lines
20 KiB
TypeScript
430 lines
20 KiB
TypeScript
// Import necessary modules, components, and models from Vue and the project
|
|
import { Component, Vue, Prop } from "vue-facing-decorator";
|
|
import VsInput from "@/components/vs-input/vs-input.vue";
|
|
import VsResult from "@/components/vs-result/vs-result.vue";
|
|
import FacetCategory from "@/components/face-category/facet-category.vue";
|
|
import ActiveFacetCategory from "@/components/active-facet-category/active-facet-category.vue";
|
|
|
|
// Import models and services
|
|
// import { SolrSettings } from "@/models/solr";
|
|
import { OpenSettings } from "@/models/solr";
|
|
import DatasetService from "../../services/dataset.service";
|
|
import { Suggestion, Dataset, SearchType } from "@/models/dataset";
|
|
// import { SolrResponse, FacetFields, FacetItem, FacetResults, FacetInstance } from "@/models/headers";
|
|
// import { SolrResponse, FacetFields, FacetItem, FacetResults, FacetInstance, OpenSearchResponse, HitHighlight } from "@/models/headers";
|
|
import { FacetItem, FacetResults, OpenSearchResponse } from "@/models/headers";
|
|
import { ActiveFilterCategories } from "@/models/solr";
|
|
// import { SOLR_HOST, SOLR_CORE } from "@/constants";
|
|
import { IPagination } from "@/models/pagination";
|
|
import PaginationComponent from "@/components/PaginationComponent.vue";
|
|
|
|
import { OPEN_HOST, OPEN_CORE } from "@/constants";
|
|
|
|
// Define the Vue component, its name, and child components
|
|
@Component({
|
|
name: "SearchViewComponent",
|
|
components: {
|
|
VsInput,
|
|
VsResult,
|
|
FacetCategory,
|
|
ActiveFacetCategory,
|
|
PaginationComponent,
|
|
},
|
|
})
|
|
|
|
// Export the default class for the component
|
|
export default class SearchViewComponent extends Vue {
|
|
// Define props passed from the parent component
|
|
@Prop()
|
|
display!: string; // Search display string
|
|
@Prop()
|
|
type!: string; // Search type
|
|
|
|
// Declare variables used in the component
|
|
results: Array<Dataset> = []; // Array to hold search results
|
|
facets: FacetResults = new FacetResults(); // Object to hold facet results
|
|
searchTerm: string | Suggestion = ""; // The search term input
|
|
activeFilterCategories: ActiveFilterCategories = new ActiveFilterCategories(); // Active filter categories for search
|
|
pagination: IPagination = { // Pagination data for the results
|
|
total: 0,
|
|
perPage: 10,
|
|
currentPage: 1,
|
|
data: [],
|
|
};
|
|
loaded = false; // Boolean to track whether data has been loaded
|
|
numFound!: number; // Number of results found
|
|
|
|
// private solr: SolrSettings = {
|
|
// core: SOLR_CORE, //"rdr_data", // SOLR.core;
|
|
// host: SOLR_HOST, //"tethys.at",
|
|
// };
|
|
|
|
// Define settings for the OpenSearch API (core and host information)
|
|
private open: OpenSettings = {
|
|
core: OPEN_CORE,
|
|
host: OPEN_HOST, //"https://catalog.geosphere.at",
|
|
};
|
|
|
|
private error = "";
|
|
|
|
// Computed property to get search term as string
|
|
get stringSearchTerm(): string {
|
|
// If searchTerm is a string, return it directly
|
|
if (typeof this.searchTerm === "string") {
|
|
return this.searchTerm;
|
|
// If searchTerm is a Suggestion, return its value and type alias
|
|
} else if (this.searchTerm instanceof Suggestion) {
|
|
return this.searchTerm.value + " (" + this.getTypeAlias(this.searchTerm.type) + ")";
|
|
// return this.searchTerm.value + " (" + this.searchTerm.type + ")";
|
|
// Default to empty string
|
|
} else {
|
|
return "";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The alias for the search term type will be set depending on the name of the type.
|
|
* This will allow to display the customised terms instead of the values currently used in the OpenSearch index.
|
|
* TODO: This should be corrected directly in the index
|
|
*/
|
|
getTypeAlias(type: string): string {
|
|
switch (type) {
|
|
case "author":
|
|
return "creator";
|
|
case "subjects":
|
|
return "keyword";
|
|
case "doctype":
|
|
return "data type";
|
|
default:
|
|
return type;
|
|
}
|
|
}
|
|
|
|
// Method to check if a search term is present
|
|
hasSearchTerm(): boolean {
|
|
if (typeof this.searchTerm === "string" && this.searchTerm !== "") {
|
|
return true;
|
|
} else if (this.searchTerm instanceof Suggestion && this.searchTerm.value !== "") {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Method to get enum key by enum value
|
|
getEnumKeyByEnumValue<T extends { [index: string]: string }>(myEnum: T, enumValue: string): keyof T | null {
|
|
const keys = Object.keys(myEnum).filter((x) => myEnum[x] == enumValue);
|
|
return keys.length > 0 ? keys[0] : null;
|
|
// return keys[0];
|
|
}
|
|
|
|
// Lifecycle hook: executed before the component is mounted
|
|
beforeMount(): void {
|
|
// Trigger search based on provided display and type props
|
|
if (this.display != "" && this.type != undefined) {
|
|
const enumKey: "Title" | "Author" | "Subject" | "Doctype" | null = this.getEnumKeyByEnumValue(SearchType, this.type);
|
|
if (enumKey) {
|
|
const suggestion = new Suggestion(this.display, "NO-IDEA", SearchType[enumKey]);
|
|
// const suggestion = new Suggestion(this.display, "" , SearchType[enumKey]);
|
|
this.onSearch(suggestion);
|
|
} else {
|
|
this.onSearch(this.display);
|
|
}
|
|
} else if (this.display != "" && this.type == undefined) {
|
|
this.onSearch(this.display);
|
|
} else {
|
|
this.onSearch("");
|
|
}
|
|
}
|
|
|
|
// Method to trigger a search
|
|
onSearch(suggestion: Suggestion | string): void {
|
|
// console.log("ONSEARCH");
|
|
|
|
// Reset active filter categories and facet results
|
|
this.activeFilterCategories = new ActiveFilterCategories();
|
|
this.facets = new FacetResults();
|
|
this.searchTerm = suggestion;
|
|
|
|
// /* Perform faceted search. The method returns an Observable, and the code subscribes to this Observable to handle the response. If the response is successful, it calls the dataHandler method
|
|
// with the Solr response as a parameter. If there is an error, it calls the errorHandler method with the error message as a parameter */
|
|
// DatasetService.facetedSearchSOLR(suggestion, this.activeFilterCategories, this.solr.core, this.solr.host, undefined).subscribe({
|
|
// next: (res: SolrResponse) => this.dataHandler(res),
|
|
// error: (error: string) => this.errorHandler(error),
|
|
// });
|
|
|
|
DatasetService.facetedSearch(suggestion, this.activeFilterCategories, this.open.core, this.open.host, undefined).subscribe({
|
|
next: (res: OpenSearchResponse) => this.dataHandler(res),
|
|
error: (error: string) => this.errorHandler(error),
|
|
});
|
|
|
|
}
|
|
|
|
// Handle the search results
|
|
private dataHandler(res: OpenSearchResponse, filterItem?: FacetItem): void {
|
|
this.results = res.hits.hits.map(hit => hit._source);
|
|
this.numFound = res.hits.total.value;
|
|
this.pagination.total = res.hits.total.value;
|
|
this.pagination.perPage = 10;
|
|
this.pagination.data = this.results;
|
|
this.pagination.lastPage = Math.ceil(this.pagination.total / this.pagination.perPage);
|
|
|
|
if (res.aggregations) {
|
|
const facet_fields = res.aggregations;
|
|
|
|
let prop: keyof typeof facet_fields;
|
|
|
|
// Iterate through facet fields
|
|
for (prop in facet_fields) {
|
|
const facetCategory = facet_fields[prop];
|
|
if (facetCategory.buckets) {
|
|
const facetItems = facetCategory.buckets.map(bucket => new FacetItem(bucket.key, bucket.doc_count));
|
|
|
|
let facetValues = facetItems.map((facetItem) => {
|
|
let rObj: FacetItem;
|
|
// Check if current facet item matches filter item
|
|
if (filterItem?.val == facetItem.val) {
|
|
rObj = filterItem;
|
|
} else if (this.facets[prop]?.some((e) => e.val === facetItem.val)) {
|
|
const indexOfFacetValue = this.facets[prop].findIndex((i) => i.val === facetItem.val);
|
|
rObj = this.facets[prop][indexOfFacetValue];
|
|
rObj.count = facetItem.count;
|
|
} else {
|
|
// Create new facet item
|
|
rObj = new FacetItem(facetItem.val, facetItem.count);
|
|
}
|
|
return rObj;
|
|
});
|
|
|
|
// Filter out null values and values with count <= 0
|
|
facetValues = facetValues.filter(el => el.count > 0);
|
|
this.facets[prop] = facetValues;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// // Method to handle search response
|
|
// private dataHandlerSOLR(res: SolrResponse, filterItem?: FacetItem): void {
|
|
// // console.log("dataHandlerSOLR (docs, numFound):");
|
|
// // console.log(res.response.docs);
|
|
// // console.log(res.response.numFound);
|
|
|
|
// // Update results
|
|
// this.results = res.response.docs;
|
|
// this.numFound = res.response.numFound;
|
|
|
|
// // Update pagination
|
|
// this.pagination["total"] = res.response.numFound;
|
|
// this.pagination["perPage"] = res.responseHeader.params.rows as number;
|
|
// this.pagination["data"] = res.response.docs;
|
|
// this.pagination.lastPage = Math.ceil(this.pagination.total / this.pagination.perPage);
|
|
|
|
// const facet_fields: FacetFields = res.facets;
|
|
|
|
// /* This code declares a variable prop with a type of keys of the facet_fields object. The keyof typeof facet_fields type represents the keys of the facet_fields object.
|
|
// This means that prop can only hold values that are keys of the facet_fields object. */
|
|
// let prop: keyof typeof facet_fields;
|
|
|
|
// // Iterate through facet fields
|
|
// for (prop in facet_fields) {
|
|
// const facetCategory = facet_fields[prop];
|
|
// if (facetCategory.buckets) {
|
|
// const facetItems: Array<FacetItem> = facetCategory.buckets;
|
|
|
|
// let facetValues = facetItems.map((facetItem) => {
|
|
// let rObj: FacetItem;
|
|
// // Check if current facet item matches filter item
|
|
// if (filterItem?.val == facetItem.val) {
|
|
// rObj = filterItem;
|
|
// } else if (this.facets[prop]?.some((e) => e.val === facetItem.val)) {
|
|
// // console.log(facetValue + " is included")
|
|
// // Update existing facet item with new count
|
|
// const indexOfFacetValue = this.facets[prop].findIndex((i) => i.val === facetItem.val);
|
|
// // console.log(indexOfFacetValue);
|
|
// rObj = this.facets[prop][indexOfFacetValue];
|
|
// rObj.count = facetItem.count;
|
|
// // rObj = new FacetItem(val, count);
|
|
// } else {
|
|
// // Create new facet item
|
|
// rObj = new FacetItem(facetItem.val, facetItem.count);
|
|
// }
|
|
// return rObj;
|
|
// });
|
|
|
|
// // Filter out null values and values with count <= 0
|
|
// facetValues = facetValues.filter(function (el) {
|
|
// return el != null && el.count > 0;
|
|
// });
|
|
// // this.facets[prop] = facetCategory;
|
|
// // Update facet values
|
|
// this.facets[prop] = facetValues;
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// Method to handle search errors
|
|
private errorHandler(err: string): void {
|
|
this.error = err;
|
|
}
|
|
|
|
// Method to handle pagination
|
|
onMenuClick(page: number) {
|
|
console.log("onMenuClick");
|
|
|
|
this.pagination.currentPage = page;
|
|
const start = page * this.pagination.perPage - this.pagination.perPage;
|
|
|
|
// // Trigger new search with updated pagination parameters
|
|
// DatasetService.facetedSearchSOLR(this.searchTerm, this.activeFilterCategories, this.solr.core, this.solr.host, start.toString()).subscribe(
|
|
// (res: SolrResponse) => this.dataHandler(res),
|
|
// (error: string) => this.errorHandler(error),
|
|
// );
|
|
|
|
DatasetService.facetedSearch(this.searchTerm, this.activeFilterCategories, this.open.core, this.open.host, start.toString()).subscribe({
|
|
next: (res: OpenSearchResponse) => this.dataHandler(res),
|
|
error: (error: string) => this.errorHandler(error),
|
|
});
|
|
}
|
|
|
|
// Method to handle facet filtering
|
|
onFilter(facetItem: FacetItem): void {
|
|
console.log("onFilter");
|
|
|
|
// Reset current page
|
|
this.pagination.currentPage = 1;
|
|
|
|
// Check if filter item already exists
|
|
if (!Object.prototype.hasOwnProperty.call(this.activeFilterCategories, facetItem.category)) {
|
|
this.activeFilterCategories[facetItem.category] = new Array<string>();
|
|
}
|
|
|
|
// Check if filter item is not already applied
|
|
if (!this.activeFilterCategories[facetItem.category].some((e) => e === facetItem.val)) {
|
|
// Add filter item to active filter categories
|
|
this.activeFilterCategories[facetItem.category].push(facetItem.val);
|
|
|
|
// DatasetService.facetedSearchSOLR(this.searchTerm, this.activeFilterCategories, this.solr.core, this.solr.host, undefined).subscribe(
|
|
// (res: SolrResponse) => this.dataHandler(res, facetItem),
|
|
// (error: string) => this.errorHandler(error),
|
|
// );
|
|
|
|
// Trigger new search with updated filter
|
|
DatasetService.facetedSearch(this.searchTerm, this.activeFilterCategories, this.open.core, this.open.host, undefined).subscribe({
|
|
next: (res: OpenSearchResponse) => this.dataHandler(res, facetItem),
|
|
error: (error: string) => this.errorHandler(error),
|
|
});
|
|
}
|
|
}
|
|
|
|
// // // Method to clear facet category filter
|
|
// onClearFacetCategorySOLR(categoryName: string): void {
|
|
// console.log("onClearFacetCategory");
|
|
|
|
// delete this.activeFilterCategories[categoryName];
|
|
|
|
// // Trigger new search with updated filter
|
|
// DatasetService.facetedSearch(this.searchTerm, this.activeFilterCategories, this.solr.core, this.solr.host, undefined).subscribe({
|
|
// next: (res: SolrResponse) => {
|
|
// this.results = res.response.docs;
|
|
// this.numFound = res.response.numFound;
|
|
|
|
// // pagination
|
|
// this.pagination["total"] = res.response.numFound;
|
|
// this.pagination["perPage"] = res.responseHeader.params.rows as number;
|
|
// this.pagination["currentPage"] = 1;
|
|
// this.pagination["data"] = res.response.docs;
|
|
|
|
// const facet_fields: FacetFields = res.facets;
|
|
// let prop: keyof typeof facet_fields;
|
|
// for (prop in facet_fields) {
|
|
// const facetCategory: FacetInstance = facet_fields[prop];
|
|
// if (facetCategory.buckets) {
|
|
// const facetItems: Array<FacetItem> = facetCategory.buckets;
|
|
|
|
// const facetValues = facetItems.map((facetItem) => {
|
|
// let rObj: FacetItem;
|
|
// if (this.facets[prop]?.some((e) => e.val === facetItem.val)) {
|
|
// // console.log(facetValue + " is included")
|
|
// // Update existing facet item with new count
|
|
// const indexOfFacetValue = this.facets[prop].findIndex((i) => i.val === facetItem.val);
|
|
// // console.log(indexOfFacetValue);
|
|
// rObj = this.facets[prop][indexOfFacetValue];
|
|
// rObj.count = facetItem.count;
|
|
// // rObj = new FacetItem(val, count);
|
|
// // if facet ccategory is reactivated category, deactivate all filter items
|
|
// if (prop == categoryName) {
|
|
// rObj.active = false;
|
|
// }
|
|
// } else {
|
|
// // Create new facet item
|
|
// rObj = new FacetItem(facetItem.val, facetItem.count);
|
|
// }
|
|
// return rObj;
|
|
// });
|
|
// this.facets[prop] = facetValues;
|
|
// }
|
|
// }
|
|
// },
|
|
// error: (error: string) => this.errorHandler(error),
|
|
// complete: () => console.log("clear facet category completed"),
|
|
// });
|
|
// }
|
|
|
|
// Method to clear facet category filter
|
|
onClearFacetCategory(categoryName: string): void {
|
|
// console.log("onClearFacetCategory");
|
|
delete this.activeFilterCategories[categoryName];
|
|
|
|
// Trigger new search with updated filter
|
|
DatasetService.facetedSearch(this.searchTerm, this.activeFilterCategories, this.open.core, this.open.host, undefined).subscribe({
|
|
next: (res: OpenSearchResponse) => {
|
|
this.results = res.hits.hits.map(hit => hit._source);
|
|
this.numFound = res.hits.total.value;
|
|
|
|
// Update pagination
|
|
this.pagination.total = res.hits.total.value;
|
|
this.pagination.perPage = 10;
|
|
this.pagination.currentPage = 1;
|
|
this.pagination.data = this.results;
|
|
this.pagination.lastPage = Math.ceil(this.pagination.total / this.pagination.perPage);
|
|
|
|
if (res.aggregations) {
|
|
const facet_fields = res.aggregations;
|
|
|
|
let prop: keyof typeof facet_fields;
|
|
|
|
for (prop in facet_fields) {
|
|
const facetCategory = facet_fields[prop];
|
|
if (facetCategory.buckets) {
|
|
const facetItems = facetCategory.buckets.map(bucket => new FacetItem(bucket.key, bucket.doc_count));
|
|
|
|
const facetValues = facetItems.map((facetItem) => {
|
|
let rObj: FacetItem;
|
|
if (this.facets[prop]?.some((e) => e.val === facetItem.val)) {
|
|
// Update existing facet item with new count
|
|
const indexOfFacetValue = this.facets[prop].findIndex((i) => i.val === facetItem.val);
|
|
rObj = this.facets[prop][indexOfFacetValue];
|
|
rObj.count = facetItem.count;
|
|
// if facet category is reactivated category, deactivate all filter items
|
|
if (prop === categoryName) {
|
|
rObj.active = false;
|
|
}
|
|
} else {
|
|
// Create new facet item
|
|
rObj = new FacetItem(facetItem.val, facetItem.count);
|
|
}
|
|
return rObj;
|
|
}).filter(el => el.count > 0); // Filter out items with count <= 0
|
|
|
|
this.facets[prop] = facetValues;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
error: (error: string) => this.errorHandler(error),
|
|
complete: () => console.log("Clear facet category completed"),
|
|
});
|
|
}
|
|
|
|
}
|