Merge branch '22-integrate-api-and-frontend' into 7-add-page-to-view-dataset-api
This commit is contained in:
commit
922dfdd26d
4
pom.xml
4
pom.xml
@ -52,8 +52,8 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.hsqldb</groupId>
|
<groupId>com.h2database</groupId>
|
||||||
<artifactId>hsqldb</artifactId>
|
<artifactId>h2</artifactId>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
package de.uni_passau.fim.PADAS.group3.DataDash.model;
|
package de.uni_passau.fim.PADAS.group3.DataDash.Dataset;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import de.uni_passau.fim.PADAS.group3.DataDash.category.Category;
|
||||||
|
|
||||||
import java.sql.Date;
|
import java.sql.Date;
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
@ -11,6 +16,7 @@ import jakarta.persistence.Enumerated;
|
|||||||
import jakarta.persistence.GeneratedValue;
|
import jakarta.persistence.GeneratedValue;
|
||||||
import jakarta.persistence.GenerationType;
|
import jakarta.persistence.GenerationType;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.ManyToOne;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
public class Dataset {
|
public class Dataset {
|
||||||
@ -39,10 +45,15 @@ public class Dataset {
|
|||||||
private int upvotes;
|
private int upvotes;
|
||||||
|
|
||||||
private URL url;
|
private URL url;
|
||||||
@Enumerated(EnumType.STRING)
|
|
||||||
|
private String licence;
|
||||||
|
|
||||||
|
private static final List<String> sortable = Arrays.asList("author", "title", "upvotes", "date");
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
private Category categorie;
|
private Category categorie;
|
||||||
|
|
||||||
public Dataset(String title, String abst, String description, String author, URL url, Category categories, Type type) {
|
public Dataset(String title, String abst, String description, String author, URL url, Category categories, Type type, String licence) {
|
||||||
|
|
||||||
this.raiting = 0;
|
this.raiting = 0;
|
||||||
this.votes = 0;
|
this.votes = 0;
|
||||||
@ -55,6 +66,7 @@ public class Dataset {
|
|||||||
setCategorie(categories);
|
setCategorie(categories);
|
||||||
setType(type);
|
setType(type);
|
||||||
setUrl(url);
|
setUrl(url);
|
||||||
|
setLicence(licence);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dataset() {
|
public Dataset() {
|
||||||
@ -109,6 +121,14 @@ public class Dataset {
|
|||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getLicence() {
|
||||||
|
return licence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<String> getSort() {
|
||||||
|
return sortable;
|
||||||
|
}
|
||||||
|
|
||||||
public void setAbst(String abst) {
|
public void setAbst(String abst) {
|
||||||
this.abst = abst.substring(0, Math.min(abst.length(), 100));
|
this.abst = abst.substring(0, Math.min(abst.length(), 100));
|
||||||
}
|
}
|
||||||
@ -153,4 +173,8 @@ public class Dataset {
|
|||||||
upvotes--;
|
upvotes--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setLicence(String licence) {
|
||||||
|
this.licence = licence;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,123 @@
|
|||||||
|
package de.uni_passau.fim.PADAS.group3.DataDash.Dataset;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.web.config.EnableSpringDataWebSupport;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
|
||||||
|
import de.uni_passau.fim.PADAS.group3.DataDash.category.Category;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/datasets")
|
||||||
|
@EnableSpringDataWebSupport
|
||||||
|
public class DatasetController {
|
||||||
|
@Autowired
|
||||||
|
private DatasetService datasetService;
|
||||||
|
|
||||||
|
@GetMapping("/id/{id}")
|
||||||
|
public ResponseEntity<Dataset> getDatasetById(@PathVariable("id") UUID id) {
|
||||||
|
Dataset d = datasetService.getDatasetById(id);
|
||||||
|
if (d == null) {
|
||||||
|
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||||
|
}
|
||||||
|
return new ResponseEntity<>(d, HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResponseStatus(HttpStatus.CREATED)
|
||||||
|
@PostMapping
|
||||||
|
public Dataset createDataset(@RequestBody Dataset dataset) {
|
||||||
|
return datasetService.addDataset(dataset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/id/{id}")
|
||||||
|
public ResponseEntity<?> deleteDataset(@PathVariable("id") UUID id) {
|
||||||
|
if (datasetService.getDatasetById(id) == null) {
|
||||||
|
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||||
|
}
|
||||||
|
datasetService.deleteDataset(id);
|
||||||
|
return new ResponseEntity<>(HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/id/{id}/upvote")
|
||||||
|
public ResponseEntity<Dataset> upvote(@PathVariable("id") UUID id) {
|
||||||
|
if (datasetService.getDatasetById(id) == null) {
|
||||||
|
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
datasetService.upvoteDataset(id);
|
||||||
|
return new ResponseEntity<>(datasetService.getDatasetById(id), HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/id/{id}/downvote")
|
||||||
|
public ResponseEntity<Dataset> downvote(@PathVariable("id") UUID id) {
|
||||||
|
if (datasetService.getDatasetById(id) == null) {
|
||||||
|
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||||
|
}
|
||||||
|
datasetService.downvoteDataset(id);
|
||||||
|
return new ResponseEntity<>(datasetService.getDatasetById(id), HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/id/{id}/stars")
|
||||||
|
public ResponseEntity<Dataset> postMethodName(@PathVariable("id") UUID id,
|
||||||
|
@RequestParam("stars") int stars) {
|
||||||
|
if (datasetService.getDatasetById(id) == null) {
|
||||||
|
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||||
|
}
|
||||||
|
if (!(stars > 0 && stars < 6)) {
|
||||||
|
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
|
datasetService.voteDataset(id, stars);
|
||||||
|
return new ResponseEntity<>(datasetService.getDatasetById(id), HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public Page<Dataset> getDatasetsByDateAfter(@RequestParam(value = "author", required = false) String author,
|
||||||
|
@RequestParam(value = "title", required = false) String title,
|
||||||
|
@RequestParam(value = "description", required = false) String description,
|
||||||
|
@RequestParam(value = "abst", required = false) String abst,
|
||||||
|
@RequestParam(value = "type", required = false) Type type,
|
||||||
|
@RequestParam(value = "min-rating", required = false) Float rating,
|
||||||
|
@RequestParam(value = "page", required = false, defaultValue = "0") int page,
|
||||||
|
@RequestParam(value = "size", required = false, defaultValue = "20") int size,
|
||||||
|
@RequestParam(value = "sort", required = false, defaultValue = "upvotes") String sort,
|
||||||
|
@RequestParam(value = "direction", required = false, defaultValue = "desc") String direction,
|
||||||
|
@RequestParam(value = "category", required = false) Category category) {
|
||||||
|
Pageable pageable = PageRequest.of(page, size,
|
||||||
|
Sort.by(Sort.Direction.fromString(direction), sort));
|
||||||
|
return datasetService.getDatasetsByOptionalCriteria(title, description, author, abst, type, rating, category,
|
||||||
|
pageable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/search")
|
||||||
|
public ResponseEntity<Page<Dataset>> search(
|
||||||
|
@RequestParam(value = "search", required = false, defaultValue = "%") String search,
|
||||||
|
@RequestParam(value = "page", required = false, defaultValue = "0") int page,
|
||||||
|
@RequestParam(value = "size", required = false, defaultValue = "20") int size,
|
||||||
|
@RequestParam(value = "sort", required = false, defaultValue = "upvotes") String sort,
|
||||||
|
@RequestParam(value = "direction", required = false, defaultValue = "desc") String direction,
|
||||||
|
@RequestParam(value = "category", required = false, defaultValue = "%") String category,
|
||||||
|
@RequestParam(value = "type", required = false, defaultValue = "%") String type) {
|
||||||
|
Pageable pageable = null;
|
||||||
|
if (!Dataset.getSort().contains(sort))
|
||||||
|
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
|
||||||
|
try {
|
||||||
|
pageable = PageRequest.of(page, size,
|
||||||
|
Sort.by(Sort.Direction.fromString(direction), sort));
|
||||||
|
} catch (Exception e) {
|
||||||
|
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ResponseEntity<>(datasetService.searchByOptionalCriteria(search, category, type, pageable),
|
||||||
|
HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package de.uni_passau.fim.PADAS.group3.DataDash.model;
|
package de.uni_passau.fim.PADAS.group3.DataDash.Dataset;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -7,15 +7,20 @@ import java.util.UUID;
|
|||||||
|
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.data.domain.Page;
|
|
||||||
|
|
||||||
|
import de.uni_passau.fim.PADAS.group3.DataDash.category.Category;
|
||||||
|
import de.uni_passau.fim.PADAS.group3.DataDash.category.CategoryRepository;
|
||||||
|
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class DatasetService {
|
public class DatasetService {
|
||||||
private dataRepository datasetRepository;
|
private dataRepository datasetRepository;
|
||||||
|
private CategoryRepository categoryRepository;
|
||||||
|
|
||||||
public DatasetService(dataRepository datasetRepository) {
|
public DatasetService(dataRepository datasetRepository, CategoryRepository categoryRepository) {
|
||||||
this.datasetRepository = datasetRepository;
|
this.datasetRepository = datasetRepository;
|
||||||
|
this.categoryRepository = categoryRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Dataset> getAllDatasets() {
|
public List<Dataset> getAllDatasets() {
|
||||||
@ -26,9 +31,9 @@ public class DatasetService {
|
|||||||
return datasetRepository.getDatasetById(id);
|
return datasetRepository.getDatasetById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addDataset(Dataset dataset) {
|
public Dataset addDataset(Dataset dataset) {
|
||||||
dataset.setDate(LocalDate.now());
|
dataset.setDate(LocalDate.now());
|
||||||
datasetRepository.save(dataset);
|
return datasetRepository.save(dataset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateDatasetTitle(UUID id, String title) {
|
public void updateDatasetTitle(UUID id, String title) {
|
||||||
@ -89,15 +94,22 @@ public class DatasetService {
|
|||||||
public Page<Dataset> getDatasetsByOptionalCriteria(String title, String description, String author, String abst,
|
public Page<Dataset> getDatasetsByOptionalCriteria(String title, String description, String author, String abst,
|
||||||
Type type, Float raiting, Category category, Pageable pageable) {
|
Type type, Float raiting, Category category, Pageable pageable) {
|
||||||
return datasetRepository.findByOptionalCriteria(Optional.ofNullable(title), Optional.ofNullable(description),
|
return datasetRepository.findByOptionalCriteria(Optional.ofNullable(title), Optional.ofNullable(description),
|
||||||
Optional.ofNullable(author), Optional.ofNullable(abst), Optional.ofNullable(type), Optional.ofNullable(category),
|
Optional.ofNullable(author), Optional.ofNullable(abst), Optional.ofNullable(type),
|
||||||
|
Optional.ofNullable(category),
|
||||||
Optional.ofNullable(raiting), pageable);
|
Optional.ofNullable(raiting), pageable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Page<Dataset> searchByOptionalCriteria(String search, String categories, String type, Pageable pageable) {
|
public Page<Dataset> searchByOptionalCriteria(String search, String categories, String type, Pageable pageable) {
|
||||||
//TODO: make it not Crash
|
Category category = categories.equals("%") ? null
|
||||||
Category category = categories.equals("%") ? null : Category.valueOf(categories);
|
: categoryRepository.getCategoryById(UUID.fromString(categories));
|
||||||
Type t = type.equals("%") ? null : Type.valueOf(type);
|
Type t = type.equals("%") ? null : Type.valueOf(type);
|
||||||
|
|
||||||
return datasetRepository.searchByOptionalCriteria(Optional.ofNullable(search), Optional.ofNullable(category), Optional.ofNullable(t),pageable);
|
if (category == null) {
|
||||||
|
return datasetRepository.searchByOptionalCriteria(Optional.ofNullable(search), Optional.ofNullable(t),
|
||||||
|
pageable);
|
||||||
|
}
|
||||||
|
return datasetRepository.searchByOptionalCriteriaWithCategory(Optional.ofNullable(search), category,
|
||||||
|
Optional.ofNullable(t), pageable);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package de.uni_passau.fim.PADAS.group3.DataDash.Dataset;
|
||||||
|
|
||||||
|
public enum Type {
|
||||||
|
DATASET,
|
||||||
|
API
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package de.uni_passau.fim.PADAS.group3.DataDash.model;
|
package de.uni_passau.fim.PADAS.group3.DataDash.Dataset;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@ -11,6 +11,8 @@ import org.springframework.data.jpa.repository.JpaRepository;
|
|||||||
import org.springframework.data.jpa.repository.Query;
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.data.repository.query.Param;
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
|
import de.uni_passau.fim.PADAS.group3.DataDash.category.Category;
|
||||||
|
|
||||||
public interface dataRepository extends JpaRepository<Dataset, UUID> {
|
public interface dataRepository extends JpaRepository<Dataset, UUID> {
|
||||||
|
|
||||||
Dataset getDatasetById(UUID id);
|
Dataset getDatasetById(UUID id);
|
||||||
@ -65,10 +67,19 @@ public interface dataRepository extends JpaRepository<Dataset, UUID> {
|
|||||||
"((LOWER(d.title) LIKE LOWER(:search)) OR " +
|
"((LOWER(d.title) LIKE LOWER(:search)) OR " +
|
||||||
"(LOWER(d.description) LIKE LOWER(:search)) OR " +
|
"(LOWER(d.description) LIKE LOWER(:search)) OR " +
|
||||||
"(LOWER(d.author) LIKE LOWER(:search))) AND" +
|
"(LOWER(d.author) LIKE LOWER(:search))) AND" +
|
||||||
"(:categorie IS NULL OR d.categorie = :categorie) AND" +
|
"(d.categorie = :categorie) AND" +
|
||||||
|
"(:type IS NULL OR d.type = :type)")
|
||||||
|
Page<Dataset> searchByOptionalCriteriaWithCategory(@Param("search") Optional<String> search,
|
||||||
|
@Param("categorie") Category categories,
|
||||||
|
@Param("type") Optional<Type> type,
|
||||||
|
Pageable pageable);
|
||||||
|
|
||||||
|
@Query("SELECT d FROM Dataset d WHERE " +
|
||||||
|
"((LOWER(d.title) LIKE LOWER(:search)) OR " +
|
||||||
|
"(LOWER(d.description) LIKE LOWER(:search)) OR " +
|
||||||
|
"(LOWER(d.author) LIKE LOWER(:search))) AND" +
|
||||||
"(:type IS NULL OR d.type = :type)")
|
"(:type IS NULL OR d.type = :type)")
|
||||||
Page<Dataset> searchByOptionalCriteria(@Param("search") Optional<String> search,
|
Page<Dataset> searchByOptionalCriteria(@Param("search") Optional<String> search,
|
||||||
@Param("categorie") Optional<Category> categories,
|
|
||||||
@Param("type") Optional<Type> type,
|
@Param("type") Optional<Type> type,
|
||||||
Pageable pageable);
|
Pageable pageable);
|
||||||
}
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package de.uni_passau.fim.PADAS.group3.DataDash.category;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
|
||||||
|
import de.uni_passau.fim.PADAS.group3.DataDash.Dataset.Dataset;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.OneToMany;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Category {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
@OneToMany(mappedBy = "categorie")
|
||||||
|
private List<Dataset> datasets;
|
||||||
|
|
||||||
|
public Category(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Category() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
package de.uni_passau.fim.PADAS.group3.DataDash.category;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/categories")
|
||||||
|
public class CategoryController {
|
||||||
|
@Autowired
|
||||||
|
private CategoryService categoryService;
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public List<CategoryDto> getMethodName() {
|
||||||
|
return categoryService.getAllCategories() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/id/{id}")
|
||||||
|
public ResponseEntity<?> fetchCategoryById(@PathVariable("id") UUID id) {
|
||||||
|
CategoryDto category = categoryService.getCategoryById(id);
|
||||||
|
if(category == null) {
|
||||||
|
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||||
|
}
|
||||||
|
return new ResponseEntity<>(category, HttpStatus.OK);
|
||||||
|
}
|
||||||
|
@ResponseStatus(HttpStatus.CREATED)
|
||||||
|
@PostMapping
|
||||||
|
public void createCategory(@RequestBody CategoryDto dto) {
|
||||||
|
categoryService.addCategory(dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package de.uni_passau.fim.PADAS.group3.DataDash.category;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class CategoryDto {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
public CategoryDto() {
|
||||||
|
}
|
||||||
|
|
||||||
|
CategoryDto(String name, UUID id) {
|
||||||
|
this.name = name;
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
|||||||
|
package de.uni_passau.fim.PADAS.group3.DataDash.category;
|
||||||
|
|
||||||
|
public class CategoryDtoMapper {
|
||||||
|
|
||||||
|
public static CategoryDto toDto(Category category) {
|
||||||
|
CategoryDto dto = new CategoryDto(category.getName(), category.getId());
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package de.uni_passau.fim.PADAS.group3.DataDash.category;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
|
||||||
|
public interface CategoryRepository extends JpaRepository<Category, UUID>{
|
||||||
|
|
||||||
|
Category getCategoryById(UUID id);
|
||||||
|
|
||||||
|
@SuppressWarnings("null")
|
||||||
|
List<Category> findAll();
|
||||||
|
List<Category> findByName(String name);
|
||||||
|
@SuppressWarnings("null")
|
||||||
|
Optional<Category> findById(UUID id);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package de.uni_passau.fim.PADAS.group3.DataDash.category;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class CategoryService {
|
||||||
|
private CategoryRepository categoryRepository;
|
||||||
|
|
||||||
|
public CategoryService(CategoryRepository categoryRepository) {
|
||||||
|
this.categoryRepository = categoryRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCategory(CategoryDto category) {
|
||||||
|
Category cat = new Category(category.getName());
|
||||||
|
categoryRepository.save(cat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<CategoryDto> getAllCategories() {
|
||||||
|
List<Category> tmp = categoryRepository.findAll();
|
||||||
|
List<CategoryDto> s = tmp.stream().map(CategoryDtoMapper::toDto).toList();
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CategoryDto getCategoryById(UUID id) {
|
||||||
|
Category c = categoryRepository.getCategoryById(id);
|
||||||
|
if (c == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return CategoryDtoMapper.toDto(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,18 +0,0 @@
|
|||||||
package de.uni_passau.fim.PADAS.group3.DataDash.controler;
|
|
||||||
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import de.uni_passau.fim.PADAS.group3.DataDash.model.Category;
|
|
||||||
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/v1/categories")
|
|
||||||
public class CategoryController {
|
|
||||||
@GetMapping
|
|
||||||
public Category[] getMethodName() {
|
|
||||||
return Category.values();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,107 +0,0 @@
|
|||||||
package de.uni_passau.fim.PADAS.group3.DataDash.controler;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.data.domain.Page;
|
|
||||||
import org.springframework.data.domain.PageRequest;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
import de.uni_passau.fim.PADAS.group3.DataDash.model.Category;
|
|
||||||
import de.uni_passau.fim.PADAS.group3.DataDash.model.Dataset;
|
|
||||||
import de.uni_passau.fim.PADAS.group3.DataDash.model.DatasetService;
|
|
||||||
import de.uni_passau.fim.PADAS.group3.DataDash.model.Type;
|
|
||||||
import org.springframework.data.domain.Pageable;
|
|
||||||
import org.springframework.data.web.config.EnableSpringDataWebSupport;
|
|
||||||
import org.springframework.data.domain.Sort;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/v1/datasets")
|
|
||||||
@EnableSpringDataWebSupport
|
|
||||||
public class DatasetController {
|
|
||||||
@Autowired
|
|
||||||
private DatasetService datasetService;
|
|
||||||
|
|
||||||
// @GetMapping
|
|
||||||
// public List<Dataset> getAllDatasets() {
|
|
||||||
// return datasetService.getAllDatasets();
|
|
||||||
// }
|
|
||||||
|
|
||||||
@GetMapping("/id/{id}")
|
|
||||||
public Dataset getDatasetById(@PathVariable("id") UUID id) {
|
|
||||||
return datasetService.getDatasetById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping
|
|
||||||
public Dataset createDataset(@RequestBody Dataset dataset) {
|
|
||||||
datasetService.addDataset(dataset);
|
|
||||||
// TODO: figure out what the fuck i need to do here
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// @PutMapping("/{id}")
|
|
||||||
// public Dataset updateDataset(@PathVariable("id") Long id, @RequestBody
|
|
||||||
// Dataset dataset) {
|
|
||||||
// return datasetService.updateDataset(id, dataset);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
|
|
||||||
@DeleteMapping("/id/{id}")
|
|
||||||
public void deleteDataset(@PathVariable("id") UUID id) {
|
|
||||||
datasetService.deleteDataset(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PutMapping("/id/{id}/upvote")
|
|
||||||
public Dataset upvote(@PathVariable("id") UUID id) {
|
|
||||||
datasetService.upvoteDataset(id);
|
|
||||||
return datasetService.getDatasetById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PutMapping("/id/{id}/downvote")
|
|
||||||
public Dataset downvote(@PathVariable("id") UUID id) {
|
|
||||||
datasetService.downvoteDataset(id);
|
|
||||||
return getDatasetById(id); // new ResponseEntity<>(null, HttpStatus.OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PutMapping("/id/{id}/stars")
|
|
||||||
public Dataset postMethodName(@PathVariable("id") UUID id,
|
|
||||||
@RequestParam("stars") int stars) {
|
|
||||||
if (stars > 0 && stars < 6) {
|
|
||||||
datasetService.voteDataset(id, stars);
|
|
||||||
}
|
|
||||||
return datasetService.getDatasetById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping
|
|
||||||
public Page<Dataset> getDatasetsByDateAfter(@RequestParam(value = "author", required = false) String author,
|
|
||||||
@RequestParam(value = "title", required = false) String title,
|
|
||||||
@RequestParam(value = "description", required = false) String description,
|
|
||||||
@RequestParam(value = "abst", required = false) String abst,
|
|
||||||
@RequestParam(value = "type", required = false) Type type,
|
|
||||||
@RequestParam(value = "min-rating", required = false) Float rating,
|
|
||||||
@RequestParam(value = "page", required = false, defaultValue = "0") int page,
|
|
||||||
@RequestParam(value = "size", required = false, defaultValue = "20") int size,
|
|
||||||
@RequestParam(value = "sort", required = false, defaultValue = "upvotes") String sort,
|
|
||||||
@RequestParam(value = "direction", required = false, defaultValue = "desc") String direction,
|
|
||||||
@RequestParam(value = "category", required = false) Category category) {
|
|
||||||
Pageable pageable = PageRequest.of(page, size,
|
|
||||||
Sort.by(direction.equals("asc") ? Sort.Direction.ASC : Sort.Direction.DESC, sort));
|
|
||||||
return datasetService.getDatasetsByOptionalCriteria(title, description, author, abst, type, rating, category,pageable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/search")
|
|
||||||
public Page<Dataset> search(@RequestParam(value = "search", required = false, defaultValue = "%") String search,
|
|
||||||
@RequestParam(value = "page", required = false, defaultValue = "0") int page,
|
|
||||||
@RequestParam(value = "size", required = false, defaultValue = "20") int size,
|
|
||||||
@RequestParam(value = "sort", required = false, defaultValue = "upvotes") String sort,
|
|
||||||
@RequestParam(value = "direction", required = false, defaultValue = "desc") String direction,
|
|
||||||
@RequestParam(value = "category", required = false, defaultValue = "%") String category,
|
|
||||||
@RequestParam(value = "type", required = false, defaultValue = "%") String type){
|
|
||||||
Pageable pageable = PageRequest.of(page, size,
|
|
||||||
Sort.by(direction.equals("asc") ? Sort.Direction.ASC : Sort.Direction.DESC, sort));
|
|
||||||
return datasetService.searchByOptionalCriteria(search, category, type, pageable);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
package de.uni_passau.fim.PADAS.group3.DataDash.controler;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
public class PageController {
|
|
||||||
@GetMapping("/add")
|
|
||||||
public String getAddPage() {
|
|
||||||
return "add";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
package de.uni_passau.fim.PADAS.group3.DataDash.model;
|
|
||||||
|
|
||||||
public enum Category {
|
|
||||||
HEALTH,
|
|
||||||
ENVIRONMENT,
|
|
||||||
ECONOMY,
|
|
||||||
POLITICS,
|
|
||||||
TECHNOLOGY,
|
|
||||||
SPORTS,
|
|
||||||
SCIENCE,
|
|
||||||
CULTURE,
|
|
||||||
EDUCATION,
|
|
||||||
OTHER
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
package de.uni_passau.fim.PADAS.group3.DataDash.model;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.boot.CommandLineRunner;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
public class LoadDummyDatabase {
|
|
||||||
|
|
||||||
private static final org.slf4j.Logger log = LoggerFactory.getLogger(LoadDummyDatabase.class);
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
CommandLineRunner initDatabase(dataRepository repository) {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return args -> {
|
|
||||||
for (int i = 0; i < 100; i++) {
|
|
||||||
Dataset dataset = new Dataset("Title" + i, "Abst" + i, "Description" + i, "Author" + i,null, Category.EDUCATION, Type.API);
|
|
||||||
for (int j = 0; j < new Random().nextInt(50); j++) {
|
|
||||||
dataset.upvote();
|
|
||||||
}
|
|
||||||
log.info("Preloading" + repository.save(dataset));
|
|
||||||
}
|
|
||||||
List<Dataset> s = repository.findByTitleLike("%Title%");
|
|
||||||
log.info("Found Entry with ID: " + s.get(1).getId());};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
package de.uni_passau.fim.PADAS.group3.DataDash.model;
|
|
||||||
|
|
||||||
public enum Type {
|
|
||||||
DATASET,
|
|
||||||
API
|
|
||||||
}
|
|
@ -1 +1,14 @@
|
|||||||
spring.application.name=DataDash
|
spring.application.name=DataDash
|
||||||
|
|
||||||
|
# Datasource configuration
|
||||||
|
spring.datasource.url=jdbc:h2:mem:studentcoursedb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
|
||||||
|
spring.datasource.driverClassName=org.h2.Driver
|
||||||
|
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
|
||||||
|
spring.sql.init.mode=always
|
||||||
|
spring.jpa.hibernate.ddl-auto=none
|
||||||
|
|
||||||
|
# Uncomment for web console
|
||||||
|
#spring.h2.console.enabled=true
|
||||||
|
#spring.h2.console.path=/h2-console
|
||||||
|
#spring.datasource.username=sa
|
||||||
|
#spring.datasource.password=pwd
|
30
src/main/resources/data.sql
Normal file
30
src/main/resources/data.sql
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
-- Insert sample data into category
|
||||||
|
INSERT INTO category (id, name) VALUES
|
||||||
|
('123e4567-e89b-12d3-a456-426614174003', 'Business'),
|
||||||
|
('123e4567-e89b-12d3-a456-426614174004', 'Education'),
|
||||||
|
('123e4567-e89b-12d3-a456-426614174005', 'Sports'),
|
||||||
|
('123e4567-e89b-12d3-a456-426614174006', 'Entertainment'),
|
||||||
|
('123e4567-e89b-12d3-a456-426614174007', 'Art'),
|
||||||
|
('123e4567-e89b-12d3-a456-426614174000', 'Science'),
|
||||||
|
('123e4567-e89b-12d3-a456-426614174001', 'Technology'),
|
||||||
|
('123e4567-e89b-12d3-a456-426614174002', 'Health');
|
||||||
|
|
||||||
|
-- Insert sample data into dataset
|
||||||
|
INSERT INTO dataset (date, raiting, upvotes, votes, categorie_id, id, abst, author, description, title, url, type, licence) VALUES
|
||||||
|
('2023-01-01', 4.5, 100, 120, '123e4567-e89b-12d3-a456-426614174000', '123e4567-e89b-12d3-a456-426614174100', 'Abstract 1', 'Author 1', 'Description 1', 'Title 1', 'http://example.com/1', 'API', 'MIT'),
|
||||||
|
('2023-01-02', 4.7, 150, 170, '123e4567-e89b-12d3-a456-426614174001', '123e4567-e89b-12d3-a456-426614174101', 'Abstract 2', 'Author 2', 'Description 2', 'Title 2', 'http://example.com/2', 'DATASET', 'MIT'),
|
||||||
|
('2023-01-03', 4.9, 200, 220, '123e4567-e89b-12d3-a456-426614174002', '123e4567-e89b-12d3-a456-426614174102', 'Abstract 3', 'Author 3', 'Description 3', 'Title 3', 'http://example.com/3', 'API', 'MIT'),
|
||||||
|
('2023-01-04', 4.2, 80, 100, '123e4567-e89b-12d3-a456-426614174003', '123e4567-e89b-12d3-a456-426614174103', 'Abstract 4', 'Author 4', 'Description 4', 'Title 4', 'http://example.com/4', 'DATASET', 'MIT'),
|
||||||
|
('2023-01-05', 4.6, 120, 140, '123e4567-e89b-12d3-a456-426614174004', '123e4567-e89b-12d3-a456-426614174104', 'Abstract 5', 'Author 5', 'Description 5', 'Title 5', 'http://example.com/5', 'API', 'MIT');
|
||||||
|
-- Insert 10 more sample data into dataset
|
||||||
|
INSERT INTO dataset (date, raiting, upvotes, votes, categorie_id, id, abst, author, description, title, url, type, licence) VALUES
|
||||||
|
('2023-01-06', 4.8, 180, 200, '123e4567-e89b-12d3-a456-426614174005', '123e4567-e89b-12d3-a456-426614174105', 'Abstract 6', 'Author 6', 'Description 6', 'Title 6', 'http://example.com/6', 'API', 'MIT'),
|
||||||
|
('2023-01-07', 4.3, 90, 110, '123e4567-e89b-12d3-a456-426614174006', '123e4567-e89b-12d3-a456-426614174106', 'Abstract 7', 'Author 7', 'Description 7', 'Title 7', 'http://example.com/7', 'DATASET', 'MIT'),
|
||||||
|
('2023-01-08', 4.7, 150, 170, '123e4567-e89b-12d3-a456-426614174007', '123e4567-e89b-12d3-a456-426614174107', 'Abstract 8', 'Author 8', 'Description 8', 'Title 8', 'http://example.com/8', 'API', 'MIT'),
|
||||||
|
('2023-01-09', 4.9, 200, 220, '123e4567-e89b-12d3-a456-426614174000', '123e4567-e89b-12d3-a456-426614174108', 'Abstract 9', 'Author 9', 'Description 9', 'Title 9', 'http://example.com/9', 'DATASET', 'MIT'),
|
||||||
|
('2023-01-10', 4.2, 80, 100, '123e4567-e89b-12d3-a456-426614174001', '123e4567-e89b-12d3-a456-426614174109', 'Abstract 10', 'Author 10', 'Description 10', 'Title 10', 'http://example.com/10', 'API', 'MIT'),
|
||||||
|
('2023-11-11', 4.6, 120, 140, '123e4567-e89b-12d3-a456-426614174002', '123e4567-e89b-12d3-a456-426614174110', 'Abstract 11', 'Author 11', 'Description 11', 'Title 11', 'http://example.com/11', 'DATASET', 'MIT'),
|
||||||
|
('2023-09-12', 4.8, 180, 200, '123e4567-e89b-12d3-a456-426614174003', '123e4567-e89b-12d3-a456-426614174111', 'Abstract 12', 'Author 12', 'Description 12', 'Title 12', 'http://example.com/12', 'API', 'MIT'),
|
||||||
|
('2023-03-13', 4.3, 90, 110, '123e4567-e89b-12d3-a456-426614174004', '123e4567-e89b-12d3-a456-426614174112', 'Abstract 13', 'Author 13', 'Description 13', 'Title 13', 'http://example.com/13', 'DATASET', 'MIT'),
|
||||||
|
('2021-01-14', 4.7, 150, 170, '123e4567-e89b-12d3-a456-426614174005', '123e4567-e89b-12d3-a456-426614174113', 'Abstract 14', 'Author 14', 'Description 14', 'Title 14', 'http://example.com/14', 'API', 'MIT'),
|
||||||
|
('2024-01-15', 4.9, 200, 220, '123e4567-e89b-12d3-a456-426614174006', '123e4567-e89b-12d3-a456-426614174114', 'Abstract 15', 'Author 15', 'Description 15', 'Title 15', 'http://example.com/15', 'DATASET', 'MIT');
|
7
src/main/resources/schema.sql
Normal file
7
src/main/resources/schema.sql
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
DROP TABLE IF EXISTS dataset;
|
||||||
|
DROP TABLE IF EXISTS category;
|
||||||
|
|
||||||
|
|
||||||
|
create table category (id uuid not null, name varchar(255), primary key (id));
|
||||||
|
create table dataset (date date, raiting float(24) not null, upvotes integer not null, votes integer not null, categorie_id uuid, id uuid not null, abst varchar(255), author varchar(255), description varchar(255), title varchar(255), url varchar(255), type enum ('API','DATASET'), licence varchar(255), primary key (id));
|
||||||
|
alter table if exists dataset add constraint FKq6qwq6u473f89h71s7rf97ruy foreign key (categorie_id) references category;
|
@ -1,25 +1,38 @@
|
|||||||
import {searchBarTimeout, searchSection} from "./main.js"
|
// TODO consider renaming this to "searchUtility.js"
|
||||||
|
|
||||||
|
import { searchBarTimeout, searchSection, lastQuery } from "./main.js"
|
||||||
import Dataset from "./dataset.js"
|
import Dataset from "./dataset.js"
|
||||||
|
|
||||||
export function fetchQuery(fetchString) {
|
export async function fetchQuery(fetchString, clearResults) {
|
||||||
clearTimeout(searchBarTimeout);
|
clearTimeout(searchBarTimeout);
|
||||||
fetch(fetchString)
|
const response = await fetch(fetchString);
|
||||||
.then(resp => resp.json())
|
const data = await response.json();
|
||||||
.then((data) => {
|
|
||||||
parseContent(data.content);
|
parseContent(data.content, clearResults);
|
||||||
});
|
lastQuery.totalPages = data.totalPages;
|
||||||
|
if (clearResults) {
|
||||||
|
lastQuery.currentPage = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseContent(content) {
|
function parseContent(content, clearResults) {
|
||||||
|
const nothingFoundElement = searchSection.querySelector("#nothing-found");
|
||||||
|
|
||||||
if (content.length === 0) {
|
if (content.length === 0) {
|
||||||
searchSection.querySelector("#nothing-found ").classList.remove("hidden");
|
nothingFoundElement.classList.remove("hidden");
|
||||||
|
searchSection.querySelector(".datasets").classList.add("hidden");
|
||||||
} else {
|
} else {
|
||||||
searchSection.querySelector("#nothing-found").classList.add("hidden");
|
nothingFoundElement.classList.add("hidden");
|
||||||
const datasets = content.map(dataset => new Dataset(dataset));
|
|
||||||
Array.from(searchSection.querySelectorAll(".datasets .dataset")).forEach(e => e.remove());
|
const datasets = content.map(dataset => Dataset.get(dataset.id) ?? new Dataset(dataset));
|
||||||
|
searchSection.querySelector(".datasets").classList.remove("hidden");
|
||||||
|
if (clearResults) {
|
||||||
|
Array.from(searchSection.querySelectorAll(".datasets .dataset")).forEach(e => e.remove());
|
||||||
|
}
|
||||||
|
|
||||||
for (const dataset of datasets) {
|
for (const dataset of datasets) {
|
||||||
searchSection.querySelector(".datasets").appendChild(dataset.createDatasetHTMLElement());
|
searchSection.querySelector(".datasets")
|
||||||
|
.appendChild(dataset.createDatasetHTMLElement());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { vote } from "./main.js";
|
import { DATASET_ENDPOINT, getBaseURL } from "./main.js";
|
||||||
|
|
||||||
export default class Dataset {
|
export default class Dataset {
|
||||||
|
static #datasets = new Map();
|
||||||
|
|
||||||
#abstract;
|
#abstract;
|
||||||
#author;
|
#author;
|
||||||
#categories;
|
#categories;
|
||||||
@ -13,8 +15,13 @@ export default class Dataset {
|
|||||||
#upvotes;
|
#upvotes;
|
||||||
#url;
|
#url;
|
||||||
#votes;
|
#votes;
|
||||||
|
#elements = [];
|
||||||
|
|
||||||
constructor({abst: shortDescription, author, categories, date, description, id, rating, title, type, upvotes, url, votes}) {
|
static get(id) {
|
||||||
|
return this.#datasets.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor({ abst: shortDescription, author, categories, date, description, id, rating, title, type, upvotes, url, votes }) {
|
||||||
this.#abstract = shortDescription;
|
this.#abstract = shortDescription;
|
||||||
this.#author = author;
|
this.#author = author;
|
||||||
this.#categories = categories;
|
this.#categories = categories;
|
||||||
@ -27,25 +34,179 @@ export default class Dataset {
|
|||||||
this.#upvotes = upvotes;
|
this.#upvotes = upvotes;
|
||||||
this.#url = url;
|
this.#url = url;
|
||||||
this.#votes = votes;
|
this.#votes = votes;
|
||||||
|
|
||||||
|
Dataset.#datasets.set(id, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Getters
|
||||||
|
get abstract() {
|
||||||
|
return this.#abstract;
|
||||||
|
}
|
||||||
|
|
||||||
|
get author() {
|
||||||
|
return this.#author;
|
||||||
|
}
|
||||||
|
|
||||||
|
get categories() {
|
||||||
|
return this.#categories;
|
||||||
|
}
|
||||||
|
|
||||||
|
get date() {
|
||||||
|
return this.#date;
|
||||||
|
}
|
||||||
|
|
||||||
|
get description() {
|
||||||
|
return this.#description;
|
||||||
|
}
|
||||||
|
|
||||||
|
get id() {
|
||||||
|
return this.#id;
|
||||||
|
}
|
||||||
|
|
||||||
|
get rating() {
|
||||||
|
return this.#rating;
|
||||||
|
}
|
||||||
|
|
||||||
|
get title() {
|
||||||
|
return this.#title;
|
||||||
|
}
|
||||||
|
|
||||||
|
get type() {
|
||||||
|
return this.#type;
|
||||||
|
}
|
||||||
|
|
||||||
|
get upvotes() {
|
||||||
|
return this.#upvotes;
|
||||||
|
}
|
||||||
|
|
||||||
|
get url() {
|
||||||
|
return this.#url;
|
||||||
|
}
|
||||||
|
|
||||||
|
get votes() {
|
||||||
|
return this.#votes;
|
||||||
|
}
|
||||||
|
|
||||||
|
get mainElement() {
|
||||||
|
return this.#elements[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
get elements() {
|
||||||
|
return this.#elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main methods
|
||||||
|
|
||||||
|
// Only on main page
|
||||||
createDatasetHTMLElement() {
|
createDatasetHTMLElement() {
|
||||||
let template = document.querySelector("#dataset-template");
|
const clone = this.#createTemplateInstance("dataset-template");
|
||||||
const clone = template.content.cloneNode(true);
|
if (clone == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
clone.querySelector(".dataset").dataset.id = this.#id;
|
clone.querySelector(".dataset").dataset.id = this.#id;
|
||||||
clone.querySelector("h3").innerText = this.#title;
|
clone.querySelector(".dataset-title").innerText = this.#title;
|
||||||
clone.querySelector("p").innerText = this.#description;
|
clone.querySelector(".dataset-description").innerText = this.#description;
|
||||||
clone.querySelector("span").innerText = this.#upvotes;
|
clone.querySelector(".upvote-count").innerText = this.#upvotes;
|
||||||
|
|
||||||
// Event Listeners
|
this.#elements.push(clone.children[0]);
|
||||||
clone.querySelector(".upvote-btn").addEventListener("click", () => {
|
this.#createUpvoteButtons(clone);
|
||||||
vote(this.#id, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
clone.querySelector(".downvote-btn").addEventListener("click", () => {
|
|
||||||
vote(this.#id, false);
|
|
||||||
})
|
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only on details page
|
||||||
|
createUpvoteComponent() {
|
||||||
|
let clone = this.#createTemplateInstance("voting-template")
|
||||||
|
|
||||||
|
clone.querySelector(".upvote-count").innerText = this.#upvotes;
|
||||||
|
|
||||||
|
this.#elements.push(clone.children[0]);
|
||||||
|
this.#createUpvoteButtons(clone);
|
||||||
|
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
#createUpvoteButtons(templateInstance) {
|
||||||
|
if (this.storageGetKey("is-voted", false)) {
|
||||||
|
// The template instance (clone) has to be pushed before this can work
|
||||||
|
this.#disableVoteBtns();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event Listeners
|
||||||
|
templateInstance.querySelector(".upvote-btn").addEventListener("click", () => {
|
||||||
|
this.vote();
|
||||||
|
});
|
||||||
|
|
||||||
|
templateInstance.querySelector(".downvote-btn").addEventListener("click", () => {
|
||||||
|
this.vote(false);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#createTemplateInstance(templateId) {
|
||||||
|
let template = document.getElementById(templateId);
|
||||||
|
if (template == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return template.content.cloneNode(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
isMainElement(element) {
|
||||||
|
return this.#elements.length > 0 && this.#elements[0].isEqualNode(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
async vote(up = true) {
|
||||||
|
const fetchURL = new URL(
|
||||||
|
`${DATASET_ENDPOINT}/id/${this.#id}/${up ? "up" : "down"}vote`,
|
||||||
|
getBaseURL(),
|
||||||
|
);
|
||||||
|
|
||||||
|
const response = await fetch(fetchURL, {
|
||||||
|
method: "PUT",
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
this.#upvotes = data.upvotes;
|
||||||
|
for (const element of this.#elements) {
|
||||||
|
element.querySelector(".upvote-count").innerText = this.#upvotes;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.storageSetKey("vote-type", up ? "upvote" : "downvote");
|
||||||
|
this.storageSetKey("is-voted", true);
|
||||||
|
this.#disableVoteBtns();
|
||||||
|
}
|
||||||
|
|
||||||
|
#disableVoteBtns() {
|
||||||
|
if (this.#elements.length > 0) {
|
||||||
|
const voteType = this.storageGetKey("vote-type", null);
|
||||||
|
|
||||||
|
this.#elements.flatMap(e => Array.from(e.querySelectorAll(".upvote .btn")))
|
||||||
|
.forEach(btn => {
|
||||||
|
btn.disabled = true;
|
||||||
|
|
||||||
|
if (btn.classList.contains(`${voteType}-btn`)) {
|
||||||
|
btn.classList.add("isVoted");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
storageGet() {
|
||||||
|
const json = localStorage.getItem(this.#id);
|
||||||
|
return json != null ? JSON.parse(json) : {};
|
||||||
|
}
|
||||||
|
|
||||||
|
storageSetKey(key, value) {
|
||||||
|
let currentStorage = this.storageGet();
|
||||||
|
currentStorage[key] = value;
|
||||||
|
localStorage.setItem(this.#id, JSON.stringify(currentStorage));
|
||||||
|
}
|
||||||
|
|
||||||
|
storageGetKey(key, defaultValue) {
|
||||||
|
return this.storageGet()?.[key] ?? defaultValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link rel="prefetch" href="https://fonts.googleapis.com/css2?family=Flow+Circular&display=swap">
|
<link rel="prefetch" href="https://fonts.googleapis.com/css2?family=Flow+Circular&display=swap">
|
||||||
<link rel="stylesheet" href="main.css">
|
<link rel="stylesheet" href="main.css">
|
||||||
<script type="module" src="main.js" defer></script>
|
<script type="module" src="main.js" defer></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="add-btn" title="Add a new API entry"></div>
|
<div id="add-btn" title="Add a new API entry"></div>
|
||||||
@ -22,8 +22,8 @@
|
|||||||
<li class="dataset" data-id="id">
|
<li class="dataset" data-id="id">
|
||||||
<div class="dataset-info">
|
<div class="dataset-info">
|
||||||
<div class="details">
|
<div class="details">
|
||||||
<h3>title</h3>
|
<h3 class="dataset-title">title</h3>
|
||||||
<p>Simply daily accountability phone call, powered by AI</p>
|
<p class="dataset-description">Simply daily accountability phone call, powered by AI</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<aside class="upvote">
|
<aside class="upvote">
|
||||||
@ -81,6 +81,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<ul class="datasets">
|
<ul class="datasets">
|
||||||
</ul>
|
</ul>
|
||||||
|
<div id="observable" style="height: 2rem"></div>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
</body>
|
</body>
|
@ -83,9 +83,6 @@ header {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
#search-entry:focus-visible {
|
#search-entry:focus-visible {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
@ -97,6 +94,11 @@ header {
|
|||||||
gap: var(--gap-medium);
|
gap: var(--gap-medium);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@container (width < 60ch) {
|
@container (width < 60ch) {
|
||||||
.datasets {
|
.datasets {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
@ -122,6 +124,7 @@ header {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--gap-small);
|
gap: var(--gap-small);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Buttons */
|
/* Buttons */
|
||||||
.upvote-btn, .downvote-btn, #search-btn, #filter-btn, #sort-btn, #reset-tools-btn {
|
.upvote-btn, .downvote-btn, #search-btn, #filter-btn, #sort-btn, #reset-tools-btn {
|
||||||
background: var(--icon-url) no-repeat;
|
background: var(--icon-url) no-repeat;
|
||||||
@ -148,6 +151,7 @@ header {
|
|||||||
--icon-url: url(looking-glass.svg);
|
--icon-url: url(looking-glass.svg);
|
||||||
--icon-size: 1rem;
|
--icon-size: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#filter-btn {
|
#filter-btn {
|
||||||
--icon-url: url(filter.svg);
|
--icon-url: url(filter.svg);
|
||||||
--icon-size: 1rem;
|
--icon-size: 1rem;
|
||||||
@ -163,6 +167,10 @@ header {
|
|||||||
--icon-size: 1rem;
|
--icon-size: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.isVoted {
|
||||||
|
filter: brightness(1.75);
|
||||||
|
}
|
||||||
|
|
||||||
.divider {
|
.divider {
|
||||||
width: .05rem;
|
width: .05rem;
|
||||||
height: 1rem;
|
height: 1rem;
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
import {fetchQuery} from "./contentUtility.js";
|
import { fetchQuery } from "./contentUtility.js";
|
||||||
import Dataset from "./dataset.js";
|
import Dataset from "./dataset.js";
|
||||||
|
|
||||||
const apiEndpoint = "/api/v1/datasets";
|
export const DATASET_ENDPOINT = "/api/v1/datasets";
|
||||||
const baseURL = location.origin;
|
export const getBaseURL = () => location.origin;
|
||||||
|
|
||||||
const defaultPagingValue = 20;
|
const defaultPagingValue = 20;
|
||||||
const lastQuery = {
|
export const lastQuery = {
|
||||||
url: "",
|
|
||||||
totalPages: 0,
|
totalPages: 0,
|
||||||
currentPage: 0
|
currentPage: 0,
|
||||||
};
|
};
|
||||||
|
const loadedCategories = new Set;
|
||||||
|
|
||||||
// definition of all buttons & sections
|
// definition of all buttons & sections
|
||||||
const addButton = document.getElementById("add-btn");
|
const addButton = document.getElementById("add-btn");
|
||||||
@ -33,33 +34,34 @@ addButton.addEventListener("click", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
filterButton.addEventListener("change", () => {
|
filterButton.addEventListener("change", () => {
|
||||||
const filterString = filterButton.value;
|
fetchQuery(createQuery(), true);
|
||||||
if (filterString !== filterButton.querySelector("#default-filter").value) {
|
|
||||||
fetchQuery(createQuery());
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
filterButton.addEventListener("click", () => {
|
||||||
|
fetchCategories();
|
||||||
|
})
|
||||||
|
|
||||||
searchButton.addEventListener("click", () => {
|
searchButton.addEventListener("click", () => {
|
||||||
fetchQuery(createQuery());
|
fetchQuery(createQuery(), true);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
searchBar.addEventListener("input", () => {
|
searchBar.addEventListener("input", () => {
|
||||||
updateSections();
|
|
||||||
clearTimeout(searchBarTimeout);
|
clearTimeout(searchBarTimeout);
|
||||||
searchBarTimeout = setTimeout(() => {
|
searchBarTimeout = setTimeout(() => {
|
||||||
fetchQuery(createQuery());
|
fetchQuery(createQuery(), true);
|
||||||
|
updateSections();
|
||||||
}, searchDelay);
|
}, searchDelay);
|
||||||
});
|
});
|
||||||
|
|
||||||
searchBar.addEventListener('keypress', function (e) {
|
searchBar.addEventListener('keypress', function (e) {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') {
|
||||||
fetchQuery(createQuery());
|
fetchQuery(createQuery(), true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
sortButton.addEventListener("change", () => {
|
sortButton.addEventListener("change", () => {
|
||||||
fetchQuery(createQuery());
|
fetchQuery(createQuery(), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
resetButton.addEventListener("click", () => {
|
resetButton.addEventListener("click", () => {
|
||||||
@ -69,37 +71,19 @@ resetButton.addEventListener("click", () => {
|
|||||||
updateSections();
|
updateSections();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Consider moving this to datasets.js completely
|
|
||||||
const upvoteButtonClickListener = e => {
|
|
||||||
const entryID = e.target.parentElement.parentElement.dataset.id;
|
|
||||||
vote(entryID, true);
|
|
||||||
};
|
|
||||||
for (const upvoteButton of upvoteButtons) {
|
|
||||||
upvoteButton.addEventListener("click", upvoteButtonClickListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consider moving this to datasets.js completely
|
|
||||||
const downvoteButtonClickListener = e => {
|
|
||||||
const entryID = e.target.parentElement.parentElement.dataset.id;
|
|
||||||
vote(entryID, false);
|
|
||||||
};
|
|
||||||
for (const downvoteButton of downvoteButtons) {
|
|
||||||
downvoteButton.addEventListener("click", downvoteButtonClickListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
// functions of the main page
|
// functions of the main page
|
||||||
function navigateToAdd() {
|
function navigateToAdd() {
|
||||||
window.location.href = "/add";
|
window.location.href = "/add.html"; //TODO: move to EventListener?
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFilterQuery() {
|
function getFilterQuery() {
|
||||||
let filterString= filterButton.value.toUpperCase();
|
let filterString = filterButton.value.toUpperCase();
|
||||||
if (filterString === "NONE") {
|
if (filterString === "NONE") {
|
||||||
return ["type", "%"]
|
return ["type", "%"]
|
||||||
} else if (document.querySelector('#filter-btn option:checked').parentElement.label === "Standard categories") {
|
} else if (document.querySelector('#filter-btn option:checked').parentElement.label === "Standard categories") {
|
||||||
return ["type", filterString];
|
return ["type", filterString];
|
||||||
} else {
|
} else {
|
||||||
return ["category", filterString];
|
return ["category", filterButton.options[filterButton.selectedIndex].value]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,39 +105,20 @@ function getSortQuery() {
|
|||||||
// creates query for the whole toolbar, so that searching, sorting and filtering are always combined
|
// creates query for the whole toolbar, so that searching, sorting and filtering are always combined
|
||||||
function createQuery() {
|
function createQuery() {
|
||||||
updateSections();
|
updateSections();
|
||||||
let queryURL = new URL(apiEndpoint + "/search", baseURL);
|
let queryURL = new URL(DATASET_ENDPOINT + "/search", getBaseURL());
|
||||||
queryURL.searchParams.append("search", getSearchQuery());
|
queryURL.searchParams.append("search", getSearchQuery());
|
||||||
|
|
||||||
let filterQuery = getFilterQuery();
|
let filterQuery = getFilterQuery();
|
||||||
queryURL.searchParams.append(filterQuery[0], filterQuery[1]);
|
queryURL.searchParams.append(filterQuery[0], filterQuery[1]);
|
||||||
|
|
||||||
let sortQuery = getSortQuery();
|
let sortQuery = getSortQuery();
|
||||||
queryURL.searchParams.append("sort", sortQuery[0]);
|
queryURL.searchParams.append("sort", sortQuery[0]);
|
||||||
queryURL.searchParams.append("direction", sortQuery[1]);
|
queryURL.searchParams.append("direction", sortQuery[1]);
|
||||||
queryURL.searchParams.append("size", defaultPagingValue.toString(10));
|
queryURL.searchParams.append("size", defaultPagingValue.toString(10));
|
||||||
|
|
||||||
return queryURL;
|
return queryURL;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function vote(entryID, up) {
|
|
||||||
const fetchURL = new URL(
|
|
||||||
`${apiEndpoint}/id/${entryID}/${up ? "up" : "down"}vote`,
|
|
||||||
baseURL,
|
|
||||||
);
|
|
||||||
fetch(fetchURL, {
|
|
||||||
method: "PUT",
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
}})
|
|
||||||
.then(resp => resp.json())
|
|
||||||
.then((data) => {
|
|
||||||
console.log(data.upvotes); // TODO: remove, check einbauen: data.id === entryID?
|
|
||||||
let dataset = document.querySelector('[data-id= ' + CSS.escape(entryID) + ']')
|
|
||||||
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.
|
// updates the page display. If no query is present, the initial page is shown, otherwise the search results.
|
||||||
function updateSections() {
|
function updateSections() {
|
||||||
if (searchBar.value === "" && sortButton.value === sortButton.querySelector("#default-sort").value
|
if (searchBar.value === "" && sortButton.value === sortButton.querySelector("#default-sort").value
|
||||||
@ -172,44 +137,47 @@ function updateSections() {
|
|||||||
|
|
||||||
// fetches the further categories used in the filter function
|
// fetches the further categories used in the filter function
|
||||||
function fetchCategories() {
|
function fetchCategories() {
|
||||||
const fetchURL = new URL(
|
const fetchURL = new URL("api/v1/categories", getBaseURL());
|
||||||
"api/v1/categories" , baseURL);
|
|
||||||
fetch(fetchURL)
|
fetch(fetchURL)
|
||||||
.then(resp => resp.json())
|
.then(resp => resp.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
let category = data[i].toLowerCase();
|
let categoryName = data[i].name.toLowerCase();
|
||||||
category = category.charAt(0).toUpperCase() + category.slice(1);
|
categoryName = categoryName.charAt(0).toUpperCase() + categoryName.slice(1);
|
||||||
document.getElementById("other-categories").appendChild(new Option(category));
|
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
|
// fetches entries for the initial page
|
||||||
function fetchInitialEntries() {
|
async function fetchInitialEntries() {
|
||||||
let recentsQueryURL = new URL(apiEndpoint + "/search", baseURL);
|
let recentsQueryURL = new URL(DATASET_ENDPOINT + "/search", getBaseURL());
|
||||||
recentsQueryURL.searchParams.append("sort", "date");
|
recentsQueryURL.searchParams.append("sort", "date");
|
||||||
recentsQueryURL.searchParams.append("direction", "desc");
|
recentsQueryURL.searchParams.append("direction", "desc");
|
||||||
recentsQueryURL.searchParams.append("size", "6");
|
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);
|
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("sort", "upvotes");
|
||||||
topVotedQueryURL.searchParams.append("direction", "desc");
|
topVotedQueryURL.searchParams.append("direction", "desc");
|
||||||
topVotedQueryURL.searchParams.append("size", "1");
|
topVotedQueryURL.searchParams.append("size", "1");
|
||||||
fetch(topVotedQueryURL)
|
|
||||||
.then(resp => resp.json())
|
const topVotedResponse = await fetch(topVotedQueryURL);
|
||||||
.then((data) => {
|
const topVotedData = await topVotedResponse.json();
|
||||||
document.querySelector("#top .datasets")
|
const topVotedDataset = new Dataset(topVotedData.content[0]);
|
||||||
.appendChild(new Dataset(data.content[0]).createDatasetHTMLElement());
|
|
||||||
});
|
document.querySelector("#top .datasets").appendChild(topVotedDataset.createDatasetHTMLElement());
|
||||||
}
|
}
|
||||||
|
|
||||||
window.onload = function () {
|
window.onload = function () {
|
||||||
@ -217,6 +185,21 @@ window.onload = function () {
|
|||||||
fetchInitialEntries();
|
fetchInitialEntries();
|
||||||
updateSections();
|
updateSections();
|
||||||
if (searchBar.value !== "") {
|
if (searchBar.value !== "") {
|
||||||
fetchQuery(createQuery());
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user