export txt, ics

This commit is contained in:
mbremer
2021-07-18 21:18:59 +02:00
parent f4bfa7ed2f
commit 6b1b1f1d00
10 changed files with 167 additions and 24 deletions

View File

@@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>de.mbremer</groupId> <groupId>de.mbremer</groupId>
<artifactId>buerokalender</artifactId> <artifactId>buerokalender</artifactId>
<version>1.0.1</version> <version>1.1.0</version>
<properties> <properties>
<compiler-plugin.version>3.8.1</compiler-plugin.version> <compiler-plugin.version>3.8.1</compiler-plugin.version>
<maven.compiler.parameters>true</maven.compiler.parameters> <maven.compiler.parameters>true</maven.compiler.parameters>
@@ -103,6 +103,11 @@
<artifactId>bootstrap-icons</artifactId> <artifactId>bootstrap-icons</artifactId>
<version>1.5.0</version> <version>1.5.0</version>
</dependency> </dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>popper.js</artifactId>
<version>2.9.2</version>
</dependency>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>

View File

@@ -20,4 +20,8 @@ public class CommonExtensions {
public static int plus(int a, int b) { public static int plus(int a, int b) {
return a + b; return a + b;
} }
public static String rightPad(String str, int length) {
return String.format("%1$-" + length + "s", str);
}
} }

View File

@@ -0,0 +1,35 @@
package de.mbremer.kalender;
import lombok.Getter;
import javax.validation.constraints.NotNull;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;
@Getter
public class Event {
private final String created;
private final String dtStart;
private final String dtEnd;
private final String uid;
public Event(@NotNull LocalDateTime created, LocalDate date) {
this.created = created.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.replaceAll("[-:]", "") + "Z";
this.dtStart = date.format(DateTimeFormatter.ISO_LOCAL_DATE)
.replace("-", "");
this.dtEnd = date.plusDays(1).format(DateTimeFormatter.ISO_LOCAL_DATE)
.replace("-", "");
this.uid = UUID.randomUUID().toString() + "@buerokalender";
}
public String getLastModified() {
return created;
}
public String getDtStamp() {
return created;
}
}

View File

