205 lines
7.3 KiB
JavaScript
205 lines
7.3 KiB
JavaScript
import { DATASET_ENDPOINT, getBaseURL } from "./constants.js"
|
|
import { fetchQuery } from "./contentUtility.js";
|
|
import Dataset from "./dataset.js";
|
|
|
|
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 !== "" || sortButton.value !== sortButton.querySelector("#default-sort").value
|
|
|| filterButton.value !== filterButton.querySelector("#default-filter").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);
|
|
}
|
|
}
|