other merge conflict resloves

This commit is contained in:
s5260822 2025-03-18 20:38:50 +01:00
parent 37a300fa50
commit 332fe49a02
5 changed files with 453 additions and 9 deletions

View file

@ -4,6 +4,7 @@ import com.mongodb.MongoClientSettings;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.WriteConcern;
import com.mongodb.WriteConcern;
import com.mongodb.bulk.BulkWriteResult;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
@ -773,6 +774,14 @@ public class MongoDBHandler {
return count > 0;
}
public String getMemberPhoto(String memberId) {
Document photoDocument = memberPhotoCollection.find(eq("memberId", memberId)).first();
if (photoDocument == null) {
return null;
}
return photoDocument.getString("base64");
}
public void close() {
mongoClient.close();
}

View file

@ -0,0 +1,161 @@
package org.texttechnologylab.project.gruppe_05_1.rest;
import gnu.trove.impl.sync.TSynchronizedShortObjectMap;
import io.javalin.http.Context;
import io.javalin.openapi.*;
import org.apache.commons.collections.bag.SynchronizedSortedBag;
import org.texttechnologylab.project.gruppe_05_1.database.MongoPprUtils;
import org.texttechnologylab.project.gruppe_05_1.domain.html.HtmlSpeech;
import org.texttechnologylab.project.gruppe_05_1.domain.html.Parlamentarier;
import org.texttechnologylab.project.gruppe_05_1.domain.html.ParlamentarierDetails;
import org.texttechnologylab.project.gruppe_05_1.domain.speech.SpeechMetaData;
import org.texttechnologylab.project.gruppe_05_1.util.Logger;
import org.texttechnologylab.project.gruppe_05_1.util.PPRUtils;
import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Speech;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class FrontEndController {
@OpenApi(
summary = "Get the homepage.",
description = "Get the homepage",
operationId = "getHomepage",
path = "/",
methods = HttpMethod.GET,
tags = {"Homepage"},
responses = {
@OpenApiResponse(status = "200")
})
public static void getHomepage(Context ctx) {
ctx.render("home.ftl");
}
@OpenApi(
summary = "Get alle Parlamentarier. Man kann nach Vor-, Nachname oder Partei filtern.",
description = "Listet alle Parlamentarier bzw. diejenige, welche den Filter entsprechen",
operationId = "getAllParlamentarier",
path = "/",
methods = HttpMethod.GET,
tags = {"Parlamentarier"},
queryParams = {
@OpenApiParam(name = "filter", description = "Full-Text-Filter. Kann Vorname, Nachname oder Partei filtern", required = false),
},
responses = {
@OpenApiResponse(status = "200", content = {@OpenApiContent(from = Parlamentarier[].class)})
})
public static void getAllParlamentarier(Context ctx) {
String filter = ctx.queryParam("filter");
Logger.info("Filter: '" + filter + "'");
List<Parlamentarier> parlamentarier = MongoPprUtils.getAllParlamentarier(filter);
PPRUtils.sortParlamentarierByName(parlamentarier);
Logger.info(parlamentarier.size() + " MdBs gefunden");
Map<String, Object> attributes = new HashMap<>();
attributes.put("parlamentarier", parlamentarier);
attributes.put("filter", filter);
ctx.render("parlamentarier.ftl", attributes);
}
/**
* Zeigt die Details eines Parlamentariers an:
* - persönliche Daten (Geburtsdatum, -ort, Vita, Religion etc.).
* - Mitgliederschaften, falls vorhanden
* - Fotos, falls vorhanden
* @param ctx JavaLin-Context
*/
@OpenApi(
summary = "Zeigt die Details eines Parlamentariers an",
description = "Zeigt persönliche Daten, Mitgliederschaften, Fotos",
operationId = "getParlamentarierDetails",
path = "/portfolio/{id}",
methods = HttpMethod.GET,
tags = {"Parlamentarier"},
pathParams = {
@OpenApiParam(name = "id", description = "id des Parlamentariers", required = true),
},
responses = {
@OpenApiResponse(status = "200", content = {@OpenApiContent(from = ParlamentarierDetails.class)})
})
public static void getParlamentarierDetails(Context ctx) {
String id = ctx.pathParam("id");
Logger.info("getParlamentarierDetails, ID = " + id);
ParlamentarierDetails pd = MongoPprUtils.getParlamentarierDetailsByID(id);
Map<String, Object> attributes = new HashMap<>();
attributes.put("p", pd);
Long speechCount = MongoPprUtils.countSpeechesOfSpeaker(pd.getId());
attributes.put("speechesCount", speechCount);
attributes.put("pic", MongoPprUtils.getMemberPhoto(pd.getId()));
if (speechCount == 0) {
attributes.put("speechesPlaceholder", null);
} else {
attributes.put("speechesPlaceholder", new ArrayList<>());
}
ctx.render("parlamentarierDetails.ftl", attributes);
}
/**
* Liste alle Reden eines Parlamentariers an
* @param ctx Javalin Context
*/
@OpenApi(
summary = "Liste alle Reden eines Parlamentariers an",
description = "Liste alle Reden eines Parlamentariers an",
operationId = "listSpeeches",
path = "/reden/{id}",
methods = HttpMethod.GET,
tags = {"Rede"},
pathParams = {
@OpenApiParam(name = "id", description = "id des Parlamentariers", required = true),
},
responses = {
@OpenApiResponse(status = "200", content = {@OpenApiContent(from = Speech[].class)})
})
public static void listSpeeches(Context ctx) {
String parlamentarierId = ctx.pathParam("id");
ParlamentarierDetails p = MongoPprUtils.getParlamentarierDetailsByID(parlamentarierId);
List<SpeechMetaData> speechMetaDataList = MongoPprUtils.getSpeechesMetadataForSpeaker(parlamentarierId);
Map<String, Object> attributes = new HashMap<>();
attributes.put("p", p);
attributes.put("speechesMetaDataList", speechMetaDataList);
ctx.render("showSpeechesList.ftl", attributes);
}
/**
* Zeige eine bestimmte Rede des Parlamentariers an
* @param ctx Javalin Context
*/
@OpenApi(
summary = "Zeige eine bestimmte Rede des Parlamentariers an",
description = "Zeige eine bestimmte Rede des Parlamentariers an",
operationId = "showSpeech",
path = "/reden/{id}/{redeID}",
methods = HttpMethod.GET,
tags = {"Rede"},
pathParams = {
@OpenApiParam(name = "id", description = "id des Parlamentariers", required = true),
@OpenApiParam(name = "redeId", description = "id der Rede", required = true),
},
responses = {
@OpenApiResponse(status = "200", content = {@OpenApiContent(from = Speech.class)})
})
public static void showSpeech(Context ctx) {
String redeId = ctx.pathParam("redeId");
Map<String, Object> attributes = new HashMap<>();
HtmlSpeech speech = MongoPprUtils.getSpeechByKey(redeId);
attributes.put("s", speech);
ctx.render("speech.ftl", attributes);
}
}

