diff --git a/src/main/resources/static/add.css b/src/main/resources/static/add.css index a4b4b92..6d62a6f 100644 --- a/src/main/resources/static/add.css +++ b/src/main/resources/static/add.css @@ -4,20 +4,6 @@ --accent-color: oklch(65.33% 0.158 247.76); } -form label:after { - content: ":"; -} - -form :is(input[type=text], textarea) { - background-color: var(--fg-color); - border: none; - border-radius: .25lh; - color: var(--text-color, white); - padding: .5em; - font-family: sans-serif; -} - -/* quick info box */ form { display: grid; grid-template-columns: 1fr 1fr auto; @@ -30,17 +16,57 @@ form > * { gap: 1rem; } -form :is(input[type=text], textarea) { +form label:after { + content: ":"; +} + +/* text entries */ +form :is(input[type=text], input[type=url], textarea) { + background-color: var(--fg-color); + border: none; + border-radius: .25lh; + color: var(--text-color, white); + padding: .5em; + font-family: sans-serif; flex-grow: 1; } +/* focus outlines */ +:is(form :is(input[type=text], input[type=url], textarea), .btn):focus-visible { + outline: 2px solid var(--accent-color); +} + +.btn, #is-dataset-toggle { + transition: outline ease-in 100ms; +} + +/* input validation */ +form :is(input[type=text], input[type=url], textarea):user-valid { + --validation-color: lime; +} + +form :is(input[type=text], input[type=url], textarea):user-invalid { + --validation-color: red; + outline-style: solid; +} + +form :is(input[type=text], input[type=url], textarea):is(:user-valid, :user-invalid) { + outline-color: var(--validation-color); +} + +form :is(input[type=text], input[type=url], textarea):is(:user-valid, :user-invalid):not(:focus-visible) { + outline-width: 1px; +} + /* switch */ label:has(#is-dataset) { gap: 0; } #is-dataset { - display: none; + top: -100vh; + left: -100vw; + position: absolute; } #is-dataset-toggle { @@ -69,6 +95,10 @@ label:has(#is-dataset) { filter: drop-shadow(rgba(0, 0, 0, .8) 0 0 .25rem); } +#is-dataset:focus-visible + #is-dataset-toggle { + outline: 2px solid var(--accent-color); +} + #is-dataset:not(:checked) + #is-dataset-toggle::before { left: 0; } @@ -79,7 +109,11 @@ label:has(#is-dataset) { /* short description box */ form :has(#short-description) { - grid-column: 1 / 3; + grid-column: 1 / 2; +} + +form :has(#url) { + grid-column: 2 / 4; } /* full description box */ @@ -116,13 +150,18 @@ form :has(#short-description) { --drop-shadow-opacity: .5; --drop-shadow-offset-y: 0; --drop-shadow-blur: .25rem; - filter: drop-shadow( + --drop-shadow: drop-shadow( rgba(0, 0, 0, var(--drop-shadow-opacity)) 0 var(--drop-shadow-offset-y) var(--drop-shadow-blur) ); + filter: var(--drop-shadow); } -.btn:hover { +.btn:focus-visible, #is-dataset:focus-visible + #is-dataset-toggle { + outline-offset: 2px; +} + +.btn:not(:disabled):hover { background-color: color-mix(in oklab, var(--btn-color) 80%, var(--bg-color)); --drop-shadow-opacity: .8; --drop-shadow-offset-y: .25rem; @@ -132,3 +171,7 @@ form :has(#short-description) { .btn.suggested { --btn-color: var(--accent-color); } + +.btn:disabled { + filter: var(--drop-shadow) grayscale(.5) brightness(.5); +} diff --git a/src/main/resources/static/add.js b/src/main/resources/static/add.js new file mode 100644 index 0000000..f35c62d --- /dev/null +++ b/src/main/resources/static/add.js @@ -0,0 +1,56 @@ +const form = document.forms[0]; +const { + title: titleEntry, + author: authorEntry, + ["is-dataset"]: isDatasetSwitch, + ["short-description"]: shortDescriptionEntry, + url: urlEntry, + ["full-description"]: fullDescriptionEntry, + ["btn-add"]: addBtn, + ["btn-cancel"]: cancelBtn, +} = form.elements; + +const validationListener = () => { + addBtn.disabled = !form.checkValidity(); +}; + +// Register validationListener on all required inputs that must be valid +[ + titleEntry, + authorEntry, + shortDescriptionEntry, + urlEntry, + fullDescriptionEntry, +].forEach(input => input.addEventListener("input", validationListener)); + +form.addEventListener("submit", e => { + e.preventDefault(); + if (!form.reportValidity()) return; + + // Create the request body + const newContent = { + title: titleEntry.value, + author: authorEntry.value, + abst: shortDescriptionEntry.value, + url: urlEntry.value, + 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; + + fetch("/api/v1/datasets", { + method: "POST", + body: JSON.stringify(newContent), + }).then(response => { + if (response.status == 200) { + location.assign("/"); + } else { + addBtn.disabled = !checkValidity(); + } + }); +}); diff --git a/src/main/resources/templates/add.html b/src/main/resources/templates/add.html index d8472c1..eb8cd36 100644 --- a/src/main/resources/templates/add.html +++ b/src/main/resources/templates/add.html @@ -5,6 +5,7 @@