import { Component, Vue, Prop } from "vue-facing-decorator"; import { DbDataset } from "@/models/dataset"; import DatasetService from "../../services/dataset.service"; import { Subscription } from "rxjs"; import dayjs from "dayjs"; import advancedFormat from "dayjs/plugin/advancedFormat"; import VsInput from "@/components/vs-input/vs-input.vue"; import { Suggestion } from "@/models/dataset"; import { VUE_API } from "@/constants"; // import DataMetricsBadge from "data-metrics-badge/dist/data-metrics-badge.js"; // import DataMetricsBadge from "@/components/datacite/DataMetricsBadge.vue"; @Component({ name: "DatasetDetailComponent", components: { VsInput, // DataMetricsBadge, // Commented out but prepared for future use }, }) export default class DatasetDetailComponent extends Vue { @Prop() datasetId!: string; // datasetId is passed as a prop and is required. searchTerm: string | Suggestion = ""; // Search term used in the search functionality. private subscriptions: Array = []; // 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 = ["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. // 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); // Adds advanced date formatting options to dayjs. if (!this.datasetId.includes(".")) { // Fetch dataset by publish_id (numeric ID) this.getDataset(Number(this.datasetId)); } else { // 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 { for (const subs of this.subscriptions) { subs.unsubscribe(); } } /** * 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; window.open("https://tethys.at/search/" + term, "_self"); } else if (suggestion instanceof Suggestion) { term = suggestion.value; const type = suggestion.type; window.open("https://tethys.at/search/" + term + "/" + type, "_self"); } } else { // Otherwise, route internally to search page let term; if (typeof suggestion === "string") { term = suggestion; this.$router.push({ name: "Search", params: { display: term } }); } else if (suggestion instanceof Suggestion) { term = suggestion.value; this.$router.push({ name: "Search", params: { display: term, type: suggestion.type } }); } } } /** * 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; // Store dataset in component state. this.loaded = true; // Mark as loaded. }, error: (error: string) => { this.error = error; // Capture any errors during fetch. }, }); 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; // Store dataset in component state. this.loaded = true; // Mark as loaded. }, error: (error: string) => this.errorHandler(error), }); 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; // Update error message. } /** * Navigates back by one page in the router history, similar to browser back. */ public goBack(): void { 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"]; // Units for size. let i; for (i = 0; size >= 1024 && i < unit.length - 1; i++) { size = size / 1024; // Convert size to appropriate unit. } 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 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 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"); } /** * 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) => { let name = u.last_name; if (u.first_name) { name += ", " + u.first_name?.substring(0, 1).toUpperCase() + "."; } return name; }) .join(", "); citation += " (" + dayjs(this.dataset.server_date_published).format("YYYY") + "): "; citation += this.dataset.MainTitle?.value; citation += ". " + this.dataset.creating_corporation + ", "; citation += this.dataset.publisher_name; citation += ", Wien"; return citation; } }