Add missing fields to add page
This commit is contained in:
parent
9215148eff
commit
4b00b6010a
@ -171,3 +171,30 @@ form :has(#url) {
|
||||
.btn:disabled {
|
||||
filter: var(--drop-shadow) grayscale(.5) brightness(.5);
|
||||
}
|
||||
|
||||
#category[value="new"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
label[for="category"] {
|
||||
width: 0;
|
||||
user-select: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
span:has(#category) {
|
||||
gap: unset;
|
||||
}
|
||||
|
||||
#new-category-group:not(.hidden) {
|
||||
display: flex;
|
||||
justify-content: stretch;
|
||||
gap: var(--gap-small);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#new-category-group button {
|
||||
background-image: url("./sort.svg");
|
||||
background-size: contain;
|
||||
background-origin: content-box;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@
|
||||
</span>
|
||||
|
||||
<span id="author-box">
|
||||
<label for="author">Author</label>
|
||||
<label for="author">Author/provider</label>
|
||||
<input type="text" name="author" id="author" required>
|
||||
</span>
|
||||
|
||||
@ -48,6 +48,29 @@
|
||||
<input type="url" name="url" id="url" required>
|
||||
</span>
|
||||
|
||||
<span>
|
||||
<label for="terms-of-use">Terms of Use URL</label>
|
||||
<input type="url" name="terms-of-use" id="terms-of-use" required>
|
||||
</span>
|
||||
|
||||
<span>
|
||||
<label for="license">License</label>
|
||||
<input type="text" name="license" id="license" required>
|
||||
</span>
|
||||
|
||||
<span>
|
||||
<label for="category">Category</label>
|
||||
<select name="category" id="category" class="btn" required autocomplete="off">
|
||||
<option value="" selected disabled hidden>Category</option>
|
||||
<option value="new">New category</option>
|
||||
<hr>
|
||||
</select>
|
||||
<span id="new-category-group" class="hidden">
|
||||
<input type="text" id="new-category" size="2" required disabled autocomplete="off">
|
||||
<button id="change-category-btn" class="btn flat" title="change category"></button>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<span id="full-description-box">
|
||||
<label for="full-description">Full description</label>
|
||||
<textarea name="full-description" id="full-description" spellcheck="true"></textarea>
|
||||
|
@ -7,10 +7,16 @@ const {
|
||||
["is-dataset"]: isDatasetSwitch,
|
||||
["short-description"]: shortDescriptionEntry,
|
||||
url: urlEntry,
|
||||
["terms-of-use"]: termsOfUseEntry,
|
||||
license: licenseEntry,
|
||||
category: categorySpinner,
|
||||
["new-category"]: newCategoryEntry,
|
||||
["change-category-btn"]: changeCategoryBtn,
|
||||
["full-description"]: fullDescriptionEntry,
|
||||
["btn-add"]: addBtn,
|
||||
["btn-cancel"]: cancelBtn,
|
||||
} = form.elements;
|
||||
const newCategoryGroup = document.getElementById("new-category-group");
|
||||
|
||||
const validationListener = () => {
|
||||
addBtn.disabled = !form.checkValidity();
|
||||
@ -22,44 +28,127 @@ const validationListener = () => {
|
||||
authorEntry,
|
||||
shortDescriptionEntry,
|
||||
urlEntry,
|
||||
termsOfUseEntry,
|
||||
licenseEntry,
|
||||
newCategoryEntry,
|
||||
fullDescriptionEntry,
|
||||
].forEach(input => input.addEventListener("input", validationListener));
|
||||
|
||||
// Category spinner
|
||||
const categorySpinnerSet = (...args) => {
|
||||
if (args.length > 0) {
|
||||
categorySpinner.value = args[0];
|
||||
}
|
||||
|
||||
categorySpinner.setAttribute("value", categorySpinner.value);
|
||||
|
||||
if (categorySpinner.value == "new") {
|
||||
newCategoryGroup.classList.remove("hidden");
|
||||
newCategoryEntry.disabled = false;
|
||||
newCategoryEntry.focus();
|
||||
} else {
|
||||
newCategoryGroup.classList.add("hidden");
|
||||
newCategoryEntry.disabled = true;
|
||||
}
|
||||
};
|
||||
|
||||
const getCategory = () => {
|
||||
return categorySpinner.value == "new"
|
||||
? newCategoryEntry.value
|
||||
: categorySpinner.value;
|
||||
}
|
||||
|
||||
categorySpinner.addEventListener("input", e => {
|
||||
categorySpinnerSet();
|
||||
validationListener();
|
||||
});
|
||||
|
||||
changeCategoryBtn.addEventListener("click", e => {
|
||||
e.preventDefault();
|
||||
categorySpinnerSet("");
|
||||
validationListener();
|
||||
});
|
||||
|
||||
let categoriesResponse = await fetch(`${location.origin}/api/v1/categories`);
|
||||
let categories = [];
|
||||
if (!categoriesResponse.ok) {
|
||||
console.warn("Could not load categories!");
|
||||
} else {
|
||||
categories = await categoriesResponse.json();
|
||||
for (const category of categories) {
|
||||
let option = document.createElement("option");
|
||||
option.value = category.id;
|
||||
option.text = category.name;
|
||||
categorySpinner.add(option);
|
||||
}
|
||||
}
|
||||
|
||||
// Form listeners
|
||||
cancelBtn.addEventListener("click", () => {
|
||||
window.location.href = location.origin;
|
||||
})
|
||||
|
||||
form.addEventListener("submit", async e => {
|
||||
e.preventDefault();
|
||||
if (!form.reportValidity()) return;
|
||||
if (!form.reportValidity()) {
|
||||
addBtn.disabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
let categoryID = categorySpinner.value;
|
||||
|
||||
if (categoryID == "new") {
|
||||
const newCategoryName = newCategoryEntry.value.trim();
|
||||
|
||||
if (!categories.map(c => c.name).includes(newCategoryName)) {
|
||||
// Try to add the new category
|
||||
const newCategoryResponse = await fetch(`/api/v1/categories`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json;charset=utf-8" },
|
||||
body: JSON.stringify({ name: newCategoryName }),
|
||||
});
|
||||
|
||||
if (!newCategoryResponse.ok) {
|
||||
newCategoryEntry.setCustomValidity(
|
||||
`Could not create new category: ${newCategoryResponse.statusText}`
|
||||
);
|
||||
form.reportValidity();
|
||||
return;
|
||||
}
|
||||
|
||||
const newCategory = await newCategoryResponse.json();
|
||||
categoryID = newCategory.id;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the request body
|
||||
const newContent = {
|
||||
title: titleEntry.value,
|
||||
author: authorEntry.value,
|
||||
type: isDatasetSwitch.checked ? "API" : "DATASET",
|
||||
abst: shortDescriptionEntry.value,
|
||||
url: urlEntry.value,
|
||||
termsOfUse: termsOfUseEntry.value,
|
||||
licence: licenseEntry.value,
|
||||
categorie: {
|
||||
id: categoryID,
|
||||
},
|
||||
description: fullDescriptionEntry.value,
|
||||
type: isDatasetSwitch.checked ? "API" : "DATASET",
|
||||
categories: [],
|
||||
};
|
||||
|
||||
console.debug(newContent);
|
||||
|
||||
// Don't allow several requests to be sent at the same time
|
||||
addBtn.disabled = true;
|
||||
|
||||
let response = await fetch("/api/v1/datasets", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json;charset=utf-8" },
|
||||
body: JSON.stringify(newContent),
|
||||
headers: {
|
||||
"Content-Type": "application/json;charset=utf-8"
|
||||
}
|
||||
|
||||
});
|
||||
let data = await response.json();
|
||||
|
||||
let dataset = new Dataset(data);
|
||||
dataset.storageSetKey("created-locally", true);
|
||||
|
||||
if (response.ok) {
|
||||
location.assign("/");
|
||||
} else {
|
||||
|
@ -23,7 +23,7 @@ export default class Dataset {
|
||||
return this.#datasets.get(id);
|
||||
}
|
||||
|
||||
constructor({ abst: shortDescription, author, categorie, date, description, id, raiting, title, type, upvotes, url, votes, license, termsOfUse }) {
|
||||
constructor({ abst: shortDescription, author, categorie, date, description, id, raiting, title, type, upvotes, url, votes, licence: license, termsOfUse }) {
|
||||
this.#shortDescription = shortDescription;
|
||||
this.#author = author;
|
||||
this.#category = categorie;
|
||||
|
@ -18,12 +18,10 @@ const currentLocation = new URL(location.href);
|
||||
if (currentLocation.searchParams.has("id")) {
|
||||
const id = currentLocation.searchParams.get("id");
|
||||
const response = await fetch(`${currentLocation.origin}/api/v1/datasets/id/${id}`);
|
||||
console.dir(response);
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
const dataset = new Dataset(data);
|
||||
console.dir(data, dataset);
|
||||
const upvoteComponent = dataset.createUpvoteComponent();
|
||||
|
||||
title.innerText = dataset.title;
|
||||
|
Loading…
Reference in New Issue
Block a user