Author SHA1 Message Date
brausjonas cb2ddc7bcf Hinweis zu Online Backend URL 2023-07-09 00:49:57 +02:00
brausjonas 68e2d553f9 Weitere backend kommentare 2023-07-09 00:42:44 +02:00
brausjonas 86f9e559b5 Weitere Kommentare im Frontend 2023-07-09 00:22:52 +02:00
AliGitGut 65a399693e Comments
Alle, von mir zu bearbeitenden, komplizierten und relevanten Codeteile wurden ausführlich beschrieben
2023-07-08 14:54:50 +02:00
AlexE030 3382d732a9 Improved Calender Side Bar jump Feature
Wenn man jetzt in der Kalender-Sidebar auf einen Monat klickt, dann springt er nicht mehr immer zum Ersten des Monats.
2023-06-30 00:58:11 +02:00
brausjonas 7b6a82c073 Update README.md 2023-06-28 09:31:07 +02:00
brausjonas d80abcaf8c Create LICENSE 2023-06-28 09:29:11 +02:00
brausjonas 17a3ad0b33 Fixed Logout Bug 2023-06-22 00:16:30 +02:00
brausjonas be9ace5238 Fixed User Loading Bug
Manchmal wurden User im Input Form nicht richtig geladen. Dieser Bug ist hiermit behoben
2023-06-22 00:01:48 +02:00
Amira24523 fcdf8492a6 Merge branch 'main' of https://github.com/DHBWLoerrach/TIF22A_AnwProjekt_B 2023-06-21 23:34:58 +02:00
Amira24523 d4d01c730a Login Module in deutsch 2023-06-21 23:33:33 +02:00
brausjonas a4c600301e Bessere Erkennbarkeit von nicht Zuordnung von Dozenten zu Modulen 2023-06-21 23:22:25 +02:00
Amira24523 4ec1cb0749 Fixed SideBar 2023-06-21 23:10:02 +02:00
AliGitGut 20e2351ba9 Bugfix Pausen
Pausen werden nicht mehr angerecht aber dem Dozenten mitgeteilt
2023-06-21 22:49:47 +02:00
Amira24523 4f45d48061 InputForm Semester Width change 2023-06-21 22:36:33 +02:00
Amira24523 ee5805434d StatusBar Color update 2023-06-21 22:32:57 +02:00
AliGitGut 024d22711f Firefox
Firefox ist jetzt freigeschalten, wird aber nicht empfohlen
2023-06-21 21:04:27 +02:00
AliGitGut 9315f5b18d Merge branch 'main' of https://github.com/DHBWLoerrach/TIF22A_AnwProjekt_B 2023-06-21 20:38:39 +02:00
AliGitGut 34c2786840 Pausen Updates
Pausenskalierung angepasst, Pausen werden nun in den Modulen angezeigt
2023-06-21 20:38:36 +02:00
brausjonas ca23f7f993 More Dummy Data For Modules 2023-06-21 20:21:22 +02:00
AliGitGut d81922d188 Pausenvalidierung
Alle 4h muss ein Dozent eine Pause von 15 min einlegen // alle 8h eine von 30 min
2023-06-21 20:00:17 +02:00
brausjonas c979c3a801 Multiselect Fixed by Changing Columns 2023-06-21 17:04:26 +02:00
Amira24523 0a3a390bb8 Warning message 2023-06-21 15:55:40 +02:00
AliGitGut 09f288532e names changed 2023-06-20 18:21:50 +02:00
AliGitGut 137684f5be Help Page Angepasst
Help Page nochmal angepasst
2023-06-20 10:53:27 +02:00
AliGitGut a0841f4b2b Help Page Aktualisiert
Die Hilfe Seite wurde auf den neusten Stand gebracht, auf der Login Page entfernt und hat einen Back button bekommen
2023-06-19 15:29:56 +02:00
brausjonas 571e6e72c0 Grayed Out Bug Fixed 2023-06-19 15:02:09 +02:00
brausjonas ac4b62f32c Design Dateien Wiederhergestellt 2023-06-18 14:27:18 +02:00
brausjonas 8dc16c5b2c Bug Fix 2023-06-18 14:10:29 +02:00
brausjonas dd6f08880a Function Status Bar and Time Validation 2023-06-18 11:29:06 +02:00
AlexE030 b3fb3b1b8f Added Status Bar for Admins
There are still some minor Bugs to fix, but it works
2023-06-16 22:38:19 +02:00
AlexE030 dc20f35fb8 Finished Status Bar
Submit-Validation not yet implemented
2023-06-16 16:49:21 +02:00
AlexE030 9024dbc26e Bugfix localStorage is not defined 2023-06-16 12:35:37 +02:00
AlexE030 05a6a3ee23 Zwischenpush 2023-06-16 12:13:20 +02:00
brausjonas c9f3efd7f9 Merge branch 'AlexUndMikeBranch' of https://github.com/DHBWLoerrach/TIF22A_AnwProjekt_B into AlexUndMikeBranch 2023-06-16 11:59:09 +02:00
brausjonas 7983e23815 Calender View Module and Semester names and Numbers are shown
Also in the Dashboard for Lecturers
2023-06-16 11:59:06 +02:00
AliGitGut 5446b2d1cb Input Form Bugfix
Kursname, Theorieanfang und Ende müssen nun gesetzt werden sonst kann kein Kurs angelegt werden
2023-06-16 11:48:34 +02:00
brausjonas 8205b7d9d9 Calender View Angepasst auf die Module ID eines Entries 2023-06-16 11:33:36 +02:00
brausjonas 53ac8ff0bf Merge Of Branches Multiselect 2023-06-16 10:33:04 +02:00
AlexE030 e436e61041 Added Status Check 2023-06-16 10:02:57 +02:00
99 changed files with 675245 additions and 8100 deletions
Vendored
BIN
View File
Binary file not shown.
+9
View File
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
-12
View File
@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
-16
View File
@@ -1,16 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="CssUnknownProperty" enabled="true" level="WARNING" enabled_by_default="true">
<option name="myCustomPropertiesEnabled" value="true" />
<option name="myIgnoreVendorSpecificProperties" value="false" />
<option name="myCustomPropertiesList">
<value>
<list size="1">
<item index="0" class="java.lang.String" itemvalue="font-color" />
</list>
</value>
</option>
</inspection_tool>
</profile>
</component>
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JpaBuddyIdeaProjectConfig">
<option name="renamerInitialized" value="true" />
</component>
</project>
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<includedPredefinedLibrary name="Node.js Core" />
</component>
</project>
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="16" project-jdk-type="JavaSDK" />
<component name="ProjectType">
<option name="id" value="jpab" />
</component>
</project>
+1 -1
View File
@@ -2,7 +2,7 @@
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/anwendungsprojekt.iml" filepath="$PROJECT_DIR$/.idea/anwendungsprojekt.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/TIF22A_AnwProjekt_B.iml" filepath="$PROJECT_DIR$/.idea/TIF22A_AnwProjekt_B.iml" />
</modules>
</component>
</project>
+170
View File
@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="744e9299-0ce3-415c-8733-c935bf920887" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/anwendung/src/components/CalendarSideBar.jsx" beforeDir="false" afterPath="$PROJECT_DIR$/anwendung/src/components/CalendarSideBar.jsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/anwendung/src/components/DateElement.jsx" beforeDir="false" afterPath="$PROJECT_DIR$/anwendung/src/components/DateElement.jsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/anwendung/src/components/WeekSelector.jsx" beforeDir="false" afterPath="$PROJECT_DIR$/anwendung/src/components/WeekSelector.jsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/anwendung/src/pages/semesteroverview.js" beforeDir="false" afterPath="$PROJECT_DIR$/anwendung/src/pages/semesteroverview.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/anwendung/src/pages/semesteroverviewLecturer.js" beforeDir="false" afterPath="$PROJECT_DIR$/anwendung/src/pages/semesteroverviewLecturer.js" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="CSS File" />
<option value="JavaScript File" />
</list>
</option>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="ProjectId" id="2PV5k9t8lC9xvqgtEIMZ2TApWUu" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;WebServerToolWindowFactoryState&quot;: &quot;false&quot;,
&quot;git-widget-placeholder&quot;: &quot;main&quot;,
&quot;ignore.virus.scanning.warn.message&quot;: &quot;true&quot;,
&quot;last_opened_file_path&quot;: &quot;C:/Users/afist/WebstormProjects/SideBarCalendarTest&quot;,
&quot;list.type.of.created.stylesheet&quot;: &quot;CSS&quot;,
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
&quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
&quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;preferences.pluginManager&quot;,
&quot;ts.external.directory.path&quot;: &quot;C:\\Users\\afist\\AppData\\Local\\JetBrains\\Toolbox\\apps\\WebStorm\\ch-0\\231.8770.64\\plugins\\javascript-impl\\jsLanguageServicesImpl\\external&quot;,
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
}
}</component>
<component name="RecentsManager">
<key name="MoveFile.RECENT_KEYS">
<recent name="C:\TIF22A_AnwProjekt_B\anwendung\src\images" />
</key>
</component>
<component name="RunManager" selected="npm.dev">
<configuration name="index.js" type="NodeJSConfigurationType" temporary="true" nameIsGenerated="true" path-to-js-file="index.js" working-dir="$PROJECT_DIR$/anwendung/src/pages">
<method v="2" />
</configuration>
<configuration name="build" type="js.build_tools.npm">
<package-json value="$PROJECT_DIR$/anwendung/package.json" />
<command value="run" />
<scripts>
<script value="build" />
</scripts>
<node-interpreter value="node" />
<envs />
<method v="2" />
</configuration>
<configuration name="dev" type="js.build_tools.npm" nameIsGenerated="true">
<package-json value="$PROJECT_DIR$/anwendung/package.json" />
<command value="run" />
<scripts>
<script value="dev" />
</scripts>
<node-interpreter value="node" />
<package-manager value="npm" />
<envs />
<method v="2">
<option name="NpmBeforeRunTask" enabled="true">
<package-json value="$PROJECT_DIR$/anwendung/package.json" />
<command value="run" />
<scripts>
<script value="build" />
</scripts>
<node-interpreter value="node" />
<package-manager value="npm" />
<envs />
</option>
</method>
</configuration>
<list>
<item itemvalue="Node.js.index.js" />
<item itemvalue="npm.build" />
<item itemvalue="npm.dev" />
</list>
<recent_temporary>
<list>
<item itemvalue="Node.js.index.js" />
</list>
</recent_temporary>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="744e9299-0ce3-415c-8733-c935bf920887" name="Changes" comment="" />
<created>1683529551159</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1683529551159</updated>
<workItem from="1683529552463" duration="1756000" />
<workItem from="1683830457997" duration="1285000" />
<workItem from="1684223646646" duration="1195000" />
<workItem from="1684228236564" duration="1017000" />
<workItem from="1684257831013" duration="1011000" />
<workItem from="1684267194850" duration="890000" />
<workItem from="1684672228161" duration="1603000" />
<workItem from="1684788345629" duration="1507000" />
<workItem from="1684856925307" duration="3000" />
<workItem from="1684856964097" duration="5995000" />
<workItem from="1684915449317" duration="9318000" />
<workItem from="1685011281036" duration="2214000" />
<workItem from="1685055429281" duration="634000" />
<workItem from="1685103879210" duration="2066000" />
<workItem from="1685142372079" duration="5289000" />
<workItem from="1685311018550" duration="2063000" />
<workItem from="1685356323722" duration="4005000" />
<workItem from="1685389394962" duration="4465000" />
<workItem from="1685439319096" duration="492000" />
<workItem from="1686165563810" duration="18166000" />
<workItem from="1686259026223" duration="2970000" />
<workItem from="1686313568230" duration="1725000" />
<workItem from="1686331195896" duration="7520000" />
<workItem from="1686345244271" duration="7553000" />
<workItem from="1686572559048" duration="4289000" />
<workItem from="1686655739777" duration="3725000" />
<workItem from="1686659590430" duration="2344000" />
<workItem from="1686690018802" duration="32000" />
<workItem from="1686690072078" duration="307000" />
<workItem from="1686727178400" duration="9281000" />
<workItem from="1686825740350" duration="2964000" />
<workItem from="1686831091729" duration="595000" />
<workItem from="1686906198799" duration="2151000" />
<workItem from="1686910129813" duration="1653000" />
<workItem from="1686923077769" duration="3441000" />
<workItem from="1687173723149" duration="7011000" />
<workItem from="1687240431966" duration="47000" />
<workItem from="1687245202053" duration="3425000" />
<workItem from="1687249039012" duration="3407000" />
<workItem from="1687349584578" duration="477000" />
<workItem from="1687354510081" duration="453000" />
<workItem from="1687354999964" duration="291000" />
<workItem from="1687431213516" duration="596000" />
<workItem from="1688661149524" duration="602000" />
<workItem from="1688661766941" duration="1680000" />
<workItem from="1688812359996" duration="6843000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
</project>
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Ali Fistik, Jonas Braus, Amira Michels, Alexander Ebner, Mike Baier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+64 -4
View File
@@ -1,4 +1,64 @@
# TIF22A_AnwProjekt_B
Team B im Anwendungsprojekt (TIF22A)
Website can be accessed under: http://lectureplanner.de/ (caution no https, only http)
# TIF22A_AnwProjekt_B
Team B im Anwendungsprojekt (TIF22A)
Website can be accessed under: http://lectureplanner.de/ (caution no https, only http)
Hinweise für Lokale Installation:
Hinweis: Alles ist auf Windows getestet, sollte aber auch auf Mac und Linux funktionieren
1. es sollte java in einer der neusten Versionen installiert sein. (Empfehlung Java 20)
Downloadlink: https://www.oracle.com/de/java/technologies/downloads/
Eventuell müssen Sie nach der Installation den PC neu Starten.
Im Terminal können Sie mit "java -version" Ihre aktuelle Java version überprüfen.
2. Für das Frontend muss zusätzlich npm auf dem Computer installiert sein. (Weiteres siehe z.B. hier: https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
3. Es sollte feiertagejs installiert sein "npm install feiertagejs" (weiters: https://github.com/sfakir/feiertagejs)
Ausführen des Backends (nicht im "backend" ordner):
1. Öffnen Sie ein Terminal, dort wo die datei "backend.jar" liegt. Achten Sie darauf, dass die Dateien "database.mv.db" und "database.trace.db" im gleichen Ordner
wie die ".jar" Datei liegen.
2. Geben sie im Terminal ein: "java -jar backend.jar"
Ausführen des Frontends:
1. Gehen Sie in den Ordner "anwendung"
2. Öffnen Sie hier ein Terminal und führen den Command "npm run build" aus. (Bitte beachten, dass Feiertagejs vorher hier installiert sein sollte)
3. Führen Sie nun im gleichen Terminal den Command "npm run start" aus.
4. Gehen Sie im Browser auf "http://localhost:3000" oder einem davon abeweichenden Link der im Terminal angezeigt wird.
5. Einloggen können Sie sich mit folgenden User-Daten:
Sollte das ausführen lokal nicht funktionieren, können Sie das Projekt immer noch über die website http://www.lectureplanner.de betrachten.
Admins:
Email -------------------- Passwort
braus@gmail.com 123
fistik@gmail.com 123
Dozenten:
Email -------------------- Passwort
gloessner@gmail.com 123
birn@mail.com 123
behrends@gmx.de 123
-5
View File
@@ -1,5 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>
+9
View File
@@ -9,6 +9,7 @@
"version": "0.1.0",
"dependencies": {
"autoprefixer": "10.4.14",
"feiertagejs": "^1.3.9",
"next": "13.3.4",
"postcss": "8.4.23",
"react": "18.2.0",
@@ -530,6 +531,14 @@
"reusify": "^1.0.4"
}
},
"node_modules/feiertagejs": {
"version": "1.3.9",
"resolved": "https://registry.npmjs.org/feiertagejs/-/feiertagejs-1.3.9.tgz",
"integrity": "sha512-tUP+WBv2OWBhPwe3NfqwCtjMq+ym598a42tfqmL0FySswEb9xs96p2iKwqqx+lxKieu1njJBRZKsFm92bJhxZw==",
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+1
View File
@@ -10,6 +10,7 @@
},
"dependencies": {
"autoprefixer": "10.4.14",
"feiertagejs": "^1.3.9",
"next": "13.3.4",
"postcss": "8.4.23",
"react": "18.2.0",
+1
View File
@@ -2,6 +2,7 @@ import React from "react";
export default function Background()
{
//diese komponente generiert über css properties und geschickte rotationen von div element im raum das hintergrundbild
return (
<div style={{
position: "absolute",
+1 -1
View File
@@ -41,7 +41,7 @@ export default function Button(p) {
iconHTML = "";
}
//return the button
//return the button html
return (
<>
<button className={"round-border button font font-small"}
+23 -23
View File
@@ -14,9 +14,9 @@ export default function BasicDateCalendar(p) {
const ref = useRef(null)
function getBackMonthColor(monthIndex)
function getBackMonthColor(monthIndex) //Farbliche Kennzeichnung des Monats in dem man aktuell Plant
{
let date = new Date(parseInt(startParts[2]), parseInt(startParts[1]) + monthIndex - 1, 1)
let date = new Date(parseInt(startParts[2]), parseInt(startParts[1]) + monthIndex - 1, 1) //Datums Objekt des Monats in dem man sich aktuell befindet
if (date.getFullYear() === p.highlightYear && date.getMonth() === p.highlightMonth)
{
if(lastMonth !== p.highlightMonth)
@@ -35,8 +35,8 @@ export default function BasicDateCalendar(p) {
result = []
calculatedDay = []
startDate = new Date(p.startyear, 0 ,p.startday)
let endDate = new Date(p.endyear, 0 , p.endday)
startDate = new Date(p.startyear, 0 ,p.startday) //Startdatum des Theoriesemesters
let endDate = new Date(p.endyear, 0 , p.endday) //Enddatum des Theoriesemesters
let startString = startDate.getDate() + "." + (startDate.getMonth() + 1) + "." + p.startyear
let endString = endDate.getDate() + "." + (endDate.getMonth() + 1) + "." + p.endyear
generateCalendar(startString, endString)
@@ -45,10 +45,10 @@ export default function BasicDateCalendar(p) {
return (
<div className={"Allround"} ref={ref}>
<div className={"Down"}>
{result.map((monthResult, index) => (
{result.map((monthResult, index) => ( //map durch alle Monate aus dem Array monthResult
<div className={"A box-shadow"} onClick={() => p.onMonthClick(
(parseInt(startParts[1]) + index),
startParts
startParts //gibt zurück auf welchen Monat geklickt wurde, wodurch direkt in den jeweiligen Monat gewechselt werden kann
)} >
<p style={{
textAlign : "center",
@@ -63,7 +63,7 @@ export default function BasicDateCalendar(p) {
pointerEvents: "none"
}}>
{weekdays.map((weekday) => (
<p key={weekday} style={{
<p key={weekday} style={{ //generiere einmal alle Wochentage (Montag,...,Sonntag)
pointerEvents: "none"
}}>{weekday}</p>
))}
@@ -82,8 +82,7 @@ export default function BasicDateCalendar(p) {
}
function getMonthName(monthIndex) {
function getMonthName(monthIndex) { //holt die relevanten Monatsnamen aus dem 2D Array
if (startParts[1] - 1 + monthIndex < 12) {
return months[startParts[1] - 1 + monthIndex][0];
} else {
@@ -94,31 +93,31 @@ function getMonthName(monthIndex) {
function generateCalendar(start, ende)
{
splitter(start, ende)
if (startParts[2] < endParts[2])
if (startParts[2] < endParts[2]) //Abfrage für den Fall, dass ein Theoriesemester Jahresübergreifend ist
{
for (let i = startParts[1] - 1; i <= 11; i++)
for (let i = startParts[1] - 1; i <= 11; i++) //Durchlaufe alle Monate bis zum Jahresende
{
let monthResult = [];
for (let j = 1; j <= days[i]; j++)
for (let j = 1; j <= days[i]; j++) //durchlaufe alle Tage des Monats in dem wir uns befinden
{
if (
new Date(startParts[2], i, j) >= new Date(startParts[2], startParts[1] - 1, startParts[0]) &&
new Date(startParts[2], i, j) <= new Date(startParts[2], 11, 31)
)
) //überprüft ob der Tag noch in der angegebenen Zeitspanne des Theoriesemsters liegt
{
monthResult.push(j);
calculateDay(startParts[2], i, j)
}
}
result.push(monthResult);
if (i == 11)
if (i == 11) //erstes Jahr ist fertig abgebildet
{
for (let h = 0; h <= endParts[1] - 1; h++)
for (let h = 0; h <= endParts[1] - 1; h++) //laufe vom Anfang des Jahres bis zum angegebenen Ende des Theoriesemesters
{
let monthResultNewYear = [];
for (let g = 1; g <= days[h]; g++)
for (let g = 1; g <= days[h]; g++) //durchlaufe alle Tage des Monats in dem wir uns befinden
{
if (new Date(endParts[2], h, g) <= new Date(endParts[2], endParts[1] - 1, endParts[0]))
if (new Date(endParts[2], h, g) <= new Date(endParts[2], endParts[1] - 1, endParts[0])) //überprüft ob der Tag noch in der angegebenen Zeitspanne des Theoriesemsters liegt
{
monthResultNewYear.push(g);
calculateDay(endParts[2], h, g)
@@ -128,17 +127,17 @@ function generateCalendar(start, ende)
}
}
}
} else
} else //Normalfall das ein Anfang und Ende eines Theoriesemester im gleichen Jahr liegt
{
for (let i = startParts[1] - 1; i <= endParts[1] - 1; i++)
for (let i = startParts[1] - 1; i <= endParts[1] - 1; i++) //durchlaufe alle Monate in der angegebenen Zeitspanne
{
let monthResult = [];
for (let j = 1; j <= days[i]; j++)
for (let j = 1; j <= days[i]; j++) //durchlaufe alle Tage des Monats in dem wir uns befinden
{
if (
new Date(startParts[2], i, j) >= new Date(startParts[2], startParts[1] - 1, startParts[0]) &&
new Date(startParts[2], i, j) <= new Date(startParts[2], endParts[1] - 1, endParts[0])
)
) //überprüft ob der Tag noch in der angegebenen Zeitspanne des Theoriesemsters liegt
{
monthResult.push(j)
calculateDay(startParts[2], i, j)
@@ -149,7 +148,8 @@ function generateCalendar(start, ende)
}
}
function calculateDay(x, i, j){
function calculateDay(x, i, j)//berechnet den Wochentag eines Datums (Montag,...,Sonntag)
{
if (j == startDate.getDate() && i == startDate.getMonth() || j == 1){
let monthStart = new Date(x, i, j)
if (monthStart.getDay() == 0)
@@ -158,7 +158,7 @@ function calculateDay(x, i, j){
}
}
function freeSpaces(index)
function freeSpaces(index)//generiert Leerzeichen damit Tage genau unter ihrem jeweiligen Wochentag stehen
{
let arrayTest = []
for (let i = 0; i < calculatedDay[index]; i++) {
File diff suppressed because it is too large Load Diff
+3
View File
@@ -1,2 +1,5 @@
//Achtung!!! hier kann die URL für das Backend auf das Online Backend geändert werden. Verwendung des Online Backends
//auf eigene Gefahr. Aktuellster Stand der Software kann hier in Kombination mit einem Lokalen Frontend nicht gewährleistet werden.
//export const baseURL = "http://185.245.96.48:8080"
export const baseURL = "http://localhost:8080"
+3 -3
View File
@@ -9,9 +9,9 @@ export default function DateElement(p){
let startDate = new Date(p.year, 0, p.startday);
let endDate = new Date(p.year, 0, p.startday + 5);
let startDateString = `${startDate.getDate()}.${startDate.getMonth()+1}.${startDate.getFullYear()}`;
let endDateString = `${endDate.getDate()}.${endDate.getMonth()+1}.${endDate.getFullYear()}`;
return (
let startDateString = `${startDate.getDate()}.${startDate.getMonth()+1}.${startDate.getFullYear()}`; //Anfang der Woche in der man sich befindet wird in startDateString geladen
let endDateString = `${endDate.getDate()}.${endDate.getMonth()+1}.${endDate.getFullYear()}`; //Ende der Woche in der man sich befindet wird in endDateString geladen
return /*Anzeige des Beginns und Endes der Woche in der man sich befindet*/(
<>
<div className="dateElement round-border box-shadow">
<p>{startDateString} - {endDateString}</p>
+1
View File
@@ -1,3 +1,4 @@
//hier werden fehlertypen mit ihrem anzeigetext für die CalenderView hinterlegt
export const ErrorType = {
Okay: "Okay",
TooLong: "Zu lang, maximal 8h pro Tag!",
+3
View File
@@ -1,3 +1,6 @@
//hier sind wichtige svg images zur späteren verwendung auf buttons usw. hinterlegt. In diese können später evtl. per stringmanipulation weitere infos
//wie breite und höhe eingearbeitet werden.
export const arrowLeft = `<svg xmlns="http://www.w3.org/2000/svg" fill="white" class="bi bi-arrow-left" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8z"/>
</svg>`
+240 -255
View File
@@ -5,298 +5,270 @@ import Background from "@/components/Background";
import {baseURL} from "@/components/Constants";
import Back from "@/components/Back";
//dummy daten für die vorlesungsfächer
let modulesDummy = [
["Analysis", "Theo Inf 1"],
["Lineare Algebra", "Anwendungsprojekt"],
["Theo Inf 3", "Software Eng"],
["Security", "BWL"],
["Software Eng", "Security"],
["Studienarbeit", "Bachelor"]
["Grundlagen u. Logik", "Programmieren 1", "Programmieren 2", "Digitaltechnik", "Web. Eng.", "Analysis"],
["Lineare Algebra", "Anwendungsprojekt", "BWL", "Projektmanagement", "Algo. Kompl.", "Python", "Prolog"],
["Software Eng. 1", "Netztechnik", "Betriebssysteme", "Rechnerarchitektur", "Systemnahe Progra.", "Algorithmen 2", "Stochastik", "Angewandte Mathe."],
["Software Eng. 2", "Datenbanken", "Compilerbau", "Automaten", "Formale Sprachen", "IT-Sicherheit", "IOT"],
["Software Eng. 3", "Datenbanken 2", ],
["Bachelor"]
]
let tempSemesterNumber = 0
let update = false
let baseMapping = []
//speichert ab, ob die nummer des semesters in der bearbeitung geändert wurde.
//wichtig umd daten (aus alten semester nummern) korrekt löschen zu können
let hasSemesterNumberChanged = false
export default function InputForm(p) {
const [startDate, setStartDate] = useState("0000-00-00")
const [endDate, setEndDate] = useState("0000-00-00")
const [courseName, setCourseName] = useState("")
const [startDate, setStartDate] = useState("")
const [endDate, setEndDate] = useState("")
const [semesterNumber, setSemesterNumber] = useState(0)
const [users, setUsers] = useState([])
const [modulesSelectorValues, setModulesSelectorValues] = useState(["nothing", "nothing"])
const [userModulesMapping, setUserModulesMapping] = useState({})
const [isChecked, setIsChecked] = useState([])
const [isActivated, setIsActivated] = useState([])
const [moduleUserMapping, setModuleUserMapping] = useState([])
const router = useRouter()
useEffect(() => {
let base = baseURL + "/semester/id?sessionid=" + localStorage.getItem("sessionid") + "&id=" + localStorage.getItem("currentsid")
fetch(base).then(r => r.json()).then(j => {
setCourseName(j.name)
hasSemesterNumberChanged = false
let tempStartDate = new Date(parseInt(j.startyear), 0, parseInt(j.startday))
let tempEndDate = new Date(parseInt(j.endyear), 0, parseInt(j.endday))
setStartDate(tempStartDate.getFullYear() + "-" + ((tempStartDate.getMonth() + 1).toString().padStart(2, "0")) + "-" + tempStartDate.getDate().toString().padStart(2, "0"))
setEndDate(tempEndDate.getFullYear() + "-" + ((tempEndDate.getMonth() + 1).toString().padStart(2, "0")) + "-" + tempEndDate.getDate().toString().padStart(2, "0"))
setSemesterNumber(j.number)
tempSemesterNumber = j.number
}).then(() => {
readModules()
update = true
}).catch(() => readModules())
}, [])
function readModules() {
let usersTemp = []
let userURL = baseURL + "/users/all?sessionid=" + localStorage.getItem("sessionid")
fetch(userURL).then(r => r.json()).then(j => {
setUsers(j)
usersTemp = j
let temp = [false, false, false]
let temp2 = []
for (let i = 0; i < j.length; i++) {
temp.push(false)
temp2.push(false)
}
setIsChecked(temp)
setIsActivated(temp2)
}).then(() => {
let modulesURL = baseURL + "/module/bysemesterid?sessionid=" + localStorage.getItem("sessionid") + "&semesterid=" + localStorage.getItem("currentsid");
fetch(modulesURL).then(r => r.json()).then(j => {
setUserModulesMapping(j)
baseMapping = j
let temp = isChecked.slice()
let temp2 = isActivated.slice()
for (let i = 0; i < usersTemp.length; i++) {
let currentUser = usersTemp[i]
let found = false
let foundModuleLast = null
for (let f = 0; f < j.length; f++) {
let currentModule = j[f]
if (currentModule.userid === currentUser.id) {
found = true
foundModuleLast = currentModule
}
}
if (found) {
temp[i] = true
temp2[i] = foundModuleLast.activated === 1
}
}
setIsChecked(temp)
setIsActivated(temp2)
})
}).then(() => {
setModulesSelectorValues(modulesDummy[tempSemesterNumber])
//lädt zu beginn alle dummy daten des ersten semesters
let arr = []
modulesDummy[0].map(e => {
arr.push({"moduleid": -1, "userid": -1, "activated": 0})
})
}
setModuleUserMapping(arr)
function onCourseNameChange(e) {
setCourseName(e.target.value)
}
let url = baseURL + "/users/all?sessionid=" + localStorage.getItem("sessionid")
//holt alle dozenten, die für das dozieren in fragen kommen.
fetch(url).then(r => r.json()).then(u => {
setUsers(u)
}).then(() => {
let tempSemesterNumber = 0
//hier kann ausgemacht werden, ob ein semester neu erstellt werden soll oder bearbeitet, wenn 0 dann wird neu erstellt
//also hier wird bearbeitet
if(localStorage.getItem("currentsid") != 0)
{
//holen alle daten, die bis jetzt in diesem semester vorhanden sind (noch keine zuweisungen von dozenten zu vorlesungen)
fetch(baseURL + "/semester/id?sessionid=" + localStorage.getItem("sessionid") + "&id=" + localStorage.getItem("currentsid")).then(r => r.json()).then(semester => {
setCourseName(semester.name)
let startYear = semester.startyear
let endYear = semester.endyear
let start = new Date(startYear, 0, semester.startday)
let end = new Date(endYear, 0, semester.endday)
function onStartDateChange(e) {
setStartDate(e.target.value)
}
setStartDate(startYear + "-" + ((start.getMonth() + 1) < 10 ? "0" + (start.getMonth() + 1) : (start.getMonth() + 1)) + "-" + (start.getDate() < 10 ? "0" + start.getDate() : start.getDate()))
setEndDate(endYear + "-" + ((end.getMonth() + 1) < 10 ? "0" + (end.getMonth() + 1) : (end.getMonth() + 1)) + "-" + (end.getDate() < 10 ? "0" + end.getDate() : end.getDate()))
function onEndDateChange(e) {
setEndDate(e.target.value)
}
tempSemesterNumber = semester.number
setSemesterNumber(semester.number)
function onSemesterNumberChange(e) {
setSemesterNumber(e.target.value)
setModulesSelectorValues(modulesDummy[e.target.value])
}
arr = []
modulesDummy[semester.number].map(e => {
arr.push({"moduleid": -1, "userid": -1, "activated": 0})
})
function isOptionSelected(e, userid) {
let found = false;
}).then(() => {
//hole alle zuweisungen von dozenten zu vorlesungen / fächern innerhalb dieses semesters.
fetch(baseURL + "/module/bysemesterid?sessionid=" + localStorage.getItem("sessionid") + "&semesterid=" + localStorage.getItem("currentsid")).then(r => r.json()).then(modules => {
console.log(modules)
for(let i = 0; i < modules.length; i++)
{
for(let j = 0; j < modulesDummy[tempSemesterNumber].length; j++)
{
if(modulesDummy[tempSemesterNumber][j] == modules[i].name)
{
arr[j].userid = modules[i].userid
arr[j].moduleid = modules[i].id
arr[j].activated = modules[i].activated
break
}
}
}
for (let i = 0; i < userModulesMapping.length; i++) {
let current = userModulesMapping[i]
if (current.name === e && current.userid === userid) {
found = true;
}
}
return found;
}
function onCheckedChange(e, index) {
let temp = isChecked.slice()
temp[index] = e.target.checked
setIsChecked(temp)
if (!e.target.checked) {
let temp = []
let currentUser = users[index]
for (let j = 0; j < userModulesMapping.length; j++) {
if (userModulesMapping[j].userid !== currentUser.id) {
temp.push(userModulesMapping[j])
}
}
setUserModulesMapping(temp)
}
}
function onActivatedChange(e, index) {
let temp = isActivated.slice()
temp[index] = e.target.checked
setIsActivated(temp)
let userid = users[index].id
for (let j = 0; j < userModulesMapping.length; j++) {
if (userModulesMapping[j].userid === userid) {
userModulesMapping[j].activated = e.target.checked ? 1 : 0
}
}
}
function onModuleSelectionChange(e, index) {
let userid = users[index].id
let newMapping = []
let oldNamesIds = new Map()
for (let j = 0; j < userModulesMapping.length; j++) {
let currentModuleMapping = userModulesMapping[j]
if (currentModuleMapping.userid != userid) {
newMapping.push(currentModuleMapping)
} else {
oldNamesIds.set(currentModuleMapping.name, currentModuleMapping.id)
}
}
let found = false
for (let i = 0; i < e.target.options.length; i++) {
let currentOption = e.target.options[i]
if (currentOption.selected) {
found = true
newMapping.push({
"id": oldNamesIds.has(currentOption.value) ? oldNamesIds.get(currentOption.value) : -1,
"userid": userid,
"semesterid": -1,
"name": currentOption.value,
"activated": isActivated[index] ? 1 : 0
setModuleUserMapping(arr)
})
})
}
}
})
}, [])
let temp = isChecked.slice()
temp[index] = found
setIsChecked(temp)
setUserModulesMapping(newMapping)
}
function onButtonAbort() {
//sollte auf abbrechen geklickt worden sein...
function onButtonAbort(e) {
router.back()
}
function onButtonSave() {
let tempDateStart = new Date(parseInt(startDate.split("-")[0]), parseInt(startDate.split("-")[1]) - 1, parseInt(startDate.split("-")[2]))
let tempDateEnd = new Date(parseInt(endDate.split("-")[0]), parseInt(endDate.split("-")[1]) - 1, parseInt(endDate.split("-")[2]))
//sollte auf speichern geklickt worden sein... hier werden nur daten des semesters übermittelt, noch nicht die
//zweisungen von dozenten und vorlesungen / modulen
function onButtonSave(e) {
let startDayInYear = Math.round((tempDateStart - new Date(tempDateStart.getFullYear(), 0, 0)) / (1000 * 60 * 60 * 24))
let endDayInYear = Math.round((tempDateEnd - new Date(tempDateEnd.getFullYear(), 0, 0)) / (1000 * 60 * 60 * 24))
//bereite alle relevanten daten des input form auf
let semesterid = localStorage.getItem("currentsid")
let startYear = parseInt(startDate.split("-")[0])
let endYear = parseInt(endDate.split("-")[0])
let semesterJson = {
"id": update ? localStorage.getItem("currentsid") : 0,
"startday": startDayInYear,
"endday": endDayInYear,
"name": courseName,
"startyear": tempDateStart.getFullYear(),
"endyear": tempDateEnd.getFullYear(),
"number": semesterNumber
let start = new Date(startYear, parseInt(startDate.split("-")[1]) - 1, parseInt(startDate.split("-")[2]))
let end = new Date(endYear, parseInt(endDate.split("-")[1]) - 1, parseInt(endDate.split("-")[2]))
let startDayInYear = Math.round((start - new Date(startYear, 0, 0)) / (1000 * 60 * 60 * 24))
let endDayInYear = Math.round((end - new Date(endYear, 0, 0)) / (1000 * 60 * 60 * 24))
//wenn das semester neu erstellt werden soll, sende eine post anfrage and das backend.
if(semesterid == 0)
{
fetch(baseURL + "/semester?sessionid=" + localStorage.getItem("sessionid"), {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({
"id": 0,
"startday": startDayInYear,
"endday": endDayInYear,
"name": courseName,
"startyear": startYear,
"endyear": endYear,
"number": semesterNumber
})
}).then(r => r.json()).then(semester => {semesterid = semester.id}).then(() => modulesInBackend(semesterid))
}
//wenn das semester nur editiert wurde, stelle eine put anfrage an das backend.
else
{
fetch(baseURL + "/semester?sessionid=" + localStorage.getItem("sessionid"), {
method: "PUT",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({
"id": semesterid,
"startday": startDayInYear,
"endday": endDayInYear,
"name": courseName,
"startyear": startYear,
"endyear": endYear,
"number": semesterNumber
})
}).then(() => modulesInBackend(semesterid))
}
}
fetch(baseURL + "/semester?sessionid=" + localStorage.getItem("sessionid"), {
method: update ? "PUT" : "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify(semesterJson)
}).then(r => r.json()).then(async sem => {
let semesterID = sem.id
for (let i = 0; i < baseMapping.length; i++) {
let found = false
for (let j = 0; j < userModulesMapping.length; j++) {
if (baseMapping[i].name === userModulesMapping[j].name) {
found = true
function modulesInBackend(semesterid)
{
//sollte sich die nummer des semesters geändert haben, lösche alle alten zuweisungen von dozenten und modulen aus dem backend.
if (hasSemesterNumberChanged) {
fetch(baseURL + "/module/bysemesterid?sessionid=" + localStorage.getItem("sessionid") + "&id=" + localStorage.getItem("currentsid"), {
method: "DELETE"
}).then(() => {
for (let i = 0; i < moduleUserMapping.length; i++) {
let current = moduleUserMapping[i]
if (current.userid != -1) {
if (current.moduleid == -1) {
fetch(baseURL + "/module?sessionid=" + localStorage.getItem("sessionid"), {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({
"id": 0,
"userid": current.userid,
"semesterid": semesterid,
"name": modulesDummy[semesterNumber][i],
"activated": current.activated
})
})
}
}
}
})
} else {
if (!found) {
fetch(baseURL + "/module?sessionid=" + localStorage.getItem("sessionid") + "&id=" + baseMapping[i].id, {
method: "DELETE"
})
//hier werden modulzuweisungen zu dozenten am backend aktualisiert
for (let i = 0; i < moduleUserMapping.length; i++) {
let current = moduleUserMapping[i]
//solte die zuweisung des modules zum dozenten noch aktiv sein...
if (current.userid != -1) {
//im fall, dass das die zuweisung nocht nie existiert hat, stelle eine post anfrage
if (current.moduleid == -1) {
fetch(baseURL + "/module?sessionid=" + localStorage.getItem("sessionid"), {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({
"id": 0,
"userid": current.userid,
"semesterid": semesterid,
"name": modulesDummy[semesterNumber][i],
"activated": current.activated
})
})
} else {
//im fall, dass die zuweisung schon existiert hat aber nur geändert wurde, stelle eine PUT anfrage
fetch(baseURL + "/module?sessionid=" + localStorage.getItem("sessionid"), {
method: "PUT",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({
"id": current.moduleid,
"userid": current.userid,
"semesterid": 0,
"name": "",
"activated": current.activated
})
})
}
//.. ist diese zuweisung nicht mehr aktiv, lösche die zuweisung aus dem backend.
} else {
if (current.moduleid != -1) {
fetch(baseURL + "/module?sessionid=" + localStorage.getItem("sessionid") + "&id=" + current.moduleid, {
method: "DELETE"
})
}
}
}
}
for (let i = 0; i < userModulesMapping.length; i++) {
userModulesMapping[i].semesterid = semesterID
setTimeout(() => {
console.log(userModulesMapping[i])
fetch(baseURL + "/module?sessionid=" + localStorage.getItem("sessionid"), {
method: userModulesMapping[i].id === -1 ? "POST" : "PUT",
headers: {"Content-Type": "application/json"},
body: JSON.stringify(userModulesMapping[i])
})
}, i * 100)
}
})
//gehe nach dem speichern zurück auf das dashboard
router.back()
}
return (
<>
{/*das hintergrundbild*/}
<Background/>
<div className={"box-shadow input-form round-border"}>
{/*grundlegende input forms für namen... semesternummer usw.*/}
<p>Kursname</p>
<input type={"text"} className={"box-shadow round-border"} style={{padding: 8, width: "100%"}}
onChange={e => onCourseNameChange(e)} value={courseName}/>
<input type={"text"} className={"box-shadow round-border"}
style={{padding: 8, width: "100%", backgroundColor: (courseName == "") ? "#E44747" : "white"}}
onChange={(e) => {
setCourseName(e.target.value)
}} value={courseName}/>
<div style={{display: "flex", justifyContent: "flex-start", gap: 40}}>
<p>Theorie Anfang</p>
<p>Theorie Ende</p>
</div>
<div style={{display: "flex", justifyContent: "flex-start", gap: 20}}>
<input type={"date"} className={"box-shadow round-border"} style={{padding: 8}}
onChange={e => onStartDateChange(e)} value={startDate}/>
<input type={"date"} className={"box-shadow round-border"} style={{padding: 8}}
onChange={e => onEndDateChange(e)} value={endDate}/>
<input type={"date"} className={"box-shadow round-border"} style={{
padding: 8, backgroundColor: (startDate == "" || startDate >= endDate) ? "#E44747" : "white"
}} value={startDate} onChange={e => {
setStartDate(e.target.value)
}}/>
<input type={"date"} className={"box-shadow round-border"} style={{
padding: 8, backgroundColor: (endDate == "" || startDate >= endDate) ? "#E44747" : "white"
}} value={endDate} onChange={e => {
setEndDate(e.target.value)
}}/>
</div>
<p>Semester Wählen</p>
<select className={"round-border box-shadow"} style={{padding: 5, width: "100%"}} value={semesterNumber}
onChange={e => onSemesterNumberChange(e)}>
<select className={"round-border box-shadow"} style={{padding: 5, width: "27%"}} value={semesterNumber}
onChange={e => {
setSemesterNumber(e.target.value)
let arr = []
modulesDummy[e.target.value].map(e => {
arr.push({"moduleid": -1, "userid": -1, "activated": 0})
})
setModuleUserMapping(arr)
hasSemesterNumberChanged = true
}}>
<option value={0}>1. Semester</option>
<option value={1}>2. Semester</option>
<option value={2}>3. Semester</option>
@@ -305,36 +277,45 @@ export default function InputForm(p) {
<option value={5}>6. Semester</option>
</select>
{/*hier die tabelle, die alle zuweisungen von dozenten und modulen / vorlesungen anzeigt*/}
<div className={"table-wrapper"}>
<table>
<tbody>
<tr>
<th>Wählen</th>
<th>Freischalten</th>
<th>Dozent</th>
<th>Modul</th>
<th>Dozent</th>
</tr>
{
users.map((user, index) => (
<tr>
modulesDummy[semesterNumber].map((module, index) => (
<tr style={{height: 50}}>
<td>
<input type={"checkbox"} checked={isChecked[index]}
onChange={e => onCheckedChange(e, index)}/>
<input type={"checkbox"}
checked={index < moduleUserMapping.length && moduleUserMapping[index].activated == 1}
onChange={e => {
let arr = moduleUserMapping.slice()
arr[index].activated = e.target.checked ? 1 : 0
setModuleUserMapping(arr)
}
}></input>
</td>
<td>
<input type={"checkbox"} checked={isActivated[index]}
onChange={e => onActivatedChange(e, index)}/>
<p style={{fontWeight: "normal"}}>{module}</p>
</td>
<td>
{user.firstName + " " + user.lastName}
</td>
<td>
<select multiple={true} className={"box-shadow round-border"}
style={{padding: 5}}
onChange={e => onModuleSelectionChange(e, index)}>
{modulesSelectorValues.map(msv => (
<option value={msv}
selected={isOptionSelected(msv, user.id)}>{msv}</option>
<select className={"box-shadow round-border"} style={{padding: 5}}
onChange={e => {
let arr = moduleUserMapping.slice()
arr[index].userid = e.target.value
setModuleUserMapping(arr)
console.log(moduleUserMapping)
}}
value={index < moduleUserMapping.length && moduleUserMapping[index].userid}>
<option value={-1}>-</option>
{users.map(user => (
<option value={user.id}>{user.firstName} {user.lastName}</option>
))}
</select>
</td>
@@ -352,8 +333,12 @@ export default function InputForm(p) {
width: "100%",
gap: 10
}}>
{/*hier die knöpfe abbrechen und speichern mit einer kleinen validierung, ob die grundlegen semesterdaten angegeben wurden*/}
<Button text={"Abbrechen"} onClick={onButtonAbort}/>
<Button text={"Speichern"} color={"#77932b"} onClick={onButtonSave}/>
<Button text={"Speichern"} color={"#77932b"} onClick={() => {
(startDate == "" || endDate == "" || startDate >= endDate || courseName == "") ? () => {
} : onButtonSave()
}}/>
</div>
</div>
</>
+17 -5
View File
@@ -9,13 +9,18 @@ export default function Login() {
let url = baseURL + "/users"
//sollte auf den login knopf geklickt worden sein...
async function on_login_click() {
//füge der url die mail und das passwort an, sicherheitsfeatures werden die hier vorläufig nicht berücktsichtigt
url += "?mail=" + inputUserName + "&password=" + inputPassword;
let response = await fetch(url, {
method: "GET",
});
//lese die antwort vom backend, und versuche die sessionid (für weitere anfragen am backend wird diese übergeben) auszulesen.
//ist der status nicht "failed" wurden die einloggdaten gefunden und im fall, dass kein fehler aufgetreten ist
//eine sessionid zurückgegeben.
let reader = response.body.getReader();
let value = String.fromCharCode.apply(null, ((await reader.read()).value))
if (value != "failed") {
@@ -26,7 +31,12 @@ export default function Login() {
let admin = 0
await fetch(url).then(o => o.json()).then(user => {
admin = user.permissions})
//setze für die spätere verwendung im localstorage, ob es sich bei dem aktuellen nutzer um einen admin handelt.
//selbst wenn diese informationen vom nutzer im browser manuell editiert werden, blockt das backend
//über sämtliche anfrage mit einer sessionid die dozenten bezogen ist ab. => diese information ist nur für die anzeige.
//diese könnte allerdings nicht ordnungsgemäß funktionieren sollte ein nutzer versuchen das tool "auszutricksen"
localStorage.setItem("admin", admin)
//leite den nutzer je nach seinem status auf die admin oder dozenten ansicht weiter.
if(admin === 1) {
await router.push("/semesteroverview")
}else await router.push("/semesteroverviewLecturer")
@@ -40,7 +50,9 @@ export default function Login() {
const [inputUserName, setInputUserName] = useState("")
const [inputPassword, setInputPassword] = useState("")
const [hint, setHint] = useState("type here")
//hier states für die hinweise in den loginfeldern für späteres anzeigen von evtl. fehlgeschlagen login versuchen.
const [hint, setHint] = useState("Benutzername")
const [hint2, setHint2] = useState("Passwort")
const [backgroundColor, setBackgroundColor] = useState("rgb(255, 255, 255)")
const router = useRouter()
@@ -48,19 +60,19 @@ export default function Login() {
return (
// <div className="border">
<login className={"login-container box-shadow"}>
<p className={"font-big-fat placement"}>Login</p>
<div className={"placement"}>
<br/>
<p className={"font-kinda-big"}>Username</p>
<p className={"font-kinda-big"}>Benutzername:</p>
<input type="text" value={inputUserName} onChange={e => setInputUserName(e.target.value.toLowerCase())}
placeholder={hint} className="input input-bordered input-sm w-full max-w-xs box-shadow"
style={{
backgroundColor: backgroundColor
}}/>
<br/>
<p className={"font-kinda-big"}>Password</p>
<p className={"font-kinda-big"}>Passwort:</p>
<input type="password" value={inputPassword} onChange={e => setInputPassword(e.target.value)}
placeholder={hint} className="input input-bordered input-sm w-full max-w-xs box-shadow"
placeholder={hint2} className="input input-bordered input-sm w-full max-w-xs box-shadow"
style={{
backgroundColor: backgroundColor
}}/>
+2 -1
View File
@@ -9,7 +9,8 @@ export default function PopUp(p) {
return (
<>
<div style={{
display: p.displayState
display: p.displayState,
zIndex: 1000
}}>
<div className={"modal-container"}>
@@ -1,8 +1,4 @@
import StatusBar from "@/components/StatusBar";
import React, {useEffect} from "react";
import Button from "@/components/Button";
import {deleteItem, editItem} from "@/components/Icons";
export default function SemesterTile(p)
{
let editable = true;
+20 -6
View File
@@ -1,20 +1,34 @@
import React from "react"
import React, {useState} from "react"
import {baseURL} from "@/components/Constants";
import {console} from "next/dist/compiled/@edge-runtime/primitives/console";
export default function StatusBar(p)
{
if(p.progress > 100) p.progress = 100;
let classNames = ["not-started", "started", "finished"];
let classNames = ["not-started"];
let index = p.progress / 50;
let index2 = p.progress / 100;
let index3 = p.progress - 100;
let index4 = p.progress - 50;
let actives = ["", "", ""]
let actives = ["", "", ""];
actives[index] = "active";
let actives2 = ["", "", ""];
actives2[index2] = "active";
let actives3 = ["", "", ""];
actives3[index3] = "active";
let actives4 = ["", "", ""];
actives4[index4] = "active";
return (
<div className={"step-container"}>
<div className={"steps"}>
<span className={"step " + classNames[0] + " " + actives[0]}>1</span>
<span className={"step " + classNames[1] + " " + actives[1]}>2</span>
<span className={"step " + classNames[2] + " " + actives[2]}>3</span>
<span className={"step " + classNames[0] + " " + actives[0] + actives2[1] + actives3[1] + actives4[0]}>1</span>
<span className={"step " + classNames[0] + " " + actives[1] + actives2[1] + actives3[1] + actives4[1]}>2</span>
<span className={"step " + classNames[0] + " " + actives[2] + actives2[2] + actives3[2] + actives4[2]}>3</span>
<div className={"progress-bar " + classNames[index]}
style={{
width: p.progress + "%"
-21
View File
@@ -1,21 +0,0 @@
import Button from "@/components/Button";
import { baseURL } from "@/components/Constants";
import {useRouter} from "next/router";
export default function SubmitButton() {
const router = useRouter();
return (
<div
style={{
position: "absolute",
right: 70,
bottom: 20,
borderBottomRightRadius: 10,
}}
>
<Button onClick={() => router.push("/submit")} text={"Abgeben"} color={"#77932b"} width={100} height={40} />
</div>
);
}
@@ -1,56 +0,0 @@
import {baseURL} from "@/components/Constants";
import Button from "@/components/Button";
export default function SubmitWarning(p){
async function submit() {
let url = baseURL + "/module?sessionid=" + localStorage.getItem("sessionid");
let json1 = {
"id": 0,
"userid": localStorage.getItem("userid"),
"semesterid": localStorage.getItem("currentsid"),
"name": localStorage.getItem("currentmodulename"),
"activated": 0
}
await fetch(url, {
method: "PUT",
headers: {"Content-Type": "application/json"},
body: JSON.stringify(json1)
})
p.onClick();
p.onClick();
}
return (
<div className="box-shadow" style={{
position: "absolute",
top: 300,
left: 0,
right: 0,
borderRadius: 5,
textAlign: "center",
fontSize: 20,
margin: "auto",
width: 600
}}>
<p style={{paddingTop: 20, paddingBottom: 5}}>Möchten Sie wirklich abgeben?</p>
<p>Danach können Sie keine Änderungen mehr vornehmen!</p>
<div style={{
display: "flex",
flexDirection: "row",
justifyContent: "center",
paddingTop: 40,
paddingBottom: 20
}}>
<Button onClick={() => submit()} text={"Bestätigen"} color={"#77932b"} width={100} height={40} />
<div style={{width: 20}}></div>
<Button onClick={() => p.onClick()} text={"Abbrechen"} color={"red"} width={100} height={40} />
</div>
</div>
)
}
+7 -12
View File
@@ -1,19 +1,14 @@
//hier ein test für die umrechnung zwischen internen und externen datumsformaten. Kann zur nachvollziehbarkeit der rechnung evtl. nützlich sein.
export default function Test(p)
{
// let datum = new Date(2023, 1, 10);
// let start = new Date(datum.getFullYear(), 0, 0);
//
// let difference = (datum - start) / (1000 * 60 * 60 * 24)
let day = 41
let datum = new Date(2023, 0, 30)
let datum = new Date(2023, 0, day)
datum.getMonth()
return (
<div>
<p>{datum.getMonth()}</p>
</div>
);
let datum2 = new Date(2023, 5, 12);
let start = new Date(datum2.getFullYear(), 0, 0);
let dayInYear = (datum2 - start) / (1000 * 60 * 60 * 24)
}
+2
View File
@@ -1,5 +1,7 @@
import React from 'react';
//hier eine verworfene version der SemesterTile, welche einen hübschen hover effekt ansetzt. Könnte evtl.
//wieder eingepflegt werden.
const Tile = () => {
const [isHovered, setIsHovered] = React.useState(false);
const [cursorPosition, setCursorPosition] = React.useState({ x: 0, y: 0 });
+1 -2
View File
@@ -2,13 +2,12 @@ import Button from "@/components/Button";
import DateElement from "@/components/DateElement";
import { arrowLeft } from "./Icons"
import { arrowRight } from "./Icons"
import { useState } from 'react'
export default function WeekSelector(p){
return (
return /*Aufruf des DateElements mit aktuellem Starttag im Jahr und dem Jahr, sowie Buttons zum hin und her Wechsel der Wochen*/(
<>
<div className="weekSelector">
<Button icon={arrowLeft} onClick={() => p.onFunctionLeft()} width={50} color={"#346991"}/>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 19 KiB

+34 -34
View File
@@ -15,27 +15,26 @@ export default function Help(p)
return (
<div>
<Back onClick={() => router.back()}/>
<div className={"help-line"}>
<img src={screen1.src}/>
<div className={"text-form"}>
<h1>Die Monats-Seiten-Leiste</h1>
<p>- Hier kannst du sehen in welchem Monat du dich aktuell befindest (blau hinterlegt).</p>
<p>- Durch einen Links-Klick auf eine Monatskacheln kannst du direkt an den Anfang dieses Monats springen</p>
<h1>Die Monats-Leiste</h1>
<p>- Hier siehst du in welchem Monat Sie sich aktuell befinden (blau hinterlegt)</p>
<p>- Durch einen Links-Klick auf eine Monatskacheln springst du direkt an den Anfang des jeweiligen Monats</p>
</div>
</div>
<div className={"help-line"}>
<img src={screen2.src}/>
<img src={screen2.src} width={1000}/>
<div className={"text-form"}>
<h1>Die Planungs-Ansicht</h1>
<p>- Hier siehst du alle deine Termine in grün (bzw. gelb bei Warnungen) und von anderen Dozenten in grau</p>
<p>- Hier siehst du deine eingetragenen Vorlesungen in diesem Kurs in Grün, deine eigenen Vorlesungen aus anderen Kursen in Blau und die geplanten Vorlesungen anderer Dozenten in Grau</p>
<p>- Durch einen Links-Klick kannst du eine neue Vorlesung an einem Tag erstellen</p>
<p>- Durch Halten der dunkleren Leisten kannst du die Zeiten des Termins anpassen</p>
<p>- Durch Rechts-Klick kannst du eine Vorlesung löschen</p>
<p>- Durch Klicken auf die Pfeiltasten oben kannst du die Woche wechseln</p>
<p>- Bitte beachte, dass du Vorlesungen nur zwischen den beiden Roten linien erstellen kannst</p>
<p>- Ausgegraute Tage liegen nicht im Semester, hier kannst du nicht planen</p>
<p>- Durch Halten der dunkleren Leisten ist es möglich die Zeiten deiner Termine anzupassen</p>
<p>- Durch einen Rechts-Klick können eigene Termine gelöscht werden</p>
<p>- Mithilfe der Navigationsleiste ist es möglich die Wochen zur Planung zu wechseln</p>
<p>- Ausgegraute Tage liegen entweder nicht im Semester oder sind Feiertage, hier kann nicht geplant werden</p>
</div>
</div>
@@ -44,16 +43,7 @@ export default function Help(p)
<div className={"text-form"}>
<h1>Die Warnungs-Ansicht</h1>
<p>- Sollte ein Termin gelb erscheinen kannst du hier sehen woran das liegt</p>
<p>- Warnung sind empfohlene Verbesserungsverschläge aber müssen nicht zwangshaft beachtet werden</p>
<p>- Sollte hier "Okay" für einen Tag stehen ist alles perfekt</p>
</div>
</div>
<div className={"help-line"}>
<img src={screen5.src}/>
<div className={"text-form"}>
<h1>Der Login</h1>
<p>- Hier kannst du dich mit deiner Email und deinem Passwort einloggen</p>
<p>- Warnung sind empfohlene Verbesserungsverschläge, müssen aber nicht zwangshaft beachtet werden</p>
</div>
</div>
@@ -69,15 +59,23 @@ export default function Help(p)
<div className={"help-line"}>
<img src={screen6.src}/>
<div className={"text-form"}>
<h1>Das Dashboard</h1>
<h2>Für Admins:</h2>
<p>- Über den "+" Knopf kannst du ein neues Semester erstellen</p>
<p>- Über den Stift kannst du ein bestehendes Semester editieren</p>
<p>- Über den Mülleimer kannst du ein bestehndes Semester löschen</p>
<h2>Für Dozenten (und Admins):</h2>
<p>- Hier siehst du deine Semester mit den jeweiligen Modulen</p>
<p>- Sollte ein Semester bei dir Ausgegraut sein, wurdest du für dieses schon gewählt aber noch nicht freigeschalten</p>
<p>- Duch einen Links-Klick auf ein weises Semester kann in die Planungsübersicht gewechselt werden</p>
<h1>Das Dashboard für Admins</h1>
<p>- Hier werden alle bestehenden Semester gelistet</p>
<p>- Über den "+" Button ist es möglich ein neues Semester zu erstellen</p>
<p>- Über das Stift-Symbol kann ein bestehends Semester editiert werden</p>
<p>- Über das Mülleimer-Symbol kann ein bestehndes Semester gelöscht werden</p>
<p>- Die Fortschrittsanzeige bleibt auf der (1) bis ein Dozent seinen Plan abgegeben hat, sobald das geschieht wechselt sie auf die (2) und wenn alle Dozenten ihre Pläne abgegeben haben, springt die Anzeige auf die (3)</p>
</div>
</div>
<div className={"help-line"}>
<img src={screen5.src}/>
<div className={"text-form"}>
<h2>Das Dashboard für Dozenten</h2>
<p>- Hier werden alle Semester angzeigt in welchem der eingeloggte Dozent Vorlesungen planen soll</p>
<p>- Sollte ein Semester ausgegraut sein, wurden Sie für dieses schon gewählt aber noch nicht freigeschalten</p>
<p>- Durch einen Links-Klick auf ein weißes Semester kann in die Planungsübersicht gewechselt werden</p>
<p>- Die Fortschrittsanzeige bleibt auf der (1) bis eine Vorlesung geplant wird, sobald das geschieht wechselt sie auf die (2) und wenn der Dozent seinen Plan abgibt, springt die Anzeige auf die (3)</p>
</div>
</div>
@@ -85,10 +83,12 @@ export default function Help(p)
<img src={screen7.src}/>
<div className={"text-form"}>
<h1>Semester erstellen / bearbeiten</h1>
<p>- Hier kannst du alle daten wie Name, Start- und Endzeitpunkt eines Semesters eintragen</p>
<p>- Du kannst einen Dozenten "wählen" d.h. er soll in diesem Semester dozieren</p>
<p>- Jedem Dozenten kannst du ein Modul zuordnen, welches er dozieren soll</p>
<p>- Sobald du die Schaltfläche "Freischalten" aktiviert hast, kann der Dozent mit der eigenständigen Planung beginnen.</p>
<p>- Hier müssen die folgenden Daten eingetragen werden: Kursname sowie Start- und Endzeitpunkt einer Vorlesungsphase</p>
<p>- Der Start muss vor dem Endzeitpunkt liegen</p>
<p>- Einen Dozenten zu wählen bedeutet ihn dem Kurs hinzuzufügen, sollte ihm kein Modul zugewiesen werden, wird er automatisch abgewählt</p>
<p>- Ein Dozent muss mindestens ein, kann aber auch mehrere Module zugewiesen bekommen</p>
<p>- Um einem Dozenten mehrere Module zuzuweisen, halte die "STRG"-Taste gedrückt während du per Links klick die Module auswählst</p>
<p>- Sobald die Schaltfläche "Freischalten" aktiviert wurde, kann der Dozent mit der eigenständigen Planung beginnen</p>
<p>- Jeder genannte Schritt, insbesondere der Letzte kann auch nachträglich im Bearbeitungsmodus ausgeführt werden</p>
</div>
</div>
+14 -2
View File
@@ -11,11 +11,15 @@ const inter = Inter({subsets: ['latin']})
export default function Home(p) {
const router = useRouter()
//hier wird im login fenster überpüft ob der aktuelle browser mit dem tool kompatibel ist.
//evtl. sind auch browser, die nicht chrome basiert sind kompatibel, diese konnten aber nicht ausführlich genug getest werden.
useEffect(() => {
let isEdge = window.navigator.userAgent.indexOf("Edg") > -1
let isChrome = window.navigator.userAgent.indexOf("Chrome") > -1
let isFireFox = window.navigator.userAgent.indexOf("firefox") > -1
if(!(isEdge || isChrome))
//ist der browser nicht unterstützt so wird der nutzer auf die browser nicht unterstützt seite weitergeleitet.
if(!(isEdge || isChrome || isFireFox))
{
router.push("/browserNotSupported")
}
@@ -26,7 +30,6 @@ export default function Home(p) {
<div className={"normal-centered"}>
<Background/>
<HelpButton/>
<h1 style={{
fontSize: 40,
fontWeight: "bold",
@@ -36,6 +39,15 @@ export default function Home(p) {
textAlign: "center"
}}>Willkommen in deinem Vorlesungsplaner</h1>
<Login/>
<p1 style={{
fontSize: 18,
fontWeight: "bold",
color: "red",
marginTop: "5%",
textAlign: "center",
maxWidth: 450,
justifyContent: "start"
}}>Es handelt sich hierbei um eine BETA-VERSION! Keine Gewähr auf Korrekte oder vollständige Informationen</p1>
</div>
)
}
+8 -3
View File
@@ -5,21 +5,26 @@ import Back from "@/components/Back";
import BasicDateCalendar from "@/components/CalendarSideBar";
import {useRouter} from "next/router";
import HelpButton from "@/components/HelpButton";
import SubmitButton from "@/components/SubmitButton";
export default function planning(p)
{
let router = useRouter()
let semesterName;
if (typeof window !== 'undefined'){
semesterName = localStorage.getItem("semestername") + " " + (localStorage.getItem("admin") == 1 ? "" : localStorage.getItem("currentmodulename"))
}
return (
<div className={"normal-centered"}>
<Logout/>
<Back onClick={() => router.back()}/>
<HelpButton/>
<Background/>
<CalenderView/>
<SubmitButton />
<CalenderView semesterName={semesterName}/>
</div>
)
}
+102 -21
View File
@@ -12,12 +12,86 @@ import StatusBar from "@/components/StatusBar";
import {deleteItem, editItem} from "@/components/Icons";
export default function SemesterOverview(p) {
async function getSemesters() {
const [progresses, setProgresses] = useState([])
async function getSemesters(set) {
let urlTest = baseURL + "/semester/all?sessionid=" + localStorage.getItem("sessionid");
let allSemesters
let allModules
let allEntries
//Datenanfrage an das Backend für alle existierenden Semester
await fetch(urlTest).then(response => response.json()).then(s => {
setEntries(s)
allSemesters = s
if (set) {
setEntries(s)
}
}).then(() => {
if(!set)
{
//Datenanfrage an das Backend um alle Module zu erhalten
fetch(baseURL + "/module/all?sessionid=" + localStorage.getItem("sessionid")).then(r => r.json()).then(mod => {
allModules = mod
}).then(() => {
//Datenanfrage an das Backend um alle gesetzten Entries zu erhalten
fetch(baseURL + "/entries/all?sessionid=" + localStorage.getItem("sessionid")).then(r => r.json()).then(en => {
allEntries = en
}).then(() => {
let modulesCountInSemester = []
for (let i = 0; i < allSemesters.length; i++) //durchlaufe die Anzahl der Semester welche von dem Backend zurück gegeben wurden
{
let count = 0
for (let j = 0; j < allModules.length; j++) { //durchlaufe die Anzahl der Module welche von dem Backend zurück gegeben wurden
if (allSemesters[i].id === allModules[j].semesterid) //Prüfe ob das Modul zu dem jeweiligen Semester gehört und erhöhe count
{
count++;
}
}
modulesCountInSemester.push(count)
}
let temp = []
for (let s = 0; s < allSemesters.length; s++) //durchlaufe die Anzahl der Semester welche von dem Backend zurück gegeben wurden
{
let count = 0;
for (let i = 0; i < allModules.length; i++) //durchlaufe die Anzahl der Module welche von dem Backend zurück gegeben wurden
{
if (allModules[i].semesterid === allSemesters[s].id) //Prüfe ob das Modul zu dem jeweiligen Semester gehört
{
let sum = 0
let ent = allEntries.filter(e => e.moduleid === allModules[i].id) //lade alle Entries die zu dem Modul gehören in dem wir uns befinden in die Variable
for (let j = 0; j < ent.length; j++) //durchlaufe die Anzahl der Entries aus ent
{
sum += ent[j].timeend - ent[j].timestart //summiere die Dauer aller Entries in dem Semester
}
sum /= 3
if (sum >= 20 && allModules[i].activated === 0) //Überprüfung ob alle 20 Schulstunden eines Moduls gesetzt worden sind und der Vorlesungsplan des Moduls abgegeben worden ist
{
count++;
}
}
}
if (count === 0) {
temp.push(0)
} else if (count >= 1 && count !== modulesCountInSemester[s]) {
temp.push(50)
} else {
temp.push(100)
}
setProgresses(temp) //setze die Fortschrittsleiste entsprechend der Einträge im Semester
}
})
})
}
})
}
@@ -25,14 +99,15 @@ export default function SemesterOverview(p) {
function onClickSemester(e, m) {
if (m.target === m.currentTarget) {
localStorage.setItem("currentsid", e.id)
router.push("/planning")
router.push("/planning") //leite weiter auf die Planungsseite
localStorage.setItem("semestername", e.name + " Sem. " + (e.number + 1))
}
}
function onClickNewSemester() {
localStorage.setItem("currentsid", 0);
router.push("/createSemester");
router.push("/createSemester"); //leite weiter auf die Seite für das Inputform zur Erstellung eines neuen Semesters
}
@@ -50,13 +125,13 @@ export default function SemesterOverview(p) {
async function funcButtonDelete() {
let id = localStorage.getItem("currentsid");
let url = baseURL + "/semester?sessionid=" + localStorage.getItem("sessionid") + "&id=" + id;
let url = baseURL + "/semester?sessionid=" + localStorage.getItem("sessionid") + "&id=" + id; //Anfrage an das Backend auf spezifisches Semesters auf das geklickt worden ist
await fetch(url, {
method: "DELETE"
method: "DELETE" //lösche das spezifisch angeklickte Semester
});
togglePopup();
getSemesters();
getSemesters(true);
}
async function funcButtonEdit(e, m) {
@@ -64,6 +139,7 @@ export default function SemesterOverview(p) {
localStorage.setItem("currentsid", e.id);
let semester = e;
//setze die Einträge des Semesters auf die aktuell gespeicherten Einträge
let startYear = semester.startyear;
let endYear = semester.endyear;
let startDay = semester.startday;
@@ -72,6 +148,7 @@ export default function SemesterOverview(p) {
let startDate = new Date(startYear, 0, startDay + 1);
let endDate = new Date(endYear, 0, endDay + 1);
//speichere die abgeänderten Daten des Semesters
await router.push({
pathname: "/createSemester",
query: {
@@ -80,11 +157,14 @@ export default function SemesterOverview(p) {
endDate: endDate.toISOString().slice(0, 10)
},
});
getSemesters();
}
useEffect(() => {
getSemesters();
getSemesters(true);
setTimeout(() => {
getSemesters(false)
}, 2000)
}, [])
@@ -100,22 +180,23 @@ export default function SemesterOverview(p) {
<HelpButton/>
<Background/>
{
entries.map(e => (
entries.map((e, index) => (
<div className={"semester-tile box-shadow"} onClick={(f) => onClickSemester(e, f)}>
<SemesterTile text={e.name} onClick={(f) => onClickSemester(e, f)} onButtonDeleteClick={() => {
<SemesterTile text={e.name + " Sem. " + (e.number + 1)} onClick={(f) => onClickSemester(e, f) /*Darstellung der Semester mit ihren Namen und der Semesternummer in welcher der Kurs sich befindet*/}
onButtonDeleteClick={() => {
localStorage.setItem("currentsid", e.id)
setModalHint(e.name + " Löschen?");
togglePopup();
}} onButtonEditClick={(m) => {
localStorage.setItem("currentsid", e.id)
setModalHint(e.name + " Löschen?");
togglePopup();
}} onButtonEditClick={(m) => {
localStorage.setItem("currentsid", e.id)
funcButtonEdit(e, m);
funcButtonEdit(e, m) /*Aufruf der Editierfunktion für das Angeklickte Semester*/;
}}/>
<StatusBar progress={0}/>
<StatusBar progress={progresses[index] /*Fortschrittsleiste wird gesetzt*/}/>
<div style={
{
display:"flex",
justifyContent:"center",
alignItems:"center"
display: "flex",
justifyContent: "center",
alignItems: "center"
}
}>
<Button icon={deleteItem} width={30} height={30} color={"#ffffff"}
@@ -133,7 +214,7 @@ export default function SemesterOverview(p) {
</div>))
}
<Button color={"#dcdcdc"} text={"+"} width={240} height={160} fontColor={"black"} fontSize={50}
onClick={() => onClickNewSemester()}/>
onClick={() => onClickNewSemester() /*Zuweisung der Funktion für den Button zu Erstellung eines neuen Semesters*/}/>
<PopUp hint={modalHint} text1={"Abbrechen"} text2={"Löschen"} displayState={modalDisplay}
function1={funcButtonAbort} function2={funcButtonDelete}/>
</div>
+62 -10
View File
@@ -8,37 +8,71 @@ import HelpButton from "@/components/HelpButton";
import StatusBar from "@/components/StatusBar";
export default function SemesteroverviewLecturer(p) {
const [timeStamps, setTimeStamps] = useState([])
function getModules() {
let urlTest = baseURL + "/module/id?sessionid=" + localStorage.getItem("sessionid");
//Datenanfrage an das Backend für alle Module welche dem User zugewiesen worden sind
fetch(urlTest).then(response => response.json()).then(m => {
setEntries(m);
let args = "";
for (let i = 0; i < m.length; i++) {
args += m[i].semesterid;
for (let i = 0; i < m.length; i++) //durchlaufe die Anzahl der Module
{
args += m[i].semesterid; //füge dem String "args" die Einträge hinzu
if (i < m.length - 1) {
args += "a";
args += "a"; //trenne die Einträge durch ein "a" voneinander ab
}
}
let temp = []
let semesterURL = baseURL + "/semester/id/all?ids=" + args + "&sessionid=" + localStorage.getItem("sessionid");
//Datenanfrage an das Backend für alle Semester welche dem User für die Planung zugewiesen sind
fetch(semesterURL).then(r => r.json()).then(sem => {
sem.map(e => {
temp.push(e.name)
temp.push(e.name + " Sem. " + (e.number + 1)) //lade das Semester in welchem der Kurs sich befindet in das Array "temp"
})
}).then(() => setSemesterNames(temp))
}).then(() => setSemesterNames(temp)).then(() => {
let entriesURL = baseURL + "/entries/all?sessionid=" + localStorage.getItem("sessionid")
//Datenanfrage an das Backend aller Entries eines Moduls eines Semesters (automatisch nur die Entries die durch den User erstellt worden sind)
fetch(entriesURL).then(r => r.json()).then(en => {
let tempTimeStamps = []
for(let j = 0; j < m.length; j++) //durchlaufe die Anzahl an Modulen die von dem Backend zurückgegeben worden sind
{
let sum = 0
let currentModule = m[j]
for (let i = 0; i < en.length; i++) //durchlaufe die Anzahl der Entries die von dem Backend zurückgegeben worden sind
{
if(currentModule.id === en[i].moduleid)
{
sum += en[i].timeend - en[i].timestart //summiere die Dauer all dieser Entries
}
}
sum /= 3
tempTimeStamps.push(sum) //lade die Summe aller Entries eines Moduls in das Array "tempTimeStamps"
}
setTimeStamps(tempTimeStamps)
})
})
})
}
function onClickSemester(e, m) {
function onClickSemester(e, m, name) {
if (e.activated == 1) {
if (m.target === m.currentTarget) {
localStorage.setItem("currentsid", e.semesterid)
localStorage.setItem("currentmodulename", e.name)
localStorage.setItem("moduleid", e.id)
localStorage.setItem("semestername", name)
router.push("/planning")
}
}
@@ -46,13 +80,31 @@ export default function SemesteroverviewLecturer(p) {
useEffect(() => {
getModules();
setTimeout(() => {
getModules();
}, 1000)
}, [])
const [entries, setEntries] = useState([]);
const [semesterNames, setSemesterNames] = useState([]);
const router = useRouter();
function getProgressForTime(time, activated)//überprüfe welchen Status die Fortschrittsanzeige haben muss und gib diesen zurück
{
if(time === 0)
{
return 0
}
else if( 20 >= time > 0 && activated === 1)
{
return 50
}
else if(time >= 20 && activated === 0)
{
return 100
}
}
return (
<div className={"semester-overview"}>
@@ -62,12 +114,12 @@ export default function SemesteroverviewLecturer(p) {
{entries.map((e, index) => (
<div className={"semester-tile box-shadow"} style={{
backgroundColor: e.activated == 1 ? "#ffffff" : "#aaaaaa"
}} onClick={(f) => onClickSemester(e, f)}>
}} onClick={(f) => onClickSemester(e, f, semesterNames[index])}>
<SemesterTile
editable={false} text={semesterNames[index]} text2={e.name}
onClick={(f) => onClickSemester(e, f)}
onClick={(f) => onClickSemester(e, f, semesterNames[index])}
/>
<StatusBar progress={0}/>
<StatusBar progress={getProgressForTime(timeStamps[index], e.activated)/*beladenes Array "timeStamps" an der Stelle "index" => relevante Summe der Einträge eines Moduls in einem Semester/Kurs*/} module={e}/>
</div>
))}
</div>
-19
View File
@@ -1,19 +0,0 @@
import Logout from "@/components/Logout";
import SubmitWarning from "@/components/SubmitWarning";
import Back from "@/components/Back";
import {useRouter} from "next/router";
import Background from "@/components/Background";
export default function Submit(){
const router = useRouter();
return(
<div>
<Background />
<Logout />
<SubmitWarning onClick={() => router.back()}/>
<Back onClick={() => router.back()}/>
</div>
)
}
+5 -17
View File
@@ -183,37 +183,26 @@ Step Progress Bar
color: white;
font-weight: bold;
pointer-events: none;
z-index: 101;
}
.steps .not-started {
/*background-image: linear-gradient(#b42121, #b44821);*/
background-color: #77932b;
background-color: grey;
}
.steps .started {
/*background-image: linear-gradient(#c75c0c, #c77c0c);*/
background-color: #77932b;
}
.steps .finished {
/*background-image: linear-gradient(#43C20BFF, #0bc27c);*/
background-color: #77932b;
}
.steps .active {
/*border-width: 2px;*/
/*border-color: #1e2428;*/
background-color: #346991;
background-color: #77932b;
}
.progress-bar {
position: absolute;
height: 8px;
background-color: #5d606e;
z-index: -1;
background-color: #77932b;
z-index: 100;
}
/*
@@ -445,7 +434,6 @@ Login
flex-direction: column;
align-items: center;
justify-content: space-evenly;
/*gap: 10px;*/
border-radius: 10px;
background-color: rgba(255, 255, 255, 0.5);
width: 375px;
-33
View File
@@ -1,33 +0,0 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
+3
View File
@@ -3,3 +3,6 @@
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="backend" />
</profile>
</annotationProcessing>
</component>
<component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
<module name="backend" options="-parameters" />
</option>
</component>
</project>
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
</component>
</project>
+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
</component>
</project>
+9
View File
@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="h2-2.1.214">
<CLASSES>
<root url="jar://$PROJECT_DIR$/H2JDBCDriver/h2-2.1.214.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="20" project-jdk-type="JavaSDK" />
</project>
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>
Binary file not shown.
+673305 -7075
View File
File diff suppressed because it is too large Load Diff
@@ -10,6 +10,16 @@ import java.sql.*;
import java.util.ArrayList;
import java.util.List;
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//kleiner hinweis zur Datenbank:
//die datenkbank H2 benötigt die beiden dateien database.mv.db und database.trace.db
//um die datenbank verwenden zu können muss der jdbc driver in das projekt eingebunden sein.
//dieser driver liegt im ordner als h2jdbcdriver als .jar datei
//der nutzername für die datenbank ist: adm
//das passwort für die datenbank ist: 73bgjfdsfJ!934
//die datenbank als einzelnes kann entweder über die h2console (windows) oder jetbrains datagrip (alle systeme) editiert werden.
//oder über jedes weitere tool welches h2 datenbanken unterstützt.
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
public class DataBaseHandler {
//singleton instance of database handler
private static DataBaseHandler instance = null;
@@ -42,13 +52,17 @@ public class DataBaseHandler {
/**
* ENTRIES
*/
public void addEntry(Entry entry) {
try {
st.executeUpdate("insert into entries (daynumber, yearnumber, semesterid, usercreatedbyid, timestart, timeend, info) values (" +
public void addEntry(Entry entry)
{
try
{
st.executeUpdate("insert into entries (daynumber, yearnumber, semesterid, usercreatedbyid, timestart, timeend, moduleid, info) values (" +
entry.getDaynumber() + ", " + entry.getYearnumber() + ", " + entry.getSemesterid() + ", " +
entry.getUsercreatedbyid() + ", " + entry.getTimestart() + ", " + entry.getTimeend() + ", '" + entry.getInfo() + "')"
);
} catch (Exception e) {
entry.getUsercreatedbyid() + ", " + entry.getTimestart() + ", " + entry.getTimeend() + ", " + entry.getModuleid() + " ,'" + entry.getInfo() + "')"
); //Datenbank Eintrag eines neu erstellten Entry mit allen nötigen Informationen
}
catch(Exception e)
{
e.printStackTrace();
}
}
@@ -64,28 +78,31 @@ public class DataBaseHandler {
Entry current = null;
while ((current = resultSetToEntry(rs)) != null) {
entryList.add(current);
}
} //Datenbankanfrage für alle Entries bei denen die Semesterid, das Jahr und der Tag mit den übergebenen Paramtern übereinstimmt
Entry[][] entries = new Entry[6][20];
for (int i = 0; i < 6; i++) {
for (int i = 0; i < 6; i++) //durchlaufe die Anzahl der Tage einer Vorlesungswoche (Montag,...,Samstag)
{
int f = 0;
for (int j = 0; j < entryList.size(); j++) {
for (int j = 0; j < entryList.size(); j++)
{
if (entryList.get(j).getDaynumber() == i + daynumber) {
entries[i][f] = entryList.get(j);
entries[i][f] = entryList.get(j); //belade das Array "entries" mit dem entries einer woche
f++;
}
}
}
return entries;
return entries; //gib das Array "entries" zurück
} catch (Exception e) {
return null;
}
}
public Entry[][] getAllEntrys(int semesterid, int daynumber, int yearnumber, int userid) {
public Entry[][] getAllEntrys(int semesterid, int daynumber, int yearnumber, int userid) //Datenbankanfrage für alle Entries eines Users in einem Semester
{
try {
ResultSet rs = st.executeQuery("select * from entries where " +
"semesterid<>" + semesterid +
@@ -114,23 +131,46 @@ public class DataBaseHandler {
}
}
public Entry[] getAllEntries(int semesterid, int userid) {
public Entry[] getAllEntries() //Datenbankanfrage für alle Entries
{
try {
ResultSet rs = st.executeQuery("select * from entries where " +
"semesterid=" + semesterid +
" and usercreatedbyid=" + userid);
ResultSet rs = st.executeQuery("select * from entries");
List<Entry> entriestate = new ArrayList<>();
Entry current = null;
while ((current = resultSetToEntry(rs)) != null) {
Entry current = null;
while((current = resultSetToEntry(rs)) != null)
{
entriestate.add(current);
}
return entriestate.toArray(new Entry[0]);
} catch (Exception e) {
}catch (Exception e){
System.out.println(e.getMessage());
return null;
}
}
public void deleteEntry(int id) {
public Entry[] getAllEntriesModule(int moduleid) //Datenbankanfrage für alle Entries eines spezifischen Moduls
{
try {
ResultSet rs = st.executeQuery("select * from entries where moduleid=" + moduleid);
List<Entry> result = new ArrayList<>();
Entry current = null;
while((current = resultSetToEntry(rs)) != null)
{
result.add(current);
}
return result.toArray(new Entry[0]);
}
catch(Exception e)
{
return new Entry[]{};
}
}
public void deleteEntry(int id) //Löschung eines spezifischen entries
{
try {
st.executeUpdate("delete from entries where id=" + id);
} catch (Exception e) {
@@ -138,7 +178,8 @@ public class DataBaseHandler {
}
}
public void updateEntry(Entry entry) {
public void updateEntry(Entry entry) //Aktualisiere Einträge eines Entry falls es verändert wurde
{
try {
st.executeUpdate("update entries set timeend=" + entry.getTimeend() + ", timestart=" + entry.getTimestart() + " where id=" + entry.getId());
} catch (Exception e) {
@@ -146,8 +187,10 @@ public class DataBaseHandler {
}
}
public Entry resultSetToEntry(ResultSet rs) {
try {
public Entry resultSetToEntry(ResultSet rs)
{
try
{
rs.next();
return new Entry(
rs.getInt("id"),
@@ -157,9 +200,12 @@ public class DataBaseHandler {
rs.getInt("timestart"),
rs.getInt("timeend"),
rs.getInt("semesterid"),
rs.getInt("moduleid"),
rs.getString("info")
);
} catch (Exception e) {
}
catch(Exception e)
{
return null;
}
}
@@ -178,7 +224,8 @@ public class DataBaseHandler {
}
}
public Semester getSemester(int id) {
public Semester getSemester(int id)
{
try {
ResultSet rs = st.executeQuery("select * from semester where id=" + id);
return resultSetToSemester(rs);
@@ -213,7 +260,8 @@ public class DataBaseHandler {
}
}
public Semester updateSemester(Semester semester) {
public Semester updateSemester(Semester semester) //Aktualisiere die Einträge eines Semesters bei Veränderungen durch editier Funktion
{
try {
st.executeUpdate("update semester set startday=" + semester.getStartday() + ", " +
"endday=" + semester.getEndday() + ", " +
@@ -229,16 +277,18 @@ public class DataBaseHandler {
}
}
//ist dafür da, um ein semester anhand seiner id aus der datenbank zu löschen
public void deleteSemester(int id) {
try {
st.executeUpdate("DELETE FROM modules WHERE semesterid=" + id);
st.executeUpdate("delete from semester where id=" + id);
st.executeUpdate("delete from entries where semesterid=" + id);
} catch (Exception e) {
}
}
//kann ein resultset der datenbank in ein internes semester objekt umwandeln.
public Semester resultSetToSemester(ResultSet rs) {
try {
rs.next();
@@ -270,6 +320,7 @@ public class DataBaseHandler {
}
}
//ein modul anhand der zuweisung von dozent und semester bekommen.
public Module getModule(int userid, int semesterid) {
try {
ResultSet rs = st.executeQuery("select * from modules where userid=" + userid + " and semesterid=" + semesterid);
@@ -280,7 +331,7 @@ public class DataBaseHandler {
}
}
//get module objects by its semester and its lecturer
//bekomme alle modulzuweisungen, die zu einem dozenten gehören.
public Module[] getModules(int userid) {
try {
ResultSet rs = st.executeQuery("SELECT * FROM modules WHERE userid = " + userid);
@@ -297,6 +348,7 @@ public class DataBaseHandler {
}
}
//füge eine neue modulzuweisung zwischen dozenten und fächern hinzu
public Module addModule(Module m) {
try {
st.executeUpdate("insert into modules (userid, semesterid, name, activated) " +
@@ -309,6 +361,7 @@ public class DataBaseHandler {
}
}
//gibt alle zuweisungen zurück.
public Module[] getAllModules() {
try {
ResultSet rs = st.executeQuery("SELECT * FROM modules");
@@ -324,30 +377,60 @@ public class DataBaseHandler {
}
}
//updatet eine zuweisung anhand ihrer id
public Module updateModule(Module m) {
try {
st.executeUpdate("update modules set activated=" + m.getActivated() + ", semesterid=" + m.getsemesterid() + ", name='" + m.getName() + "' where id=" + m.getid());
st.executeUpdate("update modules set activated=" + m.getActivated() + ", userid=" + m.getUserid() + " where id=" + m.getid());
return null;
return getModule(m.getid());
} catch (SQLException ex) {
ex.printStackTrace();
return null;
}
}
public boolean deleteModule(int id) {
//setzt die aktivierung einer modulzuweisung zurück.
public void submitModule(int id)
{
try
{
st.executeUpdate("update modules set activated=0 where id=" + id);
}
catch(Exception e)
{
}
}
//kann alle modulzuweisungen innerhalb eines semesters löschen.
//hierbei werden auch alle termine mit gelöscht.
public boolean deleteModuleBySemesterID(int id) {
try {
st.executeUpdate("delete from modules where id=" + id);
st.executeUpdate("delete from modules where semesterid=" + id);
st.executeUpdate("delete from entries where semesterid=" + id);
return true;
} catch (Exception ex) {
return false;
}
}
//kann eine einzelne modulzuweisung anhand ihrer id löschen.
//hierbei werden auch alle zu dieser zuweisung gehörigen termine gelöscht
public boolean deleteModule(int id) {
try {
st.executeUpdate("delete from modules where id=" + id);
st.executeUpdate("delete from entries where moduleid=" + id);
return true;
} catch (Exception ex) {
return false;
}
}
//kann ein result set der datenbank in ein internes modul objekt umwandeln.
public Module resultSetToModule(ResultSet rs) {
try {
rs.next();
@@ -386,7 +469,7 @@ public class DataBaseHandler {
}
}
//einen User
//einen User anhand seiner email und passwort zurückgeben.
public User getUser(String mail, String password) {
try {
@@ -399,6 +482,8 @@ public class DataBaseHandler {
return null;
}
//einen nutzer andhand seiner id zurückgeben.
//diese funktion sollte nur für admins verfügbar sein.
public User getUser(int id) {
try {
ResultSet rs = st.executeQuery("select * from users where id=" + id);
@@ -408,6 +493,7 @@ public class DataBaseHandler {
}
}
//ein nutzer anhand seiner mail zurückgeben. diese funktion sollte nur für admins erreichbar sein.
public User getUser(String mail) {
try {
ResultSet rs = st.executeQuery("select * from users where mail='" + mail + "'");
@@ -421,6 +507,8 @@ public class DataBaseHandler {
}
}
//kann ein result set der datenbank in ein internes nutzer objekt umwandeln.
public User resultSetToUser(ResultSet rs) {
try {
rs.next();
@@ -463,6 +551,8 @@ public class DataBaseHandler {
}
//kann einen nutzer updaten, aber auch dessen rechte verändern, hierbei werden die rechte nur angepasst,
//wenn der boolean elevationRequestByAdmin true ist
public User updateUser(User user, int id, boolean elevationRequestByAdmin) {
try {
String password = user.getPassword();
@@ -500,6 +590,8 @@ public class DataBaseHandler {
}
}
//hier kann ein nutzer anhand seiner email addresse gelöscht werden.
//diese funktion sollte nur für den eigenen nutzer oder für admins verfügbar sein.
public boolean deleteUser(String mail) {
try {
ResultSet rs = st.executeQuery("SELECT id FROM user WHERE mail='" + mail + "'");
@@ -1,6 +1,6 @@
package com.example.backend.anwprj.Entries;
//entry data class
//interne klasse für die darstellung von terminen
public class Entry
{
private int id;
@@ -10,9 +10,10 @@ public class Entry
private int timestart;
private int timeend;
private int semesterid;
private int moduleid;
private String info;
public Entry(int id, int daynumber, int yearnumber, int usercreatedbyid, int timestart, int timeend, int semesterid, String info)
public Entry(int id, int daynumber, int yearnumber, int usercreatedbyid, int timestart, int timeend, int semesterid, int moduleid, String info)
{
this.id = id;
this.daynumber = daynumber;
@@ -21,6 +22,7 @@ public class Entry
this.timestart = timestart;
this.timeend = timeend;
this.semesterid = semesterid;
this.moduleid = moduleid;
this.info = info;
}
@@ -59,6 +61,8 @@ public class Entry
return semesterid;
}
public int getModuleid() {return moduleid;}
public String getInfo()
{
return info;
@@ -1,6 +1,6 @@
package com.example.backend.anwprj.Module;
//module data class
//klasse für die interne darstellungen für die zuweisungen zwischen dozenten und fächern.
public class Module {
private int id;
private int userid;
@@ -1,6 +1,6 @@
package com.example.backend.anwprj.Semesters;
//semester data class
//klasse für die interne darstellung von semestern.
public class Semester
{
private int id;
@@ -1,6 +1,6 @@
package com.example.backend.anwprj.Users;
//user data class
//klasse für die darstellung von benutzerobjekten.
public class User
{
private int id;
@@ -1,6 +1,6 @@
package com.example.backend.anwprj.Users;
//mapping of the integer rights to enum
// zuweisung der zahlen 0 für normaler user / dozenten und 1 für admin.
public enum UserPermissions
{
self(0),
@@ -5,6 +5,9 @@ import com.example.backend.anwprj.Database.DataBaseHandler;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
//diese klasse kümmert sich um die zuweisungen von nutzern und deren sessionids.
//wird für alle möglichen anfragen der nutzer an das backend verwendet um eine sessionid
//in ein benutzerobjekt aufzulösen.
public class UserSessionIDHandler
{
//stores mapping of session ids to users
@@ -59,23 +59,49 @@ public class EntriesController
}
@CrossOrigin
@GetMapping("/entries/planned")
public ResponseEntity<Integer[]> getEntries(@RequestParam(name = "semesterid") int semesterid,
@RequestParam(name = "sessionid") String sessionid)
@GetMapping("/entries/all")
public ResponseEntity<Entry[]> getAllEntries(@RequestParam(name = "sessionid") String sessionid)
{
User sessionUser = UserSessionIDHandler.getUserBySessionID(sessionid);
if (sessionUser != null)
{
var entries = db.getAllEntries(semesterid, sessionUser.getId());
var count = 0;
for (int i = 0; i < entries.length; i++) {
count += entries[i].getTimeend()-entries[i].getTimestart();
}
return new ResponseEntity<>(new Integer[]{count}, HttpStatus.OK);
var entries = db.getAllEntries();
return new ResponseEntity<>(entries, HttpStatus.OK);
}
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
@CrossOrigin
@GetMapping("/entries/all/module")
public ResponseEntity<Entry[]> getAllEntriesModule(@RequestParam(name="sessionid") String sessionid, @RequestParam(name="moduleid") int moduleid)
{
User sessionUser = UserSessionIDHandler.getUserBySessionID(sessionid);
if (sessionUser != null)
{
return new ResponseEntity<>(db.getAllEntriesModule(moduleid), HttpStatus.OK);
}
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
// @CrossOrigin
// @GetMapping("/entries")
// public ResponseEntity<Integer[]> getEntries(@RequestParam(name = "semesterid") int semesterid,
// @RequestParam(name = "sessionid") String sessionid)
// {
// User sessionUser = UserSessionIDHandler.getUserBySessionID(sessionid);
// if (sessionUser != null)
// {
// var entries = db.getAllEntries(semesterid, sessionUser.getId());
// var count = 0;
// for (int i = 0; i < entries.length; i++) {
// count += entries[i].getTimeend()-entries[i].getTimestart();
// }
// return new ResponseEntity<>(new Integer[]{count}, HttpStatus.OK);
// }
// return new ResponseEntity<>(HttpStatus.FORBIDDEN);
// }
/**
POST
A new entry to the database. Every user except of admins is allowed
@@ -99,6 +99,7 @@ public class ModuleController
return null;
}
/**
POST
a new module entry. (When a user is selected in a semester.)
@@ -143,17 +144,43 @@ public class ModuleController
{
return new ResponseEntity<>(m, HttpStatus.OK);
}
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
@CrossOrigin
@PutMapping("/module/submit")
public ResponseEntity<Module> submitModule(@RequestParam(name="sessionid") String sessionID, @RequestParam(name="id") int id)
{
User u = UserSessionIDHandler.getUserBySessionID(sessionID);
if (u != null)
{
db.submitModule(id);
return new ResponseEntity<>(null, HttpStatus.OK);
}
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
/**
DELETE
Delete A Module
*/
@CrossOrigin
@DeleteMapping("/module/bysemesterid")
public void deleteModuleBySemesterID(@RequestParam(name = "sessionid") String sessionid, @RequestParam(name="id") int id)
{
User u = UserSessionIDHandler.getUserBySessionID(sessionid);
if (u != null && u.getPermissions() == UserPermissions.admin.getValue())
{
db.deleteModuleBySemesterID(id);
}
}
@CrossOrigin
@DeleteMapping("/module")
public void deleteModule(@RequestParam(name = "sessionid") String sessionid, @RequestParam(name="id") int id)
@@ -43,6 +43,7 @@ public class SemesterController
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
//get a semester object by its id
@CrossOrigin
@GetMapping("/semester/id")
public ResponseEntity<Semester> getSemester(@RequestParam(name="id") int id, @RequestParam(name="sessionid") String sessionID)
@@ -63,6 +64,7 @@ public class SemesterController
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
//takes in a list of semester ids seperatet by an a as list seperator
@CrossOrigin
@GetMapping("/semester/id/all")
public ResponseEntity<Semester[]> getSemestersAll(@RequestParam(name="ids") String ids, @RequestParam(name="sessionid") String sessionid)
@@ -80,6 +82,7 @@ public class SemesterController
return new ResponseEntity<>(resultList.toArray(new Semester[0]), HttpStatus.OK);
}
//gibt alle semester zurück
@CrossOrigin
@GetMapping("/semester/all")
public ResponseEntity<Semester[]> getSemester(@RequestParam(name="sessionid") String sessionid)
@@ -122,6 +125,7 @@ public class SemesterController
}
//updatet ein semester
@CrossOrigin
@PutMapping("/semester")
public ResponseEntity<Semester> updateSemester(@RequestBody Semester semester, @RequestParam(name="sessionid") String sessionID)
@@ -142,6 +146,7 @@ public class SemesterController
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
//löscht ein semester anhand seiner id
@CrossOrigin
@DeleteMapping("/semester")
public void deleteSemester(@RequestParam(name="sessionid") String sessionid, @RequestParam(name="id") int id)
@@ -9,6 +9,11 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
/*
Hier sind einige nutzer funktionen mehr, als für das tool benötigt werden. Diese dienen nur testzwecken
zum verwalten von nutzer z.b. über postman.
*/
@RestController
public class UserController {
//reference to the database handler
@@ -18,6 +23,7 @@ public class UserController {
db = DataBaseHandler.getInstance();
}
//hole alle user, nur erlaubt für admins
@CrossOrigin
@GetMapping("/users/all")
public ResponseEntity<User[]> getAllUsers(@RequestParam(name = "sessionid") String sessionid)
@@ -57,6 +63,7 @@ public class UserController {
return new ResponseEntity<>(sessionID, HttpStatus.OK);
}
//ein nutzer möchte sich ausloggen, damit sollte seinen sessionid entfernt werden.
@CrossOrigin
@GetMapping("/users/logout")
public ResponseEntity<Boolean> logout(@RequestParam(name = "sessionid") String sessionID) {
@@ -64,6 +71,7 @@ public class UserController {
return new ResponseEntity<>(success, HttpStatus.OK);
}
//admins können hier die daten eiens nutzer anfordern.
@CrossOrigin
@GetMapping("/users/data")
public ResponseEntity<User> getUserData(
@@ -141,6 +149,7 @@ public class UserController {
return new ResponseEntity<>(false, HttpStatus.FORBIDDEN);
}
//rechte eines nutzers erhöhen, kann nur von admins ausgeführt werden.
@CrossOrigin
@PutMapping("/users/elevate")
public ResponseEntity<Boolean> elevateUser(
@@ -9,6 +9,7 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
//alte verworfenen klasse für die funktionalität nicht wichtig
@RestController
public class DayController
{
@@ -1,5 +1,6 @@
package com.example.backend.discard.Days;
//alte verworfene klasse nicht wichtig für die funktionalität
public class Day
{
private int id;
@@ -5,6 +5,8 @@ import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.*;
//hier ein versuch für die übertragung von vertraulichen daten wie nutzername und passwörtern RSA verschlüsselung anzuwenden.
//finde aktuell keine anwendung im projekt.
public class RSA {
private PublicKey publicKey;
@@ -1,3 +1,19 @@
!!!!!!!!!
!!!!!!!!!
hier sieht man eine sammlung alter databasehandler funktionen,
welche nicht benötigt wurden. Von deren Verwendung ist abzuraten,
die Funkionalität dieser bei erneutem einfügen in den Databasehandler
kann nicht gewährleistet werden
!!!!!!!!
!!!!!!!!
!!!!!!!!
/**
* WEEKS
*/
@@ -1,5 +1,6 @@
package com.example.backend.discard.Week;
//alte verworfene klasse, nicht wichtig für die funktionalität
public class Week {
private int id;
@@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.*;
import java.sql.SQLException;
//alte verworfene klassen, für die funktionalität des tools nicht wichtig
@RestController
public class WeekController
{
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
@@ -0,0 +1,3 @@
artifactId=backend
groupId=com.example
version=0.0.1-SNAPSHOT
@@ -0,0 +1,17 @@
D:\DH\TIF22A_AnwProjekt_B\backend\src\main\java\com\example\backend\anwprj\controller\EntriesController.java
D:\DH\TIF22A_AnwProjekt_B\backend\src\main\java\com\example\backend\discard\WeekController.java
D:\DH\TIF22A_AnwProjekt_B\backend\src\main\java\com\example\backend\BackendApplication.java
D:\DH\TIF22A_AnwProjekt_B\backend\src\main\java\com\example\backend\anwprj\controller\ModuleController.java
D:\DH\TIF22A_AnwProjekt_B\backend\src\main\java\com\example\backend\anwprj\Users\UserSessionIDHandler.java
D:\DH\TIF22A_AnwProjekt_B\backend\src\main\java\com\example\backend\anwprj\controller\UserController.java
D:\DH\TIF22A_AnwProjekt_B\backend\src\main\java\com\example\backend\discard\Week\Week.java
D:\DH\TIF22A_AnwProjekt_B\backend\src\main\java\com\example\backend\discard\Encryption\RSA.java
D:\DH\TIF22A_AnwProjekt_B\backend\src\main\java\com\example\backend\anwprj\Users\User.java
D:\DH\TIF22A_AnwProjekt_B\backend\src\main\java\com\example\backend\anwprj\Semesters\Semester.java
D:\DH\TIF22A_AnwProjekt_B\backend\src\main\java\com\example\backend\anwprj\Users\UserPermissions.java
D:\DH\TIF22A_AnwProjekt_B\backend\src\main\java\com\example\backend\discard\Days\Day.java
D:\DH\TIF22A_AnwProjekt_B\backend\src\main\java\com\example\backend\anwprj\controller\SemesterController.java
D:\DH\TIF22A_AnwProjekt_B\backend\src\main\java\com\example\backend\anwprj\Entries\Entry.java
D:\DH\TIF22A_AnwProjekt_B\backend\src\main\java\com\example\backend\anwprj\Module\Module.java
D:\DH\TIF22A_AnwProjekt_B\backend\src\main\java\com\example\backend\discard\DayController.java
D:\DH\TIF22A_AnwProjekt_B\backend\src\main\java\com\example\backend\anwprj\Database\DataBaseHandler.java
@@ -0,0 +1 @@
com\example\backend\BackendApplicationTests.class
@@ -0,0 +1 @@
D:\DH\TIF22A_AnwProjekt_B\backend\src\test\java\com\example\backend\BackendApplicationTests.java
@@ -0,0 +1,14 @@
# Created at 2023-06-07T22:11:58.299
System.exit() or native command error interrupted process checker.
java.lang.IllegalStateException: error [STOPPED] to read process 132
at org.apache.maven.surefire.booter.PpidChecker.checkProcessInfo(PpidChecker.java:145)
at org.apache.maven.surefire.booter.PpidChecker.isProcessAlive(PpidChecker.java:116)
at org.apache.maven.surefire.booter.ForkedBooter$2.run(ForkedBooter.java:214)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:577)
at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:358)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
at java.base/java.lang.Thread.run(Thread.java:1623)
File diff suppressed because one or more lines are too long
@@ -0,0 +1,4 @@
-------------------------------------------------------------------------------
Test set: com.example.backend.BackendApplicationTests
-------------------------------------------------------------------------------
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.552 s - in com.example.backend.BackendApplicationTests