Author SHA1 Message Date
brausjonas 6c13caca85 Input Form new Design 2023-05-24 12:47:15 +02:00
brausjonas 2fba6b4354 Popup Animated 2023-05-24 01:21:19 +02:00
brausjonas 12f5773930 Design Extended to button 2023-05-24 01:05:04 +02:00
brausjonas 702e3e8e4d Design idea 2023-05-24 00:49:59 +02:00
brausjonas aadd9f5f94 Module Controller Fixed 2023-05-23 18:40:49 +02:00
brausjonas ed13b80a23 Revert "Added modules to Database"
This reverts commit 1da2f5be41.
2023-05-23 18:18:37 +02:00
brausjonas d46e125ff1 Added Modules Table To DataBase 2023-05-23 17:59:04 +02:00
AlexE030 1da2f5be41 Added modules to Database
+ small changes in backend
2023-05-23 17:44:35 +02:00
AliGitGut 2a87d54102 Kalender Side Bar Bugfix
Noch etwas Bugfix + neue Funktionalität hinzugefügt :)
2023-05-22 23:49:01 +02:00
AliGitGut 4741ba6911 Merge branch 'main' of https://github.com/DHBWLoerrach/TIF22A_AnwProjekt_B 2023-05-22 22:58:44 +02:00
brausjonas d8cc85713c In Semester Edit and Create there are real users to select now
And dummy data of modules to select from a list
2023-05-22 22:58:35 +02:00
AliGitGut 09188005f6 Kalender Side Bar Bugfix
Monatsnamen werden nun Jahresübergreifend richtig angezeigt
2023-05-22 22:51:50 +02:00
brausjonas 7d6d48d09e Fixed "React UseState useEffect" Loop on Semester overview 2023-05-22 19:43:26 +02:00
brausjonas aa408b27d1 Merge branch 'main' of https://github.com/DHBWLoerrach/TIF22A_AnwProjekt_B 2023-05-22 19:31:23 +02:00
brausjonas f8d36fcd8a Update Logic For Semester 2023-05-22 19:31:19 +02:00
AliGitGut 10d7dbf1df Update GruppenAufteilungEtc.pdf 2023-05-22 15:21:42 +02:00
AliGitGut 59fa7185cc Calendar Side Bar added
Calendar Side Bar and CSS File added
Don´t touch it, CSS makes problems
2023-05-21 14:50:39 +02:00
AlexE030 313df3e343 Added automatic module delete
+ small Changes
2023-05-20 22:33:53 +02:00
AlexE030 e92712d1d6 Added Modules to DBHandler
Datenbankeinträge fehlen noch.
2023-05-20 00:45:58 +02:00
brausjonas 8a1f0854a6 Delete Button For Semester Tile 2023-05-16 23:39:36 +02:00
brausjonas 99f22c77e3 Can Delete Semester on Right click menu 2023-05-16 23:23:51 +02:00
brausjonas ce38765fe1 Input Form Connected with Backend 2023-05-16 22:47:45 +02:00
brausjonas b1ede8005d Had To Move Some code because states wont work otherwise 2023-05-16 22:17:55 +02:00
brausjonas f6af4be682 First Prototype Frontend (Not Finished) 2023-05-16 22:03:02 +02:00
brausjonas ef1358baa4 OnLoginClick Logic
Fetch data from the backend and save the session id to the local storage
2023-05-16 19:52:58 +02:00
brausjonas bd6ec7b21f Login Function added 2023-05-16 19:22:54 +02:00
brausjonas 2da3e62c15 Database structure (Temp) 2023-05-16 11:49:29 +02:00
AliGitGut 34a6ca5aea Day Controller umgebogen
Day Controller wurde angepasst (wie Jonas sagen würde: umgebogen)
2023-05-16 11:38:08 +02:00
brausjonas 3a5768f51e Semester Fixed in databasehandler 2023-05-16 11:14:01 +02:00
brausjonas 0e4bee203d Semester Structure Changed 2023-05-16 11:10:05 +02:00
brausjonas 574ecaf305 Test Day In Year 2023-05-16 10:46:26 +02:00
AlexE030 8ef1540ff5 added Module Prototype 2023-05-16 00:32:55 +02:00
MikeBaier5 824e612140 WeekController finished 2023-05-14 22:10:54 +02:00
brausjonas ad025c07fb Database Handler Error Message on Connection Failed 2023-05-14 16:39:46 +02:00
brausjonas 301f976cb9 Add files via upload 2023-05-14 15:46:02 +02:00
brausjonas 8f68ff16a5 Merge branch 'main' of https://github.com/DHBWLoerrach/TIF22A_AnwProjekt_B 2023-05-14 15:41:52 +02:00
brausjonas 9daff98b9e Backend Frontend Merge 2023-05-14 15:41:49 +02:00
brausjonas 076263e89b Delete projekt directory 2023-05-14 15:39:58 +02:00
Amira24523 83a426d86e Final Login Design 2023-05-14 15:27:32 +02:00
Amira24523 371c9c7997 Login design update 2023-05-11 21:40:54 +02:00
AlexE030 22635bb6e5 Merge branch 'main' of https://github.com/DHBWLoerrach/TIF22A_AnwProjekt_B 2023-05-10 18:22:30 +02:00
AlexE030 7db358248d Added static Input-Form Prototype 2023-05-10 18:19:34 +02:00
Amira24523 a24ba0fb3b Added Login 2023-05-08 11:52:46 +02:00
MikeBaier5 646c64c7d9 Hovering tile finished 2023-05-08 01:46:31 +02:00
65 changed files with 1595437 additions and 1474 deletions
Vendored
BIN
View File
Binary file not shown.
+5
View File
@@ -0,0 +1,5 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
+12
View File
@@ -0,0 +1,12 @@
<?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
@@ -0,0 +1,16 @@
<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="JavaScriptLibraryMappings">
<includedPredefinedLibrary name="Node.js Core" />
</component>
</project>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/anwendungsprojekt.iml" filepath="$PROJECT_DIR$/.idea/anwendungsprojekt.iml" />
</modules>
</component>
</project>
Generated
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>
Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

+35
View File
@@ -0,0 +1,35 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
+5
View File
@@ -0,0 +1,5 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
+12
View File
@@ -0,0 +1,12 @@
<?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>
+5
View File
@@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/anwendung.iml" filepath="$PROJECT_DIR$/.idea/anwendung.iml" />
</modules>
</component>
</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>
+38
View File
@@ -0,0 +1,38 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
+7
View File
@@ -0,0 +1,7 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
}
}
+6
View File
@@ -0,0 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
}
module.exports = nextConfig
+1462
View File
File diff suppressed because it is too large Load Diff
+19
View File
@@ -0,0 +1,19 @@
{
"name": "anwendung",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"autoprefixer": "10.4.14",
"next": "13.3.4",
"postcss": "8.4.23",
"react": "18.2.0",
"react-dom": "18.2.0",
"tailwindcss": "3.3.2"
}
}
+6
View File
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 283 64"><path fill="black" d="M141 16c-11 0-19 7-19 18s9 18 20 18c7 0 13-3 16-7l-7-5c-2 3-6 4-9 4-5 0-9-3-10-7h28v-3c0-11-8-18-19-18zm-9 15c1-4 4-7 9-7s8 3 9 7h-18zm117-15c-11 0-19 7-19 18s9 18 20 18c6 0 12-3 16-7l-8-5c-2 3-5 4-8 4-5 0-9-3-11-7h28l1-3c0-11-8-18-19-18zm-10 15c2-4 5-7 10-7s8 3 9 7h-19zm-39 3c0 6 4 10 10 10 4 0 7-2 9-5l8 5c-3 5-9 8-17 8-11 0-19-7-19-18s8-18 19-18c8 0 14 3 17 8l-8 5c-2-3-5-5-9-5-6 0-10 4-10 10zm83-29v46h-9V5h9zM37 0l37 64H0L37 0zm92 5-27 48L74 5h10l18 30 17-30h10zm59 12v10l-3-1c-6 0-10 4-10 10v15h-9V17h9v9c0-5 6-9 13-9z"/></svg>

After

Width:  |  Height:  |  Size: 629 B

