einfache Reservierung möglich

This commit is contained in:
mbremer
2021-07-04 20:02:08 +02:00
parent 825363e491
commit 166871165f
10 changed files with 269 additions and 17 deletions

10
pom.xml
View File

@@ -79,6 +79,16 @@
<artifactId>rest-assured</artifactId> <artifactId>rest-assured</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-security</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-panache-mock</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.webjars</groupId> <groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId> <artifactId>bootstrap</artifactId>

View File

@@ -0,0 +1,15 @@
package de.mbremer.extension;
import io.quarkus.qute.TemplateExtension;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
@TemplateExtension
public class CommonExtensions {
public static String formatCommon(LocalDate date) {
return date == null ? "" : date.atStartOfDay(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("EEEE, d.M.yyyy"));
}
}

View File

@@ -1,19 +1,31 @@
package de.mbremer.kalender; package de.mbremer.kalender;
import de.mbremer.secutity.User;
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 org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.providers.multipart.MultipartForm;
import javax.annotation.security.RolesAllowed; import javax.annotation.security.RolesAllowed;
import javax.inject.Inject; import javax.inject.Inject;
import javax.ws.rs.GET; import javax.persistence.NoResultException;
import javax.ws.rs.Path; import javax.transaction.Transactional;
import javax.ws.rs.Produces; import javax.ws.rs.*;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import java.time.LocalDate;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Path("/kalender") @Path("/kalender")
@RolesAllowed({"USER", "ADMIN"}) @RolesAllowed({"USER", "ADMIN"})
public class KalenderResource { public class KalenderResource {
@Inject
Logger log;
@Inject
SecurityIdentity identity;
@Inject @Inject
Template kalender; Template kalender;
@@ -21,6 +33,54 @@ public class KalenderResource {
@GET @GET
@Produces(MediaType.TEXT_HTML) @Produces(MediaType.TEXT_HTML)
public TemplateInstance kalender() { public TemplateInstance kalender() {
return kalender.instance(); User currentUser = User.find("username", identity.getPrincipal().getName()).singleResult();
LocalDate today = LocalDate.now();
LocalDate montag = today.minusDays(today.getDayOfWeek().getValue() - 1);
List<KalenderTag> week0 = getWeek(currentUser, montag);
List<KalenderTag> week1 = getWeek(currentUser, montag.plusDays(7));
List<KalenderTag> week2 = getWeek(currentUser, montag.plusDays(14));
return kalender
.data("today", today)
.data("week0", week0)
.data("week1", week1)
.data("week2", week2);
}
private List<KalenderTag> getWeek(User currentUser, LocalDate start) {
return Stream.iterate(0, i -> i < 5, i -> ++i)
.map(d -> {
LocalDate day = start.plusDays(d);
KalenderTag tag = (KalenderTag) KalenderTag.find("day", day).singleResultOptional().orElse(new KalenderTag(day));
tag.setCurrentUserInOffice(currentUser.equals(tag.getInOffice()));
return tag;
})
.collect(Collectors.toList());
}
@POST
@Transactional
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Path("/inoffice/{day}")
public TemplateInstance update(@PathParam("day") String day, @MultipartForm KalenderTagForm kalenderForm) {
LocalDate dayParsed = LocalDate.parse(day);
User currentUser = User.find("username", identity.getPrincipal().getName()).singleResult();
try {
KalenderTag tag = KalenderTag.find("day", dayParsed).singleResult();
if (kalenderForm.isInOffice() && tag.getInOffice() == null) {
tag.setInOffice(currentUser);
} else if (!kalenderForm.isInOffice() && currentUser.equals(tag.getInOffice())) {
tag.setInOffice(null);
}
} catch (NoResultException e) {
KalenderTag tag = new KalenderTag(dayParsed);
tag.setInOffice(currentUser);
tag.persist();
}
return kalender();
} }
} }

View File

@@ -3,18 +3,27 @@ package de.mbremer.kalender;
import de.mbremer.secutity.User; import de.mbremer.secutity.User;
import io.quarkus.hibernate.orm.panache.PanacheEntity; import io.quarkus.hibernate.orm.panache.PanacheEntity;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter; import lombok.Setter;
import javax.persistence.GeneratedValue; import javax.persistence.Entity;
import javax.persistence.Id; import javax.persistence.OneToOne;
import javax.persistence.OneToMany; import javax.persistence.Transient;
import java.time.LocalDate; import java.time.LocalDate;
@Getter @Getter
@Setter @Setter
@RequiredArgsConstructor
@Entity
public class KalenderTag extends PanacheEntity { public class KalenderTag extends PanacheEntity {
private LocalDate date; private LocalDate day;
@OneToMany @OneToOne
private User inOffice; private User inOffice;
@Transient
private boolean currentUserInOffice;
public KalenderTag(LocalDate day) {
this.day = day;
}
} }

View File

@@ -0,0 +1,16 @@
package de.mbremer.kalender;
import org.jboss.resteasy.annotations.providers.multipart.PartType;
import javax.ws.rs.FormParam;
import javax.ws.rs.core.MediaType;
public class KalenderTagForm {
@FormParam("inoffice")
@PartType(MediaType.TEXT_PLAIN)
String inOffice;
boolean isInOffice() {
return "on".equals(inOffice);
}
}

View File

@@ -11,6 +11,6 @@ quarkus.flyway.migrate-at-start=true
# Security # Security
quarkus.http.auth.form.enabled=true quarkus.http.auth.form.enabled=true
quarkus.http.auth.session.encryption-key=zHId14V+uiyxmbzhEPCyi7VvbaI80UeEO5yu0H/hVLs= #quarkus.http.auth.session.encryption-key=zHId14V+uiyxmbzhEPCyi7VvbaI80UeEO5yu0H/hVLs=
# 24h # 24h
quarkus.http.auth.form.timeout=86400 quarkus.http.auth.form.timeout=86400

View File

@@ -9,6 +9,6 @@ create table users (
create table kalendertag ( create table kalendertag (
id bigint not null primary key, id bigint not null primary key,
date date not null unique, day date not null unique,
inoffice_id bigint not null references users inoffice_id bigint references users
); );

View File

@@ -3,10 +3,93 @@
{#contents} {#contents}
<div class="mt-2"> <div class="mt-2">
aktuelle Woche<br> Heute ist {today.formatCommon}
nächste Woche<br> </div>
übernächste Woche<br> <div class="mt-2">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th scope="col" class="col-2">Ich will ins Büro</th>
<th scope="col" class="col-3">Datum</th>
<th scope="col">Im Büro</th>
</tr>
</thead>
<tbody>
{#for day in week0}
<tr>
<td>
<form action="/kalender/inoffice/{day.day}" method="POST" name="kalenderForm" enctype="multipart/form-data">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="inoffice" onchange="this.form.submit()"
{#if day.isCurrentUserInOffice}checked{/if} >
</div>
</form>
</td>
<td>
{day.day.formatCommon}
</td>
<td>
{#if day.inOffice}{day.inOffice.username}{/if}
</td>
</tr>
{/for}
</tbody>
</table>
</div> </div>
{/contents} <div class="mt-2">
{/include} <table class="table table-striped table-bordered">
<tbody>
{#for day in week1}
<tr>
<td class="col-2">
<form action="/kalender/inoffice/{day.day}" method="POST" name="kalenderForm" enctype="multipart/form-data">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="inoffice" onchange="this.form.submit()"
{#if day.isCurrentUserInOffice}checked{/if} >
</div>
</form>
</td>
<td class="col-3">
{day.day.formatCommon}
</td>
<td>
{#if day.inOffice}{day.inOffice.username}{/if}
</td>
</tr>
{/for}
</tbody>
</table>
<div class="mt-2">
<table class="table table-striped table-bordered">
<tbody>
{#for day in week2}
<tr>
<td class="col-2">
<form action="/kalender/inoffice/{day.day}" method="POST" name="kalenderForm" enctype="multipart/form-data">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="inoffice" onchange="this.form.submit()"
{#if day.isCurrentUserInOffice}checked{/if} >
</div>
</form>
</td>
<td class="col-3">
{day.day.formatCommon}
</td>
<td>
{#if day.inOffice}{day.inOffice.username}{/if}
</td>
</tr>
{/for}
</tbody>
</table>
</div>
{/contents}
{/include}

View File

@@ -0,0 +1,15 @@
package de.mbremer.extension;
import org.junit.jupiter.api.Test;
import java.time.LocalDate;
import static org.junit.jupiter.api.Assertions.*;
class CommonExtensionsTest {
@Test
void testFormatCommon() {
assertEquals("Sonntag, 4.7.2021", CommonExtensions.formatCommon(LocalDate.of(2021, 7, 4)));
}
}

View File

@@ -0,0 +1,44 @@
package de.mbremer.kalender;
import de.mbremer.secutity.User;
import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
import io.quarkus.hibernate.orm.panache.PanacheQuery;
import io.quarkus.panache.mock.PanacheMock;
import io.quarkus.security.identity.SecurityIdentity;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.mockito.InjectMock;
import io.quarkus.test.security.TestSecurity;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.security.Principal;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.containsString;
import static org.mockito.Mockito.when;
@QuarkusTest
class KalenderResourceTest {
@InjectMock
SecurityIdentity identity;
@Test
@TestSecurity(authorizationEnabled = false)
void testKalender() {
PanacheMock.mock(User.class);
Principal principal = Mockito.mock(Principal.class);
PanacheQuery<PanacheEntityBase> query = Mockito.mock(PanacheQuery.class);
when(principal.getName()).thenReturn("admin");
when(identity.getPrincipal()).thenReturn(principal);
when(query.singleResult()).thenReturn(new User());
when(User.find("username", "admin")).thenReturn(query);
given()
.when().get("/kalender")
.then()
.statusCode(200)
.body(containsString("Heute ist"));
}
}