View file

@ -0,0 +1,69 @@
package org.texttechnologylab.project.gruppe_05_1.rest;
import freemarker.template.Configuration;
import freemarker.template.TemplateExceptionHandler;
import io.javalin.Javalin;
import io.javalin.http.staticfiles.Location;
import io.javalin.openapi.plugin.OpenApiPlugin;
import io.javalin.openapi.plugin.redoc.ReDocPlugin;
import io.javalin.rendering.template.JavalinFreemarker;
import org.texttechnologylab.project.gruppe_05_1.util.Logger;
import java.io.File;
import java.io.IOException;
import static org.texttechnologylab.project.gruppe_05_1.Main.JAVALIN_STATIC_FILES_DIR;
import static org.texttechnologylab.project.gruppe_05_1.Main.JAVALIN_TEMPLATE_DIR;
public class RESTHandlerOld {
public void startJavalin() {
// Javalin Konfiguration (z.B. port)
JavalinConfig jlConfig = new JavalinConfig();
int port = jlConfig.getPort();
// FreeMarker Konfiguration
Configuration fmConfig = new Configuration(Configuration.VERSION_2_3_33);
fmConfig.setDefaultEncoding("UTF-8");
try {
fmConfig.setDirectoryForTemplateLoading(new File(JAVALIN_TEMPLATE_DIR));
} catch (IOException e) {
throw new RuntimeException(e);
}
fmConfig.setLogTemplateExceptions(true);
fmConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
// Erzeuge die Javalin app
Javalin app = Javalin.create(config -> {
config.staticFiles.add(JAVALIN_STATIC_FILES_DIR, Location.EXTERNAL); // momentan nicht benutzt
config.fileRenderer(new JavalinFreemarker(fmConfig));
config.registerPlugin(new OpenApiPlugin(pluginConfig -> {
// Define OpenAPI spec configuration
pluginConfig.withDefinitionConfiguration((version, definition) -> {
definition.withOpenApiInfo(info -> info.setTitle("Javalin OpenAPI Documentation"));
});
}));
config.registerPlugin(new ReDocPlugin());
})
.start(port);
Logger.info("Javalin app started on http://localhost:" + port);
// Routes
// ======
// Parlamentarier
app.get("/", ParlamentarierController::getAllParlamentarier);
app.get("/portfolio/{id}", ParlamentarierController::getParlamentarierDetails);
app.delete("/deleteParlamentarier", ParlamentarierController::deleteAllParlamentarier);
// Reden
app.get("/reden/{id}", SpeechController::listSpeeches); // zeige Reden eines Parlamentariers an
app.get("/reden/{id}/{redeId}", SpeechController::showSpeech); // zeige eine bestimmte Rede des Parlamentariers an
}
}

