implemented storing of appointments
+ attachments next: attach links, tags Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
description = "OpenCloudCal : API"
|
description = "OpenCloudCal : API"
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("de.srsoftware:tools.util:1.2.2")
|
implementation("de.srsoftware:tools.util:1.2.3")
|
||||||
implementation("org.json:json:20240303")
|
implementation("org.json:json:20240303")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ public interface Appointment {
|
|||||||
*/
|
*/
|
||||||
Optional<Coords> coords();
|
Optional<Coords> coords();
|
||||||
|
|
||||||
|
Appointment clone(long newId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Descriptive text of the event
|
* Descriptive text of the event
|
||||||
* @return the description
|
* @return the description
|
||||||
@@ -41,7 +43,6 @@ public interface Appointment {
|
|||||||
*/
|
*/
|
||||||
long id();
|
long id();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get a json representation of this Appointment
|
* get a json representation of this Appointment
|
||||||
* @return a JSON Object
|
* @return a JSON Object
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ dependencies {
|
|||||||
implementation("de.srsoftware:configuration.api:1.0.0")
|
implementation("de.srsoftware:configuration.api:1.0.0")
|
||||||
implementation("de.srsoftware:configuration.json:1.0.0")
|
implementation("de.srsoftware:configuration.json:1.0.0")
|
||||||
implementation("de.srsoftware:tools.http:1.0.4")
|
implementation("de.srsoftware:tools.http:1.0.4")
|
||||||
implementation("de.srsoftware:tools.logging:1.0.1")
|
implementation("de.srsoftware:tools.logging:1.0.2")
|
||||||
implementation("de.srsoftware:tools.web:1.3.8")
|
implementation("de.srsoftware:tools.web:1.3.8")
|
||||||
implementation("com.mysql:mysql-connector-j:9.1.0")
|
implementation("com.mysql:mysql-connector-j:9.1.0")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ dependencies {
|
|||||||
implementation(project(":de.srsoftware.cal.api"))
|
implementation(project(":de.srsoftware.cal.api"))
|
||||||
|
|
||||||
implementation("de.srsoftware:tools.optionals:1.0.0")
|
implementation("de.srsoftware:tools.optionals:1.0.0")
|
||||||
implementation("de.srsoftware:tools.util:1.2.2")
|
implementation("de.srsoftware:tools.util:1.2.3")
|
||||||
implementation("de.srsoftware:tools.web:1.3.8")
|
implementation("de.srsoftware:tools.web:1.3.8")
|
||||||
implementation("org.json:json:20240303")
|
implementation("org.json:json:20240303")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ import org.json.JSONObject;
|
|||||||
*/
|
*/
|
||||||
public class BaseAppointment implements Appointment {
|
public class BaseAppointment implements Appointment {
|
||||||
private static final DateTimeFormatter DATE_TIME = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
|
private static final DateTimeFormatter DATE_TIME = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
|
||||||
private final long id;
|
private long id;
|
||||||
private final String title, description;
|
private final String title, description;
|
||||||
private final LocalDateTime end, start;
|
private final LocalDateTime end, start;
|
||||||
private final String hash;
|
private final String slug;
|
||||||
private Coords coords = null;
|
private Coords coords = null;
|
||||||
private final Set<Attachment> attachments = new HashSet<>();
|
private final Set<Attachment> attachments = new HashSet<>();
|
||||||
private final Set<String> tags = new HashSet<>();
|
private final Set<String> tags = new HashSet<>();
|
||||||
@@ -39,7 +39,7 @@ public class BaseAppointment implements Appointment {
|
|||||||
public BaseAppointment(long id, String title, String description, LocalDateTime start, LocalDateTime end, String location, String slug) {
|
public BaseAppointment(long id, String title, String description, LocalDateTime start, LocalDateTime end, String location, String slug) {
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.end = end;
|
this.end = end;
|
||||||
this.hash = slug;
|
this.slug = slug;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.location = location;
|
this.location = location;
|
||||||
this.start = start;
|
this.start = start;
|
||||||
@@ -98,7 +98,12 @@ public class BaseAppointment implements Appointment {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Attachment> attachments() {
|
public Set<Attachment> attachments() {
|
||||||
return Set.of();
|
return attachments;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Appointment clone(long newId) {
|
||||||
|
return new BaseAppointment(newId, title, description, start, end, location, slug).coords(coords).addLinks(links).add(attachments);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -116,7 +121,6 @@ public class BaseAppointment implements Appointment {
|
|||||||
return nullable(end);
|
return nullable(end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long id() {
|
public long id() {
|
||||||
return id;
|
return id;
|
||||||
@@ -148,7 +152,7 @@ public class BaseAppointment implements Appointment {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String slug() {
|
public String slug() {
|
||||||
return hash;
|
return slug;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/* © SRSoftware 2024 */
|
/* © SRSoftware 2024 */
|
||||||
package de.srsoftware.cal;
|
package de.srsoftware.cal;
|
||||||
|
|
||||||
|
import static de.srsoftware.tools.Result.transform;
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
import de.srsoftware.cal.api.*;
|
import de.srsoftware.cal.api.*;
|
||||||
@@ -44,8 +45,8 @@ public abstract class BaseImporter implements Importer {
|
|||||||
.map(tag -> tag.get("src"))
|
.map(tag -> tag.get("src"))
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.map(Payload::of)
|
.map(Payload::of)
|
||||||
.map(this::url)
|
.map(BaseImporter::url)
|
||||||
.map(this::toAttachment)
|
.map(BaseImporter::toAttachment)
|
||||||
.map(Result::optional)
|
.map(Result::optional)
|
||||||
.flatMap(Optional::stream)
|
.flatMap(Optional::stream)
|
||||||
.toList();
|
.toList();
|
||||||
@@ -140,9 +141,9 @@ public abstract class BaseImporter implements Importer {
|
|||||||
var text = anchor.inner(0).orElse(href);
|
var text = anchor.inner(0).orElse(href);
|
||||||
Payload //
|
Payload //
|
||||||
.of(href)
|
.of(href)
|
||||||
.map(this::url)
|
.map(BaseImporter::url)
|
||||||
|
.map(url -> link(url,text))
|
||||||
.optional()
|
.optional()
|
||||||
.map(url -> new Link(url, text))
|
|
||||||
.ifPresent(links::add);
|
.ifPresent(links::add);
|
||||||
});
|
});
|
||||||
return links;
|
return links;
|
||||||
@@ -195,7 +196,7 @@ public abstract class BaseImporter implements Importer {
|
|||||||
.map(this::extractEventUrls)
|
.map(this::extractEventUrls)
|
||||||
.stream();
|
.stream();
|
||||||
return stream //
|
return stream //
|
||||||
.map(this::url)
|
.map(BaseImporter::url)
|
||||||
.map(this::loadEvent)
|
.map(this::loadEvent)
|
||||||
.peek(e -> {
|
.peek(e -> {
|
||||||
if (e instanceof Error<Appointment> err) System.err.println(err);
|
if (e instanceof Error<Appointment> err) System.err.println(err);
|
||||||
@@ -216,6 +217,12 @@ public abstract class BaseImporter implements Importer {
|
|||||||
return Error.format("Invalid parameter: %s", result.getClass().getSimpleName());
|
return Error.format("Invalid parameter: %s", result.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static Result<Link> link(Result<URL> url, String text) {
|
||||||
|
var opt = url.optional();
|
||||||
|
if (opt.isEmpty()) return transform(url);
|
||||||
|
return Payload.of(new Link(opt.get(),text));
|
||||||
|
}
|
||||||
|
|
||||||
protected Result<Appointment> loadEvent(Result<URL> urlResult) {
|
protected Result<Appointment> loadEvent(Result<URL> urlResult) {
|
||||||
var link = urlResult //
|
var link = urlResult //
|
||||||
.optional().map(url -> new Link(url, "Event-Seite")).orElse(null);
|
.optional().map(url -> new Link(url, "Event-Seite")).orElse(null);
|
||||||
@@ -271,22 +278,19 @@ public abstract class BaseImporter implements Importer {
|
|||||||
|
|
||||||
protected abstract String programURL();
|
protected abstract String programURL();
|
||||||
|
|
||||||
protected Result<Attachment> toAttachment(Result<URL> urlResult) {
|
protected static Result<Attachment> toAttachment(Result<URL> urlResult) {
|
||||||
switch (urlResult) {
|
var opt = urlResult.optional();
|
||||||
case Payload<URL> payload:
|
if (opt.isEmpty()) return transform(urlResult);
|
||||||
try {
|
try {
|
||||||
var mime = payload.get().openConnection().getContentType();
|
var mime = opt.get().openConnection().getContentType();
|
||||||
return Payload.of(new Attachment(payload.get(), mime));
|
return Payload.of(new Attachment(opt.get(), mime));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return Error.format("Failed to read mime type of %s", payload);
|
e.printStackTrace();
|
||||||
}
|
return Error.format("Failed to read mime type of %s", opt.get());
|
||||||
case Error<URL> err:
|
|
||||||
return err.transform();
|
|
||||||
default:
|
|
||||||
return invalidParameter(urlResult);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected static Result<Integer> toNumericMonth(String month) {
|
protected static Result<Integer> toNumericMonth(String month) {
|
||||||
month = month.toLowerCase();
|
month = month.toLowerCase();
|
||||||
if (month.startsWith("ja")) return Payload.of(1);
|
if (month.startsWith("ja")) return Payload.of(1);
|
||||||
@@ -305,24 +309,13 @@ public abstract class BaseImporter implements Importer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected <T> Result<T> transform(Result<?> result) {
|
protected static Result<URL> url(Result<String> urlResult) {
|
||||||
if (result instanceof Error<?> err) return err.transform();
|
if (urlResult.optional().isEmpty()) return transform(urlResult);
|
||||||
return invalidParameter(result);
|
var url = urlResult.optional().get();
|
||||||
}
|
try {
|
||||||
|
return Payload.of(new URI(url).toURL());
|
||||||
protected Result<URL> url(Result<String> urlResult) {
|
} catch (MalformedURLException | URISyntaxException e) {
|
||||||
switch (urlResult) {
|
return Error.of("Failed to create URL of %s".formatted(url), e);
|
||||||
case Payload<String> payload:
|
|
||||||
var url = payload.get();
|
|
||||||
try {
|
|
||||||
return Payload.of(new URI(url).toURL());
|
|
||||||
} catch (MalformedURLException | URISyntaxException e) {
|
|
||||||
return de.srsoftware.tools.Error.of("Failed to create URL of %s".formatted(url), e);
|
|
||||||
}
|
|
||||||
case de.srsoftware.tools.Error<String> err:
|
|
||||||
return err.transform();
|
|
||||||
default:
|
|
||||||
return invalidParameter(urlResult);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ dependencies {
|
|||||||
implementation(project(":de.srsoftware.cal.api"))
|
implementation(project(":de.srsoftware.cal.api"))
|
||||||
implementation(project(":de.srsoftware.cal.base"))
|
implementation(project(":de.srsoftware.cal.base"))
|
||||||
|
|
||||||
implementation("de.srsoftware:tools.jdbc:1.1.0")
|
implementation("de.srsoftware:tools.jdbc:1.1.1")
|
||||||
implementation("de.srsoftware:tools.optionals:1.0.0")
|
implementation("de.srsoftware:tools.optionals:1.0.0")
|
||||||
implementation("de.srsoftware:tools.util:1.2.2")
|
implementation("de.srsoftware:tools.util:1.2.3")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ public interface Database {
|
|||||||
/**
|
/**
|
||||||
* add an appointment to the database
|
* add an appointment to the database
|
||||||
* @param appointment the appointment to store
|
* @param appointment the appointment to store
|
||||||
* @return the Database object
|
* @return a clone of the provided appointment with id field set
|
||||||
*/
|
*/
|
||||||
public Database add(Appointment appointment);
|
public Result<Appointment> add(Appointment appointment);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list appointments unfiltered
|
* list appointments unfiltered
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/* © SRSoftware 2024 */
|
||||||
|
package de.srsoftware.cal.db;
|
||||||
|
|
||||||
|
public class Fields {
|
||||||
|
public static final String AID = "aid";
|
||||||
|
public static final String ALL = "*";
|
||||||
|
public static final String COORDS = "coords";
|
||||||
|
public static final String DESCRIPTION = "description";
|
||||||
|
public static final String END = "end";
|
||||||
|
public static final String KEYWORD = "keyword";
|
||||||
|
public static final String LOCATION = "location";
|
||||||
|
public static final String MIME = "mime";
|
||||||
|
public static final String SLUG = "slug";
|
||||||
|
public static final String START = "start";
|
||||||
|
public static final String TID = "tid";
|
||||||
|
public static final String TITLE = "title";
|
||||||
|
public static final String UID = "uid";
|
||||||
|
public static final String URL = "url";
|
||||||
|
|
||||||
|
private Fields() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,8 @@
|
|||||||
package de.srsoftware.cal.db;
|
package de.srsoftware.cal.db;
|
||||||
|
|
||||||
import static de.srsoftware.cal.db.Database.slug;
|
import static de.srsoftware.cal.db.Database.slug;
|
||||||
import static de.srsoftware.tools.NotImplemented.notImplemented;
|
import static de.srsoftware.cal.db.Fields.*;
|
||||||
|
import static de.srsoftware.cal.db.Fields.ALL;
|
||||||
import static de.srsoftware.tools.Optionals.*;
|
import static de.srsoftware.tools.Optionals.*;
|
||||||
import static de.srsoftware.tools.Result.transform;
|
import static de.srsoftware.tools.Result.transform;
|
||||||
import static de.srsoftware.tools.jdbc.Condition.*;
|
import static de.srsoftware.tools.jdbc.Condition.*;
|
||||||
@@ -19,6 +20,7 @@ import de.srsoftware.tools.Result;
|
|||||||
import de.srsoftware.tools.jdbc.Query;
|
import de.srsoftware.tools.jdbc.Query;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -27,17 +29,9 @@ public class MariaDB implements Database {
|
|||||||
private static final System.Logger LOG = System.getLogger(MariaDB.class.getSimpleName());
|
private static final System.Logger LOG = System.getLogger(MariaDB.class.getSimpleName());
|
||||||
private static final String ADD_SLUG = "ALTER TABLE appointments ADD slug VARCHAR(255) UNIQUE";
|
private static final String ADD_SLUG = "ALTER TABLE appointments ADD slug VARCHAR(255) UNIQUE";
|
||||||
private static final String APPOINTMENTS = "appointments";
|
private static final String APPOINTMENTS = "appointments";
|
||||||
private static final String AID = "aid";
|
|
||||||
private static final String ALL = "*";
|
|
||||||
private static final String KEYWORD = "keyword";
|
|
||||||
private static final String APPOINTMENT_TAGS = "appointment_tags";
|
private static final String APPOINTMENT_TAGS = "appointment_tags";
|
||||||
private static final String URL = "url";
|
|
||||||
private static final String APPOINTMENT_URLS = "appointment_urls";
|
private static final String APPOINTMENT_URLS = "appointment_urls";
|
||||||
private static final String DESCRIPTION = "description";
|
|
||||||
private static final String UID = "uid";
|
|
||||||
private static final String URLS = "urls";
|
private static final String URLS = "urls";
|
||||||
private static final String TID = "tid";
|
|
||||||
private static final String MIME = "mime";
|
|
||||||
private static final String APPOINTMENT_ATTACHMENTS = "appointment_attachments";
|
private static final String APPOINTMENT_ATTACHMENTS = "appointment_attachments";
|
||||||
private static final String TAGS = "tags";
|
private static final String TAGS = "tags";
|
||||||
private static final String SLUG = "slug";
|
private static final String SLUG = "slug";
|
||||||
@@ -106,8 +100,45 @@ public class MariaDB implements Database {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Database add(Appointment appointment) {
|
public Result<Appointment> add(Appointment appointment) {
|
||||||
throw notImplemented(this, "add(Appointment)");
|
try {
|
||||||
|
ResultSet keys = Query //
|
||||||
|
.insertInto(APPOINTMENTS, TITLE, DESCRIPTION, START, END, LOCATION, COORDS, SLUG)
|
||||||
|
.values(appointment.title(), appointment.description(), appointment.start(), appointment.end().orElse(null), appointment.location(), appointment.coords().orElse(null), appointment.slug())
|
||||||
|
.execute(connection)
|
||||||
|
.getGeneratedKeys();
|
||||||
|
Appointment saved = null;
|
||||||
|
if (keys.next()) saved = appointment.clone(keys.getLong(1));
|
||||||
|
keys.close();
|
||||||
|
if (saved == null) return Error.of("Insert query did not return appointment id!");
|
||||||
|
var attachments = saved.attachments();
|
||||||
|
Query.InsertQuery assignQuery = null;
|
||||||
|
|
||||||
|
for (var attachment : attachments){
|
||||||
|
if (assignQuery == null) assignQuery = Query.insertInto(APPOINTMENT_ATTACHMENTS,AID,UID,MIME);
|
||||||
|
var urlId = getOrCreateUrl(attachment.url());
|
||||||
|
if (urlId.isPresent()) assignQuery.values(saved.id(), urlId.get(),attachment.mime());
|
||||||
|
}
|
||||||
|
if (assignQuery != null) assignQuery.execute(connection);
|
||||||
|
|
||||||
|
return Payload.of(saved);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
LOG.log(ERROR,"Failed to store appointment",e);
|
||||||
|
return Error.of("Failed to store appointment", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<Long> getOrCreateUrl(URL url) throws SQLException {
|
||||||
|
var rs = Query.select(UID).from(URLS).where(URL,equal(url.toString())).exec(connection);
|
||||||
|
Long uid = null;
|
||||||
|
if (rs.next()) uid = rs.getLong(1);
|
||||||
|
rs.close();
|
||||||
|
if (uid == null){
|
||||||
|
rs = Query.insertInto(URLS,URL).values(url.toString()).execute(connection).getGeneratedKeys();
|
||||||
|
if (rs.next()) uid = rs.getLong(1);
|
||||||
|
rs.close();
|
||||||
|
}
|
||||||
|
return nullable(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Database connect(String jdbc, String user, String pass) throws SQLException {
|
public static Database connect(String jdbc, String user, String pass) throws SQLException {
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ dependencies {
|
|||||||
implementation(project(":de.srsoftware.cal.api"))
|
implementation(project(":de.srsoftware.cal.api"))
|
||||||
implementation(project(":de.srsoftware.cal.base"))
|
implementation(project(":de.srsoftware.cal.base"))
|
||||||
implementation("de.srsoftware:tools.optionals:1.0.0")
|
implementation("de.srsoftware:tools.optionals:1.0.0")
|
||||||
implementation("de.srsoftware:tools.util:1.2.2")
|
implementation("de.srsoftware:tools.util:1.2.3")
|
||||||
implementation("de.srsoftware:tools.web:1.3.8")
|
implementation("de.srsoftware:tools.web:1.3.8")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/* © SRSoftware 2024 */
|
/* © SRSoftware 2024 */
|
||||||
package de.srsoftware.cal.importer.jena;
|
package de.srsoftware.cal.importer.jena;
|
||||||
|
|
||||||
|
import static de.srsoftware.tools.Result.transform;
|
||||||
import static de.srsoftware.tools.TagFilter.*;
|
import static de.srsoftware.tools.TagFilter.*;
|
||||||
|
|
||||||
import de.srsoftware.cal.BaseImporter;
|
import de.srsoftware.cal.BaseImporter;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
package de.srsoftware.cal.importer.jena;
|
package de.srsoftware.cal.importer.jena;
|
||||||
|
|
||||||
import static de.srsoftware.tools.Optionals.nullable;
|
import static de.srsoftware.tools.Optionals.nullable;
|
||||||
|
import static de.srsoftware.tools.Result.transform;
|
||||||
import static de.srsoftware.tools.TagFilter.*;
|
import static de.srsoftware.tools.TagFilter.*;
|
||||||
|
|
||||||
import de.srsoftware.cal.BaseImporter;
|
import de.srsoftware.cal.BaseImporter;
|
||||||
|
|||||||
@@ -7,6 +7,6 @@ dependencies {
|
|||||||
|
|
||||||
implementation("de.srsoftware:tools.http:1.0.4")
|
implementation("de.srsoftware:tools.http:1.0.4")
|
||||||
implementation("de.srsoftware:tools.optionals:1.0.0")
|
implementation("de.srsoftware:tools.optionals:1.0.0")
|
||||||
implementation("de.srsoftware:tools.util:1.2.2")
|
implementation("de.srsoftware:tools.util:1.2.3")
|
||||||
implementation("org.json:json:20240303")
|
implementation("org.json:json:20240303")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/* © SRSoftware 2024 */
|
/* © SRSoftware 2024 */
|
||||||
package de.srsoftware.cal;
|
package de.srsoftware.cal;
|
||||||
|
|
||||||
|
import static de.srsoftware.cal.db.Fields.*;
|
||||||
import static de.srsoftware.tools.Optionals.nullIfEmpty;
|
import static de.srsoftware.tools.Optionals.nullIfEmpty;
|
||||||
import static de.srsoftware.tools.Optionals.nullable;
|
import static de.srsoftware.tools.Optionals.nullable;
|
||||||
import static java.lang.System.*;
|
import static java.lang.System.*;
|
||||||
@@ -9,6 +10,7 @@ import static java.time.format.DateTimeFormatter.ISO_DATE_TIME;
|
|||||||
|
|
||||||
import com.sun.net.httpserver.HttpExchange;
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
import de.srsoftware.cal.api.Appointment;
|
import de.srsoftware.cal.api.Appointment;
|
||||||
|
import de.srsoftware.cal.api.Link;
|
||||||
import de.srsoftware.cal.db.Database;
|
import de.srsoftware.cal.db.Database;
|
||||||
import de.srsoftware.tools.Error;
|
import de.srsoftware.tools.Error;
|
||||||
import de.srsoftware.tools.PathHandler;
|
import de.srsoftware.tools.PathHandler;
|
||||||
@@ -25,12 +27,8 @@ import org.json.JSONObject;
|
|||||||
|
|
||||||
public class ApiHandler extends PathHandler {
|
public class ApiHandler extends PathHandler {
|
||||||
private static final Logger LOG = getLogger(ApiHandler.class.getSimpleName());
|
private static final Logger LOG = getLogger(ApiHandler.class.getSimpleName());
|
||||||
private static final String SLUG = "slug";
|
private static final String ATTACHMENTS = "attachments";
|
||||||
private static final String DESCRIPTION = "description";
|
private static final String LINKS = "links";
|
||||||
private static final String TITLE = "title";
|
|
||||||
private static final String START = "start";
|
|
||||||
private static final String END = "end";
|
|
||||||
private static final String LOCATION = "location";
|
|
||||||
private final Database db;
|
private final Database db;
|
||||||
|
|
||||||
public ApiHandler(Database db) {
|
public ApiHandler(Database db) {
|
||||||
@@ -89,8 +87,33 @@ public class ApiHandler extends PathHandler {
|
|||||||
var serverSlug = Database.slug(location, startDate);
|
var serverSlug = Database.slug(location, startDate);
|
||||||
if (!serverSlug.equals(clientSlug)) return sendContent(ex, Error.of("Slug mismatch!"));
|
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, serverSlug);
|
||||||
db.add(event);
|
if (json.has(ATTACHMENTS)) {
|
||||||
return sendContent(ex, Error.of("createEvent not implemented"));
|
json.getJSONArray(ATTACHMENTS).forEach(att -> {
|
||||||
|
Payload //
|
||||||
|
.of(att.toString())
|
||||||
|
.map(BaseImporter::url)
|
||||||
|
.map(BaseImporter::toAttachment)
|
||||||
|
.optional()
|
||||||
|
.ifPresent(event::add);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (json.has(LINKS)) {
|
||||||
|
json.getJSONArray(LINKS).forEach(o -> {
|
||||||
|
if (o instanceof JSONObject j) toLink(j).optional().ifPresent(event::addLinks);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var res = db.add(event).map(ApiHandler::toJson);
|
||||||
|
return sendContent(ex, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static Result<Link> toLink(JSONObject json) {
|
||||||
|
try {
|
||||||
|
var description = json.getString(DESCRIPTION);
|
||||||
|
return Payload.of(json.getString(URL)).map(BaseImporter::url).map(url -> BaseImporter.link(url, description));
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Error.of("Failed to create link from %s".formatted(json), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean update(HttpExchange ex, Appointment event, JSONObject json) throws IOException {
|
private boolean update(HttpExchange ex, Appointment event, JSONObject json) throws IOException {
|
||||||
|
|||||||
@@ -140,6 +140,8 @@ async function slug(start,location){
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function saveEvent(){
|
async function saveEvent(){
|
||||||
|
element('save').toggleAttribute("disabled");
|
||||||
|
|
||||||
var location = element('location').value;
|
var location = element('location').value;
|
||||||
var start = element('start').value;
|
var start = element('start').value;
|
||||||
var slugVal = await slug(start,location);
|
var slugVal = await slug(start,location);
|
||||||
|
|||||||
Reference in New Issue
Block a user