+33
View File
@@ -0,0 +1,33 @@
import React from "react";
export default function Background()
{
return (
<div style={{
position: "absolute",
width: "100%",
height: "100%",
overflow: "clip",
pointerEvents: "none"
}}>
<div style={{
position: "absolute",
transform: "skew(20deg)",
width: "100%",
height: "100%",
zIndex: -10,
backgroundColor: "#f2f2f2",
borderTopLeftRadius: 400,
borderBottomRightRadius: 800,
}}></div>
<div style={{
position: "absolute",
width: "100%",
height: "100%",
zIndex: -11,
backgroundColor: "#346991",
}}></div>
</div>
);
}
+65
View File
@@ -0,0 +1,65 @@
/**
* Function Takes in Paramter for:
* text: text to be shown on the button
* width, height: width and height of the button
* icon: an icon that should be shown on the button (HTML <svg> tag) (see Icons.js for example)
* iconWidth, iconHeight: width and height of the icon
* onClick: a function that should be run if the button is clicked
* Example for onClick:
* <Button onClick={onClick={() => {console.log("do something")}}
* Example for icon:
*/
export default function Button(p) {
//default parameters for the button
let text = p.text;
let width = p.width, height = p.height;
let iconHTML = p.icon;
let iconWidth = p.iconWidth, iconHeight = p.iconHeight;
let onClick = p.onClick;
let color = p.color;
let fontColor = p.fontColor;
let font_size = p.fontSize;
//if parameters are not set, they are set to default values
if (height == null) height = 0;
if (width == null) width = 0;
if (iconWidth == null) iconWidth = width-10;
if (iconHeight == null) iconHeight = height-10;
if (onClick == null) onClick = () => {};
if (color == null) color = "#363636";
if (fontColor == null) fontColor = "white";
if (font_size == null) font_size = 16;
//build in the icon width and height to the svg tag (svg tag should not contain any size information by default)
if (iconHTML != null) {
let split = iconHTML.split("fill=");
split[1] = "fill=" + split[1];
split[0] += " width=" + iconWidth + " height=" + iconHeight + " ";
iconHTML = split[0] + split[1]
} else {
iconHTML = "";
}
//return the button
return (
<>
<button className={"round-border button font font-small"}
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
backgroundColor: color,
color: fontColor,
fontSize: font_size,
minWidth: width,
minHeight: height,
textAlign: "center",
}}
onClick={onClick}>
{text}
<div dangerouslySetInnerHTML={{__html: iconHTML}}/>
</button>
</>
);
}
@@ -0,0 +1,117 @@
let startParts = []
let endParts = []
const months = [["Januar", 31], ["Februar", 28], ["März", 31], ["April", 30], ["Mai", 31], ["Juni", 30], ["Juli", 31], ["August", 31], ["September", 30], ["Oktober", 31], ["November", 30], ["Dezember", 31]]
const days = months.map((month => month[1]))
let result = []
let check = true
const weekdays = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"]
export default function BasicDateCalendar(p) {
if (check) {
generateCalendar("01.12.2024", "15.09.2025")
check = false
}
return (
<div className={"Down"}>
{result.map((monthResult, index = 0) => (
<div key={months} className={"A"}>
<p>{getMonthName(index)}</p>
<div className={"Days"}>
{weekdays.map((weekday) => (
<p key={weekday}>{weekday}</p>
))}
{monthResult.map((date) => (
<p key={date}>{date}</p>
))}
</div>
</div>
))}
</div>
)
}
function getMonthName(monthIndex) {
if (startParts[1] - 1 + monthIndex < 12) {
return months[startParts[1] - 1 + monthIndex][0];
} else {
return months[startParts[1] - 1 + monthIndex - 12][0];
}
}
function generateCalendar(start, ende)
{
splitter(start, ende)
if (startParts[2] < endParts[2])
{
for (let i = startParts[1] - 1; i <= 11; i++)
{
let monthResult = [];
for (let j = 1; j <= days[i]; j++)
{
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)
)
{
monthResult.push(j);
}
}
result.push(monthResult);
if (i == 11)
{
for (let h = 0; h <= endParts[1] - 1; h++)
{
let monthResultNewYear = [];
for (let g = 1; g <= days[h]; g++)
{
if (new Date(endParts[2], h, g) <= new Date(endParts[2], endParts[1] - 1, endParts[0]))
{
monthResultNewYear.push(g);
}
}
result.push(monthResultNewYear);
}
}
}
} else
{
for (let i = startParts[1] - 1; i <= endParts[1] - 1; i++)
{
let monthResult = [];
for (let j = 1; j <= days[i]; j++)
{
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])
)
{
monthResult.push(j);
}
}
result.push(monthResult);
}
}
}
function splitter(startDate, endDate)
{
startParts = startDate.split(".")
//Transformer()
if (startParts[1][0] === 0) //prüft ob die erste Stelle des Monats eine 0 vorne stehen hat
{
startParts[1] = startParts[1][1] //überschreibt den Monat ohne die 0
}
endParts = endDate.split(".") //prüft ob die erste Stelle des Monats eine 0 vorne stehen hat
if (endParts[1][0] === 0)
{
endParts[1] = endParts[1][1] //überschreibt den Monat ohne die 0
}
}
function Transformer()
{
let formattedDateStr = startParts[1] + "/" + startParts[0] + "/" + startParts[2];
console.log(formattedDateStr)
let weekday = new Date(formattedDateStr).getDay();
console.log(weekday);
}
@@ -0,0 +1,9 @@
export class CalenderEntry
{
constructor(start_point, end_point)
{
this.start_point = start_point;
this.end_point = end_point;
this.colorID = 0;
}
}
+568
View File
@@ -0,0 +1,568 @@
import {useEffect, useState} from "react";
import {CalenderEntry} from "@/components/CalenderEntry";
import Button from "@/components/Button";
import {list} from "postcss";
//all entries of the current week
let entries = {mo: [], tu: [], we: [], th: [], fr: [], sa: []}
//a variable that saves the currently grabbed resize bar
let grabbed = null;
let grabbedUp = false;
let grabbed_in_list = null;
//a variable the saves if the mouse is pressed or not
let mouseDown = false;
//a variable that stores the currently grabbed element to move
let selectedElement = null;
//move offset from top row to cursor
let selectedOffsetTop = 0;
//move offset from bottom row to cursor
let selectedOffsetBottom = 0;
//the list, the grabbed element to move is currently in
let selectedListID = "";
//variable for the hight of one cell / row. Important for resizing the calender view
let cellHeight = 25;
let colors = ["#f80000", "#414141"]
export default function CalenderView(p)
{
//state to update the calender view
const [t, setT] = useState(false)
//a blocker for the right click context menu
useEffect(() =>
{
window.addEventListener("contextmenu", (e) => (e.preventDefault()))
})
function does_element_overlap(entry, start, end, search_list)
{
let current = null;
for(let i = 0; i < search_list.length; i++)
{
current = search_list[i];
if(current !== entry)
{
if (start > current.start_point && start < current.end_point)
{
return true;
} else if (end > current.start_point && end < current.end_point)
{
return true;
} else if (start <= current.start_point && end >= current.end_point)
{
return true;
}
}
}
return false;
}
//function to delete an elemente and resize the corresponding list in the entries dictionary
function delete_element(index, element)
{
let currentList = entries[index];
let temp = []
for (let i = 0; i < currentList.length; i++)
{
if (element !== currentList[i])
{
temp.push(currentList[i]);
}
}
entries[index] = temp;
}
//resize a grabbed element to the row paramter
function size_grabbed(row, current_list)
{
if (row >= 0 && row <= 96)
{
if (grabbedUp)
{
console.log(grabbed.start_point)
if (row < grabbed.end_point - 1)
{
if(!does_element_overlap(grabbed, row, grabbed.end_point, current_list))
{
grabbed.start_point = row;
}
}
} else
{
if (row > grabbed.start_point)
{
if(!does_element_overlap(grabbed, grabbed.start_point, row + 1, current_list))
{
grabbed.end_point = row + 1;
}
}
}
}
}
//moves the selected element to row and list with id
function move_selected(row, id)
{
if (selectedListID !== id)
{
if(!does_element_overlap(selectedElement, row - selectedOffsetTop, row + selectedOffsetBottom, entries[id]))
{
delete_element(selectedListID, selectedElement);
entries[id].push(selectedElement);
selectedListID = id;
}
}
if (row - selectedOffsetTop > 0 && row + selectedOffsetBottom <= 97)
{
if(!does_element_overlap(selectedElement, row - selectedOffsetTop, row + selectedOffsetBottom, entries[id]))
{
selectedElement.start_point = row - selectedOffsetTop;
selectedElement.end_point = row + selectedOffsetBottom;
}
}
}
//routine, when mouse is moved
function mouse_move(e)
{
//checks if mouse is still down
if (mouseDown)
{
//get the y coordinate of the cursor
let y_window = e.clientY;
//get the offset to the calender view
let y_target_offset = e.currentTarget.getBoundingClientRect().top;
//get the id of the current column
let id = e.currentTarget.id;
//calcultes the current row the cursor hovers
let row = Math.floor((y_window - y_target_offset) / cellHeight) + 1
let current_list = entries[e.currentTarget.id];
//if a edge of an element was grabbed, resize it
if (grabbed != null)
{
size_grabbed(row, grabbed_in_list);
//if a whole element was grabbed, move it
} else if (selectedElement != null)
{
move_selected(row, id);
}
}
//update the calender view
setT(!t);
}
//routine when mouse was released
function mouse_up(e)
{
mouseDown = false;
//remove all selected elements
if (grabbed != null)
{
grabbed.colorID = 0;
grabbed = null;
}
if (selectedElement != null)
{
selectedElement.colorID = 0;
selectedElement = null;
}
setT(!t);
}
//find the current element on row in the selected list (search_list)
function find_current(row, search_list)
{
let current = null;
for (let i = 0; i < search_list.length; i++)
{
current = search_list[i];
if (current.start_point <= row && current.end_point >= row)
{
break;
}
current = null;
}
return current;
}
//places a new entry to the calender
function place_new_entry(row, list)
{
if (row < 96)
{
let free = true;
for (let i = 0; i < list.length; i++)
{
let current = list[i];
for (let r = row; r < row + 3; r++)
{
for (let s = current.start_point; s < current.end_point; s++)
{
if (s === r)
{
free = false;
break;
}
}
}
}
if (free)
{
list.push(new CalenderEntry(row, row + 3));
setT(!t);
}
}
}
//routine when mouse was pressed
function mouse_down(e)
{
//get the cursors y coordinate in the window
let y_window = e.clientY;
//get the offset of the calender view
let y_target_offset = e.currentTarget.getBoundingClientRect().top;
//calculate the row clicked on
let row = Math.floor((y_window - y_target_offset) / cellHeight) + 1;
//get the list of entries clicked on
let current_list = entries[e.currentTarget.id];
//if right clicked
if (e.button === 2)
{
//if right clicked on an element / entry delete it
let current = find_current(row, current_list);
if (current != null)
{
delete_element(e.currentTarget.id, current);
}
}
else
{
mouseDown = true;
//if a resize bar was grabbed
if (e.target.id === "grab")
{
//get the entry the resize bar is child of
let entry = e.target.parentElement;
//get the startRow of the entry
let rowStart = parseInt(window.getComputedStyle(entry).gridRowStart);
grabbed_in_list = current_list;
//check if the upper or lower resize bar was grabbed
if (row === rowStart)
{
//+ / - 1 to avoid select the wrong element when overlapping
grabbed = find_current(row + 1, current_list);
grabbedUp = true;
} else
{
grabbed = find_current(row - 1, current_list);
grabbedUp = false;
}
grabbed.colorID = 1;
setT(!t);
}
//if a whole element was clicked to move
else if (e.target.id === "entry")
{
let rowStart = parseInt(window.getComputedStyle(e.target).gridRowStart);
selectedListID = e.currentTarget.id;
if(rowStart === row)
{
selectedElement = find_current(row + 1, current_list);
}
else
{
selectedElement = find_current(row, current_list);
}
selectedElement.colorID = 1;
setT(!t);
selectedOffsetTop = row - parseInt(window.getComputedStyle(e.target).gridRowStart);
selectedOffsetBottom = parseInt(window.getComputedStyle(e.target).gridRowEnd) - row;
}
//single click places a new entry
else
{
place_new_entry(row, current_list)
}
}
}
//returns internal format (0 - 96) to a string
function internal_to_time(internal)
{
internal -= 1
internal /= 4
let integer = Math.floor(internal)
let decimal = internal.toFixed(2);
let minutes = Math.floor((decimal - integer) * 60);
let minutes_string = minutes.toString().length === 1 ? "0" + minutes : minutes
return integer + ":" + minutes_string;
}
let temp = []
for (let i = 2; i <= 96; i += 2)
{
temp.push(i);
}
//html of the calender view
return (
// calender outer container, contains the calender view and resize buttons
<div style={{display: "flex", flexDirection: "row", justifyContent: "center", alignItems: "center", gap: 5}}>
{/* resize butto*/}
<Button text={"-"} fontSize={25} onClick={() =>
{
if (cellHeight - 5 >= 10) cellHeight -= 5;
setT(!t);
}} width={50} height={50}/>
{/*shows the day over the columns*/}
<div id={t} style={{border: "5px solid #363636", borderRadius: 10}}>
<div style={{backgroundColor: "#363636"}}>
<div className={"wochen-tag-container"}>
<div className={"wochen-tag font-big"}>Montag</div>
<div className={"wochen-tag font-big"}>Dienstag</div>
<div className={"wochen-tag font-big"}>Mittwoch</div>
<div className={"wochen-tag font-big"}>Donnerstag</div>
<div className={"wochen-tag font-big"}>Freitag</div>
<div className={"wochen-tag font-big"}>Samstag</div>
</div>
</div>
{/*the viewport of the actual calender*/}
<div className={"calender-container"}>
{/*the content of the calender (rows and columns)*/}
<div className={"calender-view content"} style={{height: cellHeight * 96 + 10}}>
{/*a row which contains all the entries of monday*/}
<div className={"spalte"} onMouseDown={mouse_down} onMouseUp={mouse_up} onMouseMove={mouse_move}
id={"mo"} style={{gridTemplateRows: `repeat(96, ${cellHeight}px)`}}>
{/*maps all monday entries to new visible div elements*/}
{entries["mo"].map(d => (<div className={"entry"} style={{
width: "100%",
gridRowStart: d.start_point,
gridRowEnd: d.end_point,
gridColumnStart: 0,
gridColumnEnd: 0,
backgroundColor: colors[d.colorID],
}} id={"entry"}>
{/*content of the entry / element*/}
{/*upper resize bar*/}
<div className={"resize-grab"} id={"grab"}></div>
<div style={{maxHeight: "60%"}} className={"no-pointer-events"}>
{/*shows the time span of the entry*/}
<p>{internal_to_time(d.start_point) + " - " + internal_to_time(d.end_point)}</p>
<p>Moduel etc.</p>
<p>Mehr Infos</p>
<p>Raum</p>
</div>
{/*lower resize bar*/}
<div className={"resize-grab"} id={"grab"}></div>
</div>))}
</div>
{/*same as monday*/}
<div className={"spalte"} onMouseDown={mouse_down} onMouseUp={mouse_up} onMouseMove={mouse_move}
id={"tu"} style={{gridTemplateRows: `repeat(96, ${cellHeight}px)`}}>
{entries["tu"].map(d => (<div className={"entry"} style={{
width: "100%",
gridRowStart: d.start_point,
gridRowEnd: d.end_point,
backgroundColor: colors[d.colorID]
}} id={"entry"}>
<div className={"resize-grab"} id={"grab"}></div>
<div style={{maxHeight: "60%"}} className={"no-pointer-events"}>
<p>{internal_to_time(d.start_point) + " - " + internal_to_time(d.end_point)}</p>
<p>Moduel etc.</p>
<p>Mehr Infos</p>
<p>Raum</p>
</div>
<div className={"resize-grab"} id={"grab"}></div>
</div>))}
</div>
{/*same as monday*/}
<div className={"spalte"} onMouseDown={mouse_down} onMouseUp={mouse_up} onMouseMove={mouse_move}
id={"we"} style={{gridTemplateRows: `repeat(96, ${cellHeight}px)`}}>
{entries["we"].map(d => (<div className={"entry"} style={{
width: "100%",
gridRowStart: d.start_point,
gridRowEnd: d.end_point,
backgroundColor: colors[d.colorID]
}} id={"entry"}>
<div className={"resize-grab"} id={"grab"}></div>
<div style={{maxHeight: "60%"}} className={"no-pointer-events"}>
<p>{internal_to_time(d.start_point) + " - " + internal_to_time(d.end_point)}</p>
<p>Moduel etc.</p>
<p>Mehr Infos</p>
<p>Raum</p>
</div>
<div className={"resize-grab"} id={"grab"}></div>
</div>))}
</div>
{/*same as monday*/}
<div className={"spalte"} onMouseDown={mouse_down} onMouseUp={mouse_up} onMouseMove={mouse_move}
id={"th"} style={{gridTemplateRows: `repeat(96, ${cellHeight}px)`}}>
{entries["th"].map(d => (<div className={"entry"} style={{
width: "100%",
gridRowStart: d.start_point,
gridRowEnd: d.end_point,
backgroundColor: colors[d.colorID]
}} id={"entry"}>
<div className={"resize-grab"} id={"grab"}></div>
<div style={{maxHeight: "60%"}} className={"no-pointer-events"}>
<p>{internal_to_time(d.start_point) + " - " + internal_to_time(d.end_point)}</p>
<p>Moduel etc.</p>
<p>Mehr Infos</p>
<p>Raum</p>
</div>
<div className={"resize-grab"} id={"grab"}></div>
</div>))}
</div>
{/*same as monday*/}
<div className={"spalte"} onMouseDown={mouse_down} onMouseUp={mouse_up} onMouseMove={mouse_move}
id={"fr"} style={{gridTemplateRows: `repeat(96, ${cellHeight}px)`}}>
{entries["fr"].map(d => (<div className={"entry"} style={{
width: "100%",
gridRowStart: d.start_point,
gridRowEnd: d.end_point,
backgroundColor: colors[d.colorID]
}} id={"entry"}>
<div className={"resize-grab"} id={"grab"}></div>
<div style={{maxHeight: "60%"}} className={"no-pointer-events"}>
<p>{internal_to_time(d.start_point) + " - " + internal_to_time(d.end_point)}</p>
<p>Moduel etc.</p>
<p>Mehr Infos</p>
<p>Raum</p>
</div>
<div className={"resize-grab"} id={"grab"}></div>
</div>))}
</div>
{/*same as monday*/}
<div className={"spalte"} onMouseDown={mouse_down} onMouseUp={mouse_up} onMouseMove={mouse_move}
id={"sa"} style={{gridTemplateRows: `repeat(96, ${cellHeight}px)`}}>
{entries["sa"].map(d => (<div className={"entry"} style={{
width: "100%",
gridRowStart: d.start_point,
gridRowEnd: d.end_point,
backgroundColor: colors[d.colorID]
}} id={"entry"}>
<div className={"resize-grab"} id={"grab"}></div>
<div style={{maxHeight: "60%"}} className={"no-pointer-events"}>
<p>{internal_to_time(d.start_point) + " - " + internal_to_time(d.end_point)}</p>
<p>Moduel etc.</p>
<p>Mehr Infos</p>
<p>Raum</p>
</div>
<div className={"resize-grab"} id={"grab"}></div>
</div>))}
</div>
</div>
{/*overlay with timeline*/}
<div className={"overlay"} style={{backgroundColor: "rgba(0, 0, 0, 0)"}}>
{/*maps a list of internal time stamps to lines and time stamps*/}
{temp.map(i => (<div style={{
width: "100%",
height: cellHeight * 2,
borderBottom: "1px solid #363636",
display: "flex",
flexDirection: "row",
justifyContent: "space-around",
alignItems: "center",
}} className={"no-pointer-events"}>
<p style={{
color: "gray",
marginTop: cellHeight - 3,
marginRight: 120,
fontSize: 12,
textAlign: "center"
}}>{internal_to_time(i + 1)}</p>
<p style={{
color: "gray",
marginTop: cellHeight - 3,
marginRight: 120,
fontSize: 12,
textAlign: "center"
}}>{internal_to_time(i + 1)}</p>
<p style={{
color: "gray",
marginTop: cellHeight - 3,
marginRight: 120,
fontSize: 12,
textAlign: "center"
}}>{internal_to_time(i + 1)}</p>
<p style={{
color: "gray",
marginTop: cellHeight - 3,
marginRight: 120,
fontSize: 12,
textAlign: "center"
}}>{internal_to_time(i + 1)}</p>
<p style={{
color: "gray",
marginTop: cellHeight - 3,
marginRight: 120,
fontSize: 12,
textAlign: "center"
}}>{internal_to_time(i + 1)}</p>
<p style={{
color: "gray",
marginTop: cellHeight - 3,
marginRight: 120,
fontSize: 12,
textAlign: "center"
}}>{internal_to_time(i + 1)}</p>
</div>))}
</div>
</div>
</div>
{/*the second resize button*/}
<Button text={"+"} fontSize={25} onClick={() =>
{
cellHeight += 5;
setT(!t)
}} width={50} height={50}/>
</div>
)
}
+25
View File
@@ -0,0 +1,25 @@
function addDays(date, days) {
let result = new Date(date);
result.setDate(result.getDate() + days);
return result;
}
export default function DateElement(props){
let startDate;
let endDate;
const currDate = new Date();
startDate = addDays(currDate, (currDate.getDay()-1)*-1); //berechnet den Montag der aktuellen Woche
startDate = addDays(startDate, props.week*7); //erhöht das Datum um 7 Tage für jede Woche, die weiter geklickt wurde.
endDate = addDays(startDate, 6);
const startDateString = `${startDate.getDate()}.${startDate.getMonth()+1}.${startDate.getFullYear()}`;
const endDateString = `${endDate.getDate()}.${endDate.getMonth()+1}.${endDate.getFullYear()}`;
return (
<>
<div className="dateElement round-border">
<p>{startDateString} - {endDateString}</p>
</div>
</>
);
}
+15
View File
@@ -0,0 +1,15 @@
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>`
export const arrowRight = `<svg xmlns="http://www.w3.org/2000/svg" fill="white" class="bi bi-arrow-right" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8z"/>
</svg>`
export const deleteItem = `<svg xmlns="http://www.w3.org/2000/svg" fill="black" class="bi bi-trash-fill" viewBox="0 0 16 16">
<path d="M2.5 1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1H3v9a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V4h.5a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H10a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1H2.5zm3 4a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 .5-.5zM8 5a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7A.5.5 0 0 1 8 5zm3 .5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 1 0z"/>
</svg>`
export const editItem = `<svg xmlns="http://www.w3.org/2000/svg" fill="black" class="bi bi-pencil-fill" viewBox="0 0 16 16">
<path d="M12.854.146a.5.5 0 0 0-.707 0L10.5 1.793 14.207 5.5l1.647-1.646a.5.5 0 0 0 0-.708l-3-3zm.646 6.061L9.793 2.5 3.293 9H3.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.207l6.5-6.5zm-7.468 7.468A.5.5 0 0 1 6 13.5V13h-.5a.5.5 0 0 1-.5-.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.5-.5V10h-.5a.499.499 0 0 1-.175-.032l-.179.178a.5.5 0 0 0-.11.168l-2 5a.5.5 0 0 0 .65.65l5-2a.5.5 0 0 0 .168-.11l.178-.178z"/>
</svg>`
+247
View File
@@ -0,0 +1,247 @@
import Button from "@/components/Button";
import {useRouter} from "next/router";
import {useEffect, useState} from "react";
import Background from "@/components/Background";
let userInfo = []
export default function InputForm(p) {
class UserInfo {
constructor(userid, modules) {
this.userid = userid;
this.module = modules;
this.checked = false;
}
setChecked(checked) {
this.checked = checked;
}
setModule(module) {
this.module = module;
}
}
let startDateParam = "";
let endDateParam = "";
let courseNameParam = "";
if (p.startDate != null) startDateParam = p.startDate;
if (p.endDate != null) endDateParam = p.endDate;
if (p.courseName != null) courseNameParam = p.courseName;
const router = useRouter();
const [startDate, setStartDate] = useState(startDateParam);
const [endDate, setEndDate] = useState(endDateParam);
const [courseName, setCourseName] = useState(courseNameParam);
const [users, setUsers] = useState([]);
async function getAllUsers() {
let sessionid = localStorage.getItem("sessionid");
let url = "http://localhost:8080/users/all?sessionid=" + sessionid;
await fetch(url).then(response => response.json()).then(user => setUsers(user));
}
useEffect(() => {
userInfo = [];
getAllUsers();
}, [])
async function onCreateClicked() {
let startSplit = startDate.split("-");
let endSplit = endDate.split("-");
let startYear = parseInt(startSplit[0]);
let endYear = parseInt(endSplit[0]);
//month - 1 because jan = 0, day like month... but because of next lines 3 to 4 not - 1
let startInternalDate = new Date(startYear, parseInt(startSplit[1]) - 1, parseInt(startSplit[2]))
let endInternalDate = new Date(endYear, parseInt(endSplit[1]) - 1, parseInt(endSplit[2]))
let startDayInYear = Math.round((startInternalDate - new Date(startYear, 0, 0)) / (1000 * 60 * 60 * 24));
let endDayInYear = Math.round((endInternalDate - new Date(endYear, 0, 0)) / (1000 * 60 * 60 * 24));
let id = p.courseName == null ? 0 : localStorage.getItem("currentsid");
let json = {
"id": id,
"startday": startDayInYear,
"endday": endDayInYear,
"name": courseName,
"startyear": startYear,
"endyear": endYear
}
let url = "http://localhost:8080/semester?sessionid=" + localStorage.getItem("sessionid");
let method = p.courseName == null ? "POST" : "PUT";
await fetch(url, {
method: method,
headers: {"Content-Type": "application/json"},
body: JSON.stringify(json)
}).then(response => response.json()).then(semester => console.log(semester));
router.back();
}
function onModuleClicked(user, module) {
let found = false;
for (let i = 0; i < userInfo.length; i++) {
let current = userInfo[i];
if (current !== undefined && current.userid === user.id) {
userInfo[i].setModule(module);
found = true;
}
}
if (!found) {
userInfo.push(new UserInfo(user.id, module));
}
}
function onCheckBoxClicked(user, e) {
onModuleClicked(user, "");
let found = false;
for (let i = 0; i < userInfo.length; i++) {
let current = userInfo[i];
if (current !== undefined && current.userid === user.id) {
userInfo[i].setChecked(e.target.checked);
found = true;
}
}
if (!found) {
let temp = new UserInfo(user.id, "");
temp.setChecked(e.target.checked);
userInfo.push(temp);
}
}
return (
<>
<Background/>
<div className="inputForm box-shadow">
<p style={{
fontSize: "18px",
color: "#777777",
fontWeight: 500,
width: 150
}}>SemesterName</p>
<input className="courseNameInput box-shadow" value={courseName}
onChange={(e) => setCourseName(e.target.value)}/>
<div className="semesterRangeInput">
<div className="semesterDateLables">
<p className="semesterDateLable" style={{
fontSize: " 18px",
color: "#777777",
fontWeight: 500,
width: 150
}}>Semesterstart</p>
<p className="semesterDateLable" style={{
fontSize: " 18px",
color: "#777777",
fontWeight: 500,
width: 150
}}>Semesterende</p>
</div>
<div className="semesterDateInputPair">
<input type="date" id="start" className={"box-shadow selector"} value={startDate}
style={{padding: 5}}
onChange={(e) => setStartDate(e.target.value)}/>
<p className="inputFieldSeperator">-</p>
<input type="date" id="start" className={"box-shadow selector"} value={endDate}
style={{padding: 5}}
onChange={(e) => setEndDate(e.target.value)}/>
</div>
</div>
<div className="round-border dozentSelector">
<table>
<tbody>
<tr>
<th style={{
fontSize: " 18px",
color: "#777777",
fontWeight: 500,
}}>Wählen
</th>
<th style={{
fontSize: " 18px",
color: "#777777",
fontWeight: 500,
}}>Freischalten
</th>
<th style={{
fontSize: " 18px",
color: "#777777",
fontWeight: 500,
textAlign: "center"
}}>Dozent
</th>
<th style={{
fontSize: " 18px",
color: "#777777",
fontWeight: 500,
textAlign: "center",
}}>Modul
</th>
</tr>
{users.map(user => (
<tr>
<td><div style={{
display: "flex",
flexDirection: "row",
justifyContent: "center",
}}><input type="checkbox" onChange={(e) => {
onCheckBoxClicked(user, e);
}}/></div></td>
<td><div style={{
display: "flex",
flexDirection: "row",
justifyContent: "center",
}}><input type="checkbox" onChange={(e) => {
onCheckBoxClicked(user, e);
}}/></div></td>
<td style={{}}>{user.firstName + " " + user.lastName}</td>
<select id={"userSelect"} name={"userSelect"} className={"box-shadow selector"}
multiple={false} style={{
maxHeight: 80,
marginTop: 10,
padding: "5px 2px"
}} onChange={(e) => {
onModuleClicked(user, e.target.value)
}}>
<option value={"Programmieren"}>Programmieren</option>
<option value={"BWL"}>BWL</option>
<option value={"Lineare Algebra"}>Lineare Algebra</option>
<option value={"Analysis"}>Analysis</option>
<option value={"AnwendungsProjekt"}>AnwendungsProjekt</option>
</select>
</tr>
))}
</tbody>
</table>
</div>
<div id="buttons">
<Button color="rgba(54,54,54,0.64)" width="100px" height="30px" text="Abbrechen" onClick={() => {
router.back()
}}/>
<Button color="#77932b" width="100px" height="30px" text="Speichern" onClick={() => {
onCreateClicked()
}}/>
</div>
</div>
</>
)
}
+65
View File
@@ -0,0 +1,65 @@
import React, {useState} from "react";
import Button from "@/components/Button";
import {NextResponse} from "next/server";
import Link from "next/link";
import {useRouter} from "next/router";
export default function Login() {
let url = "http://localhost:8080/users"
async function on_login_click() {
url += "?mail=" + inputUserName + "&password=" + inputPassword;
let response = await fetch(url, {
method: "GET",
});
let reader = response.body.getReader();
let value = String.fromCharCode.apply(null, ((await reader.read()).value))
if (value != "failed") {
localStorage.setItem("sessionid", value);
await router.push("/semesteroverview")
} else {
setInputPassword("");
setInputUserName("");
setHint("wrong login credentials")
}
}
const [inputUserName, setInputUserName] = useState("")
const [inputPassword, setInputPassword] = useState("")
const [hint, setHint] = useState("type here")
const [backgroundColor, setBackgroundColor] = useState("rgb(255, 255, 255)")
const router = useRouter()
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>
<input type="text" value={inputUserName} onChange={e => setInputUserName(e.target.value)}
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>
<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"
style={{
backgroundColor: backgroundColor
}}/>
</div>
<Button text={"Login"} color={"#77932b"} width={100} height={40} onClick={() => on_login_click()}/>
</login>
// </div>
);
}
+28
View File
@@ -0,0 +1,28 @@
import Button from "@/components/Button";
import {useState} from "react";
let shown = false;
export default function PopUp(p) {
return (
<>
<div style={{
display: p.displayState
}}>
<div className={"modal-container"}>
<div className={"modal box-shadow"}>
<p className={"font-middle"}>{p.hint}</p>
<div>
<Button text={p.text1} color={"rgba(54,54,54,0.64)"} onClick={p.function1}/>
<Button text={p.text2} color={"#77932b"} onClick={p.function2}/>
</div>
</div>
</div>
</div>
</>
)
}
+29
View File
@@ -0,0 +1,29 @@
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)
{
useEffect(() =>
{
window.addEventListener("contextmenu", (e) => (e.preventDefault()))
})
return (
<div onClick={(e) => p.onClick(e)} className={"semester-tile box-shadow"}>
<p>{p.text}</p>
<StatusBar progress={0}/>
<div style={{
display: "flex",
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
gap: 5
}}>
<Button icon={deleteItem} width={30} height={30} color={"#ffffff"} onClick={p.onButtonDeleteClick}/>
<Button icon={editItem} width={30} height={30} color={"#ffffff"} onClick={p.onButtonEditClick}/>
</div>
</div>
)
}
+26
View File
@@ -0,0 +1,26 @@
import React from "react"
export default function StatusBar(p)
{
if(p.progress > 100) p.progress = 100;
let classNames = ["not-started", "started", "finished"];
let index = p.progress / 50;
let actives = ["", "", ""]
actives[index] = "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>
<div className={"progress-bar " + classNames[index]}
style={{
width: p.progress + "%"
}}
></div>
</div>
</div>
)
}
+19
View File
@@ -0,0 +1,19 @@
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)
return (
<div>
<p>{datum.getMonth()}</p>
</div>
);
}
+67
View File
@@ -0,0 +1,67 @@
import React from 'react';
const Tile = () => {
const [isHovered, setIsHovered] = React.useState(false);
const [cursorPosition, setCursorPosition] = React.useState({ x: 0, y: 0 });
const tileRef = React.useRef(null);
const handleMouseEnter = () => {
setIsHovered(true);
};
const handleMouseLeave = () => {
setIsHovered(false);
};
const handleMouseMove = (event) => {
if (tileRef.current) {
const rect = tileRef.current.getBoundingClientRect();
setCursorPosition({
x: event.clientX - rect.left,
y: event.clientY - rect.top,
});
}
};
return (
<div
ref={tileRef}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onMouseMove={handleMouseMove}
style={{
backgroundColor: 'rgba(255,0,0,0.89)',
width: '250px',
height: '150px',
margin: '10px',
transition: 'transform 0.2s',
transform: isHovered ? 'translateY(-5px)' : 'none',
position: 'relative',
borderRadius: '10px',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
<span style = {{ color: 'white', fontWeight: 'bold'}}>Kalender</span>
{isHovered && (
<div
style={{
position: 'absolute',
top: cursorPosition.y - 10,
left: cursorPosition.x - 10,
width: '20px',
height: '20px',
borderRadius: '50%',
background:
'radial-gradient(circle at center, rgba(255, 255, 255) 0%, rgba(255,255,255,0) 70%)',
}}
/>
)}
</div>
);
};
export default Tile;
+20
View File
@@ -0,0 +1,20 @@
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(){
const [weeks, setWeeks] = useState(0)
return (
<>
<div className="weekSelector">
<Button icon={arrowLeft} onClick={() => setWeeks(weeks-1)} />
<DateElement week={weeks}/>
<Button icon={arrowRight} onClick={() => setWeeks(weeks+1)}/>
</div>
</>
)
}
+6
View File
@@ -0,0 +1,6 @@
import '@/styles/globals.css'
import '@/styles/calendarSideBar.css'
export default function App({ Component, pageProps }) {
return <Component {...pageProps} />
}
+5
View File
@@ -0,0 +1,5 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
export default function handler(req, res) {
res.status(200).json({ name: 'John Doe' })
}
+14
View File
@@ -0,0 +1,14 @@
import InputForm from "@/components/InputForm";
import {useRouter} from "next/router";
export default function CreateSemester()
{
const router = useRouter();
let {courseName, startDate, endDate} = router.query;
return (
<div className={"normal-centered"}>
<InputForm startDate={startDate} endDate={endDate} courseName={courseName}/>
</div>
)
}
+38
View File
@@ -0,0 +1,38 @@
import {Inter} from 'next/font/google'
import React, {useState} from "react";
import StatusBar from "@/components/StatusBar";
import Button from "@/components/Button";
import {arrowLeft, arrowRight} from "@/components/Icons";
import WeekSelector from "@/components/WeekSelector";
import PopUp from "@/components/PopUp";
import CalenderView from "@/components/CalenderView";
import DateElement from "@/components/DateElement";
import InputForm from "@/components/InputForm";
import Login from "@/components/Login";
import Test from "@/components/Test";
import BasicDateCalendar from "@/components/CalendarSideBar";
import {randomInt} from "next/dist/shared/lib/bloom-filter/utils";
import Background from "@/components/Background";
const inter = Inter({subsets: ['latin']})
export default function Home(p) {
return (
<div className={"normal-centered"}>
<Background/>
<h1 style={{
fontSize: 40,
fontWeight: "bold",
color: "#77932b",
marginBottom: "5%",
textShadow: "2px 2px 2px rgba(0, 0, 0, 0.2)",
textAlign: "center"
}}>Willkommen in deinem Vorlesungsplaner</h1>
<Login/>
</div>
)
}
+112
View File
@@ -0,0 +1,112 @@
import Button from "@/components/Button";
import React, {useEffect, useState} from "react";
import SemesterTile from "@/components/SemesterTile";
import InputForm from "@/components/InputForm";
import {useRouter} from "next/router";
import PopUp from "@/components/PopUp";
import Background from "@/components/Background";
export default function SemesterOverview(p)
{
async function getSemesters()
{
let urlTest = "http://localhost:8080/semester/all?sessionid=" + localStorage.getItem("sessionid");
await fetch(urlTest).then(response => response.json()).then(s => {
setEntries(s)
})
}
function onClickSemester(e, m)
{
if(m.target === m.currentTarget)
{
localStorage.setItem("currentsid", e.id)
}
}
function onClickNewSemester()
{
router.push("/createSemester");
}
function togglePopup()
{
if(modalDisplay === "block")
{
setModalDisplay("none");
}
else
{
setModalDisplay("block");
}
}
function funcButtonAbort()
{
togglePopup();
}
async function funcButtonDelete()
{
let id = localStorage.getItem("currentsid");
let url = "http://localhost:8080/semester?sessionid=" + localStorage.getItem("sessionid") + "&id=" + id;
await fetch(url, {
method: "DELETE"
});
togglePopup();
getSemesters();
}
async function funcButtonEdit(e, m)
{
localStorage.setItem("currentsid", e.id);
let semester = e;
let startYear = semester.startyear;
let endYear = semester.endyear;
let startDay = semester.startday;
let endDay = semester.endday;
//+1 because input field shows date in another way then the date object does
let startDate = new Date(startYear, 0, startDay + 1);
let endDate = new Date(endYear, 0, endDay + 1);
await router.push({
pathname: "/createSemester",
query: {courseName: semester.name, startDate: startDate.toISOString().slice(0, 10), endDate: endDate.toISOString().slice(0, 10)},
});
getSemesters();
}
useEffect(() => {
getSemesters();
}, [])
const [entries, setEntries] = useState([])
const [modalDisplay, setModalDisplay] = useState("none");
const [modalHint, setModalHint] = useState("");
const router = useRouter()
return (
<div className={"semester-overview"}>
<Background/>
{
entries.map(e => (<SemesterTile text={e.name} onClick={(f) => onClickSemester(e, f)} onButtonDeleteClick={() => {
localStorage.setItem("currentsid", e.id)
setModalHint(e.name + " Löschen?");
togglePopup();
}} onButtonEditClick={(m) => {
localStorage.setItem("currentsid", e.id)
funcButtonEdit(e, m);
}}/>))
}
<Button color={"#dcdcdc"} text={"+"} width={240} height={160} fontColor={"black"} fontSize={50}
onClick={() => onClickNewSemester()}/>
<PopUp hint={modalHint} text1={"Abbrechen"} text2={"Löschen"} displayState={modalDisplay}
function1={funcButtonAbort} function2={funcButtonDelete}/>
</div>
)
}
+35
View File
@@ -0,0 +1,35 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.A
{
border: 2px solid;
border-color: black;
border-radius: 20px;
margin: 2px;
background: linear-gradient(to bottom, #FFC1C1, #CD3333);
}
.Days
{
display: inline-grid;
grid-template-columns: repeat(7, 1fr);
grid-template-rows: repeat(5, 1fr);
height: 50%;
width: 100%;
}
.Down
{
border-radius: 20px;
display: inline-grid;
grid-column: auto;
height: 200%;
width: 20%;
}
+531
View File
@@ -0,0 +1,531 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
--foreground-rgb: 0, 0, 0;
--background-start-rgb: 255, 255, 255;
--background-end-rgb: 255, 255, 255;
}
body {
background-color: #f2f2f2;
}
.splash {
position: absolute;
border-radius: 70px;
background-color: #c77c0c;
z-index: -5;
}
/**
Page Layouts
*/
.normal-centered {
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.semester-overview {
height: 100vh;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
flex-wrap: wrap;
align-content: center;
gap: 10px;
}
body {
height: 100vh;
}
.box-shadow
{
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
}
.box-shadow-heavy
{
box-shadow: 0 0 10px rgba(0, 0, 0,1);
}
/*
Button
*/
.round-border {
border-radius: 10px;
border-width: 0;
}
.font-small {
font-size: 12px;
}
.font-middle {
font-size: 16px;
}
.font-big {
font-size: 22px;
}
.button {
background-color: #363636;
padding: 5px;
color: white;
}
.button:hover
{
filter: brightness(0.65);
}
.button:hover {
background-color: #585858;
}
/*
Step Progress Bar
*/
.step-container {
display: flex;
flex-direction: column;
align-items: center;
max-width: 400px;
}
.steps {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
gap: 20px;
width: 100%;
position: relative;
}
.step {
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
}
.steps .not-started {
/*background-image: linear-gradient(#b42121, #b44821);*/
background-color: #77932b;
}
.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;
}
.progress-bar {
position: absolute;
height: 8px;
background-color: #5d606e;
z-index: -1;
}
/*
weekSelector
*/
.dateElement {
display: flex;
margin-left: 20px;
margin-right: 20px;
height: 50px;
width: 200px;
align-items: center;
justify-content: center;
background-color: #0d52ce;
}
.weekSelector {
display: flex;
}
/*
Popup
*/
.modal-container {
z-index: 1;
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.5);
}
.modal {
height: 180px;
width: 300px;
border-radius: 10px;
background-color: rgb(255, 255, 255);
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: 20px;
animation-name: modalgrow;
animation-duration: 0.2s;
animation-play-state: running;
}
@keyframes modalgrow {
from
{
height: 90px;
width: 150px;
}
to
{
height: 180px;
width: 300px;
}
}
.modal p {
text-align: center;
pointer-events: none;
font-weight: bold;
font-size: 20px;
}
.modal div {
display: flex;
flex-direction: row;
width: 100%;
justify-content: end;
gap: 5px;
}
/*
Calender View
*/
.calender-container {
max-height: 600px;
overflow-y: scroll;
display: grid;
}
.calender-container::-webkit-scrollbar {
display: none;
}
.content {
grid-area: 1 / 1;
}
.overlay {
padding: 2px 0 0 0;
grid-area: 1 / 1;
pointer-events: none;
}
.no-pointer-events {
pointer-events: none;
}
.wochen-tag-container {
display: flex;
flex-direction: row;
justify-content: space-between;
height: 60px;
width: 1000px;
gap: 5px;
padding: 0 0 5px 0;
background-color: #363636;
}
.calender-view {
width: 1000px;
height: 2400px;
background-color: #363636;
display: flex;
flex-direction: row;
align-items: stretch;
justify-content: stretch;
gap: 5px;
user-select: none;
padding: 2px 0 0 0;
}
.calender-view .spalte {
border-radius: 10px;
width: 400px;
background-color: white;
display: grid;
padding: 0 3px;
grid-template-columns: 100%;
}
.wochen-tag-container .wochen-tag {
text-align: center;
background-color: #f80000;
width: 400px;
color: white;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
grid-row-start: 1;
grid-row-end: 4;
}
.entry {
border-radius: 10px;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 0 2px;
align-items: center;
cursor: move;
z-index: 10;
overflow: hidden;
margin-top: 1px;
margin-bottom: 1px;
}
.entry .resize-grab {
height: 5px;
cursor: ns-resize;
width: 100%;
}
.entry p {
color: white;
font-size: 16px;
cursor: default;
pointer-events: none;
}
/*
inputForm
*/
input {
border-width: 2px;
border-radius: 5px;
}
.courseNameInput {
width: 300px;
padding: 5px;
border: none;
background-color: white;
border-radius: 5px;
font-family: Arial, serif;
}
.selector
{
border-width: 0;
border-radius: 10px;
}
.semesterDateInput {
width: 150px;
padding: 5px;
border: none;
background-color: white;
border-radius: 5px;
font-family: Arial, serif;
}
.semesterDateLables, .semesterDateInputPair {
display: flex;
flex-direction: row;
justify-content: left;
padding: 0;
border: none;
background-color: white;
border-radius: 5px;
}
.inputFieldSeperator {
width: 40px;
text-align: center;
}
.semesterDateLable {
margin-right: 32px;
}
.semesterRangeInput {
margin-top: 50px;
}
.inputForm {
width: 600px;
height: 600px;
padding: 20px;
/*border: solid;*/
border-radius: 10px;
display: flex;
flex-direction: column;
background-color: white;
}
#buttons {
align-self: flex-end;
display: flex;
flex-direction: row;
align-items: flex-end;
gap: 10px;
}
.dozentSelector {
height: 350px;
/*border: solid;*/
margin-top: 20px;
width: 500px;
padding: 10px;
margin-bottom: 20px;
}
th {
text-align: left;
padding: 0 10px;
}
td {
padding: 0 10px;
}
/*
Login
*/
.login-container {
display: flex;
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;
height: 350px;
}
.input-bordered {
border: none;
border-radius: 5px;
}
.input {
padding: 5px;
border: none;
background-color: white;
border-radius: 5px;
font-size: 16px;
}
.input:focus
{
outline: none;
}
.placement {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: left;
}
.font-kinda-big {
font-size: 18px;
color: #777777;
font-weight: 500;
}
.font-big-fat {
font-size: 22px;
font-weight: bold;
}
.input-sm {
height: 2rem /* 32px */;
padding-left: 0.75rem /* 12px */;
padding-right: 0.75rem /* 12px */;
font-size: 0.875rem /* 14px */;
line-height: 2rem /* 32px */;
}
/**
SemesterTile
*/
.semester-tile {
background-color: #ffffff;
width: 240px;
height: 160px;
color: black;
border-radius: 10px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: 20px;
gap: 10px;
}
.semester-tile:hover {
background-color: #e1e1e1;
}
.semester-tile p {
pointer-events: none;
font-weight: bold;
font-size: 23px;
}
.semester-tile .step-container {
pointer-events: none;
}
+17
View File
@@ -0,0 +1,17 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./src/pages/**/*.{js,ts,jsx,tsx,mdx}',
'./src/components/**/*.{js,ts,jsx,tsx,mdx}',
'./src/app/**/*.{js,ts,jsx,tsx,mdx}',
],
theme: {
extend: {
backgroundImage: {
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
'gradient-conic':
'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
},
},
},
}
Binary file not shown.
+128029 -1379
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+27
View File
@@ -27,6 +27,12 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.1.214</version>
</dependency>
</dependencies>
<build>
@@ -35,6 +41,27 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<groupId>com.example</groupId>
<artifactId>example</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<file>${basedir}/H2JDBCDriver/h2-2.1.214.jar</file>
<generatePom>true</generatePom>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
@@ -5,6 +5,8 @@ import com.example.backend.anwprj.Days.Day;
import com.example.backend.anwprj.Entries.Entry;
import com.example.backend.anwprj.Semesters.Semester;
import com.example.backend.anwprj.Users.User;
import com.example.backend.anwprj.Week.Week;
import com.example.backend.anwprj.Module.Module;
import java.sql.*;
import java.util.ArrayList;
@@ -40,76 +42,83 @@ public class DataBaseHandler
st = connection.createStatement();
} catch (SQLException e)
{
e.printStackTrace();
System.out.println("No Connection!");
}
}
/*
TEMPPPPPP
/**
* WEEKS
*/
public static class Week
{
public int semesterid, id, weeknumber;
public Week(int id, int semesterid, int weeknumber)
{
this.semesterid = semesterid;
this.weeknumber = weeknumber;
this.id = id;
}
}
public Week addWeek(Week week)
{
try
{
st.executeUpdate("insert into weeks (semesterid, weeknumber) values (" + week.semesterid + ", " + week.weeknumber + ")");
return getWeek(week.semesterid, week.weeknumber);
st.executeUpdate("insert into weeks (semesterid, weeknumber) values (" + week.getSemesterid() + ", " + week.getWeeknumber() + ")");
return getWeek(week.getSemesterid(), week.getWeeknumber());
} catch (SQLException e)
{
throw new RuntimeException(e);
return null;
}
}
public Week getWeek(int id)
{
ResultSet rs = null;
try
{
rs = st.executeQuery("select * from weeks where id=" + id);
return resultSetToWeek(rs);
} catch (SQLException e)
{
return null;
}
}
public Week getWeek(int semesterid, int weeknumber)
{
try
{
ResultSet rs = st.executeQuery("select w.* from weeks w, semester s where s.id=" + semesterid + " and " + "w.weeknumber=" + weeknumber);
rs.next();
return new Week(rs.getInt("id"), rs.getInt("semesterid"), rs.getInt("weeknumber"));
} catch (SQLException e)
{
throw new RuntimeException(e);
ResultSet rs = st.executeQuery("select * from weeks where semesterid =" + semesterid + " and weeknumber=" + weeknumber);
return resultSetToWeek(rs);
}
catch (SQLException e)
{
return null;
}
}
public Week getWeekById(int id)
{
try
{
ResultSet rs = st.executeQuery("select * from weeks where id=" + id);
private Week resultSetToWeek(ResultSet rs) {
try {
rs.next();
return new Week(rs.getInt("id"), rs.getInt("semesterid"), rs.getInt("weeknumber"));
}
catch(Exception e)
{
return new Week(
rs.getInt("id"),
rs.getInt("semesterid"),
rs.getInt("weeknumber")
);
} catch (SQLException e) {
return null;
}
}
/*
TEMP END!!!!!!!!!!!!
*/
/**
DAYS
DAYS
*/
public Day addDay(Day day)
{
try
{
st.executeUpdate("insert into days (dayinweek, weekid) values (" + day.getDayinweek() + ", " + day.getWeekid() + ")");
Week w = getWeekById(day.getWeekid());
return getDay(day.getDayinweek(), w.weeknumber, w.semesterid);
st.executeUpdate("insert into days (dayinyear, yearnumber, semesterid) values (" + day.getDayinyear() + ", " + day.getYearnumber() + ", " + day.getSemesterid() + ")");
return getDay(day.getDayinyear(), day.getYearnumber(), day.getSemesterid());
} catch (SQLException e)
{
return null;
@@ -130,16 +139,11 @@ public class DataBaseHandler
}
}
public Day getDay(int dayinweek, int weeknumber, int semesterid)
public Day getDay(int dayinyear, int yearnumber, int semesterid)
{
try
{
ResultSet rs = st.executeQuery("select d.* from days d, weeks w, semester s " +
"where d.weekid = w.id and " +
"w.semesterid = s.id and " +
"d.dayinweek = " + dayinweek + " and " +
"w.weeknumber = " + weeknumber + " and " +
"s.id = " + semesterid);
ResultSet rs = st.executeQuery("select * from days where dayinyear =" + dayinyear + " and yearnumber =" + yearnumber + " and semesterid =" + semesterid);
return resultSetToDay(rs);
}
@@ -157,8 +161,9 @@ public class DataBaseHandler
return new Day(
rs.getInt("id"),
rs.getInt("dayinweek"),
rs.getInt("weekid")
rs.getInt("dayinyear"),
rs.getInt("yearnumber"),
rs.getInt("semesterid")
);
} catch (SQLException e)
{
@@ -167,7 +172,7 @@ public class DataBaseHandler
}
/**
ENTRIES
ENTRIES
*/
//method that returns all entries of a day based on the given parameters
public Entry[] getEntries(int dayinweek, int weeknumber, int semesterid, User user)
@@ -222,7 +227,7 @@ public class DataBaseHandler
}
/**
SEMESTER
SEMESTER
*/
//get a semester object by its name
public Semester getSemester(String name)
@@ -256,7 +261,7 @@ public class DataBaseHandler
{
try
{
st.executeUpdate("insert into SEMESTER (startweeknumber, endweeknumber, name, startyear, endyear) values (" + s.getStartweeknumber() + ", " + s.getEndweeknumber() + ", '" + s.getName() + "', " + s.getStartyear() + ", " + s.getEndyear() + ")");
st.executeUpdate("insert into SEMESTER (startday, endday, name, startyear, endyear) values (" + s.getStartday() + ", " + s.getEndday() + ", '" + s.getName() + "', " + s.getStartyear() + ", " + s.getEndyear() + ")");
return getSemester(s.getName());
} catch (Exception e)
@@ -265,12 +270,32 @@ public class DataBaseHandler
}
}
public Semester[] getAllSemesters()
{
try
{
ResultSet rs = st.executeQuery("select * from semester");
List<Semester> semestersList = new ArrayList<>();
Semester s = null;
while((s = resultSetToSemester(rs)) != null)
{
semestersList.add(s);
}
return semestersList.toArray(new Semester[0]);
}
catch(Exception e)
{
return null;
}
}
public Semester updateSemester(Semester semester)
{
try
{
st.executeUpdate("update semester set startweeknumber=" + semester.getStartweeknumber() + ", " +
"endweeknumber=" + semester.getEndweeknumber() + ", " +
st.executeUpdate("update semester set startday=" + semester.getStartday() + ", " +
"endday=" + semester.getEndday() + ", " +
"name='" + semester.getName() + "', " +
"startyear=" + semester.getStartyear() + ", " +
"endyear=" + semester.getEndyear() + " where id=" + semester.getId());
@@ -283,6 +308,20 @@ public class DataBaseHandler
}
}
public void deleteSemester(int id)
{
try
{
st.executeUpdate("DELETE FROM modules WHERE semesterId = " + id);
st.executeUpdate("delete from semester where id=" + id);
}
catch(Exception e)
{
}
}
public Semester resultSetToSemester(ResultSet rs)
{
try
@@ -290,8 +329,8 @@ public class DataBaseHandler
rs.next();
return new Semester(
rs.getInt("id"),
rs.getInt("startweeknumber"),
rs.getInt("endweeknumber"),
rs.getInt("startday"),
rs.getInt("endday"),
rs.getString("name"),
rs.getInt("startyear"),
rs.getInt("endyear")
@@ -304,8 +343,156 @@ public class DataBaseHandler
}
/**
USER
MODULE
*/
//get a module object by its id
public Module getModule(int id) {
try {
ResultSet rs = st.executeQuery("SELECT * FROM modules WHERE id=" + id);
return resultSetToModule(rs);
}
catch (Exception ex) {
return null;
}
}
public Module getModule(int userid, int semesterid, String name)
{
try
{
ResultSet rs = st.executeQuery("select * from modules where userid=" + userid + " and semesterid=" + semesterid + " and name='" + name + "'");
return resultSetToModule(rs);
}
catch (Exception e)
{
return null;
}
}
//get module objects by its semester and its lecturer
public Module[] getModules(int userid) {
try {
ResultSet rs = st.executeQuery("SELECT * FROM modules WHERE userid = " + userid);
List<Module> moduleList = new ArrayList<>();
Module m = null;
while((m = resultSetToModule(rs)) != null)
{
moduleList.add(m);
}
return moduleList.toArray(new Module[0]);
}
catch (Exception ex){
return null;
}
}
public Module addModule(Module m)
{
try {
st.executeUpdate("insert into modules (userid, semesterid, name, activated) " +
"Values (" + m.getUserid() + ", " + m.getSemesterId() + ", '" + m.getName() + "', " + m.getActivated() + ")");
return getModule(m.getUserid(), m.getSemesterId(), m.getName());
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
public Module[] getAllModules() {
try
{
ResultSet rs = st.executeQuery("SELECT * FROM modules");
List<Module> moduleList = new ArrayList<>();
Module m = null;
while((m = resultSetToModule(rs)) != null)
{
moduleList.add(m);
}
return moduleList.toArray(new Module[0]);
}
catch(Exception e)
{
return null;
}
}
public Module updateModule(Module m)
{
System.out.println(m.getActivated());
try {
st.executeUpdate("update modules set activated=" + m.getActivated() + " where userid=" + m.getUserid() + " and semesterid=" + m.getSemesterId() + " and name='" + m.getName() + "'");
return getModule(m.getUserid(), m.getSemesterId(), m.getName());
}
catch (SQLException ex) {
ex.printStackTrace();
return null;
}
}
public boolean deleteModule(int id)
{
try {
st.executeUpdate("DELETE FROM modules WHERE id=" + id);
return true;
}
catch(Exception ex) {
return false;
}
}
public Module resultSetToModule(ResultSet rs) {
try {
rs.next();
return new Module(
rs.getInt("id"),
rs.getInt("userid"),
rs.getInt("semesterid"),
rs.getString("name"),
rs.getInt("activated"));
}
catch (Exception ex) {
return null;
}
}
/**
USER
*/
//TODO: Nur nicht admins werden aktuell ausgegeben
public User[] getAllUsers()
{
try
{
ResultSet rs = st.executeQuery("select * from users where permission=0");
User u = null;
List<User> output = new ArrayList<>();
while((u = resultSetToUser(rs)) != null)
{
u.clearOutPassword();
output.add(u);
}
return output.toArray(new User[0]);
}
catch(Exception e)
{
return null;
}
}
//get a user object by mail and password from the database
public User getUser(String mail, String password)
{
@@ -449,6 +636,11 @@ public class DataBaseHandler
{
try
{
ResultSet rs = st.executeQuery("SELECT id FROM user WHERE mail='" + mail + "'");
rs.next();
int id = rs.getInt("id");
st.executeUpdate("DELETE FROM modules WHERE lecturerId = " + id);
st.executeUpdate("delete from users where mail='" + mail + "'");
return true;
}
@@ -3,28 +3,30 @@ package com.example.backend.anwprj.Days;
public class Day
{
private int id;
private int dayinweek;
private int weekid;
private int dayinyear;
private int yearnumber;
private int semesterid;
public Day(int id, int dayinweek, int weekid)
{
public Day(int id, int dayinyear, int yearnumber, int semesterid) {
this.id = id;
this.dayinweek = dayinweek;
this.weekid = weekid;
this.dayinyear = dayinyear;
this.yearnumber = yearnumber;
this.semesterid = semesterid;
}
public int getId()
{
public int getId() {
return id;
}
public int getDayinweek()
{
return dayinweek;
public int getDayinyear() {
return dayinyear;
}
public int getWeekid()
{
return weekid;
public int getYearnumber() {
return yearnumber;
}
public int getSemesterid() {
return semesterid;
}
}
@@ -0,0 +1,31 @@
package com.example.backend.anwprj.Module;
//module data class
public class Module {
private int id;
private int userid;
private int semesterid;
private String name;
private int activated;
public Module(int id, int userid, int semesterid, String name, int activated)
{
this.id = id;
this.userid = userid;
this.semesterid = semesterid;
this.name = name;
this.activated = activated;
}
public int getId() { return id; }
public int getUserid() { return userid; }
public int getSemesterId() { return semesterid; }
public String getName() { return name; }
public int getActivated() { return activated; }
}
@@ -4,49 +4,42 @@ package com.example.backend.anwprj.Semesters;
public class Semester
{
private int id;
private int startweeknumber;
private int endweeknumber;
private int startday;
private int endday;
private String name;
private int startyear;
private int endyear;
public Semester(int id, int startweeknumber, int endweeknumber, String name, int startyear, int endyear)
{
public Semester(int id, int startday, int endday, String name, int startyear, int endyear) {
this.id = id;
this.startweeknumber = startweeknumber;
this.endweeknumber = endweeknumber;
this.startday = startday;
this.endday = endday;
this.name = name;
this.startyear = startyear;
this.endyear = endyear;
}
public int getId()
{
public int getId() {
return id;
}
public int getStartweeknumber()
{
return startweeknumber;
public int getStartday() {
return startday;
}
public int getEndweeknumber()
{
return endweeknumber;
public int getEndday() {
return endday;
}
public String getName()
{
public String getName() {
return name;
}
public int getStartyear()
{
public int getStartyear() {
return startyear;
}
public int getEndyear()
{
public int getEndyear() {
return endyear;
}
}
@@ -63,6 +63,6 @@ public class UserSessionIDHandler
return generatedString;
}
return "";
return "failed";
}
}
@@ -0,0 +1,26 @@
package com.example.backend.anwprj.Week;
public class Week {
private int id;
private int semesterid;
private int weeknumber;
public Week(int id, int semesterid, int weeknumber) {
this.id = id;
this.semesterid = semesterid;
this.weeknumber = weeknumber;
}
public int getId() {
return id;
}
public int getSemesterid() {
return semesterid;
}
public int getWeeknumber() {
return weeknumber;
}
}
@@ -23,15 +23,15 @@ public class DayController
@GetMapping("/days")
public ResponseEntity<Day> getDay(
@RequestParam(name="sessionid") String sessionID,
@RequestParam(name="dayinweek") int dayInWeek,
@RequestParam(name="weeknumber") int weekNumber,
@RequestParam(name="dayinyear") int dayinyear,
@RequestParam(name="yearnumber") int yearnumber,
@RequestParam(name="semesterid") int semesterID)
{
User u = UserSessionIDHandler.getUserBySessionID(sessionID);
if(u != null)
{
Day d = db.getDay(dayInWeek, weekNumber, semesterID);
Day d = db.getDay(dayinyear, yearnumber, semesterID);
if (d != null)
{
@@ -0,0 +1,118 @@
package com.example.backend.anwprj.controller;
import com.example.backend.anwprj.DataBaseHandler;
import com.example.backend.anwprj.Module.Module;
import com.example.backend.anwprj.Users.User;
import com.example.backend.anwprj.Users.UserPermissions;
import com.example.backend.anwprj.Users.UserSessionIDHandler;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
public class ModuleController {
private final DataBaseHandler db;
{
db = DataBaseHandler.getInstance();
}
// @CrossOrigin
// @GetMapping("/module")
// public ResponseEntity<Module> getModule(
// @RequestParam(name="id") int id,
// @RequestParam(name="sessionid") String sessionID) {
//
// User user = UserSessionIDHandler.getUserBySessionID(sessionID);
//
// if (user != null){
// Module module = db.getModule(id);
// if(module != null) {
// return new ResponseEntity<>(module, HttpStatus.OK);
// }
//
// return new ResponseEntity<>(HttpStatus.NOT_FOUND);
// }
//
// return new ResponseEntity<>(HttpStatus.FORBIDDEN);
// }
@CrossOrigin
@GetMapping("/module/id")
public ResponseEntity<Module[]> getModules(
@RequestParam(name="sessionid") String sessionID) {
User user = UserSessionIDHandler.getUserBySessionID(sessionID);
if(user != null)
{
Module[] modules = db.getModules(user.getId());
if (modules != null) {
return new ResponseEntity<>(modules, HttpStatus.OK);
}
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
@CrossOrigin
@GetMapping("/module/all")
public ResponseEntity<Module[]> getModule(@RequestParam(name="sessionid") String sessionid) {
User u = UserSessionIDHandler.getUserBySessionID(sessionid);
if(u != null) {
if(u.getPermissions() == UserPermissions.admin.getValue()) {
return new ResponseEntity<>(db.getAllModules(), HttpStatus.OK);
}
}
return null;
}
@CrossOrigin
@PostMapping("/module")
public ResponseEntity<Module> addModule(@RequestBody Module module, @RequestParam(name="sessionid") String sessionID) {
User user = UserSessionIDHandler.getUserBySessionID(sessionID);
if(user.getPermissions() == UserPermissions.admin.getValue()) {
Module m = db.addModule(module);
if(m != null) {
return new ResponseEntity<>(m, HttpStatus.OK);
}
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
@CrossOrigin
@PutMapping("/module")
public ResponseEntity<Module> updateModule(@RequestBody Module module, @RequestParam(name="sessionid") String sessionID) {
User u = UserSessionIDHandler.getUserBySessionID(sessionID);
if(u != null && u.getPermissions() == UserPermissions.admin.getValue()) {
Module m = db.updateModule(module);
if(m != null) {
return new ResponseEntity<>(m, HttpStatus.OK);
}
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
@CrossOrigin
@DeleteMapping("/module")
public void deleteModule(@RequestParam(name="sessionid") String sessionid, @RequestParam(name="id") int id) {
User u = UserSessionIDHandler.getUserBySessionID(sessionid);
if(u != null && u.getPermissions() == UserPermissions.admin.getValue()) {
db.deleteModule(id);
}
}
}
@@ -9,6 +9,8 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
@RestController
public class SemesterController
{
@@ -31,10 +33,11 @@ public class SemesterController
Semester s = db.addSemester(semester);
if(s != null)
{
System.out.println(s.getStartday());
return new ResponseEntity<>(s, HttpStatus.OK);
}
return new ResponseEntity<>(s, HttpStatus.NOT_FOUND);
return new ResponseEntity<>(null, HttpStatus.NOT_FOUND);
}
@@ -82,6 +85,23 @@ public class SemesterController
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
@CrossOrigin
@GetMapping("/semester/all")
public ResponseEntity<Semester[]> getSemester(@RequestParam(name="sessionid") String sessionid)
{
User u = UserSessionIDHandler.getUserBySessionID(sessionid);
if(u != null)
{
if(u.getPermissions() == UserPermissions.admin.getValue())
{
return new ResponseEntity<>(db.getAllSemesters(), HttpStatus.OK);
}
}
return null;
}
@CrossOrigin
@PutMapping("/semester")
public ResponseEntity<Semester> updateSemester(@RequestBody Semester semester, @RequestParam(name="sessionid") String sessionID)
@@ -102,4 +122,16 @@ public class SemesterController
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
@CrossOrigin
@DeleteMapping("/semester")
public void deleteSemester(@RequestParam(name="sessionid") String sessionid, @RequestParam(name="id") int id)
{
User u = UserSessionIDHandler.getUserBySessionID(sessionid);
if(u != null && u.getPermissions() == UserPermissions.admin.getValue())
{
db.deleteSemester(id);
}
}
}
@@ -45,7 +45,7 @@ public class UserController {
@GetMapping("/users")
public ResponseEntity<String> login(@RequestParam(name = "mail") String mail, @RequestParam(name = "password") String password) {
//generate a session id for the user trying to login
boolean isEncrypted = true;
boolean isEncrypted = false;
if(isEncrypted)
{
RSA rsa = RSA.getInstance();
@@ -151,4 +151,19 @@ public class UserController {
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
@CrossOrigin
@GetMapping("/users/all")
public ResponseEntity<User[]> getAllUsers(@RequestParam(name = "sessionid") String sessionid)
{
User u = UserSessionIDHandler.getUserBySessionID(sessionid);
if(u != null && u.getPermissions() == UserPermissions.admin.getValue())
{
User[] output = db.getAllUsers();
return new ResponseEntity<>(output, HttpStatus.OK);
}
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
}
@@ -0,0 +1,60 @@
package com.example.backend.anwprj.controller;
import com.example.backend.anwprj.DataBaseHandler;
import com.example.backend.anwprj.Days.Day;
import com.example.backend.anwprj.Users.User;
import com.example.backend.anwprj.Users.UserPermissions;
import com.example.backend.anwprj.Users.UserSessionIDHandler;
import org.springframework.http.HttpStatus;
import com.example.backend.anwprj.Week.Week;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.sql.SQLException;
@RestController
public class WeekController
{
private DataBaseHandler db;
{
db = DataBaseHandler.getInstance();
}
@CrossOrigin
@GetMapping("/weeks")
public ResponseEntity<Week> getWeek(
@RequestParam(name="sessionid") String sessionID,
@RequestParam(name="semesterid") int semesterID,
@RequestParam(name="weeknumber") int weekNumber) throws SQLException {
User u = UserSessionIDHandler.getUserBySessionID(sessionID);
if(u != null)
{
Week w = db.getWeek(semesterID,weekNumber);
if(w != null)
{
return new ResponseEntity<>(w, HttpStatus.OK);
}
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
@CrossOrigin
@PostMapping("/weeks")
public ResponseEntity<Week> addWeek(@RequestBody Week week, @RequestParam(name="sessionid") String sessionID)
{
User u = UserSessionIDHandler.getUserBySessionID(sessionID);
if(u !=null && u.getPermissions() == UserPermissions.admin.getValue())
{
return new ResponseEntity<>(db.addWeek(week), HttpStatus.OK);
}
return new ResponseEntity<>(null, HttpStatus.FORBIDDEN);
}
}