From 353a0e0547b45cdc04034af12a1d1e19ecc123a8 Mon Sep 17 00:00:00 2001 From: Schlaumeier5 Date: Tue, 31 Mar 2026 16:25:07 +0200 Subject: [PATCH 1/9] Added a new Template type: DynamicHTMLTemplate this one is basically meant as a hook for plugins to inject their own templates into pages without completely rewriting the pages --- .../de/igslandstuhl/database/Registry.java | 5 +++ .../database/client/HTMLTemplate.java | 4 ++ .../client/dynamic/DynamicFieldType.java | 44 +++++++++++++++++++ .../client/dynamic/DynamicHTMLTemplate.java | 27 ++++++++++++ .../meta/dynamic/dynamic_field_types.json | 3 ++ 5 files changed, 83 insertions(+) create mode 100644 src/main/java/de/igslandstuhl/database/client/dynamic/DynamicFieldType.java create mode 100644 src/main/java/de/igslandstuhl/database/client/dynamic/DynamicHTMLTemplate.java create mode 100644 src/main/resources/meta/dynamic/dynamic_field_types.json diff --git a/src/main/java/de/igslandstuhl/database/Registry.java b/src/main/java/de/igslandstuhl/database/Registry.java index 6e756e2..12e09f8 100644 --- a/src/main/java/de/igslandstuhl/database/Registry.java +++ b/src/main/java/de/igslandstuhl/database/Registry.java @@ -8,6 +8,7 @@ import java.util.stream.Stream; import de.igslandstuhl.database.client.HTMLTemplate; +import de.igslandstuhl.database.client.dynamic.DynamicFieldType; import de.igslandstuhl.database.client.navigation.NavigationElement; import de.igslandstuhl.database.client.navigation.NavigationType; import de.igslandstuhl.database.plugins.Plugin; @@ -28,6 +29,7 @@ public class Registry implements Closeable { private static final Registry WEB_PATH_REGISTRY = new Registry<>(); private static final EnumRegistry NAVIGATION_REGISTRY = new EnumRegistry<>(NavigationType.class); + private static final EnumRegistry DYNAMIC_TEMPLATES_REGISTRY = new EnumRegistry<>(DynamicFieldType.class); private static final Registry TEMPLATE_REGISTRY = new Registry<>(); public static Registry commandRegistry() { @@ -51,6 +53,9 @@ public static Registry webPathRegistry() { public static EnumRegistry navigationRegistry() { return NAVIGATION_REGISTRY; } + public static EnumRegistry dynamicTemplatesRegistry() { + return DYNAMIC_TEMPLATES_REGISTRY; + } public static Registry templateRegistry() { return TEMPLATE_REGISTRY; } diff --git a/src/main/java/de/igslandstuhl/database/client/HTMLTemplate.java b/src/main/java/de/igslandstuhl/database/client/HTMLTemplate.java index 79a3d20..2315956 100644 --- a/src/main/java/de/igslandstuhl/database/client/HTMLTemplate.java +++ b/src/main/java/de/igslandstuhl/database/client/HTMLTemplate.java @@ -4,6 +4,8 @@ import java.util.Map; import de.igslandstuhl.database.Registry; +import de.igslandstuhl.database.client.dynamic.DynamicFieldType; +import de.igslandstuhl.database.client.dynamic.DynamicHTMLTemplate; import de.igslandstuhl.database.client.navigation.HTMLNavigationTemplate; import de.igslandstuhl.database.client.navigation.NavigationAppearance; import de.igslandstuhl.database.client.navigation.NavigationElement; @@ -36,6 +38,8 @@ public static void registerAll() { break; case "HTMLNavigationTemplate": register(new HTMLNavigationTemplate(NavigationAppearance.valueOf((String) template.get("appearance")), NavigationType.valueOf((String) template.get("navigation_type"))), key); + case "DynamicHTMLTemplate": + register(new DynamicHTMLTemplate(DynamicFieldType.valueOf((String) template.get("dynamic_field_type"))), key); default: break; } diff --git a/src/main/java/de/igslandstuhl/database/client/dynamic/DynamicFieldType.java b/src/main/java/de/igslandstuhl/database/client/dynamic/DynamicFieldType.java new file mode 100644 index 0000000..7220797 --- /dev/null +++ b/src/main/java/de/igslandstuhl/database/client/dynamic/DynamicFieldType.java @@ -0,0 +1,44 @@ +package de.igslandstuhl.database.client.dynamic; + +import java.lang.reflect.InvocationTargetException; +import java.util.List; + +import de.igslandstuhl.database.Registry; +import de.igslandstuhl.database.server.resources.ResourceLocation; +import de.igslandstuhl.database.utils.RegistryEnum; + +public class DynamicFieldType extends RegistryEnum { + protected DynamicFieldType(Registry registry, String key) { + super(registry, key); + } + + private static final ResourceLocation meta = new ResourceLocation("meta", "dynamic", "dynamic_field_types.json"); + @Override + protected DynamicFieldType[] values(Registry registry) { + List DynamicFieldTypes = registry.stream().toList(); + DynamicFieldType[] arr = new DynamicFieldType[DynamicFieldTypes.size()]; + return DynamicFieldTypes.toArray(arr); + } + + @Override + protected void initValues() { + initUsingJSONMeta(meta); + } + + @Override + protected DynamicFieldType initValue(Registry registry,String key) { + return new DynamicFieldType(registry, key); + } + + public static DynamicFieldType valueOf(String string) { + return RegistryEnum.valueOf(string, DynamicFieldType.class); + } + public static void init() { + try { + RegistryEnum.init(DynamicFieldType.class); + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException | SecurityException e) { + throw new ExceptionInInitializerError(e); + } + } +} diff --git a/src/main/java/de/igslandstuhl/database/client/dynamic/DynamicHTMLTemplate.java b/src/main/java/de/igslandstuhl/database/client/dynamic/DynamicHTMLTemplate.java new file mode 100644 index 0000000..9558733 --- /dev/null +++ b/src/main/java/de/igslandstuhl/database/client/dynamic/DynamicHTMLTemplate.java @@ -0,0 +1,27 @@ +package de.igslandstuhl.database.client.dynamic; + +import java.io.IOException; +import java.util.Map; + +import de.igslandstuhl.database.Registry; +import de.igslandstuhl.database.client.HTMLTemplate; +import de.igslandstuhl.database.client.TemplatingPreprocessor; + +public record DynamicHTMLTemplate(DynamicFieldType type) implements HTMLTemplate { + @Override + public String fill(Map args) { + return Registry.dynamicTemplatesRegistry().stream(type) + .map(Registry.templateRegistry()::get) + .map((t) -> t.fill(args)) + .map(arg0 -> { + try { + return TemplatingPreprocessor.getInstance().executeTemplating(arg0); + } catch (IOException e) { + System.err.println("Failed filling template " + arg0); + e.printStackTrace(); + return ""; + } + }) + .reduce("", (s1, s2) -> s1 + "\n" + s2); + } +} \ No newline at end of file diff --git a/src/main/resources/meta/dynamic/dynamic_field_types.json b/src/main/resources/meta/dynamic/dynamic_field_types.json new file mode 100644 index 0000000..1610ea1 --- /dev/null +++ b/src/main/resources/meta/dynamic/dynamic_field_types.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file From fa49f6c004c4880ee1c16ca0a1c3c53a44b7e634 Mon Sep 17 00:00:00 2001 From: Schlaumeier5 Date: Tue, 31 Mar 2026 16:57:18 +0200 Subject: [PATCH 2/9] Added the first dynamic field type: student_header --- .../igslandstuhl/database/client/HTMLTemplate.java | 2 ++ .../client/dynamic/DynamicHTMLTemplate.java | 14 ++++++++++++++ .../resources/meta/dynamic/dynamic_elements.json | 6 ++++++ .../meta/dynamic/dynamic_field_types.json | 2 +- src/main/resources/meta/templates/templates.json | 9 +++++++++ .../templates/html/student_dashboard.html | 3 +-- .../resources/templates/html/student_header.html | 4 ++++ 7 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 src/main/resources/meta/dynamic/dynamic_elements.json create mode 100644 src/main/resources/templates/html/student_header.html diff --git a/src/main/java/de/igslandstuhl/database/client/HTMLTemplate.java b/src/main/java/de/igslandstuhl/database/client/HTMLTemplate.java index 2315956..8b20614 100644 --- a/src/main/java/de/igslandstuhl/database/client/HTMLTemplate.java +++ b/src/main/java/de/igslandstuhl/database/client/HTMLTemplate.java @@ -21,6 +21,7 @@ private static void register(HTMLTemplate template, String key) { } public static void registerAll() { NavigationElement.registerAll(); + DynamicHTMLTemplate.registerDynamicElements(); Map json = Server.getInstance().getResourceManager().readJsonResourceMerged(meta); json.keySet().forEach((key) -> { @SuppressWarnings("unchecked") @@ -38,6 +39,7 @@ public static void registerAll() { break; case "HTMLNavigationTemplate": register(new HTMLNavigationTemplate(NavigationAppearance.valueOf((String) template.get("appearance")), NavigationType.valueOf((String) template.get("navigation_type"))), key); + break; case "DynamicHTMLTemplate": register(new DynamicHTMLTemplate(DynamicFieldType.valueOf((String) template.get("dynamic_field_type"))), key); default: diff --git a/src/main/java/de/igslandstuhl/database/client/dynamic/DynamicHTMLTemplate.java b/src/main/java/de/igslandstuhl/database/client/dynamic/DynamicHTMLTemplate.java index 9558733..e425e1a 100644 --- a/src/main/java/de/igslandstuhl/database/client/dynamic/DynamicHTMLTemplate.java +++ b/src/main/java/de/igslandstuhl/database/client/dynamic/DynamicHTMLTemplate.java @@ -1,11 +1,16 @@ package de.igslandstuhl.database.client.dynamic; import java.io.IOException; +import java.util.List; import java.util.Map; +import com.google.gson.reflect.TypeToken; + import de.igslandstuhl.database.Registry; import de.igslandstuhl.database.client.HTMLTemplate; import de.igslandstuhl.database.client.TemplatingPreprocessor; +import de.igslandstuhl.database.server.Server; +import de.igslandstuhl.database.server.resources.ResourceLocation; public record DynamicHTMLTemplate(DynamicFieldType type) implements HTMLTemplate { @Override @@ -24,4 +29,13 @@ public String fill(Map args) { }) .reduce("", (s1, s2) -> s1 + "\n" + s2); } + public static final ResourceLocation meta = new ResourceLocation("meta", "dynamic", "dynamic_elements.json"); + public static void registerDynamicElements() { + List> elements = Server.getInstance().getResourceManager().readJsonListMerged(meta, new TypeToken>>() {}); + elements.forEach((m) -> { + DynamicFieldType type = DynamicFieldType.valueOf(m.get("type")); + String template = m.get("template"); + Registry.dynamicTemplatesRegistry().register(type, template); + }); + } } \ No newline at end of file diff --git a/src/main/resources/meta/dynamic/dynamic_elements.json b/src/main/resources/meta/dynamic/dynamic_elements.json new file mode 100644 index 0000000..9f25510 --- /dev/null +++ b/src/main/resources/meta/dynamic/dynamic_elements.json @@ -0,0 +1,6 @@ +[ + { + "type": "STUDENT_HEADER", + "template": "student_header_builtin" + } +] \ No newline at end of file diff --git a/src/main/resources/meta/dynamic/dynamic_field_types.json b/src/main/resources/meta/dynamic/dynamic_field_types.json index 1610ea1..a2a6757 100644 --- a/src/main/resources/meta/dynamic/dynamic_field_types.json +++ b/src/main/resources/meta/dynamic/dynamic_field_types.json @@ -1,3 +1,3 @@ [ - + "STUDENT_HEADER" ] \ No newline at end of file diff --git a/src/main/resources/meta/templates/templates.json b/src/main/resources/meta/templates/templates.json index 69d6494..3e854a1 100644 --- a/src/main/resources/meta/templates/templates.json +++ b/src/main/resources/meta/templates/templates.json @@ -27,6 +27,10 @@ "type": "HTMLFileTemplate", "path": "subject_info" }, + "student_header_builtin": { + "type": "HTMLFileTemplate", + "path": "student_header" + }, "admin_dashboard_nav": { "type": "HTMLNavigationTemplate", @@ -92,5 +96,10 @@ "type": "HTMLNavigationTemplate", "navigation_type": "STUDENT_OTHER", "appearance": "BUTTON_APPEARANCE" + }, + + "student_header": { + "type": "DynamicHTMLTemplate", + "dynamic_field_type": "STUDENT_HEADER" } } \ No newline at end of file diff --git a/src/main/resources/templates/html/student_dashboard.html b/src/main/resources/templates/html/student_dashboard.html index 196edfc..88a92f0 100644 --- a/src/main/resources/templates/html/student_dashboard.html +++ b/src/main/resources/templates/html/student_dashboard.html @@ -1,8 +1,7 @@ %[site;title=Schüler-Dashboard;content=!FOLLOWS]
-

Schüler:

-

Klasse: | E-Mail: | Graduierung:

+ %[student_header]
diff --git a/src/main/resources/templates/html/student_header.html b/src/main/resources/templates/html/student_header.html new file mode 100644 index 0000000..3ab1306 --- /dev/null +++ b/src/main/resources/templates/html/student_header.html @@ -0,0 +1,4 @@ +
+

Schüler:

+

Klasse: | E-Mail: | Graduierung:

+
\ No newline at end of file From 1b1386256ec3a9d6b3eef01fbfa610fe4f46b222 Mon Sep 17 00:00:00 2001 From: Schlaumeier5 Date: Tue, 31 Mar 2026 18:36:06 +0200 Subject: [PATCH 3/9] Added new dynamic templates --- src/main/resources/html/admin/teacher.html | 4 +--- src/main/resources/html/teacher/dashboard.html | 4 +--- .../meta/dynamic/dynamic_elements.json | 18 ++++++++++++++++++ .../meta/dynamic/dynamic_field_types.json | 4 +++- .../resources/meta/templates/templates.json | 12 ++++++++++++ .../templates/html/room_selection.html | 4 ++++ .../templates/html/student_dashboard.html | 5 +---- 7 files changed, 40 insertions(+), 11 deletions(-) create mode 100644 src/main/resources/templates/html/room_selection.html diff --git a/src/main/resources/html/admin/teacher.html b/src/main/resources/html/admin/teacher.html index e6c43f5..96eb3ee 100644 --- a/src/main/resources/html/admin/teacher.html +++ b/src/main/resources/html/admin/teacher.html @@ -19,9 +19,7 @@

Lehrer bearbeiten

- %[class_info] - %[subject_info] - %[room_info] + %[teacher_infos]
\ No newline at end of file diff --git a/src/main/resources/meta/dynamic/dynamic_elements.json b/src/main/resources/meta/dynamic/dynamic_elements.json index 9f25510..c3c7475 100644 --- a/src/main/resources/meta/dynamic/dynamic_elements.json +++ b/src/main/resources/meta/dynamic/dynamic_elements.json @@ -2,5 +2,23 @@ { "type": "STUDENT_HEADER", "template": "student_header_builtin" + }, + + { + "type": "STUDENT_TOP", + "template": "room_selection" + }, + + { + "type": "TEACHER_INFOS", + "template": "class_info" + }, + { + "type": "TEACHER_INFOS", + "template": "subject_info" + }, + { + "type": "TEACHER_INFOS", + "template": "room_info" } ] \ No newline at end of file diff --git a/src/main/resources/meta/dynamic/dynamic_field_types.json b/src/main/resources/meta/dynamic/dynamic_field_types.json index a2a6757..e457ceb 100644 --- a/src/main/resources/meta/dynamic/dynamic_field_types.json +++ b/src/main/resources/meta/dynamic/dynamic_field_types.json @@ -1,3 +1,5 @@ [ - "STUDENT_HEADER" + "STUDENT_HEADER", + "STUDENT_TOP", + "TEACHER_INFOS" ] \ No newline at end of file diff --git a/src/main/resources/meta/templates/templates.json b/src/main/resources/meta/templates/templates.json index 3e854a1..7afddcd 100644 --- a/src/main/resources/meta/templates/templates.json +++ b/src/main/resources/meta/templates/templates.json @@ -31,6 +31,10 @@ "type": "HTMLFileTemplate", "path": "student_header" }, + "room_selection": { + "type": "HTMLFileTemplate", + "path": "room_selection" + }, "admin_dashboard_nav": { "type": "HTMLNavigationTemplate", @@ -101,5 +105,13 @@ "student_header": { "type": "DynamicHTMLTemplate", "dynamic_field_type": "STUDENT_HEADER" + }, + "student_top": { + "type": "DynamicHTMLTemplate", + "dynamic_field_type": "STUDENT_TOP" + }, + "teacher_infos": { + "type": "DynamicHTMLTemplate", + "dynamic_field_type": "TEACHER_INFOS" } } \ No newline at end of file diff --git a/src/main/resources/templates/html/room_selection.html b/src/main/resources/templates/html/room_selection.html new file mode 100644 index 0000000..a5150e7 --- /dev/null +++ b/src/main/resources/templates/html/room_selection.html @@ -0,0 +1,4 @@ +
+ + +
\ No newline at end of file diff --git a/src/main/resources/templates/html/student_dashboard.html b/src/main/resources/templates/html/student_dashboard.html index 88a92f0..abbb85b 100644 --- a/src/main/resources/templates/html/student_dashboard.html +++ b/src/main/resources/templates/html/student_dashboard.html @@ -3,10 +3,7 @@
%[student_header]
-
- - -
+ %[student_top]

Fächer

From ca64da1543c280f922610f8f852b970b9725badf Mon Sep 17 00:00:00 2001 From: Schlaumeier5 Date: Tue, 31 Mar 2026 19:45:49 +0200 Subject: [PATCH 4/9] Moved rooms to external plugin --- .../de/igslandstuhl/database/api/Room.java | 240 ------------------ .../de/igslandstuhl/database/api/Student.java | 22 -- .../igslandstuhl/database/server/Server.java | 3 - .../database/server/commands/Command.java | 65 ----- .../handlers/PostRequestHandler.java | 46 +--- .../webserver/requests/APIPostRequest.java | 6 - .../resources/html/admin/manage_rooms.html | 46 ---- .../resources/js/site/student-database.js | 49 ---- .../meta/dynamic/dynamic_elements.json | 9 - .../meta/navigation/navigation_elements.json | 5 - src/main/resources/meta/paths/get_paths.json | 28 -- .../resources/meta/templates/templates.json | 8 - src/main/resources/sql/pushes/add_room.sql | 5 - src/main/resources/sql/pushes/delete_room.sql | 2 - .../resources/sql/queries/get_all_rooms.sql | 1 - .../sql/queries/get_room_by_label.sql | 3 - src/main/resources/sql/tables/rooms.sql | 4 - .../resources/templates/html/room_info.html | 20 -- .../templates/html/room_selection.html | 4 - .../igslandstuhl/database/api/RoomTest.java | 43 ---- 20 files changed, 2 insertions(+), 607 deletions(-) delete mode 100644 src/main/java/de/igslandstuhl/database/api/Room.java delete mode 100644 src/main/resources/html/admin/manage_rooms.html delete mode 100644 src/main/resources/sql/pushes/add_room.sql delete mode 100644 src/main/resources/sql/pushes/delete_room.sql delete mode 100644 src/main/resources/sql/queries/get_all_rooms.sql delete mode 100644 src/main/resources/sql/queries/get_room_by_label.sql delete mode 100644 src/main/resources/sql/tables/rooms.sql delete mode 100644 src/main/resources/templates/html/room_info.html delete mode 100644 src/main/resources/templates/html/room_selection.html delete mode 100644 src/test/java/de/igslandstuhl/database/api/RoomTest.java diff --git a/src/main/java/de/igslandstuhl/database/api/Room.java b/src/main/java/de/igslandstuhl/database/api/Room.java deleted file mode 100644 index 9919a6c..0000000 --- a/src/main/java/de/igslandstuhl/database/api/Room.java +++ /dev/null @@ -1,240 +0,0 @@ -package de.igslandstuhl.database.api; - -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import de.igslandstuhl.database.server.Server; -import de.igslandstuhl.database.server.sql.SQLHelper; - -/** - * Represents a room in the system. - * Each room has a label and a minimum level required for students to access it. - */ -public class Room implements APIObject { - private static final String[] SQL_FIELDS = {"label", "minimum_level"}; - /** - * A map to store all rooms, keyed by their label. - * This allows for quick access to room information without repeated database queries. - */ - private static final Map rooms = new HashMap<>(); - /** - * The label of the room, which is a unique identifier. - */ - private final String label; - /** - * The minimum level required for students to access this room. - * This is used to determine if a student is eligible to enter the room. - */ - private final int minimumLevel; - - /** - * Constructs a new Room. - * @param label the label of the room - * @param minimumLevel the minimum level required to access the room - */ - private Room(String label, int minimumLevel) { - this.label = label; - this.minimumLevel = minimumLevel; - } - /** - * Creates a Room instance from SQL result fields. - * This method is used to convert the result of a database query into a Room object. - * @param sqlResult the result fields from the SQL query - * @return a Room object constructed from the SQL fields - * @see Room#SQL_FIELDS - */ - private static Room fromSQLFields(String[] sqlResult) { - String label = sqlResult[0]; - int minimumLevel = Integer.parseInt(sqlResult[1]); - return new Room(label, minimumLevel); - } - /** - * Fetches all rooms from the database and populates the static map. - * This method retrieves all room records and stores them in the `rooms` map for quick access. - * @throws SQLException if there is an error accessing the database - */ - public static void fetchAll() throws SQLException { - rooms.clear(); - Server.getInstance().processRequest((fields) -> { - Room room = fromSQLFields(fields); - rooms.put(room.getLabel(), room); - }, "get_all_rooms", SQL_FIELDS); - } - /** - * Checks if the rooms map is empty and fetches all rooms if it is. - * This method ensures that the rooms are loaded into memory only once, - * preventing unnecessary database queries in subsequent calls. - * @throws SQLException if there is an error accessing the database - */ - public static void fetchAllIfNotExists() throws SQLException { - if (rooms.size() == 0) { - fetchAll(); - } - } - - /** - * Returns a map of all rooms. - * This method ensures that all rooms are fetched from the database if they haven't been loaded yet. - * @return a map of room labels to Room objects - * @throws IllegalStateException if there is an error fetching rooms from the database - */ - public static Map getRooms() { - try { - fetchAllIfNotExists(); - } catch (SQLException e) { - throw new IllegalStateException("Could not fetch rooms", e); - } - return rooms; - } - /** - * Retrieves a room by its label. - * This method checks if the room is already in the static map; if not, it fetches it from the database. - * @param label the label of the room to retrieve - * @return the Room object corresponding to the label, or null if not found - */ - public static Room getRoom(String label) { - if (rooms.keySet().contains(label)) { - return rooms.get(label); - } else { - try { - Room room = Server.getInstance().processSingleRequest(Room::fromSQLFields, "get_room_by_label", SQL_FIELDS, label); - if (room == null) { - return null; - } - rooms.put(label, room); - return room; - } catch (SQLException e) { - e.printStackTrace(); - return null; - } - } - } - /** - * Adds a new room to the database and the static map. - * This method creates a new Room object, inserts it into the database, - * and adds it to the `rooms` map for future access. - * @param label the label of the new room - * @param minimumLevel the minimum level required to access the new room - * @return the newly created Room object - * @throws SQLException if there is an error inserting the room into the database - */ - public static Room addRoom(String label, int minimumLevel) throws SQLException { - Room room = new Room(label, minimumLevel); - Server.getInstance().getConnection().executeVoidProcessSecure(SQLHelper.getAddObjectProcess("room", label, String.valueOf(minimumLevel))); - rooms.put(label, room); - return room; - } - public void delete() throws SQLException { - Server.getInstance().getConnection().executeVoidProcessSecure(SQLHelper.getDeleteObjectProcess("room", getLabel())); - rooms.remove(getLabel()); - } - /** - * Returns the label of the room. - * This is used to identify the room in various operations. - * @return the label of the room - */ - public String getLabel() { - return label; - } - /** - * Returns the minimum level required to access the room. - * This is used to determine if a student meets the requirements to enter the room. - * @return the minimum level required for access - */ - public int getMinimumLevel() { - return minimumLevel; - } - - public Room setMinimumLevel(int level) throws SQLException { - if (level < 0 || level > 3) throw new IllegalArgumentException("Level " + level + " out of range"); - Server.getInstance().getConnection().executeVoidProcessSecure(SQLHelper.getUpdateObjectProcess("level_of_room", getLabel(), String.valueOf(level))); - rooms.remove(getLabel()); - return getRoom(getLabel()); - } - - @Override - public String toString() { - return "{\"label\": \""+label+ "\", \"minimumLevel\": \"" + minimumLevel + "\"}"; - } - /** - * Adds multiple rooms to the database and the static map. - * This method allows for batch creation of rooms, ensuring that all rooms are added in a single operation. - * @param labels a list of room labels - * @param minimumLevels a list of minimum levels corresponding to each room - * @return a list of Room objects created - * @throws SQLException if there is an error inserting any of the rooms into the database - */ - public static List addAllRooms(List labels, List minimumLevels) throws SQLException { - if (labels.size() != minimumLevels.size()) { - throw new IllegalArgumentException("Labels and minimum levels must have the same size"); - } - List rooms = new ArrayList<>(); - for (int i = 0; i < labels.size(); i++) { - rooms.add(addRoom(labels.get(i), minimumLevels.get(i))); - } - return rooms; - } - /** - * Generates a list of Room objects from a CSV string. - * This method parses the CSV data and creates Room objects for each entry. - * @param csv the CSV string containing room data - * @return an array of Room objects created from the CSV data - */ - public static Room[] generateRoomsFromCSV(String csv) throws SQLException, IllegalArgumentException { - String[] lines = csv.split("\n"); - List labels = new ArrayList<>(); - List minimumLevels = new ArrayList<>(); - for (int i = 0; i < lines.length; i++) { - String[] parts = lines[i].split(","); - if (parts.length != 2) { - throw new IllegalArgumentException("Invalid CSV format for room: " + lines[i]); - } - String label = parts[0].trim(); - int minimumLevel; - try { - minimumLevel = Integer.parseInt(parts[1].trim()); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Invalid minimum level for room: " + lines[i], e); - } - labels.add(label); - minimumLevels.add(minimumLevel); - } - List rooms = Room.addAllRooms(labels, minimumLevels); - return rooms.toArray(new Room[rooms.size()]); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((label == null) ? 0 : label.hashCode()); - result = prime * result + minimumLevel; - return result; - } - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Room other = (Room) obj; - if (label == null) { - if (other.label != null) - return false; - } else if (!label.equals(other.label)) - return false; - if (minimumLevel != other.minimumLevel) - return false; - return true; - } - @Override - public String toJSON() { - return "{\"label\": \""+label+ "\", \"minimumLevel\": \"" + minimumLevel + "\"}"; - } - -} diff --git a/src/main/java/de/igslandstuhl/database/api/Student.java b/src/main/java/de/igslandstuhl/database/api/Student.java index 79eb120..933b89b 100644 --- a/src/main/java/de/igslandstuhl/database/api/Student.java +++ b/src/main/java/de/igslandstuhl/database/api/Student.java @@ -87,11 +87,6 @@ public class Student extends User { */ private final Map currentTopics = new ConcurrentHashMap<>(); - /** - * The current room of the student. - */ - private Room currentRoom = null; - /** * Constructs a new Student. * @@ -223,10 +218,6 @@ public static List getAll() { .collect(Collectors.toList()); } - public static List getByRoom(Room room) { - return students.values().stream().filter((s) -> room.equals(s.getCurrentRoom())).toList(); - } - /** * Registers a new student with a password. * This method creates a new student in the database and returns the created Student object. @@ -352,18 +343,6 @@ public String getUsername() { */ public GraduationLevel getGraduationLevel() { return graduationLevel; } - /** - * Returns the student's current room. - * @return the current room - */ - public Room getCurrentRoom() { return currentRoom; } - - /** - * Sets the student's current room. - * @param currentRoom the new room - */ - public void setCurrentRoom(Room currentRoom) { this.currentRoom = currentRoom; } - /** * Returns the set of selected tasks. * @return selected tasks @@ -553,7 +532,6 @@ public String toJSON() { .append("\"selectedTasks\": ").append(selectedTasks).append(",\n") .append("\"completedTasks\": ").append(completedTasks).append(",\n") .append("\"lockedTasks\": ").append(lockedTasks).append(",\n") - .append("\"currentRoom\": ").append(String.valueOf(currentRoom)).append(",\n") .append("\"currentRequests\": {").append(currentRequests.entrySet().stream() .map(entry -> "\"" + entry.getKey() + "\": " + entry.getValue().stream().map((r) -> '"' + r.getGermanTranslation() + '"').toList()) .reduce((a, b) -> a + ", " + b).orElse("")).append("},\n") diff --git a/src/main/java/de/igslandstuhl/database/server/Server.java b/src/main/java/de/igslandstuhl/database/server/Server.java index a4b2f98..e669d53 100644 --- a/src/main/java/de/igslandstuhl/database/server/Server.java +++ b/src/main/java/de/igslandstuhl/database/server/Server.java @@ -13,7 +13,6 @@ import org.apache.commons.codec.digest.DigestUtils; import de.igslandstuhl.database.Application; -import de.igslandstuhl.database.api.Room; import de.igslandstuhl.database.api.SchoolClass; import de.igslandstuhl.database.api.Student; import de.igslandstuhl.database.api.Subject; @@ -209,8 +208,6 @@ public String getSQLResource(String username, String resource) { if (resource.equals("mydata")) { User user = User.getUser(username); return user.toJSON(); - } else if (resource.equals("rooms")) { - return new HashSet<>(Room.getRooms().values()).toString(); } else if (resource.equals("mysubjects")) { User user = User.getUser(username); if (user instanceof Student student) { diff --git a/src/main/java/de/igslandstuhl/database/server/commands/Command.java b/src/main/java/de/igslandstuhl/database/server/commands/Command.java index 795833d..38469b1 100644 --- a/src/main/java/de/igslandstuhl/database/server/commands/Command.java +++ b/src/main/java/de/igslandstuhl/database/server/commands/Command.java @@ -78,71 +78,6 @@ public static void registerCommands() { return String.valueOf(level.getRatio() * 100) + "%"; }, new CommandDescription("get-level-ratio", "Gets the ratio of a task level", "get-level-ratio [level]")); - // Room commands - registerCommand("list-rooms", (args) -> { - try { - Room.fetchAll(); - } catch (SQLException e) { - return "Error while trying to access database:\n" + CommonUtils.getStacktrace(e); - } - return Room.getRooms().keySet().stream().reduce("Rooms:", (s1, s2) -> s1 + "\n" + s2); - }, new CommandDescription("list-rooms", "Lists all available rooms", "list-rooms")); - registerCommand("get-room-level", (args) -> { - if (args.length < 1) return "Usage: get-room-level [room]"; - Room room = Room.getRoom(argsPart(args, 0, args.length)); - if (room == null) return "Room not found. Try list-rooms for a list of available rooms"; - return "Room " + room.getLabel() + " has access level " + room.getMinimumLevel(); - }, new CommandDescription("get-room-level", "Gets the minimum level required to access a room", "get-room-level [room]")); - registerCommand("set-room-level", (args) -> { - if (args.length < 2) return "Usage: set-room-level [room] [level]"; - Room room = Room.getRoom(argsPart(args, 0, args.length-1)); - if (room == null) return "Room not found. Try list-rooms for a list of available rooms"; - int level; - try { - level = Integer.parseInt(args[args.length - 1]); - } catch (NumberFormatException e) { - return args[1] + " is not a valid number."; - } - try { - room.setMinimumLevel(level); - } catch (SQLException e) { - return "Error while trying to access database: \n" + CommonUtils.getStacktrace(e); - } catch (IllegalArgumentException e) { - return e.getMessage(); - } - return "Successfully changed room level"; - }, new CommandDescription("set-room-level", "Sets the minimum level required to access a room", "set-room-level [room] [level]")); - registerCommand("add-room", (args) -> { - if (args.length < 2) return "Usage: add-room [room] [level]"; - if (Room.getRoom(args[0]) != null) return "Room already present"; - - try { - String label = argsPart(args, 0, args.length-1); - int level = Integer.parseInt(args[args.length-1]); - - Room.addRoom(label, level); - } catch (NumberFormatException e) { - return args[args.length - 1] + " is not a valid number."; - } catch (IllegalArgumentException e) { - return e.getMessage(); - } catch (SQLException e) { - throw new IllegalStateException(e); - } - return "Room successfully added"; - }, new CommandDescription("add-room", "Adds a new room", "add-room [room] [level]")); - registerCommand("remove-room", (args) -> { - if (args.length < 1) return "Usage: remove-room [room]"; - - Room room = Room.getRoom(argsPart(args, 0, args.length)); - try { - room.delete(); - } catch (SQLException e) { - return "Error while trying to access database: \n" + CommonUtils.getStacktrace(e); - } - return "Room successfully deleted"; - }, new CommandDescription("remove-room", "Removes a room", "remove-room [room]")); - - // class commands registerCommand("list-classes", (args) -> { return SchoolClass.getAll().stream().map(SchoolClass::getLabel).reduce("Classes:", (s1,s2) -> s1 + "\n" + s2); diff --git a/src/main/java/de/igslandstuhl/database/server/webserver/handlers/PostRequestHandler.java b/src/main/java/de/igslandstuhl/database/server/webserver/handlers/PostRequestHandler.java index 6b8d4e3..5bbb557 100644 --- a/src/main/java/de/igslandstuhl/database/server/webserver/handlers/PostRequestHandler.java +++ b/src/main/java/de/igslandstuhl/database/server/webserver/handlers/PostRequestHandler.java @@ -20,7 +20,6 @@ import de.igslandstuhl.database.Application; import de.igslandstuhl.database.Registry; import de.igslandstuhl.database.api.APIObject; -import de.igslandstuhl.database.api.Room; import de.igslandstuhl.database.api.SchoolClass; import de.igslandstuhl.database.api.Student; import de.igslandstuhl.database.api.Subject; @@ -205,15 +204,6 @@ public static void registerHandlers() { } }, PostRequestHandler::csvResult) ); - HttpHandler.registerPostRequestHandler("/add-rooms", AccessLevel.ADMIN, (rq) -> - handleBatchInsertCSV(rq, "rooms", ContentType.JSON, t -> { - try { - return Room.generateRoomsFromCSV(t); - } catch (SQLException e) { - throw new IllegalStateException(e); - } - }, Arrays::toString) - ); HttpHandler.registerPostRequestHandler("/add-teacher", AccessLevel.ADMIN, (rq) -> { String firstName = prepare(rq.getString("firstName")); String lastName = prepare(rq.getString("lastName")); @@ -271,14 +261,6 @@ public static void registerHandlers() { HttpHandler.registerPostRequestHandler("/tasks", AccessLevel.USER, (rq) -> { return PostResponse.ok(JSONUtils.toJSON(rq.getTaskList()), ContentType.JSON, rq); }); - HttpHandler.registerPostRequestHandler("/update-room", AccessLevel.USER, (rq) -> { - Student student = rq.getCurrentStudent(); - if (student == null) return PostResponse.unauthorized(rq); - Room room = rq.getRoom(); - if (room == null) return PostResponse.badRequest("Room not found", rq); - student.setCurrentRoom(room); - return PostResponse.ok("Changed current room", ContentType.TEXT_PLAIN, rq); - }); HttpHandler.registerPostRequestHandler("/begin-task", AccessLevel.USER, (rq) -> handleTaskChange(rq, Task.STATUS_IN_PROGRESS)); HttpHandler.registerPostRequestHandler("/complete-task", AccessLevel.USER, (rq) -> handleTaskChange(rq, Task.STATUS_COMPLETED)); HttpHandler.registerPostRequestHandler("/cancel-task", AccessLevel.USER, (rq) -> handleTaskChange(rq, Task.STATUS_NOT_STARTED)); @@ -301,30 +283,7 @@ public static void registerHandlers() { .addProperty("id", student.getId()) .addProperty("name", student.getFirstName() + " " + student.getLastName()) .addProperty("actionRequired", student.isActionRequired()) - .addProperty("graduationLevel", student.getGraduationLevel()) - .addProperty("room", student.getCurrentRoom() != null ? student.getCurrentRoom().getLabel() : "None"); - if (rq.getJson().containsKey("subjectId") && rq.getSubject() != null) { - Set subjectRequests = student.getCurrentRequests(rq.getSubject()); - builder.addProperty("experiment",subjectRequests.stream().anyMatch(r -> r == SubjectRequest.EXPERIMENT)) - .addProperty("help", subjectRequests.stream().anyMatch(r -> r == SubjectRequest.HELP)) - .addProperty("test", subjectRequests.stream().anyMatch(r -> r == SubjectRequest.EXAM)) - .addProperty("partner", subjectRequests.stream().anyMatch(r -> r == SubjectRequest.PARTNER)); - } - }), - ContentType.JSON, rq - ); - }); - HttpHandler.registerPostRequestHandler("/get-students-by-room", AccessLevel.TEACHER, (rq) -> { - Room room = rq.getRoom(); - List students = Student.getByRoom(room); - return PostResponse.ok( - JSONUtils.toJSON(students, (student, builder) -> { - builder - .addProperty("id", student.getId()) - .addProperty("name", student.getFirstName() + " " + student.getLastName()) - .addProperty("actionRequired", student.isActionRequired()) - .addProperty("graduationLevel", student.getGraduationLevel()) - .addProperty("room", student.getCurrentRoom() != null ? student.getCurrentRoom().getLabel() : "None"); + .addProperty("graduationLevel", student.getGraduationLevel()); if (rq.getJson().containsKey("subjectId") && rq.getSubject() != null) { Set subjectRequests = student.getCurrentRequests(rq.getSubject()); builder.addProperty("experiment",subjectRequests.stream().anyMatch(r -> r == SubjectRequest.EXPERIMENT)) @@ -364,8 +323,7 @@ public static void registerHandlers() { .toList(); return PostResponse.ok(JSONUtils.toJSON(students, (partner, builder) -> { builder.addProperty("id", partner.getId()) - .addProperty("name", partner.getFirstName() + " " + partner.getLastName()) - .addProperty("room", partner.getCurrentRoom() != null ? partner.getCurrentRoom().getLabel() : "None"); + .addProperty("name", partner.getFirstName() + " " + partner.getLastName()); }), ContentType.JSON, rq); }); HttpHandler.registerPostRequestHandler("/delete-subject", AccessLevel.ADMIN, (rq) -> diff --git a/src/main/java/de/igslandstuhl/database/server/webserver/requests/APIPostRequest.java b/src/main/java/de/igslandstuhl/database/server/webserver/requests/APIPostRequest.java index 72edc41..2c070a4 100644 --- a/src/main/java/de/igslandstuhl/database/server/webserver/requests/APIPostRequest.java +++ b/src/main/java/de/igslandstuhl/database/server/webserver/requests/APIPostRequest.java @@ -7,7 +7,6 @@ import com.google.gson.reflect.TypeToken; import de.igslandstuhl.database.api.APIObject; -import de.igslandstuhl.database.api.Room; import de.igslandstuhl.database.api.SchoolClass; import de.igslandstuhl.database.api.Student; import de.igslandstuhl.database.api.Subject; @@ -58,9 +57,6 @@ public Topic getTopic() { public SubjectRequest getSubjectRequest() { return SubjectRequest.fromGermanTranslation(getString("subjectRequest")); } - public Room getRoom() { - return Room.getRoom(getString("room")); - } public Task getTask() { return Task.get(getInt("taskId")); } @@ -86,8 +82,6 @@ public T getAPIObject(TypeToken type) { return (T) getSubjectRequest(); } else if (rawType.getTypeName().contains("Task")) { return (T) getTask(); - } else if (rawType.getTypeName().contains("Room")) { - return (T) getRoom(); } else if (rawType.getTypeName().contains("SchoolClass")) { return (T) getSchoolClass(); } else { diff --git a/src/main/resources/html/admin/manage_rooms.html b/src/main/resources/html/admin/manage_rooms.html deleted file mode 100644 index bda0d6d..0000000 --- a/src/main/resources/html/admin/manage_rooms.html +++ /dev/null @@ -1,46 +0,0 @@ -%[site;title=Raumverwaltung;content=!FOLLOWS] -
-
-

Raumverwaltung

-
-
-
-

Räume hinzufügen

-
- - - -
-
-
-

Raumliste

- - - - - - - - - - -
RaumnameMindestlevel
-
-
- -
- \ No newline at end of file diff --git a/src/main/resources/js/site/student-database.js b/src/main/resources/js/site/student-database.js index ec439b1..0c24c10 100644 --- a/src/main/resources/js/site/student-database.js +++ b/src/main/resources/js/site/student-database.js @@ -50,10 +50,6 @@ async function fetchMyClasses() { const classes = await fetchJson('/myclasses'); return classes; } -async function fetchRooms() { - const rooms = await fetchJson('/rooms'); - return rooms; -} async function fetchTeacherClasses(teacherId) { const classes = await getJsonWithPost('/teacher-classes', { teacherId }); return classes; @@ -108,9 +104,6 @@ async function getStudents(classId) { async function getStudentsBySubject(classId, subjectId) { return await getJsonWithPost('/student-list', { classId, subjectId }); } -async function getStudentsByRoom(room) { - return await getJsonWithPost('/get-students-by-room', { room }); -} async function searchPartner(subjectId, topicId, classId, studentId) { return await getJsonWithPost('/search-partner', { subjectId, topicId, classId, studentId}); } @@ -159,9 +152,6 @@ async function reopenTask(studentId, taskId) { async function beginTask(studentId, taskId) { return await post('/begin-task', { studentId, taskId }); } -async function updateRoom(studentId, room) { - return await post('/update-room', { studentId, room }); -} async function togglePlugin(pluginKey) { return await post('/toggle-plugin', { key: pluginKey }); } @@ -221,21 +211,6 @@ async function populateSubjectStudentList(subjectSelectId, classSelectId, studen studentTable.appendChild(row); }); } -async function populateRoomStudentList(room) { - const students = await getStudentsByRoom(room); - - const studentTable = document.getElementById("roomStudentTableBody"); - studentTable.innerHTML = ""; // clear previous rows - students.forEach(student => { - const row = document.createElement('tr'); - row.innerHTML = ` - ${student.name} - ${student.actionRequired ? "Ja" : "Nein"} - - `; - studentTable.appendChild(row); - }); -} async function populatePartnerSubjectStudentList(subjectId, studentData) { const topicId = (await fetchMyCurrentTopic(subjectId)).id; const classId = studentData.schoolClass.id; @@ -310,30 +285,6 @@ async function populateGradeSelect(gradeSelectId, subjectId) { gradeSelect.appendChild(option) }) } -async function populateRoomSelect(roomSelectId) { - const roomSelect = document.getElementById(roomSelectId); - roomSelect.innerHTML = ""; // clear previous options if any - const rooms = await fetchRooms(); - rooms.forEach(room => { - const option = document.createElement('option'); - option.value = room.label; - option.textContent = room.label; - roomSelect.appendChild(option); - }); -} -async function populateRoomSelectWithLevel(roomSelectId, graduationLevel) { - const roomSelect = document.getElementById(roomSelectId); - roomSelect.innerHTML = ""; // clear previous options if any - const rooms = await fetchRooms(); - rooms.forEach(room => { - if (room.minimumLevel <= graduationLevel){ - const option = document.createElement('option'); - option.value = room.label; - option.textContent = room.label; - roomSelect.appendChild(option); - } - }); -} async function populateSubjectList(subjectListId, classId) { const subjectList = document.getElementById(subjectListId); const subjects = await fetchJson("/class-subjects", { diff --git a/src/main/resources/meta/dynamic/dynamic_elements.json b/src/main/resources/meta/dynamic/dynamic_elements.json index c3c7475..d095c99 100644 --- a/src/main/resources/meta/dynamic/dynamic_elements.json +++ b/src/main/resources/meta/dynamic/dynamic_elements.json @@ -4,11 +4,6 @@ "template": "student_header_builtin" }, - { - "type": "STUDENT_TOP", - "template": "room_selection" - }, - { "type": "TEACHER_INFOS", "template": "class_info" @@ -16,9 +11,5 @@ { "type": "TEACHER_INFOS", "template": "subject_info" - }, - { - "type": "TEACHER_INFOS", - "template": "room_info" } ] \ No newline at end of file diff --git a/src/main/resources/meta/navigation/navigation_elements.json b/src/main/resources/meta/navigation/navigation_elements.json index 530ef9c..90aa2ce 100644 --- a/src/main/resources/meta/navigation/navigation_elements.json +++ b/src/main/resources/meta/navigation/navigation_elements.json @@ -4,11 +4,6 @@ "path": "/manage_classes", "label": "Klassen verwalten" }, - { - "type": "ADMIN_DASHBOARD", - "path": "/manage_rooms", - "label": "Räume verwalten" - }, { "type": "ADMIN_DASHBOARD", "path": "/manage_students", diff --git a/src/main/resources/meta/paths/get_paths.json b/src/main/resources/meta/paths/get_paths.json index 137e12a..0cee789 100644 --- a/src/main/resources/meta/paths/get_paths.json +++ b/src/main/resources/meta/paths/get_paths.json @@ -6,13 +6,6 @@ "context": "virtual", "access_level": "user" }, - "/rooms": { - "type": "GET", - "handler_type": "SQLRequestHandler", - "namespaces": ["sql"], - "context": "virtual", - "access_level": "public" - }, "/mysubjects": { "type": "GET", "handler_type": "SQLRequestHandler", @@ -136,13 +129,6 @@ "context": "html", "access_level": "admin" }, - "/manage_rooms": { - "type": "GET", - "handler_type": "TemplatingFileRequestHandler", - "namespaces": ["admin"], - "context": "html", - "access_level": "admin" - }, "/editor": { "type": "GET", "handler_type": "TemplatingFileRequestHandler", @@ -158,13 +144,6 @@ "context": "html", "access_level": "admin" }, - "/room": { - "type": "GET", - "handler_type": "TemplatingFileRequestHandler", - "namespaces": ["admin"], - "context": "html", - "access_level": "admin" - }, "/subject": { "type": "GET", "handler_type": "TemplatingFileRequestHandler", @@ -252,13 +231,6 @@ "context": "js", "access_level": "admin" }, - "/build_room.js": { - "type": "GET", - "handler_type": "FileRequestHandler", - "namespaces": ["admin"], - "context": "js", - "access_level": "admin" - }, "/build_subject.js": { "type": "GET", "handler_type": "FileRequestHandler", diff --git a/src/main/resources/meta/templates/templates.json b/src/main/resources/meta/templates/templates.json index 7afddcd..f07031f 100644 --- a/src/main/resources/meta/templates/templates.json +++ b/src/main/resources/meta/templates/templates.json @@ -11,10 +11,6 @@ "type": "HTMLFileTemplate", "path": "login" }, - "room_info": { - "type": "HTMLFileTemplate", - "path": "room_info" - }, "site": { "type": "HTMLFileTemplate", "path": "site" @@ -31,10 +27,6 @@ "type": "HTMLFileTemplate", "path": "student_header" }, - "room_selection": { - "type": "HTMLFileTemplate", - "path": "room_selection" - }, "admin_dashboard_nav": { "type": "HTMLNavigationTemplate", diff --git a/src/main/resources/sql/pushes/add_room.sql b/src/main/resources/sql/pushes/add_room.sql deleted file mode 100644 index 1470ab2..0000000 --- a/src/main/resources/sql/pushes/add_room.sql +++ /dev/null @@ -1,5 +0,0 @@ -INSERT INTO rooms (label, minimum_level) -VALUES (?, ?) -ON CONFLICT(label) DO UPDATE SET - label = excluded.label, - minimum_level = excluded.minimum_level \ No newline at end of file diff --git a/src/main/resources/sql/pushes/delete_room.sql b/src/main/resources/sql/pushes/delete_room.sql deleted file mode 100644 index 7065216..0000000 --- a/src/main/resources/sql/pushes/delete_room.sql +++ /dev/null @@ -1,2 +0,0 @@ -DELETE FROM rooms -WHERE label = ? \ No newline at end of file diff --git a/src/main/resources/sql/queries/get_all_rooms.sql b/src/main/resources/sql/queries/get_all_rooms.sql deleted file mode 100644 index ff39647..0000000 --- a/src/main/resources/sql/queries/get_all_rooms.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT * FROM rooms \ No newline at end of file diff --git a/src/main/resources/sql/queries/get_room_by_label.sql b/src/main/resources/sql/queries/get_room_by_label.sql deleted file mode 100644 index bb49047..0000000 --- a/src/main/resources/sql/queries/get_room_by_label.sql +++ /dev/null @@ -1,3 +0,0 @@ -SELECT * -FROM rooms -WHERE label=? \ No newline at end of file diff --git a/src/main/resources/sql/tables/rooms.sql b/src/main/resources/sql/tables/rooms.sql deleted file mode 100644 index a34fa52..0000000 --- a/src/main/resources/sql/tables/rooms.sql +++ /dev/null @@ -1,4 +0,0 @@ -CREATE TABLE IF NOT EXISTS rooms ( - label TEXT PRIMARY KEY, - minimum_level INTEGER NOT NULL -) \ No newline at end of file diff --git a/src/main/resources/templates/html/room_info.html b/src/main/resources/templates/html/room_info.html deleted file mode 100644 index 46a5a9b..0000000 --- a/src/main/resources/templates/html/room_info.html +++ /dev/null @@ -1,20 +0,0 @@ -
-

Raumübersicht

-
- - -
-
-

Schüler im Raum:

- - - - - - - - - -
NameBraucht Unterstützung
-
-
\ No newline at end of file diff --git a/src/main/resources/templates/html/room_selection.html b/src/main/resources/templates/html/room_selection.html deleted file mode 100644 index a5150e7..0000000 --- a/src/main/resources/templates/html/room_selection.html +++ /dev/null @@ -1,4 +0,0 @@ -
- - -
\ No newline at end of file diff --git a/src/test/java/de/igslandstuhl/database/api/RoomTest.java b/src/test/java/de/igslandstuhl/database/api/RoomTest.java deleted file mode 100644 index d79681f..0000000 --- a/src/test/java/de/igslandstuhl/database/api/RoomTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package de.igslandstuhl.database.api; - -import static org.junit.jupiter.api.Assertions.*; - -import java.sql.SQLException; -import java.util.List; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import de.igslandstuhl.database.server.Server; - -public class RoomTest { - Server server; - @BeforeEach - public void setupServer() throws SQLException { - PreConditions.setupDatabase(); - server = Server.getInstance(); - } - @Test - public void addRoom() throws SQLException { - Room room = Room.addRoom("Gelingensnachweis", 0); - assertNotNull(room); - assertEquals("Gelingensnachweis", room.getLabel()); - assertEquals(0, room.getMinimumLevel()); - } - @Test - public void getRoom() throws SQLException { - Room added = Room.addRoom("Gelingensnachweis", 0); - Room room = Room.getRoom("Gelingensnachweis"); - assertNotNull(room); - assertEquals(added, room); - } - @Test - public void addAllRooms() throws SQLException { - List rooms = Room.addAllRooms( - List.of("5 Einzelarbeitsraum", "5 Teamarbeitsraum", "5 Inputraum groß", "5 Inputraum klein", - "5 Gruppenarbeitsraum 1", "5 Gruppenarbeitsraum 2", "5 Gruppenarbeitsraum 3"), - List.of(0, 0, 0, 0, 0, 0, 0) - ); - assertEquals(7, rooms.size()); - } -} From 7bb34738bfda26656cbd5874ded5f574c22640ca Mon Sep 17 00:00:00 2001 From: Schlaumeier5 Date: Tue, 31 Mar 2026 20:08:59 +0200 Subject: [PATCH 5/9] Also removed rooms from javascript Introduced a few javascript events that will be necessary for the room plugin --- .../resources/js/site/student-database.js | 51 +++++++++++-------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/src/main/resources/js/site/student-database.js b/src/main/resources/js/site/student-database.js index 0c24c10..3104254 100644 --- a/src/main/resources/js/site/student-database.js +++ b/src/main/resources/js/site/student-database.js @@ -165,6 +165,29 @@ async function deleteClass(classId) { async function deleteSubject(subjectId) { return await post('/delete-subject', { id: subjectId }); } + +// Events +function populateStudentRowEvent(row, student) { + const event = new CustomEvent("populate-student-row", { detail: {row, student} }); + document.dispatchEvent(event); +} +function populatePartnerRowEvent(row, student) { + const event = new CustomEvent("populate-partner-row", { detail: {row, student} }); + document.dispatchEvent(event); +} +function populateTeacherClassRowEvent(row, student) { + const event = new CustomEvent("populate-teacher-class-row", { detail: { row, student } }); + document.dispatchEvent(event); +} +function teacherDashboardLoadEvent() { + const event = new Event('teacher-dashboard-load'); + document.dispatchEvent(event); +} +function studentDashboardLoadEvent() { + const event = new Event('student-dashboard-load'); + document.dispatchEvent(event); +} + // Populating functions async function populateTable(url, tableId, rowBuilder) { const data = await fetchJson(url); @@ -223,9 +246,9 @@ async function populatePartnerSubjectStudentList(subjectId, studentData) { students.forEach(student => { const row = document.createElement('tr'); row.innerHTML = ` - ${student.name} - ${student.room} + ${student.name} `; + populatePartnerRowEvent(row, student); studentTable.appendChild(row); }); } @@ -373,10 +396,10 @@ async function buildTeacherDashboard(classes, subjects) { populateStudentTable(Number(event.target.value), "studentTable", (row, student) => { row.innerHTML = ` ${student.name} - ${student.room} ${graduationLevels[student.graduationLevel]} `; + populateTeacherClassRowEvent(row, student); }); } @@ -393,9 +416,7 @@ async function buildTeacherDashboard(classes, subjects) { subjectSelect.addEventListener('change', (_) => populateSubjectStudentList('subjectSelect', 'classSelectSubject', 'subjectStudentTable')); populateSubjectStudentList('subjectSelect', 'classSelectSubject', 'subjectStudentTable'); // Trigger initial load - await populateRoomSelect('roomSelect'); - document.getElementById('roomSelect').addEventListener('change', (e) => populateRoomStudentList(e.target.value)); - populateRoomStudentList(document.getElementById('roomSelect').value); // Trigger initial load + teacherDashboardLoadEvent(); } function createRequestButton(subject, type, label) { const btn = document.createElement('button'); @@ -625,26 +646,14 @@ function decodeEntities(str) { function loadStudentDashboard(studentData, subjects, teacherPerms) { // Show student info setStudentInfo(studentData); - // Show rooms - populateRoomSelectWithLevel('room', studentData.graduationLevel); - - // Wait for the browser to render (next tick) - setTimeout(() => { - // Set room select value to current room - if (studentData.currentRoom && studentData.currentRoom.label) { - roomSelect.value = studentData.currentRoom.label; - } - }, 0); - - const roomSelect = document.getElementById('room'); - roomSelect.addEventListener('change', async () => updateRoom(studentData.id, roomSelect.value)); - // Show subjects const subjectList = document.getElementById('subject-list'); subjects.forEach(subject => { const panel = createSubjectPanel(subject, studentData, teacherPerms); subjectList.appendChild(panel); }); + + studentDashboardLoadEvent(); } let plugin_panels = {} function loadPluginSection(pluginKey) { @@ -704,10 +713,10 @@ document.addEventListener('DOMContentLoaded', async () => { populateStudentTable(currentClass.id, 'studentTable', (row, student) => { row.innerHTML = ` ${student.name} - ${student.room} ${graduationLevels[student.graduationLevel]} `; + populateStudentRowEvent(row, student); }) } if (document.getElementById('subjectSelect')) { From 2367ff370d4a0ef1e4779681bb3183333d179068 Mon Sep 17 00:00:00 2001 From: Schlaumeier5 Date: Tue, 31 Mar 2026 20:22:33 +0200 Subject: [PATCH 6/9] Added SQLRequestHandler + Registry so plugins can also define sql requests --- .../de/igslandstuhl/database/Application.java | 2 + .../de/igslandstuhl/database/Registry.java | 5 ++ .../igslandstuhl/database/server/Server.java | 45 +--------------- .../handlers/get/SQLRequestHandler.java | 51 +++++++++++++++++++ 4 files changed, 60 insertions(+), 43 deletions(-) create mode 100644 src/main/java/de/igslandstuhl/database/server/webserver/handlers/get/SQLRequestHandler.java diff --git a/src/main/java/de/igslandstuhl/database/Application.java b/src/main/java/de/igslandstuhl/database/Application.java index d84ca56..19cd206 100644 --- a/src/main/java/de/igslandstuhl/database/Application.java +++ b/src/main/java/de/igslandstuhl/database/Application.java @@ -17,6 +17,7 @@ import de.igslandstuhl.database.server.webserver.WebPath; import de.igslandstuhl.database.server.webserver.handlers.GetRequestHandler; import de.igslandstuhl.database.server.webserver.handlers.PostRequestHandler; +import de.igslandstuhl.database.server.webserver.handlers.get.SQLRequestHandler; import de.igslandstuhl.database.utils.CommandLineUtils; /** @@ -110,6 +111,7 @@ public static void main(String[] args) throws Exception { Holiday.setupCurrentSchoolYear(); PostRequestHandler.registerHandlers(); + SQLRequestHandler.register(); PluginLoader.getInstance().registerPlugins(); WebPath.registerPaths(); diff --git a/src/main/java/de/igslandstuhl/database/Registry.java b/src/main/java/de/igslandstuhl/database/Registry.java index 12e09f8..e0604f0 100644 --- a/src/main/java/de/igslandstuhl/database/Registry.java +++ b/src/main/java/de/igslandstuhl/database/Registry.java @@ -16,6 +16,7 @@ import de.igslandstuhl.database.server.commands.CommandDescription; import de.igslandstuhl.database.server.webserver.WebPath; import de.igslandstuhl.database.server.webserver.handlers.HttpHandler; +import de.igslandstuhl.database.server.webserver.handlers.get.SQLRequestHandler; import de.igslandstuhl.database.server.webserver.requests.APIPostRequest; import de.igslandstuhl.database.server.webserver.requests.GetRequest; import de.igslandstuhl.database.utils.RegistryEnum; @@ -25,6 +26,7 @@ public class Registry implements Closeable { private static final Registry COMMAND_DESCRIPTION_REGISTRY = new Registry<>(); private static final Registry> POST_HANDLER_REGISTRY = new Registry<>(); private static final Registry> GET_HANDLER_REGISTRY = new Registry<>(); + private static final Registry SQL_REQUEST_HANDLER_REGISTRY = new Registry<>(); private static final Registry PLUGIN_REGISTRY = new Registry<>(); private static final Registry WEB_PATH_REGISTRY = new Registry<>(); @@ -41,6 +43,9 @@ public static Registry> postRequestHandlerRe public static Registry> getRequestHandlerRegistry() { return GET_HANDLER_REGISTRY; } + public static Registry sqlRequestHandlerRegistry() { + return SQL_REQUEST_HANDLER_REGISTRY; + } public static Registry pluginRegistry() { return PLUGIN_REGISTRY; } diff --git a/src/main/java/de/igslandstuhl/database/server/Server.java b/src/main/java/de/igslandstuhl/database/server/Server.java index e669d53..df4aafc 100644 --- a/src/main/java/de/igslandstuhl/database/server/Server.java +++ b/src/main/java/de/igslandstuhl/database/server/Server.java @@ -3,24 +3,19 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; -import java.util.HashSet; import java.util.LinkedList; import java.util.List; -import java.util.Set; import java.util.function.Consumer; import java.util.function.Function; import org.apache.commons.codec.digest.DigestUtils; import de.igslandstuhl.database.Application; -import de.igslandstuhl.database.api.SchoolClass; -import de.igslandstuhl.database.api.Student; -import de.igslandstuhl.database.api.Subject; -import de.igslandstuhl.database.api.Teacher; import de.igslandstuhl.database.api.User; import de.igslandstuhl.database.server.resources.ResourceManager; import de.igslandstuhl.database.server.sql.SQLHelper; import de.igslandstuhl.database.server.sql.SQLiteConnection; +import de.igslandstuhl.database.server.webserver.handlers.get.SQLRequestHandler; /** * Represents the main server class that handles all incoming requests and manages the database connection. @@ -205,43 +200,7 @@ public boolean isValidUser(String username, String password) { */ public String getSQLResource(String username, String resource) { resource = resource.intern(); - if (resource.equals("mydata")) { - User user = User.getUser(username); - return user.toJSON(); - } else if (resource.equals("mysubjects")) { - User user = User.getUser(username); - if (user instanceof Student student) { - return student.getSchoolClass().getSubjects().toString(); - } else if (user instanceof Teacher teacher) { - return teacher.getSubjects().toString(); - } else { - return null; - } - } else if (resource.equals("myclasses")) { - User user = User.getUser(username); - if (user instanceof Teacher teacher) { - Set classIDs = teacher.getClassIds(); - Set classes = new HashSet<>(); - for (Integer classID : classIDs) { - classes.add("{\"classId\": " + classID + ", \"name\": \"" + SchoolClass.get(classID).getLabel() + "\"}"); - } - return classes.toString(); - } else { - return null; - } - } else if (resource.equals("teachers")) { - return new HashSet<>(Teacher.getAll()).toString(); - } else if (resource.equals("students")) { - return new HashSet<>(Student.getAll()).toString(); - } else if (resource.equals("subjects")) { - return new HashSet<>(Subject.getAll()).toString(); - } else if (resource.equals("classes")) { - return new HashSet<>(SchoolClass.getAll()).toString(); - } else if (resource.equals("all-student-results")) { - return Student.getAllResultsCSV(); - } else { - return null; - } + return SQLRequestHandler.getResource(resource, User.getUser(username)); } @Override diff --git a/src/main/java/de/igslandstuhl/database/server/webserver/handlers/get/SQLRequestHandler.java b/src/main/java/de/igslandstuhl/database/server/webserver/handlers/get/SQLRequestHandler.java new file mode 100644 index 0000000..391c9f4 --- /dev/null +++ b/src/main/java/de/igslandstuhl/database/server/webserver/handlers/get/SQLRequestHandler.java @@ -0,0 +1,51 @@ +package de.igslandstuhl.database.server.webserver.handlers.get; + +import java.util.HashSet; +import java.util.Set; + +import de.igslandstuhl.database.Registry; +import de.igslandstuhl.database.api.SchoolClass; +import de.igslandstuhl.database.api.Student; +import de.igslandstuhl.database.api.Subject; +import de.igslandstuhl.database.api.Teacher; +import de.igslandstuhl.database.api.User; + +@FunctionalInterface +public interface SQLRequestHandler { + public String get(User user); + + public static String getResource(String resource, User user) { + return Registry.sqlRequestHandlerRegistry().get(resource).get(user); + } + public static void register() { + Registry.sqlRequestHandlerRegistry().register("mydata", (user) -> user.toJSON()); + + Registry.sqlRequestHandlerRegistry().register("mysubjects", (user) -> { + if (user instanceof Student student) { + return student.getSchoolClass().getSubjects().toString(); + } else if (user instanceof Teacher teacher) { + return teacher.getSubjects().toString(); + } else { + return null; + } + }); + Registry.sqlRequestHandlerRegistry().register("myclasses", (user) -> { + if (user instanceof Teacher teacher) { + Set classIDs = teacher.getClassIds(); + Set classes = new HashSet<>(); + for (Integer classID : classIDs) { + classes.add("{\"classId\": " + classID + ", \"name\": \"" + SchoolClass.get(classID).getLabel() + "\"}"); + } + return classes.toString(); + } else { + return null; + } + }); + + Registry.sqlRequestHandlerRegistry().register("teachers", (user) -> new HashSet<>(Teacher.getAll()).toString()); + Registry.sqlRequestHandlerRegistry().register("students", (user) -> new HashSet<>(Student.getAll()).toString()); + Registry.sqlRequestHandlerRegistry().register("subjects", (user) -> new HashSet<>(Subject.getAll()).toString()); + Registry.sqlRequestHandlerRegistry().register("classes", (user) -> new HashSet<>(SchoolClass.getAll()).toString()); + Registry.sqlRequestHandlerRegistry().register("all-student-resukts", (user) -> Student.getAllResultsCSV()); + } +} From 9b1d5313c42e6bc345a055ca049020abc0812c8b Mon Sep 17 00:00:00 2001 From: Schlaumeier5 Date: Tue, 31 Mar 2026 20:23:50 +0200 Subject: [PATCH 7/9] bumped version to v1.1.0-SNAPSHOT-1 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 300b4f8..80bab18 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ plugins { group = "igs-landstuhl" -version = "v1.1.0-SNAPSHOT-0" +version = "v1.1.0-SNAPSHOT-1" application { mainClass.set("de.igslandstuhl.database.Application") From 65743a01dfecaa178c20673704c2468ffc3a7dbf Mon Sep 17 00:00:00 2001 From: Schlaumeier5 Date: Tue, 28 Apr 2026 17:17:13 +0200 Subject: [PATCH 8/9] Little updates --- build.gradle.kts | 2 +- src/main/resources/html/admin/class.html | 1 - src/main/resources/templates/html/class_info.html | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 80bab18..0243174 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ plugins { group = "igs-landstuhl" -version = "v1.1.0-SNAPSHOT-1" +version = "v1.1.0-SNAPSHOT-2" application { mainClass.set("de.igslandstuhl.database.Application") diff --git a/src/main/resources/html/admin/class.html b/src/main/resources/html/admin/class.html index cec7d6a..513c556 100644 --- a/src/main/resources/html/admin/class.html +++ b/src/main/resources/html/admin/class.html @@ -40,7 +40,6 @@

Schüler in der Klasse

Name - Raum Graduierung diff --git a/src/main/resources/templates/html/class_info.html b/src/main/resources/templates/html/class_info.html index ca36e3a..647744e 100644 --- a/src/main/resources/templates/html/class_info.html +++ b/src/main/resources/templates/html/class_info.html @@ -10,7 +10,6 @@

Schüler in der Klasse:

Name - Raum Graduierung From a0d88f3e9fc95114117f4dd2725af3ad642cdd9f Mon Sep 17 00:00:00 2001 From: Schlaumeier5 Date: Tue, 12 May 2026 19:15:32 +0200 Subject: [PATCH 9/9] Bumped version to v2.0.0-SNAPSHOT-0 to reflect great changes --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 0243174..cfdecc4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ plugins { group = "igs-landstuhl" -version = "v1.1.0-SNAPSHOT-2" +version = "v2.0.0-SNAPSHOT-0" application { mainClass.set("de.igslandstuhl.database.Application")