View file

@ -1,9 +0,0 @@
<!DOCTYPE html>
<html>
<body>
<h1>Heading</h1>
<p>paragraph.</p>
</body>
</html>

View file

@ -0,0 +1,214 @@
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css');
:root {
--primary-color: #333;
--accent-color: #a00000;
--background-color: #F4F4F9;
--confirm-button-color: #28a745;
--confirm-button-color-hover: #218838;
--header-background-color: darkgray;
}
/* General Reset */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
background-color: var(--background-color)
}
header {
background-color: var(--header-background-color);
position: fixed;
top: 0;
left: 0;
right: 0;
}
nav {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
nav a {
color: white;
text-decoration: none;
font-size: 1.25rem;
margin: 10px;
margin-top: 0;
padding: 5px 10px 5px 10px;
border: solid 1px white;
border-radius: 5px
}
footer {
background-color: black;
color: white;
text-align: center;
position: fixed;
bottom: 0;
left: 0;
right: 0;
}
/* Body Styling */
body {
font-family: 'Arial', sans-serif;
background-color: #f4f4f9;
color: var(--primary-color);
line-height: 1.6;
padding: 20px;
margin-top: 120px
}
/* Heading Styling */
h1, h2 {
text-align: center;
font-size: 2.5rem;
color: var(--accent-color);
margin-bottom: 30px;
}
h2 {
font-size: 1.5rem;
}
/* Form Styling */
form {
display: flex;
justify-content: center;
gap: 15px;
margin-bottom: 30px;
}
input[type="text"] {
padding: 10px;
font-size: 1rem;
border: 1px solid #ddd;
border-radius: 4px;
width: 200px;
}
button {
padding: 10px 20px;
font-size: 1rem;
background-color: var(--accent-color);
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s ease;
}
button:hover {
background-color: var(--accent-color);
}
/* Table Styling */
table {
width: 100%;
border-collapse: collapse;
margin-top: 30px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
th, td {
padding: 12px;
text-align: left;
border-bottom: 1px solid #ddd;
}
th {
background-color:
var(--background-color);
color: var(--accent-color);
font-size: 1.2rem;
}
td {
font-size: 1rem;
}
td a {
text-decoration: none;
color: var(--accent-color);
font-weight: bold;
transition: color 0.3s ease;
}
td a:hover {
color: var(--accent-color);
}
tbody tr:hover {
background-color: var(--background-color);
}
/* Responsive Styling */
@media (max-width: 768px) {
table, th, td {
font-size: 0.9rem;
}
form {
flex-direction: column;
align-items: center;
}
input[type="text"] {
width: 100%;
max-width: 300px;
}
button {
width: 100%;
max-width: 150px;
}
}
.add-member-button {
background-color: var(--confirm-button-color); /* Green color */
color: white;
padding: 10px 20px;
text-decoration: none;
border-radius: 5px;
font-size: 16px;
display: inline-block;
transition: background-color 0.3s ease;
}
/* Change button color on hover */
.add-member-button:hover {
background-color: var(--confirm-button-color-hover); /* Darker green on hover */
}
#search-button {
width: 75px;
background-color: var(--confirm-button-color);
border-radius: 5px;
border: 1px solid lightgray;
}
#search-button:hover {
background-color: var(--confirm-button-color-hover);
}
.back-link {
position: fixed;
bottom: 50px;
right: 50px;
background-color: var(--accent-color);
border-radius: 5px;
padding: 5px 10px 5px 10px;
text-decoration: none;
color: white
}