import { fetchQuery } from "./contentUtility.js"; import Dataset from "./dataset.js"; export const DATASET_ENDPOINT = "/api/v1/datasets"; export const getBaseURL = () => location.origin; const defaultPagingValue = 20; export const lastQuery = { totalPages: 0, currentPage: 0, }; const loadedCategories = new Set; // definition of all buttons & sections const addButton = document.getElementById("add-btn"); const filterButton = document.getElementById("filter-btn"); const searchButton = document.getElementById("search-btn"); const searchBar = document.getElementById("search-entry"); const sortButton = document.getElementById("sort-btn"); const resetButton = document.getElementById("reset-tools-btn"); const upvoteButtons = document.getElementsByClassName("upvote-btn"); const downvoteButtons = document.getElementsByClassName("downvote-btn"); export const searchSection = document.getElementById("search"); const recentSection = document.getElementById("recents"); const mostLikedSection = document.getElementById("top"); // ID of the timeout, because we need to cancel it at some point export let searchBarTimeout; const searchDelay = 500; // Event listeners addButton.addEventListener("click", () => { navigateToAdd(); }); filterButton.addEventListener("change", () => { fetchQuery(createQuery(), true); }); filterButton.addEventListener("click", () => { fetchCategories(); }) searchButton.addEventListener("click", () => { fetchQuery(createQuery(), true); }); searchBar.addEventListener("input", () => { clearTimeout(searchBarTimeout); searchBarTimeout = setTimeout(() => { fetchQuery(createQuery(), true); updateSections(); }, searchDelay); }); searchBar.addEventListener('keypress', function (e) { if (e.key === 'Enter') { fetchQuery(createQuery(), true); } }); sortButton.addEventListener("change", () => { fetchQuery(createQuery(), true); }); resetButton.addEventListener("click", () => { searchBar.value = ""; filterButton.value = filterButton.querySelector("#default-filter").value; sortButton.value = sortButton.querySelector("#default-sort").value; updateSections(); }); // functions of the main page function navigateToAdd() { window.location.href = "/add.html"; //TODO: move to EventListener? } function getFilterQuery() { let filterString = filterButton.value.toUpperCase(); if (filterString === "NONE") { return ["type", "%"] } else if (document.querySelector('#filter-btn option:checked').parentElement.label === "Standard categories") { return ["type", filterString]; } else { return ["category", filterButton.options[filterButton.selectedIndex].value] } } function getSearchQuery() { let searchString = searchBar.value; return (searchString.length === 0 ? "%" : ("%" + searchString + "%")); } function getSortQuery() { let sortString = sortButton.value.toLowerCase().split(" "); if (sortString[1] === "a-z" || sortString[1] === "↑" || sortString[1] === "oldest-newest") { sortString[1] = "asc"; } else { sortString[1] = "desc"; } return sortString } // creates query for the whole toolbar, so that searching, sorting and filtering are always combined function createQuery() { updateSections(); let queryURL = new URL(DATASET_ENDPOINT + "/search", getBaseURL()); queryURL.searchParams.append("search", getSearchQuery()); let filterQuery = getFilterQuery(); queryURL.searchParams.append(filterQuery[0], filterQuery[1]); let sortQuery = getSortQuery(); queryURL.searchParams.append("sort", sortQuery[0]); queryURL.searchParams.append("direction", sortQuery[1]); queryURL.searchParams.append("size", defaultPagingValue.toString(10)); return queryURL; } // updates the page display. If no query is present, the initial page is shown, otherwise the search results. function updateSections() { if (searchBar.value === "" && sortButton.value === sortButton.querySelector("#default-sort").value && filterButton.value === filterButton.querySelector("#default-filter").value) { searchSection.classList.add("hidden"); recentSection.classList.remove("hidden"); mostLikedSection.classList.remove("hidden"); resetButton.classList.add("hidden"); } else { searchSection.classList.remove("hidden"); recentSection.classList.add("hidden"); mostLikedSection.classList.add("hidden"); resetButton.classList.remove("hidden"); } } // fetches the further categories used in the filter function function fetchCategories() { const fetchURL = new URL("api/v1/categories", getBaseURL()); fetch(fetchURL) .then(resp => resp.json()) .then((data) => { for (let i = 0; i < data.length; i++) { let categoryName = data[i].name.toLowerCase(); categoryName = categoryName.charAt(0).toUpperCase() + categoryName.slice(1); if (!loadedCategories.has(categoryName)) { let newCategory = new Option(categoryName, data[i].id); document.getElementById("other-categories").appendChild(newCategory); loadedCategories.add(categoryName); } } }); } // fetches entries for the initial page async function fetchInitialEntries() { let recentsQueryURL = new URL(DATASET_ENDPOINT + "/search", getBaseURL()); recentsQueryURL.searchParams.append("sort", "date"); recentsQueryURL.searchParams.append("direction", "desc"); recentsQueryURL.searchParams.append("size", "6"); const recentsResponse = await fetch(recentsQueryURL); const recentsData = await recentsResponse.json(); const recentsDatasets = recentsData.content.map(dataset => new Dataset(dataset)); for (const recentDataset of recentsDatasets) { document.querySelector("#recents .datasets").appendChild(recentDataset.createDatasetHTMLElement()); } let topVotedQueryURL = new URL(DATASET_ENDPOINT + "/search", getBaseURL()); topVotedQueryURL.searchParams.append("sort", "upvotes"); topVotedQueryURL.searchParams.append("direction", "desc"); topVotedQueryURL.searchParams.append("size", "1"); const topVotedResponse = await fetch(topVotedQueryURL); const topVotedData = await topVotedResponse.json(); const topVotedDataset = new Dataset(topVotedData.content[0]); document.querySelector("#top .datasets").appendChild(topVotedDataset.createDatasetHTMLElement()); } window.onload = function () { fetchCategories(); fetchInitialEntries(); updateSections(); if (searchBar.value !== "") { fetchQuery(createQuery(), true); } let observer = new IntersectionObserver(() => { if (!searchSection.classList.contains("hidden")) { fetchPagingResults(); } }, {root: null, rootMargin: "0px", threshold: .9}); observer.observe(document.getElementById("observable")); } function fetchPagingResults() { lastQuery.currentPage++ if (lastQuery.currentPage < lastQuery.totalPages) { let pagingQuery = new URL(createQuery()); pagingQuery.searchParams.append("page", lastQuery.currentPage.toString(10)); fetchQuery(pagingQuery, false); } }