diff --git a/src/views/dataset-detail.component/dataset-detail.component.ts b/src/views/dataset-detail.component/dataset-detail.component.ts index 5185e93..c314e1f 100644 --- a/src/views/dataset-detail.component/dataset-detail.component.ts +++ b/src/views/dataset-detail.component/dataset-detail.component.ts @@ -14,56 +14,64 @@ import { VUE_API } from "@/constants"; name: "DatasetDetailComponent", components: { VsInput, - // DataMetricsBadge, + // 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 = []; // 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. - searchTerm: string | Suggestion = ""; - - private subscriptions: Array = []; - public dataset = {} as DbDataset; - private error: string = ""; - public loaded = false; - public openAccessLicences: Array = ["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 { - console.log("onSearch (dataset-detail.component)"); - + /** + * 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; @@ -74,6 +82,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; @@ -83,87 +92,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" + return "Deutsch"; } else { - return "English" + 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) => { @@ -172,7 +219,6 @@ 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") + "): "; diff --git a/src/views/dataset-detail.component/dataset-detail.component.vue b/src/views/dataset-detail.component/dataset-detail.component.vue index 66068d4..4c64dea 100644 --- a/src/views/dataset-detail.component/dataset-detail.component.vue +++ b/src/views/dataset-detail.component/dataset-detail.component.vue @@ -1,81 +1,54 @@ @@ -395,26 +353,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; } @@ -425,27 +389,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; -// } diff --git a/src/views/search-view/search-view-component.ts b/src/views/search-view/search-view-component.ts index d8e666c..93ad30e 100644 --- a/src/views/search-view/search-view-component.ts +++ b/src/views/search-view/search-view-component.ts @@ -61,16 +61,14 @@ export default class SearchViewComponent extends Vue { // }; private open: OpenSettings = { - core: OPEN_CORE, //"rdr_data", // SOLR.core; - host: OPEN_HOST, //"tethys.at", + core: OPEN_CORE, + host: OPEN_HOST, //"https://catalog.geosphere.at", }; private error = ""; // Computed property to get search term as string - get stringSearchTerm(): string { - // console.log("stringSearchTerm:", this.searchTerm); - + get stringSearchTerm(): string { if (typeof this.searchTerm === "string") { return this.searchTerm; } else if (this.searchTerm instanceof Suggestion) { @@ -109,9 +107,6 @@ 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(myEnum: T, enumValue: string): keyof T | null { @@ -122,9 +117,6 @@ export default class SearchViewComponent extends Vue { // Lifecycle hook: executed before the component is mounted beforeMount(): void { - // console.log("beforeMount!"); - - // this.rdrAPI = new DatasetService(); // 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); diff --git a/src/views/search-view/search-view-component.vue b/src/views/search-view/search-view-component.vue index f2eeb8f..3c22d1e 100644 --- a/src/views/search-view/search-view-component.vue +++ b/src/views/search-view/search-view-component.vue @@ -1,95 +1,37 @@