@@ -1,6 +1,7 @@
package de.mbremer.kalender; package de.mbremer.kalender;
import de.mbremer.secutity.User; import de.mbremer.secutity.User;
import io.quarkus.qute.Location;
import io.quarkus.qute.Template; import io.quarkus.qute.Template;
import io.quarkus.qute.TemplateInstance; import io.quarkus.qute.TemplateInstance;
import io.quarkus.security.identity.SecurityIdentity; import io.quarkus.security.identity.SecurityIdentity;
@@ -14,6 +15,7 @@ import javax.transaction.Transactional;
import javax.ws.rs.*; import javax.ws.rs.*;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@@ -28,35 +30,32 @@ public class KalenderResource {
SecurityIdentity identity; SecurityIdentity identity;
@Inject @Inject
Template kalenderpage; Template kalenderpage;
@Inject
@Location("export/textExport.txt")
Template textExport;
@Location("export/icsExport.ics")
Template icsExport;
@Path("") @Path("")
@GET @GET
@Produces(MediaType.TEXT_HTML) @Produces(MediaType.TEXT_HTML)
public TemplateInstance kalender() { public TemplateInstance kalender(@QueryParam("offset") @DefaultValue("0") int offsetInWeeks) {
return kalenderWithOffset(0); List<KalenderTag> week = getWeek(offsetInWeeks);
}
@Path("offset/{weeks}")
@GET
@Produces(MediaType.TEXT_HTML)
public TemplateInstance kalenderWithOffset(@PathParam("weeks") int offsetInWeeks) {
User currentUser = User.find("username", identity.getPrincipal().getName()).singleResult();
LocalDate today = LocalDate.now();
LocalDate montag = today.minusDays(today.getDayOfWeek().getValue() - 1).plusDays(7 * offsetInWeeks);
List<KalenderTag> week = getWeek(currentUser, montag);
return kalenderpage return kalenderpage
.data("today", today) .data("today", LocalDate.now())
.data("offset", offsetInWeeks) .data("offset", offsetInWeeks)
.data("week", week); .data("week", week);
} }
private List<KalenderTag> getWeek(User currentUser, LocalDate start) { private List<KalenderTag> getWeek(int offsetInWeeks) {
User currentUser = getCurrentUser();
LocalDate today = LocalDate.now();
LocalDate montag = today.minusDays(today.getDayOfWeek().getValue() - 1).plusDays(7 * offsetInWeeks);
return Stream.iterate(0, i -> i < 5, i -> ++i) return Stream.iterate(0, i -> i < 5, i -> ++i)
.map(d -> { .map(d -> {
LocalDate day = start.plusDays(d); LocalDate day = montag.plusDays(d);
KalenderTag tag = (KalenderTag) KalenderTag.find("day", day).singleResultOptional().orElse(new KalenderTag(day)); KalenderTag tag = (KalenderTag) KalenderTag.find("day", day).singleResultOptional().orElse(new KalenderTag(day));
tag.setCurrentUserInOffice(currentUser.equals(tag.getInOffice())); tag.setCurrentUserInOffice(currentUser.equals(tag.getInOffice()));
tag.setToday(LocalDate.now().equals(day)); tag.setToday(LocalDate.now().equals(day));
@@ -65,6 +64,14 @@ public class KalenderResource {
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
private List<Event> getEvents(int offsetInWeeks) {
List<KalenderTag> week = getWeek(offsetInWeeks);
return week.stream()
.filter(d -> d.isCurrentUserInOffice())
.map(d-> new Event(LocalDateTime.now(), d.getDay()))
.collect(Collectors.toList());
}
@POST @POST
@Transactional @Transactional
@Consumes(MediaType.MULTIPART_FORM_DATA) @Consumes(MediaType.MULTIPART_FORM_DATA)
@@ -73,7 +80,7 @@ public class KalenderResource {
@QueryParam("offset") int offsetInWeeks, @MultipartForm KalenderTagForm kalenderForm) { @QueryParam("offset") int offsetInWeeks, @MultipartForm KalenderTagForm kalenderForm) {
LocalDate dayParsed = LocalDate.parse(day); LocalDate dayParsed = LocalDate.parse(day);
User currentUser = User.find("username", identity.getPrincipal().getName()).singleResult(); User currentUser = getCurrentUser();
try { try {
KalenderTag tag = KalenderTag.find("day", dayParsed).singleResult(); KalenderTag tag = KalenderTag.find("day", dayParsed).singleResult();
if (kalenderForm.isInOffice() && tag.getInOffice() == null) { if (kalenderForm.isInOffice() && tag.getInOffice() == null) {
@@ -87,6 +94,24 @@ public class KalenderResource {
tag.persist(); tag.persist();
} }
return kalenderWithOffset(offsetInWeeks); return kalender(offsetInWeeks);
}
private User getCurrentUser() {
return User.find("username", identity.getPrincipal().getName()).singleResult();
}
@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("export/txt")
public TemplateInstance exportTxt(@QueryParam("offset") int offset) {
return textExport.data("week", getWeek(offset));
}
@GET
@Produces("text/calendar")
@Path("export/ics")
public TemplateInstance exportIcs(@QueryParam("offset") int offset) {
return icsExport.data("events", getEvents(offset));
} }
} }

View File

@@ -28,6 +28,7 @@
{#if info}<div class="alert alert-primary" role="alert">{info}</div>{/if} {#if info}<div class="alert alert-primary" role="alert">{info}</div>{/if}
{#insert contents}No contents!{/} {#insert contents}No contents!{/}
</div> </div>
<script src="/webjars/popper.js/2.9.2/umd/popper.min.js"></script>
<script src="/webjars/bootstrap/5.0.0/js/bootstrap.min.js"></script> <script src="/webjars/bootstrap/5.0.0/js/bootstrap.min.js"></script>
</body> </body>
</html> </html>

View File

@@ -0,0 +1,19 @@
BEGIN:VCALENDAR
VERSION:2.0
METHOD:PUBLISH
PRODID:-//kalender.bremer.rocks//iCal Generator//DE
{#for event in events}
BEGIN:VEVENT
CREATED:{event.created}
LAST-MODIFIED:{event.lastModified}
DTSTAMP:{event.dtStamp}
SUMMARY:VIT
DTSTART;VALUE=DATE:{event.dtStart}
DTEND;VALUE=DATE:{event.dtEnd}
URL:https://kalender.bremer.rocks
DESCRIPTION:Arbeit im VIT-Buero
TRANSP:TRANSPARENT
UID:{event.uid}
END:VEVENT
{/for}
END:VCALENDAR

View File

@@ -0,0 +1,3 @@
{#for day in week}
{day.day.formatCommon.rightPad(30)} {#if day.inOffice}{day.inOffice.username}{/if}
{/for}

View File

@@ -6,17 +6,17 @@
Heute ist {today.formatCommon} Heute ist {today.formatCommon}
</div> </div>
<div class="mt-2"> <div class="mt-3">
<nav aria-label="Page navigation example"> <nav aria-label="Page navigation example">
<ul class="pagination"> <ul class="pagination">
<li class="page-item"><a class="page-link" href="/kalender">aktuelle Woche</a></li> <li class="page-item"><a class="page-link" href="/kalender">aktuelle Woche</a></li>
<li class="page-item"> <li class="page-item">
<a class="page-link" href="/kalender/offset/{offset.minus(1)}" aria-label="Previous"> <a class="page-link" href="/kalender?offset={offset.minus(1)}" aria-label="Previous">
<span aria-hidden="true">&laquo;</span> <span aria-hidden="true">&laquo;</span>
</a> </a>
</li> </li>
<li class="page-item"> <li class="page-item">
<a class="page-link" href="/kalender/offset/{offset.plus(1)}" aria-label="Next"> <a class="page-link" href="/kalender?offset={offset.plus(1)}" aria-label="Next">
<span aria-hidden="true">&raquo;</span> <span aria-hidden="true">&raquo;</span>
</a> </a>
</li> </li>
@@ -24,7 +24,7 @@
</nav> </nav>
</div> </div>
<div class="mt-2"> <div>
<table class="table table-striped table-bordered"> <table class="table table-striped table-bordered">
<thead> <thead>
<tr> <tr>
@@ -57,5 +57,17 @@
</table> </table>
</div> </div>
<div class="mt-2">
<div class="btn-group">
<button type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
Export
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="/kalender/export/txt?offset={offset}" target="_blank">txt für alle</a></li>
<li><a class="dropdown-item" href="/kalender/export/ics?offset={offset}">ics für mich</a></li>
</ul>
</div>
</div>
{/contents} {/contents}
{/include} {/include}

View File

@@ -12,4 +12,9 @@ class CommonExtensionsTest {
void testFormatCommon() { void testFormatCommon() {
assertEquals("Sonntag, 4.7.2021", CommonExtensions.formatCommon(LocalDate.of(2021, 7, 4))); assertEquals("Sonntag, 4.7.2021", CommonExtensions.formatCommon(LocalDate.of(2021, 7, 4)));
} }
@Test
void testRightPad() {
assertEquals("foo ", CommonExtensions.rightPad("foo", 5));
}
} }

View File

@@ -0,0 +1,34 @@
package de.mbremer.kalender;
import org.junit.jupiter.api.Test;
import java.time.LocalDate;
import java.time.LocalDateTime;
import static org.junit.jupiter.api.Assertions.*;
class EventTest {
@Test
void getCreated() {
Event event = new Event(LocalDateTime.of(2021, 7, 18, 14, 25, 45), LocalDate.of(2022, 1, 2));
assertEquals("20210718T142545Z", event.getCreated());
assertEquals("20210718T142545Z", event.getLastModified());
assertEquals("20210718T142545Z", event.getDtStamp());
}
@Test
void getDtstartEnd() {
Event event = new Event(LocalDateTime.of(2021, 7, 18, 14, 25, 45), LocalDate.of(2022, 1, 2));
assertEquals("20220102", event.getDtStart());
assertEquals("20220103", event.getDtEnd());
}
@Test
void getUid() {
Event event = new Event(LocalDateTime.of(2021, 7, 18, 14, 25, 45), LocalDate.of(2022, 1, 2));
assertTrue(event.getUid().matches("([a-f0-9]{8}(-[a-f0-9]{4}){4}[a-f0-9]{8})@buerokalender"));
}
}