got rid of slug idea, as its functionality can be implemented without an additional db field

Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
2024-12-29 00:21:48 +01:00
parent 2e1f1c9697
commit d797de60c1
8 changed files with 64 additions and 147 deletions
@@ -2,8 +2,7 @@
package de.srsoftware.cal;
import static de.srsoftware.cal.db.Fields.*;
import static de.srsoftware.tools.Optionals.nullIfEmpty;
import static de.srsoftware.tools.Optionals.nullable;
import static de.srsoftware.tools.Optionals.*;
import static java.lang.System.*;
import static java.lang.System.Logger.Level.WARNING;
import static java.time.format.DateTimeFormatter.ISO_DATE_TIME;
@@ -56,22 +55,18 @@ public class ApiHandler extends PathHandler {
};
}
// spotless:off
private boolean editEvent(HttpExchange ex) throws IOException {
var json = json(ex);
// spotless:off
var slug = json.has(SLUG) ? nullIfEmpty(json.getString(SLUG)) : null;
// spotless:on
if (slug == null) sendContent(ex, Error.of("No slug value in appointment"));
var existingAppointment = db.loadEvent(slug);
return switch (existingAppointment) {
case Payload<Appointment> payload //
-> update(ex, payload.get(), json);
case Error<Appointment> err //
-> err.toString().startsWith("Failed to find appointment with slug") ? createEvent(ex, json):
sendContent(ex, err);
default -> serverError(ex, existingAppointment);
};
var location = json.has(LOCATION) ? json.getString(LOCATION) : null;
var start = json.has(START) ? LocalDateTime.parse(json.getString(START)) : null;
if (allSet(location, start)) {
var existingAppointment = db.loadEvent(location, start).optional();
if (existingAppointment.isPresent()) return update(ex, existingAppointment.get(), json);
}
return createEvent(ex, json);
}
// spotless:on
private boolean createEvent(HttpExchange ex, JSONObject json) throws IOException {
var description = json.has(DESCRIPTION) ? nullIfEmpty(json.getString(DESCRIPTION)) : null;
@@ -84,10 +79,7 @@ public class ApiHandler extends PathHandler {
var endDate = nullable(end).map(dt -> LocalDateTime.parse(dt, ISO_DATE_TIME)).orElse(null);
var location = json.has(LOCATION) ? json.getString(LOCATION) : null;
if (location == null) return sendContent(ex, Error.of("location missing"));
var clientSlug = json.has(SLUG) ? json.getString(SLUG) : null;
var serverSlug = Database.slug(location, startDate);
if (!serverSlug.equals(clientSlug)) return sendContent(ex, Error.of("Slug mismatch!"));
var event = new BaseAppointment(0, title, description, startDate, endDate, location, serverSlug);
var event = new BaseAppointment(0, title, description, startDate, endDate, location);
if (json.has(ATTACHMENTS)) {
json.getJSONArray(ATTACHMENTS).forEach(att -> {
Payload //
@@ -50,6 +50,8 @@ async function handleTags(response){
input.focus();
};
select.appendChild(option);
select.onkeyup = selectKeyPress;
});
select.style.display = 'block';
select.style.height = (22*tags.length)+'px';
@@ -61,20 +63,41 @@ function onMapClick(e) {
if (marker) marker.setLatLng(e.latlng);
}
function addTag(tag){
var list = element('taglist');
if (selectedTags.size<1) list.innerHTML = '';
list.innerHTML += `<span><button onclick="this.parentNode.parentNode.removeChild(this.parentNode);" title="click to remove">${tag}</button> </span>`;
selectedTags.add(tag);
var btn = element('save');
btn.removeAttribute("disabled");
btn.onclick= function(){ saveEvent(); };
var select = element('proposals');
select.innerHTML = '';
select.style.display = 'none';
var input = element('tags-input')
input.value = '';
input.focus();
}
function selectKeyPress(e){
if (e.keyCode == 13){
addTag(e.target.value);
}
}
function tagKeyPress(e){
var input = e.target;
if (e.keyCode == 13){
var tag = input.value;
if (!tag) return;
var list = element('taglist');
if (selectedTags.size<1) list.innerHTML = '';
list.innerHTML += `<span><button onclick="this.parentNode.parentNode.removeChild(this.parentNode);" title="click to remove">${input.value}</button> </span>`;
selectedTags.add(tag);
input.value = '';
var btn = element('save');
btn.removeAttribute("disabled");
btn.onclick= function(){ saveEvent(); };
addTag(tag);
} else if (e.keyCode == 40){
var select = element('proposals');
var val = select.firstChild.value;
select.value = val;
select.focus();
} else {
if (keyTimer != null) clearTimeout(keyTimer);
setTimeout(() => fetchTags(input.value),500);
@@ -113,39 +136,21 @@ function getAttachments(){
return urls;
}
function camelCase(text) {
if (text == null) {
return null;
} else {
var slug = '';
var upper = false;
for(var i = 0; i < text.length; i++) {
var c = text.charAt(i);
if (c == ' ') {
upper = true;
} else {
slug += upper ? c.toUpperCase() : c;
upper = false;
}
}
return slug;
}
}
async function slug(start,location){
const hash = await crypto.subtle.digest("SHA-256", (new TextEncoder()).encode(`${start}@${location}`));
return btoa(String.fromCharCode(...new Uint8Array(hash)));
}
function showError(message){
var span = document.createElement('div');
span.setAttribute('class','error');
span.innerHTML = "<span>Error: "+message+"<span>";
span.style.opacity = '1';
span.style.transition = 'opacity 1000ms linear';
element('taglist').appendChild(span);
setTimeout(() => {
span.style.opacity = '0';
setTimeout(() => span.parentNode.removeChild(span),1000);
},4000);
}
async function handleSave(response){
if (response.ok){
var json = await response.json();
@@ -163,7 +168,6 @@ async function saveEvent(){
var location = element('location').value;
var start = element('start').value;
var slugVal = await slug(start,location);
var event = {
title : element('title').value,
description : element('description').value,
@@ -173,8 +177,7 @@ async function saveEvent(){
tags: getTags(),
links: getLinks(),
coords: element('coords').value,
attachments: getAttachments(),
slug: slugVal
attachments: getAttachments()
};
fetch('/api/event/edit',{
method: 'POST',