diff --git a/src/main/java/de/uni_passau/fim/PADAS/group3/DataDash/controler/DatasetController.java b/src/main/java/de/uni_passau/fim/PADAS/group3/DataDash/controler/DatasetController.java index 8a69a50..824c5ff 100644 --- a/src/main/java/de/uni_passau/fim/PADAS/group3/DataDash/controler/DatasetController.java +++ b/src/main/java/de/uni_passau/fim/PADAS/group3/DataDash/controler/DatasetController.java @@ -65,7 +65,7 @@ public class DatasetController { return getDatasetById(id); // new ResponseEntity<>(null, HttpStatus.OK); } - @PutMapping("/id/{id}/vote") + @PutMapping("/id/{id}/stars") public Dataset postMethodName(@PathVariable("id") UUID id, @RequestParam("stars") int stars) { if (stars > 0 && stars < 6) { diff --git a/src/main/resources/static/contentUtility.js b/src/main/resources/static/contentUtility.js index e2a032e..deb5658 100644 --- a/src/main/resources/static/contentUtility.js +++ b/src/main/resources/static/contentUtility.js @@ -11,13 +11,11 @@ export function fetchQuery(fetchString) { } function parseContent(content) { - console.log(content); //TODO: remove if (content.length === 0) { searchSection.querySelector("#nothing-found ").classList.remove("hidden"); } else { searchSection.querySelector("#nothing-found").classList.add("hidden"); const datasets = content.map(dataset => new Dataset(dataset)); - console.log(datasets); //TODO: remove Array.from(searchSection.querySelectorAll(".datasets .dataset")).forEach(e => e.remove()); for (const dataset of datasets) { searchSection.querySelector(".datasets").appendChild(dataset.createDatasetHTMLElement()); diff --git a/src/main/resources/static/main.css b/src/main/resources/static/main.css index 63566c3..c62d21e 100644 --- a/src/main/resources/static/main.css +++ b/src/main/resources/static/main.css @@ -42,6 +42,7 @@ header { left: 0; z-index: 1; } + #tool-bar { display: flex; flex-direction: row; @@ -77,18 +78,6 @@ header { text-align: center; } - -/* -#search .datasets:empty { - background: url("sad-looking-glass.svg"); - height: 7rem; - width: 7rem; - padding: var(--pad-main); -} - - */ - - .hidden { display: none; } @@ -103,10 +92,6 @@ header { gap: 1rem; } - - - - @container (width < 60ch) { .datasets { grid-template-columns: 1fr; @@ -133,7 +118,7 @@ header { gap: .5em; } /* Buttons */ -.upvote-btn, .downvote-btn, #search-btn, #filter-btn, #sort-btn { +.upvote-btn, .downvote-btn, #search-btn, #filter-btn, #sort-btn, #reset-tools-btn { background: var(--icon-url) no-repeat; background-size: contain; border: none; @@ -163,6 +148,11 @@ header { --icon-size: 1rem; } +#reset-tools-btn { + --icon-url: url(reset.svg); + --icon-size: 1rem; +} + #sort-btn { --icon-url: url(sort.svg); --icon-size: 1rem; diff --git a/src/main/resources/static/main.js b/src/main/resources/static/main.js index 65c62d6..77af7e6 100644 --- a/src/main/resources/static/main.js +++ b/src/main/resources/static/main.js @@ -1,4 +1,5 @@ -import { fetchQuery } from "./contentUtility.js"; +import {fetchQuery} from "./contentUtility.js"; +import Dataset from "./dataset.js"; const apiEndpoint = "/api/v1/datasets"; const baseURL = location.origin; @@ -15,6 +16,7 @@ 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"); @@ -32,33 +34,39 @@ addButton.addEventListener("click", () => { filterButton.addEventListener("change", () => { const filterString = filterButton.value; - filter(filterString); + if (filterString !== filterButton.querySelector("#default-filter").value) { + fetchQuery(createQuery()); + } }); searchButton.addEventListener("click", () => { - const searchString = searchBar.value; - search(searchString); + fetchQuery(createQuery()); + }); searchBar.addEventListener("input", () => { updateSections(); clearTimeout(searchBarTimeout); searchBarTimeout = setTimeout(() => { - const searchString = searchBar.value; - search(searchString); + fetchQuery(createQuery()); }, searchDelay); }); searchBar.addEventListener('keypress', function (e) { if (e.key === 'Enter') { - const searchString = searchBar.value; - search(searchString); + fetchQuery(createQuery()); } -}) +}); sortButton.addEventListener("change", () => { - const sortString = sortButton.value; - sort(sortString); + fetchQuery(createQuery()); +}); + +resetButton.addEventListener("click", () => { + searchBar.value = ""; + filterButton.value = filterButton.querySelector("#default-filter").value; + sortButton.value = sortButton.querySelector("#default-sort").value; + updateSections(); }); // Consider moving this to datasets.js completely @@ -81,39 +89,47 @@ for (const downvoteButton of downvoteButtons) { // functions of the main page function navigateToAdd() { - //TODO: url to add page not yet implemented, add here window.location.href = "/add"; } -function filter(filterString) { - filterString = filterString.toUpperCase(); - let fetchURL = new URL(apiEndpoint, baseURL); - fetchURL.searchParams.append("type", filterString); - fetchURL.searchParams.append("size", defaultPagingValue); - console.log(fetchURL); // TODO: remove - fetchQuery(fetchURL); -} - -function search(searchString) { - let fetchURL = new URL(apiEndpoint + "/search", baseURL); - fetchURL.searchParams.append("search", searchString.length === 0 ? "%" : searchString); - - console.log(fetchURL); // TODO: remove - fetchQuery(fetchURL); -} - -function sort(sortString) { - let query = sortString.toLowerCase().split(" "); - if (query[1] === "a-z" || query[1] === "↑" || query[1] === "oldest-newest") { - query[1] = "asc"; +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 { - query[1] = "desc"; + return ["category", filterString]; } - let fetchURL = new URL(apiEndpoint, baseURL); - fetchURL.searchParams.append("sort", query[0]); - fetchURL.searchParams.append("direction", query[1]); - console.log(fetchURL); // TODO: remove - fetchQuery(fetchURL); +} + +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(apiEndpoint + "/search", baseURL); + 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; } export function vote(entryID, up) { @@ -121,41 +137,86 @@ export function vote(entryID, up) { `${apiEndpoint}/id/${entryID}/${up ? "up" : "down"}vote`, baseURL, ); - console.log(fetchURL); // TODO: remove fetch(fetchURL, { - method: "PUT", //mode: 'no-cors' + method: "PUT", headers: { 'Content-Type': 'application/json', - // Add other headers as needed - }, - }); - /*.then(resp => resp.json()) // TODO: wait for backend + }}) + .then(resp => resp.json()) .then((data) => { - console.log(data.content); // TODO: remove*/ + console.log(data.upvotes); // TODO: remove, check einbauen: data.id === entryID? let dataset = document.querySelector('[data-id= ' + CSS.escape(entryID) + ']') - dataset.querySelector("span").innerText++; // TODO: replace by parsed vote - /*});*/ + dataset.querySelector("span").innerText = data.upvotes; + }); } function incrementPageCount() { lastQuery.currentPage++; } +// updates the page display. If no query is present, the initial page is shown, otherwise the search results. function updateSections() { - if (searchBar.value === "") { + 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" , baseURL); + fetch(fetchURL) + .then(resp => resp.json()) + .then((data) => { + for (let i = 0; i < data.length; i++) { + let category = data[i].toLowerCase(); + category = category.charAt(0).toUpperCase() + category.slice(1); + document.getElementById("other-categories").appendChild(new Option(category)); + } + }); +} + +// fetches entries for the initial page +function fetchInitialEntries() { + let recentsQueryURL = new URL(apiEndpoint + "/search", baseURL); + recentsQueryURL.searchParams.append("sort", "date"); + recentsQueryURL.searchParams.append("direction", "desc"); + recentsQueryURL.searchParams.append("size", "6"); + fetch(recentsQueryURL) + .then(resp => resp.json()) + .then((data) => { + const datasets = data.content.map(dataset => new Dataset(dataset)); + for (const dataset of datasets) { + document.querySelector("#recents .datasets").appendChild(dataset.createDatasetHTMLElement()); + } + }); + + let topVotedQueryURL = new URL(apiEndpoint + "/search", baseURL); + topVotedQueryURL.searchParams.append("sort", "upvotes"); + topVotedQueryURL.searchParams.append("direction", "desc"); + topVotedQueryURL.searchParams.append("size", "1"); + fetch(topVotedQueryURL) + .then(resp => resp.json()) + .then((data) => { + document.querySelector("#top .datasets") + .appendChild(new Dataset(data.content[0]).createDatasetHTMLElement()); + }); +} + window.onload = function () { + fetchCategories(); + fetchInitialEntries(); updateSections(); if (searchBar.value !== "") { - search(searchBar.value); + fetchQuery(createQuery()); } } diff --git a/src/main/resources/static/reset.svg b/src/main/resources/static/reset.svg new file mode 100644 index 0000000..6915802 --- /dev/null +++ b/src/main/resources/static/reset.svg @@ -0,0 +1,52 @@ + + + + diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index a16f045..23ee989 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -32,8 +32,9 @@
+
@@ -61,84 +62,11 @@

Recently added:

Most Liked: