forked from geolba/tethys.frontend
Merge branch 'feat/opensearch' into develop
This commit is contained in:
commit
9f076daf15
30 changed files with 1821 additions and 997 deletions
|
@ -17,55 +17,65 @@ import * as L from 'leaflet';
|
|||
name: "DatasetDetailComponent",
|
||||
components: {
|
||||
VsInput,
|
||||
Minimap,
|
||||
// DataMetricsBadge,
|
||||
Minimap
|
||||
// DataMetricsBadge, // Commented out but prepared for future use
|
||||
},
|
||||
})
|
||||
export default class DatasetDetailComponent extends Vue {
|
||||
@Prop()
|
||||
datasetId!: string;
|
||||
datasetId!: string; // datasetId is passed as a prop and is required.
|
||||
|
||||
// @Prop()
|
||||
// identifier!: string;
|
||||
searchTerm: string | Suggestion = ""; // Search term used in the search functionality.
|
||||
private subscriptions: Array<Subscription> = []; // Subscriptions to RxJS observables to prevent memory leaks.
|
||||
public dataset = {} as DbDataset; // Holds dataset details.
|
||||
private error: string = ""; // Stores error messages, if any.
|
||||
public loaded = false; // Indicates whether the dataset is fully loaded.
|
||||
public openAccessLicences: Array<string> = ["CC-BY-4.0", "CC-BY-SA-4.0"]; // Available open-access licenses.
|
||||
public portal = VUE_API + "/api/file/download/"; // Portal URL for file downloads.
|
||||
|
||||
searchTerm: string | Suggestion = "";
|
||||
|
||||
private subscriptions: Array<Subscription> = [];
|
||||
public dataset = {} as DbDataset;
|
||||
private error: string = "";
|
||||
public loaded = false;
|
||||
public openAccessLicences: Array<string> = ["CC-BY-4.0", "CC-BY-SA-4.0"];
|
||||
public portal = VUE_API + "/api/file/download/";
|
||||
|
||||
public post = {
|
||||
views: 25,
|
||||
downloads: 1262,
|
||||
citations: 2424,
|
||||
};
|
||||
// If needed for stats
|
||||
// public post = {
|
||||
// views: 25, // Number of views for the dataset
|
||||
// downloads: 1262, // Number of downloads
|
||||
// citations: 2424, // Number of citations
|
||||
// };
|
||||
|
||||
/**
|
||||
* Lifecycle hook: Called when the component is created.
|
||||
* Extends dayjs with advanced format plugin and determines whether to
|
||||
* fetch dataset by ID or by DOI.
|
||||
*/
|
||||
created(): void {
|
||||
dayjs.extend(advancedFormat);
|
||||
dayjs.extend(advancedFormat); // Adds advanced date formatting options to dayjs.
|
||||
if (!this.datasetId.includes(".")) {
|
||||
// get datset by publish_id
|
||||
// Fetch dataset by publish_id (numeric ID)
|
||||
this.getDataset(Number(this.datasetId));
|
||||
} else {
|
||||
// get datset by doi_value
|
||||
// Fetch dataset by DOI (alphanumeric ID)
|
||||
this.getDatasetByIdentifier(this.datasetId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lifecycle hook: Called before the component is unmounted.
|
||||
* Unsubscribes from all subscriptions to prevent memory leaks.
|
||||
*/
|
||||
beforeUnmount(): void {
|
||||
//unsunscribe to ensure no memory leaks
|
||||
// this.subscription.unsubscribe();
|
||||
for (const subs of this.subscriptions) {
|
||||
subs.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
onSearch(suggestion: Suggestion | string): void {
|
||||
/**
|
||||
* Handles search functionality based on user input or suggestion selection.
|
||||
* Opens a new window or navigates internally based on the host's domain.
|
||||
* @param suggestion - The suggestion or search term entered by the user.
|
||||
*/
|
||||
onSearch(suggestion: Suggestion | string): void {
|
||||
const host = window.location.host;
|
||||
const parts = host.split(".");
|
||||
if (parts[0] === "doi") {
|
||||
// If in DOI subdomain, open external search in a new window
|
||||
let term;
|
||||
if (typeof suggestion === "string") {
|
||||
term = suggestion;
|
||||
|
@ -76,6 +86,7 @@ export default class DatasetDetailComponent extends Vue {
|
|||
window.open("https://tethys.at/search/" + term + "/" + type, "_self");
|
||||
}
|
||||
} else {
|
||||
// Otherwise, route internally to search page
|
||||
let term;
|
||||
if (typeof suggestion === "string") {
|
||||
term = suggestion;
|
||||
|
@ -85,79 +96,125 @@ export default class DatasetDetailComponent extends Vue {
|
|||
this.$router.push({ name: "Search", params: { display: term, type: suggestion.type } });
|
||||
}
|
||||
}
|
||||
|
||||
// this.searchTerm = suggestion;
|
||||
// this.$router.push({ name: "Search", params: { display: term, suggestion instanceof Suggestion ? ty} });
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the dataset details by ID from the service and updates the component state.
|
||||
* @param id - The dataset's numeric ID.
|
||||
*/
|
||||
private getDataset(id: number): void {
|
||||
const newSub = DatasetService.getDataset(id).subscribe({
|
||||
next: (res: DbDataset) => {
|
||||
this.dataset = res;
|
||||
this.loaded = true;
|
||||
this.dataset = res; // Store dataset in component state.
|
||||
this.loaded = true; // Mark as loaded.
|
||||
},
|
||||
// error: (error: string) => this.errorHandler(error),
|
||||
error: (error: string) => {
|
||||
this.error = error;
|
||||
this.error = error; // Capture any errors during fetch.
|
||||
},
|
||||
});
|
||||
|
||||
this.subscriptions.push(newSub);
|
||||
this.subscriptions.push(newSub); // Add subscription to array to manage unsubscribing later.
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the dataset details by DOI from the service and updates the component state.
|
||||
* @param id - The dataset's DOI (Digital Object Identifier).
|
||||
*/
|
||||
private getDatasetByIdentifier(id: string): void {
|
||||
const newSub = DatasetService.getDatasetByDoi(id).subscribe({
|
||||
next: (res: DbDataset) => {
|
||||
this.dataset = res;
|
||||
this.loaded = true;
|
||||
this.dataset = res; // Store dataset in component state.
|
||||
this.loaded = true; // Mark as loaded.
|
||||
},
|
||||
error: (error: string) => this.errorHandler(error),
|
||||
});
|
||||
|
||||
this.subscriptions.push(newSub);
|
||||
this.subscriptions.push(newSub); // Add subscription to array.
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles errors and updates the error message in the component.
|
||||
* @param err - Error message.
|
||||
*/
|
||||
private errorHandler(err: string): void {
|
||||
this.error = err;
|
||||
// this.loading = false;
|
||||
this.error = err; // Update error message.
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigates back by one page in the router history, similar to browser back.
|
||||
*/
|
||||
public goBack(): void {
|
||||
// go back by one record, the same as history.back()
|
||||
// router.go(-1);
|
||||
this.$router.go(-1);
|
||||
this.$router.go(-1); // Go back one step in the browser history.
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the file extension from a given filename.
|
||||
* @param filename - The name of the file.
|
||||
* @returns The file extension as a string.
|
||||
*/
|
||||
public getExtension(filename: string): string {
|
||||
return filename.substring(filename.lastIndexOf(".") + 1, filename.length) || filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the file size into a human-readable string with appropriate units.
|
||||
* @param file_size - The size of the file in bytes.
|
||||
* @returns The formatted file size string.
|
||||
*/
|
||||
public formatSize(file_size: number): string {
|
||||
let size = file_size;
|
||||
const unit = ["Byte", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
|
||||
const unit = ["Byte", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"]; // Units for size.
|
||||
let i;
|
||||
for (i = 0; size >= 1024 && i < unit.length - 1; i++) {
|
||||
size = size / 1024;
|
||||
size = size / 1024; // Convert size to appropriate unit.
|
||||
}
|
||||
// return Math.round((size * precision) / precision) + " " + unit[i];
|
||||
return Math.round((size + Number.EPSILON) * 100) / 100 + " " + unit[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a given date into a human-readable string with the full day, month, and year.
|
||||
* @param date - The date string to format.
|
||||
* @returns The formatted date string.
|
||||
*/
|
||||
public getPublishedDate(date: string): string {
|
||||
// return moment(date).format("ddd, MMMM Do, YYYY h:mm a");
|
||||
return dayjs(date).format("ddd, MMMM Do, YYYY h:mm a");
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a given date into a simpler "DD.MM.YYYY HH:mm" format.
|
||||
* @param date - The date string to format.
|
||||
* @returns The formatted date string.
|
||||
*/
|
||||
public getHumanDate(date: string): string {
|
||||
// return moment(date).format("DD.MM.YYYY HH:mm");
|
||||
return dayjs(date).format("DD.MM.YYYY HH:mm");
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the year from a given date string.
|
||||
* @param date - The date string to extract the year from.
|
||||
* @returns The year as a string.
|
||||
*/
|
||||
public getYear(date: string): string {
|
||||
return dayjs(date).format("YYYY");
|
||||
// return moment(date).format("YYYY");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the human-readable language string based on the language code.
|
||||
* @param language - The language code (e.g., "de" for German).
|
||||
* @returns The language name as a string.
|
||||
*/
|
||||
public getLanguage(language: string): string {
|
||||
if (language === "de") {
|
||||
return "Deutsch";
|
||||
} else {
|
||||
return "English";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a citation string for the dataset based on its authors and publication details.
|
||||
* @returns The citation as a string.
|
||||
*/
|
||||
public getCitation(): string {
|
||||
let citation = this.dataset.authors
|
||||
.map((u) => {
|
||||
|
@ -166,12 +223,11 @@ export default class DatasetDetailComponent extends Vue {
|
|||
name += ", " + u.first_name?.substring(0, 1).toUpperCase() + ".";
|
||||
}
|
||||
return name;
|
||||
// u.last_name + ", " + u.first_name?.substring(0, 1).toUpperCase() + "."
|
||||
})
|
||||
.join(", ");
|
||||
citation += " (" + dayjs(this.dataset.server_date_published).format("YYYY") + "): ";
|
||||
citation += this.dataset.MainTitle?.value;
|
||||
citation += "." + this.dataset.creating_corporation + ", ";
|
||||
citation += ". " + this.dataset.creating_corporation + ", ";
|
||||
citation += this.dataset.publisher_name;
|
||||
citation += ", Wien";
|
||||
return citation;
|
||||
|
|
|
@ -1,53 +1,55 @@
|
|||
<!-- detail-dataset.component.vue -->
|
||||
<template v-if="datasetId">
|
||||
<!-- <div class="container">
|
||||
<section class="section" v-if="dataset != undefined">
|
||||
<h2 v-if="dataset.hasOwnProperty('titles')">{{ dataset.titles[0].value }} details!</h2>
|
||||
<div v-if="dataset" class="dataset__blog-meta">published: {{ getHumanDate(dataset.server_date_published) }}</div>
|
||||
<p v-if="dataset.hasOwnProperty('abstracts')" class="dataset__abstract">{{ dataset.abstracts[0].value }}</p>
|
||||
<div><label>id: </label>{{ dataset.id }}</div>
|
||||
<button v-on:click="goBack">Back</button>
|
||||
</section>
|
||||
</div> -->
|
||||
|
||||
<div class="container-fluid banner mz-5">
|
||||
<!-- Search input component -->
|
||||
<!-- Placeholder text for search input, and triggers onSearch method when the search term changes -->
|
||||
<vs-input v-bind:placeholder="'Enter your search term...'" @search-change="onSearch"></vs-input>
|
||||
</div>
|
||||
|
||||
<!-- Section that shows the dataset details once the data is loaded -->
|
||||
<section v-if="loaded" class="section">
|
||||
<div class="container">
|
||||
<!-- <span class="is-size-5"> Basic Table </span>
|
||||
<br /> -->
|
||||
|
||||
<div class="columns">
|
||||
<!-- Main content area displaying dataset details -->
|
||||
<div class="column is-8 results_column" style="padding-top: 1.2rem; padding-right: 1rem; padding-left: 1rem">
|
||||
<!-- Card displaying the publication date -->
|
||||
<div class="card">
|
||||
<div class="column dataset__blog-meta">
|
||||
<h2 class="label uppercase">published: {{ getPublishedDate(dataset.server_date_published) }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Card displaying the dataset citation -->
|
||||
<div class="card">
|
||||
<div class="column">
|
||||
<label class="label">
|
||||
{{ getCitation() }}
|
||||
<!-- Link to the dataset's DOI if available -->
|
||||
<a v-if="dataset.identifier" target="_blank" class="link-label" v-bind:href="'https://doi.org/' + dataset.identifier.value"
|
||||
>({{ "https://doi.org/" + dataset.identifier.value }})</a
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Section showing references related to the dataset -->
|
||||
<div v-for="reference in dataset.references" v-bind:key="reference.id" class="columns">
|
||||
<div class="column is-3-desktop is-4-tablet label">{{ reference.relation }}</div>
|
||||
<div class="column is-9-desktop is-8-tablet">
|
||||
{{ reference.type }}:
|
||||
<!-- Link to the reference if it's a DOI -->
|
||||
<a v-if="reference.type === 'DOI'" target="_blank" class="link-label" v-bind:href="reference.value">
|
||||
{{ reference.value }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Section showing newer versions of the dataset -->
|
||||
<div v-for="reference in dataset.referenced_by" v-bind:key="reference.id" class="columns">
|
||||
<div class="column is-3-desktop is-4-tablet label">has newer version:</div>
|
||||
<div class="column is-9-desktop is-8-tablet">
|
||||
<!-- {{ "https://doi.org/" + reference.value }} -->
|
||||
{{ reference.type }}:
|
||||
<!-- Link to the newer version's DOI -->
|
||||
<a
|
||||
v-if="reference.type === 'DOI'"
|
||||
target="_blank"
|
||||
|
@ -60,10 +62,11 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Card displaying dataset titles -->
|
||||
<div class="card record-elem">
|
||||
<!-- Section for Main and Translated Titles -->
|
||||
<div v-if="dataset.hasOwnProperty('titles')" class="columns">
|
||||
<div class="column is-3-desktop is-4-tablet label">Title/<br />title:</div>
|
||||
<!-- <div class="column is-9-desktop is-8-tablet">{{ dataset.titles[0].value }}</div> -->
|
||||
<div class="column is-9-desktop is-8-tablet">
|
||||
<p>{{ dataset.MainTitle?.value }}</p>
|
||||
<br />
|
||||
|
@ -72,6 +75,8 @@
|
|||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Section for dataset abstracts -->
|
||||
<div v-if="dataset.hasOwnProperty('abstracts')" class="columns">
|
||||
<div class="column is-3-desktop is-4-tablet label">
|
||||
Zusammenfassung/<br />
|
||||
|
@ -85,6 +90,7 @@
|
|||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Section for series information -->
|
||||
<div v-if="dataset.hasOwnProperty('abstracts')" class="columns">
|
||||
<div class="column is-3-desktop is-4-tablet label">Serieninformation/<br />series information:</div>
|
||||
<div v-if="dataset.hasSeriesInformationAbstract()" class="column is-9-desktop is-8-tablet">
|
||||
|
@ -96,6 +102,8 @@
|
|||
</div>
|
||||
<div v-else class="column is-9-desktop is-8-tablet">-</div>
|
||||
</div>
|
||||
|
||||
<!-- Section for method description -->
|
||||
<div v-if="dataset.hasOwnProperty('abstracts')" class="columns">
|
||||
<div class="column is-3-desktop is-4-tablet label">Methodik/<br />method:</div>
|
||||
<div v-if="dataset.hasMethodsAbstract()" class="column is-9-desktop is-8-tablet">
|
||||
|
@ -104,9 +112,11 @@
|
|||
<div v-else class="column is-9-desktop is-8-tablet">-</div>
|
||||
</div>
|
||||
|
||||
<!-- Section for dataset files and their details -->
|
||||
<div class="columns">
|
||||
<div class="column is-3-desktop is-4-tablet label">Downloads/<br />downloads:</div>
|
||||
<div v-if="dataset.files.length > 0" class="column is-9-desktop is-8-tablet">
|
||||
<!-- Table showing file details if the embargo has passed -->
|
||||
<table v-if="dataset.hasEmbargoPassed()" id="items" class="table is-bordered is-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -120,7 +130,6 @@
|
|||
<td>
|
||||
<a class="link-label" target="_blank" v-bind:href="portal + file.id"> {{ file.label }} </a>
|
||||
<br />
|
||||
<!-- <span>md5: {{ file.hashvalues.find((e) => e.type === "md5")?.value }}</span> -->
|
||||
</td>
|
||||
<td>
|
||||
<span>{{ getExtension(file.path_name) }}</span>
|
||||
|
@ -136,6 +145,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Section for technical metadata of the dataset -->
|
||||
<div class="columns">
|
||||
<div class="column is-3-desktop is-4-tablet label">Technische Metadaten/<br />technical metadata:</div>
|
||||
<div class="column is-9-desktop is-8-tablet">
|
||||
|
@ -149,7 +159,10 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sidebar displaying additional dataset details -->
|
||||
<div id="id-side-bar" class="column is-4 sidebar_column" style="padding-top: 1.2rem; padding-right: 1rem; padding-left: 1rem">
|
||||
|
||||
<!-- Sidebar card for dataset details like creation year, coverage, language, etc. -->
|
||||
<div class="card">
|
||||
<div class="column">
|
||||
<h2 class="label uppercase">Details</h2>
|
||||
|
@ -164,24 +177,28 @@
|
|||
<Minimap :bounds="dataset.Bounds"></Minimap>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="column">
|
||||
<h3 class="label uppercase">Beitragende/Contributor</h3>
|
||||
<p v-if="dataset.hasContributors()">
|
||||
{{ dataset.contributors.map((u) => u.full_name).join(", ") }}
|
||||
</p>
|
||||
<p v-else>-</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Sidebar card showing dataset keywords -->
|
||||
<div class="card">
|
||||
<div class="column">
|
||||
<h3 class="label uppercase">Schlüsselwörter/Keywords</h3>
|
||||
<p v-if="dataset.hasOwnProperty('subjects')">
|
||||
{{ dataset.subjects.map((u) => u.value).join(", ") }}
|
||||
<!-- Iterate through subjects and display them as router links -->
|
||||
<span v-for="(subject, index) in dataset.subjects" :key="subject.value">
|
||||
<router-link
|
||||
:to="{ name: 'Search', params: { display: subject.value, type: 'subjects' } }"
|
||||
class="link-label"
|
||||
>
|
||||
{{ subject.value }}
|
||||
</router-link>
|
||||
<!-- Add a comma and space after each keyword except the last one -->
|
||||
<span v-if="index < dataset.subjects.length - 1">, </span>
|
||||
</span>
|
||||
</p>
|
||||
<p v-else>-</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sidebar cards displaying year, coverage, language, object type, and other dataset details -->
|
||||
<div class="card">
|
||||
<div class="column">
|
||||
<h3 class="label uppercase">Erstellungsjahr/Year</h3>
|
||||
|
@ -202,7 +219,7 @@
|
|||
<div class="column">
|
||||
<h3 class="label uppercase">Sprache/Language</h3>
|
||||
<p>
|
||||
{{ dataset.language }}
|
||||
{{ getLanguage(dataset.language) }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -214,14 +231,22 @@
|
|||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Sidebar card showing dataset licenses -->
|
||||
<div class="card">
|
||||
<div class="column">
|
||||
<h3 class="label uppercase">Lizenz/License</h3>
|
||||
<p v-if="dataset.hasLicenses()">
|
||||
<label v-for="license in dataset.licenses" v-bind:key="license.id">
|
||||
<!-- Link to the appropriate Creative Commons license -->
|
||||
<span class="normal label">
|
||||
{{ license.name }}
|
||||
<a v-if="license.name=='CC-BY-4.0'" target="_blank" class="link-label" v-bind:href="'https://creativecommons.org/licenses/by/4.0/'"
|
||||
><i class="fa-brands fa-creative-commons"></i> {{ license.name }}</a
|
||||
>
|
||||
<a v-else target="_blank" class="link-label" v-bind:href="'https://creativecommons.org/licenses/by-sa/4.0/'"
|
||||
><i class="fa-brands fa-creative-commons"></i> {{ license.name }}</a
|
||||
>
|
||||
</span>
|
||||
<!-- Display Open Access label if the license allows it -->
|
||||
<span v-if="openAccessLicences.includes(license.name)" class="normal label uppercase"
|
||||
><i class="fas fa-lock-open"></i> Open Access</span
|
||||
>
|
||||
|
@ -238,11 +263,14 @@
|
|||
<p v-else>-</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sidebar card showing references -->
|
||||
<div class="card">
|
||||
<div class="column">
|
||||
<h3 class="label uppercase">Referenzen/References</h3>
|
||||
<ul v-if="dataset.references.length > 0">
|
||||
<li v-for="(reference, i) in dataset.references" v-bind:key="reference.id">
|
||||
<!-- Link to reference if it's a DOI or URL -->
|
||||
<a
|
||||
v-if="reference.type == 'DOI' || reference.type == 'URL'"
|
||||
target="_blank"
|
||||
|
@ -255,14 +283,12 @@
|
|||
{{ `${reference.relation} (${reference.type}): ${reference.value}` }}
|
||||
</span>
|
||||
<span v-if="dataset.references.length > 0 && i < dataset.references.length - 1" class="normal label">--</span>
|
||||
<!-- <span v-if="openAccessLicences.includes(license.name)" class="normal label uppercase"
|
||||
><i class="fas fa-lock-open"></i> Open Access</span
|
||||
> -->
|
||||
</li>
|
||||
</ul>
|
||||
<p v-else>-</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Sidebar card for showing embargo details -->
|
||||
<div class="card">
|
||||
<div class="column">
|
||||
<h3 class="label uppercase">Embargo</h3>
|
||||
|
@ -272,27 +298,51 @@
|
|||
<p v-else>-</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sidebar card for displaying dataset contributors -->
|
||||
<div class="card">
|
||||
<div class="column">
|
||||
<h3 class="label uppercase">Beitragende/Contributor</h3>
|
||||
<p v-if="dataset.hasContributors()">
|
||||
{{ dataset.contributors.map((u) => u.full_name).join(", ") }}
|
||||
</p>
|
||||
<p v-else>-</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer section with partner logos -->
|
||||
<div class="container-fluid" style="padding-top: 3.8em">
|
||||
<div class="columns is-mobile partner-logos">
|
||||
<div class="column col-sm text-center">
|
||||
<a target="_blank" href="https://www.re3data.org/repository/r3d100013400"
|
||||
><img src="@/assets/site/img/re3-data-logo-mono.jpg" alt="re3 data logo"
|
||||
/></a>
|
||||
<div class="columns">
|
||||
<div class="column col-sm">
|
||||
<div class="card mx-auto" style="width: 18rem; box-shadow: none; border: 0rem">
|
||||
<div class="card-body">
|
||||
<a target="_blank" href="https://www.re3data.org/repository/r3d100013400">
|
||||
<img src="@/assets/site/img/re3-data-logo-mono.jpg" alt="re3 data logo" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column col-sm text-center">
|
||||
<a target="_blank" href="http://www.geosphere.at/">
|
||||
<img src="@/assets/site/img/geosphere-austria-logo.jpg" class="pb-3" alt="logo geosphere austria" />
|
||||
<!-- <img src="@/assets/site/img/gbaLogoRGB_web.png" alt="GeoSphere Austria logo" /> -->
|
||||
</a>
|
||||
<div class="column col-sm">
|
||||
<div class="card mx-auto" style="width: 28rem; box-shadow: none; border: 0rem">
|
||||
<div class="card-body">
|
||||
<a target="_blank" href="http://www.geosphere.at/">
|
||||
<img src="@/assets/site/img/geosphere-austria-logo.jpg" alt="logo geosphere austria" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column col-sm text-center">
|
||||
<a target="_blank" href="https://www.base-search.net/Search/Results?q=coll:fttethysrdr&refid=dctablede">
|
||||
<img src="@/assets/site/img/base-logo.gif" alt="logo base" />
|
||||
</a>
|
||||
<div class="column col-sm">
|
||||
<div class="card mx-auto" style="width: 18rem; box-shadow: none; border: 0rem">
|
||||
<div class="card-body">
|
||||
<a target="_blank" href="https://www.base-search.net/Search/Results?q=coll:fttethysrdr&refid=dctablede">
|
||||
<img src="@/assets/site/img/base_logo.png" alt="logo base" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -311,26 +361,32 @@ export default DatasetDetailComponent;
|
|||
font-size: 0.8rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 0;
|
||||
/* rempve box-shadow */
|
||||
/* Remove box-shadow for a flat design */
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.link-label {
|
||||
color: #33cccc;
|
||||
}
|
||||
|
||||
.label {
|
||||
/* color: #363636; */
|
||||
display: block;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.label.uppercase {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.normal.label {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.column p span i {
|
||||
color: #336699;
|
||||
}
|
||||
|
@ -341,27 +397,4 @@ export default DatasetDetailComponent;
|
|||
font-weight: 700;
|
||||
background-color: #ccddf1;
|
||||
}
|
||||
// input {
|
||||
// height: 2em;
|
||||
// font-size: 1em;
|
||||
// padding-left: 0.4em;
|
||||
// }
|
||||
// button {
|
||||
// margin-top: 20px;
|
||||
// font-family: Arial;
|
||||
// background-color: #eee;
|
||||
// border: none;
|
||||
// padding: 5px 10px;
|
||||
// border-radius: 4px;
|
||||
// cursor: pointer;
|
||||
// cursor: hand;
|
||||
// }
|
||||
// button:hover {
|
||||
// background-color: #cfd8dc;
|
||||
// }
|
||||
// button:disabled {
|
||||
// background-color: #eee;
|
||||
// color: #ccc;
|
||||
// cursor: auto;
|
||||
// }
|
||||
</style>
|
||||
|
|
|
@ -11,6 +11,9 @@ import { Suggestion } from "@/models/dataset";
|
|||
export default class HomeViewComponent extends Vue {
|
||||
public display = "";
|
||||
|
||||
/* This method is called when a search suggestion is selected. It takes a parameter suggestion which can be either a Suggestion object or a string.
|
||||
If it's a string, the method extracts the term and navigates to the "Search" route with the term as a parameter. If it's a Suggestion object, it extracts
|
||||
the value and type from the suggestion and navigates to the "Search" route with both parameters.*/
|
||||
onSearch(suggestion: Suggestion | string): void {
|
||||
let term;
|
||||
if (typeof suggestion === "string") {
|
||||
|
@ -22,6 +25,7 @@ export default class HomeViewComponent extends Vue {
|
|||
}
|
||||
}
|
||||
|
||||
/* This method is called when the user initiates a search. It navigates to the "Search" route with the display property as a parameter. */
|
||||
search(): void {
|
||||
this.$router.push({ name: "Search", params: { display: this.display } });
|
||||
}
|
||||
|
|
|
@ -18,13 +18,6 @@
|
|||
</a>
|
||||
</div> -->
|
||||
|
||||
<!-- <div class="column">
|
||||
<div class="col text-center py-3">
|
||||
<h1>Tethys Research Data Repository</h1>
|
||||
<p class="lead">Data Publisher for Geoscience Austria</p>
|
||||
<hr class="center-line" />
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="column">
|
||||
<div class="col text-center py-3">
|
||||
<h1>Tethys Research Data Repository</h1>
|
||||
|
|
|
@ -1,18 +1,26 @@
|
|||
// 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 { SolrSettings } from "@/models/solr";
|
||||
// import { DatasetService } from "@/services/dataset.service";
|
||||
|
||||
// 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 } 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 { 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: {
|
||||
|
@ -23,48 +31,76 @@ import PaginationComponent from "@/components/PaginationComponent.vue";
|
|||
PaginationComponent,
|
||||
},
|
||||
})
|
||||
|
||||
// Export the default class for the component
|
||||
export default class SearchViewComponent extends Vue {
|
||||
@Prop()
|
||||
display!: string;
|
||||
|
||||
@Prop()
|
||||
type!: string;
|
||||
|
||||
results: Array<Dataset> = [];
|
||||
|
||||
// facets: FacetFields = new FacetFields();
|
||||
facets: FacetResults = new FacetResults();
|
||||
searchTerm: string | Suggestion = "";
|
||||
// activeFilterCategories: Object = {};
|
||||
activeFilterCategories: ActiveFilterCategories = new ActiveFilterCategories(); // = new Array<ActiveFilterCategory>();
|
||||
pagination: IPagination = {
|
||||
// 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,
|
||||
// lastPage: 0,
|
||||
data: [],
|
||||
};
|
||||
loaded = false;
|
||||
numFound!: number;
|
||||
private solr: SolrSettings = {
|
||||
core: SOLR_CORE, //"rdr_data", // SOLR.core;
|
||||
host: SOLR_HOST, //"tethys.at",
|
||||
// core: "test_data", // SOLR.core;
|
||||
// host: "repository.geologie.ac.at",
|
||||
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 rdrAPI!: DatasetService;
|
||||
|
||||
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.searchTerm.type + ")";
|
||||
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;
|
||||
|
@ -74,21 +110,22 @@ export default class SearchViewComponent extends Vue {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
// getKeyName(value: string) {
|
||||
// return Object.entries(Suggestion).find(([key, val]) => val === value)?.[0];
|
||||
// }
|
||||
|
||||
// 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 {
|
||||
// this.rdrAPI = new DatasetService();
|
||||
// Trigger search based on provided display and type props
|
||||
if (this.display != "" && this.type != undefined) {
|
||||
const enumKey: "Title" | "Author" | "Subject" | null = this.getEnumKeyByEnumValue(SearchType, this.type);
|
||||
const enumKey: "Title" | "Author" | "Subject" | "Doctype" | null = this.getEnumKeyByEnumValue(SearchType, this.type);
|
||||
if (enumKey) {
|
||||
const suggestion = new Suggestion(this.display, SearchType[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);
|
||||
|
@ -100,216 +137,294 @@ export default class SearchViewComponent extends Vue {
|
|||
}
|
||||
}
|
||||
|
||||
// onSearch(term: string): void {
|
||||
// Method to trigger a search
|
||||
onSearch(suggestion: Suggestion | string): void {
|
||||
// let queryOperator;
|
||||
// if (typeof suggestion === "string") {
|
||||
// suggestion = suggestion + "*";
|
||||
// queryOperator = "or";
|
||||
// } else if (suggestion instanceof Suggestion) {
|
||||
// // term = suggestion.value;
|
||||
// queryOperator = "and";
|
||||
// }
|
||||
|
||||
// if (term) {
|
||||
// term = term.trim();
|
||||
// } else {
|
||||
// term = "*%3A*";
|
||||
// }
|
||||
|
||||
// console.log("ONSEARCH");
|
||||
|
||||
// Reset active filter categories and facet results
|
||||
this.activeFilterCategories = new ActiveFilterCategories();
|
||||
this.facets = new FacetResults();
|
||||
|
||||
// this.facets = {};
|
||||
this.searchTerm = suggestion;
|
||||
DatasetService.facetedSearch(suggestion, this.activeFilterCategories, this.solr.core, this.solr.host, undefined).subscribe({
|
||||
next: (res: SolrResponse) => this.dataHandler(res),
|
||||
|
||||
// /* 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),
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private dataHandler(res: SolrResponse, filterItem?: FacetItem): void {
|
||||
// this.results = datasets;
|
||||
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;
|
||||
// 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);
|
||||
|
||||
// facets
|
||||
// const facet_fields = res.facet_counts.facet_fields;
|
||||
// for (const prop in facet_fields) {
|
||||
// const facetCategory: FacetCategory<any> = facet_fields[prop];
|
||||
// const facetValues = facetCategory.key.values.map((facet_value: any, i: number) => {
|
||||
// if (i % 2 === 0 && typeof facet_value == "string") {
|
||||
// //var rObj = { value: facet, count: facet_fields[prop][i + 1] };
|
||||
// // FiletrItem with value and count
|
||||
// const rObj = new FilterItem(facet_value, facetCategory.key.values[i + 1]);
|
||||
// return rObj;
|
||||
// }
|
||||
// });
|
||||
// .filter(function (el: FilterItem) {
|
||||
// return el != null && el.count > 0;
|
||||
// });
|
||||
// //this.facets.push({ filterName: prop, values: facetValues });
|
||||
// this.facets[prop] = facetValues;
|
||||
// }
|
||||
|
||||
const facet_fields: FacetFields = res.facets;
|
||||
let prop: keyof typeof 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;
|
||||
if (filterItem?.val == facetItem.val) {
|
||||
rObj = filterItem;
|
||||
} else if (this.facets[prop]?.some((e) => e.val === facetItem.val)) {
|
||||
// console.log(facetValue + " is included")
|
||||
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 {
|
||||
rObj = new FacetItem(facetItem.val, facetItem.count);
|
||||
}
|
||||
return rObj;
|
||||
});
|
||||
|
||||
facetValues = facetValues.filter(function (el) {
|
||||
return el != null && el.count > 0;
|
||||
});
|
||||
// this.facets[prop] = facetCategory;
|
||||
this.facets[prop] = facetValues;
|
||||
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;
|
||||
// this.loading = false;
|
||||
}
|
||||
|
||||
// Method to handle pagination
|
||||
onMenuClick(page: number) {
|
||||
// const test = page;
|
||||
// console.log(test);
|
||||
console.log("onMenuClick");
|
||||
|
||||
this.pagination.currentPage = page;
|
||||
const start = page * this.pagination.perPage - this.pagination.perPage;
|
||||
|
||||
DatasetService.facetedSearch(this.searchTerm, this.activeFilterCategories, this.solr.core, this.solr.host, start.toString()).subscribe(
|
||||
(res: SolrResponse) => this.dataHandler(res),
|
||||
(error: string) => this.errorHandler(error),
|
||||
);
|
||||
// // 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;
|
||||
// console.log(facetItem.val);
|
||||
// if (!this.activeFilterCategories.hasOwnProperty(facetItem.category)) {
|
||||
|
||||
// Check if filter item already exists
|
||||
if (!Object.prototype.hasOwnProperty.call(this.activeFilterCategories, facetItem.category)) {
|
||||
this.activeFilterCategories[facetItem.category] = new Array<string>();
|
||||
}
|
||||
// if (!this.activeFilterCategories[facetItem.category].some((e) => e === facetItem.val)) {
|
||||
|
||||
// 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.facetedSearch(this.searchTerm, this.activeFilterCategories, this.solr.core, this.solr.host, undefined).subscribe(
|
||||
(res: SolrResponse) => this.dataHandler(res, facetItem),
|
||||
(error: string) => this.errorHandler(error),
|
||||
);
|
||||
// alert(this.activeFilterCategories[filter.Category]);
|
||||
// var res = await rdrApi.search(this.searchTerm, this.activeFilterCategories, this.solrCore, this.solrHost);
|
||||
// this.results = res.response.docs;
|
||||
// this.numFound = res.response.numFound;
|
||||
// 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),
|
||||
// );
|
||||
|
||||
// // pagination
|
||||
// this.pagination['total'] = res.response.numFound;
|
||||
// this.pagination['per_page'] = res.responseHeader.params.rows;
|
||||
// this.pagination['current_page'] = 1;
|
||||
// this.pagination['data'] = res.response.docs;
|
||||
|
||||
// var facet_fields = res.facet_counts.facet_fields;
|
||||
// for (var prop in facet_fields) {
|
||||
// var facetValues = facet_fields[prop].map((facetValue, i) => {
|
||||
// if (i % 2 === 0) {
|
||||
// // var rObj = { value: facetValue, count: facet_fields[prop][i + 1] };
|
||||
// var rObj;
|
||||
// if (filter.value == facetValue) {
|
||||
// rObj = filter;
|
||||
// } else if (this.facets[prop].some(e => e.value === facetValue)) {
|
||||
// // console.log(facetValue + " is included")
|
||||
// var indexOfFacetValue = this.facets[prop].findIndex(i => i.value === facetValue);
|
||||
// // console.log(indexOfFacetValue);
|
||||
// rObj = this.facets[prop][indexOfFacetValue];
|
||||
// rObj.count = facet_fields[prop][i + 1];
|
||||
// } else {
|
||||
// rObj = new FilterItem(facetValue, facet_fields[prop][i + 1]);
|
||||
// }
|
||||
// return rObj;
|
||||
// }
|
||||
// }).filter(function (el) {
|
||||
// return el != null && el.count > 0;
|
||||
// });
|
||||
// // this.facets.push({ filterName: prop, values: facetValues });
|
||||
// this.facets[prop] = facetValues;
|
||||
// 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 {
|
||||
// alert(categoryName);
|
||||
// console.log("onClearFacetCategory");
|
||||
delete this.activeFilterCategories[categoryName];
|
||||
|
||||
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")
|
||||
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;
|
||||
// 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);
|
||||
}
|
||||
} else {
|
||||
rObj = new FacetItem(facetItem.val, facetItem.count);
|
||||
}
|
||||
return rObj;
|
||||
});
|
||||
this.facets[prop] = facetValues;
|
||||
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"),
|
||||
complete: () => console.log("Clear facet category completed"),
|
||||
});
|
||||
}
|
||||
|
||||
// onPaging(page: number): void {}
|
||||
}
|
||||
|
|
|
@ -1,46 +1,38 @@
|
|||
<template>
|
||||
<div id="page_style" class="rows site-content page__style page__description" autocomplete="off">
|
||||
|
||||
<!-- Search input section -->
|
||||
<div class="container-fluid banner mz-5">
|
||||
<vs-input v-bind:propDisplay="searchTerm" v-bind:placeholder="'Enter your search term...'" @search-change="onSearch"></vs-input>
|
||||
</div>
|
||||
<div class="column is-half is-offset-one-quarter" style="padding-top: 0; margin-top: 0">
|
||||
<!-- <div class="tabs is-centered">
|
||||
<ul id="id-results-tabs">
|
||||
<li class="search_tab is-active">
|
||||
<a target="_self">Web</a>
|
||||
</li>
|
||||
<li class="search_tab">
|
||||
<a target="_self">Images</a>
|
||||
</li>
|
||||
<li class="search_tab">
|
||||
<a target="_self">Videos</a>
|
||||
</li>
|
||||
<li class="search_tab">
|
||||
<a target="_self">Homepages</a>
|
||||
</li>
|
||||
<li class="search_tab">
|
||||
<a target="_self">Food</a>
|
||||
</li>
|
||||
<li class="search_tab">
|
||||
<a target="_self">Books</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div> -->
|
||||
<div v-if="results.length > 0" class="result-list-info">
|
||||
<div v-if="hasSearchTerm()" class="resultheader">
|
||||
Your search term {{ "'" + stringSearchTerm + "'" }} yielded <strong>{{ numFound }}</strong> results:
|
||||
</div>
|
||||
|
||||
<!-- Results area on top of the list of publications -->
|
||||
<div class="columns">
|
||||
<!-- Left sidebar section. Empty, just to keep simetry -->
|
||||
<div id="id-side-bar" class="column is-4 sidebar_column" style="padding-top: 0rem; padding-right: 1.5rem; padding-left: 1.5rem">
|
||||
</div>
|
||||
<div v-else-if="results.length == 0">
|
||||
<div class="resultheader">
|
||||
Your search yielded
|
||||
<strong> 0</strong> results:
|
||||
|
||||
<!-- Results section -->
|
||||
<div class="col col-8 column is-8 results_column" style="padding-top: 0.5rem; padding-right: 1rem; padding-left: 1rem; padding-bottom: 0rem;">
|
||||
<!-- Display results if any -->
|
||||
<div v-if="results.length > 0" class="result-list-info">
|
||||
<div v-if="hasSearchTerm()" class="p-1 mb-0 text-sm bg-[#d8f4f7] rounded-lg" role="alert">
|
||||
<span class="font-medium pl-5">Your search term</span> <span class="font-semibold">{{ "'" + stringSearchTerm + "'" }}</span> yielded <strong>{{ numFound }}</strong> results:
|
||||
</div>
|
||||
</div>
|
||||
<!-- Display message if no results found -->
|
||||
<div v-else-if="results.length == 0">
|
||||
<div class="p-1 mb-0 text-sm bg-[#d8f4f7] rounded-lg" role="alert">
|
||||
<span class="font-medium pl-5">Your search yielded <strong> 0</strong> results.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Area with the list of facets (left) and list of publications (right) -->
|
||||
<div class="columns">
|
||||
<div id="id-side-bar" class="column is-4 sidebar_column" style="padding-top: 1.2rem; padding-right: 1.5rem; padding-left: 1.5rem">
|
||||
<!-- Sidebar with facets -->
|
||||
<div id="id-side-bar" class="column is-4 sidebar_column" style="padding-top: 0.5rem; padding-right: 1.5rem; padding-left: 1.5rem">
|
||||
<div id="externals" class="">
|
||||
<div v-for="(facetItems, key, index) in facets" v-bind:key="index" name="external_card" style="margin-bottom: 0px">
|
||||
<facet-category v-bind:facetItems="facetItems" v-bind:filterName="key" @filter="onFilter"></facet-category>
|
||||
|
@ -48,9 +40,11 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col col-8 column is-8 results_column" style="padding-top: 1.2rem; padding-right: 1rem; padding-left: 1rem">
|
||||
<!-- Main results section with pagination and active filters -->
|
||||
<div class="col col-8 column is-8 results_column" style="padding-top: 0.5rem; padding-right: 1rem; padding-left: 1rem">
|
||||
<div v-if="activeFilterCategories && Object.keys(activeFilterCategories).length > 0" class="column">
|
||||
<span v-for="(values, key, index) in activeFilterCategories" v-bind:key="index" class="active-filter-items">
|
||||
<!-- Active filter categories -->
|
||||
<active-facet-category
|
||||
v-bind:filterItems="values"
|
||||
v-bind:categoryName="key"
|
||||
|
@ -59,38 +53,17 @@
|
|||
</span>
|
||||
</div>
|
||||
<div class="results">
|
||||
<!-- pagination before search results -->
|
||||
<!-- Pagination before search results -->
|
||||
<PaginationComponent class="mb-5" v-bind:data="pagination" @menu-click="onMenuClick"></PaginationComponent>
|
||||
<!-- Results section -->
|
||||
<vs-result v-bind:datasets="results"></vs-result>
|
||||
<!-- pagination after serach results -->
|
||||
<!-- Pagination after search results -->
|
||||
<PaginationComponent class="mt-5" v-bind:data="pagination" @menu-click="onMenuClick"></PaginationComponent>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <PaginationComponent v-bind:data="pagination"></PaginationComponent> -->
|
||||
</div>
|
||||
|
||||
<!-- <div class="container-fluid" style="padding-top: 3.8em">
|
||||
<div class="columns is-mobile partner-logos">
|
||||
<div class="column col-sm text-center">
|
||||
<a target="_blank" href="https://www.re3data.org/repository/r3d100013400"
|
||||
><img src="@/assets/site/img/re3-data-logo-mono.jpg" alt="re3 data logo"
|
||||
/></a>
|
||||
</div>
|
||||
<div class="column col-sm text-center">
|
||||
<a target="_blank" href="http://www.geosphere.at/">
|
||||
<img src="@/assets/site/img/geosphere-austria-logo.jpg" alt="logo geosphere austria" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="column col-sm text-center">
|
||||
<a target="_blank" href="https://www.base-search.net/Search/Results?q=coll:fttethysrdr&refid=dctablede">
|
||||
<img src="@/assets/site/img/base-logo.gif" alt="logo base" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- Partner logos section -->
|
||||
<div class="container-fluid">
|
||||
<!-- <div class="columns is-mobile partner-logos"> -->
|
||||
<div class="columns">
|
||||
|
@ -134,4 +107,4 @@ export default SearchViewComponent;
|
|||
import "@/index.css";
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped></style>
|
Loading…
Add table
editor.link_modal.header
Reference in a new issue