Calender View documentation

This commit is contained in:
brausjonas
2023-05-06 15:15:18 +02:00
parent af5849affc
commit 49a53f3d05
5 changed files with 251 additions and 177 deletions
+5
View File
@@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>
+2 -1
View File
@@ -53,7 +53,8 @@ export default function Button(p) {
color: fontColor, color: fontColor,
fontSize: font_size, fontSize: font_size,
minWidth: width, minWidth: width,
minHeight: height minHeight: height,
textAlign: "center",
}} }}
onClick={onClick}> onClick={onClick}>
{text} {text}
+243 -136
View File
@@ -2,178 +2,257 @@ import {useEffect, useState} from "react";
import {CalenderEntry} from "@/components/CalenderEntry"; import {CalenderEntry} from "@/components/CalenderEntry";
import Button from "@/components/Button"; import Button from "@/components/Button";
//all entries of the current week
let entries = {mo: [], tu: [], we: [], th: [], fr: [], sa: []} let entries = {mo: [], tu: [], we: [], th: [], fr: [], sa: []}
//a variable that saves the currently grabbed resize bar
let grabbed = null; let grabbed = null;
let grabbedUp = false; let grabbedUp = false;
//a variable the saves if the mouse is pressed or not
let mouseDown = false; let mouseDown = false;
//a variable that stores the currently grabbed element to move
let selectedElement = null; let selectedElement = null;
//move offset from top row to cursor
let selectedOffsetTop = 0; let selectedOffsetTop = 0;
//move offset from bottom row to cursor
let selectedOffsetBottom = 0; let selectedOffsetBottom = 0;
//the list, the grabbed element to move is currently in
let selectedListID = ""; let selectedListID = "";
//variable for the hight of one cell / row. Important for resizing the calender view
let cellHeight = 25; let cellHeight = 25;
export default function CalenderView(p) { export default function CalenderView(p)
{
//state to update the calender view
const [t, setT] = useState(false) const [t, setT] = useState(false)
useEffect(() => { //a blocker for the right click context menu
useEffect(() =>
{
window.addEventListener("contextmenu", (e) => (e.preventDefault())) window.addEventListener("contextmenu", (e) => (e.preventDefault()))
}) })
function mouse_move(e) { //function to delete an elemente and resize the corresponding list in the entries dictionary
if (mouseDown) { function delete_element(index, element)
let y_window = e.clientY; {
let y_target_offset = e.currentTarget.getBoundingClientRect().top; let currentList = entries[index];
let id = e.currentTarget.id; let temp = []
let row = Math.floor((y_window - y_target_offset) / cellHeight) + 1 for (let i = 0; i < currentList.length; i++)
{
if (element !== currentList[i])
{
temp.push(currentList[i]);
}
}
entries[index] = temp;
}
if (grabbed != null) { //resize a grabbed element to the row paramter
function size_grabbed(row)
{
if (row >= 0 && row <= 96)
{
if (grabbedUp)
{
if (row >= 0 && row <= 96) { if (row < grabbed.end_point - 1)
if (grabbedUp) { {
grabbed.start_point = row;
if (row < grabbed.end_point - 1) {
grabbed.start_point = row;
}
} else {
if (row > grabbed.start_point) {
grabbed.end_point = row + 1;
}
}
} }
} else if (selectedElement != null) { } else
if (selectedListID !== id) { {
let index = -1; if (row > grabbed.start_point)
let currentList = entries[selectedListID]; {
let temp = []; grabbed.end_point = row + 1;
for (let i = 0; i < currentList.length; i++) {
if (selectedElement !== currentList[i]) {
temp.push(currentList[i]);
}
}
entries[selectedListID] = temp;
entries[id].push(selectedElement);
selectedListID = id;
}
if (row - selectedOffsetTop > 0 && row + selectedOffsetBottom <= 97) {
selectedElement.start_point = row - selectedOffsetTop;
selectedElement.end_point = row + selectedOffsetBottom;
} }
} }
} }
}
//moves the selected element to row and list with id
function move_selected(row, id)
{
if (selectedListID !== id)
{
delete_element(selectedListID, selectedElement);
entries[id].push(selectedElement);
selectedListID = id;
}
if (row - selectedOffsetTop > 0 && row + selectedOffsetBottom <= 97)
{
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
//if a edge of an element was grabbed, resize it
if (grabbed != null)
{
size_grabbed(row);
//if a whole element was grabbed, move it
} else if (selectedElement != null)
{
move_selected(row, id);
}
}
//update the calender view
setT(!t); setT(!t);
} }
function mouse_up(e) { //routine when mouse was released
function mouse_up(e)
{
mouseDown = false; mouseDown = false;
let y_window = e.clientY;
let y_target_offset = e.currentTarget.getBoundingClientRect().top;
let row = Math.floor((y_window - y_target_offset) / cellHeight) + 1
let current_list = entries[e.currentTarget.id];
if (grabbed != null) { //remove all selected elements
if (grabbed != null)
{
grabbed = null; grabbed = null;
} }
if (selectedElement != null) { if (selectedElement != null)
{
selectedElement = null; selectedElement = null;
} }
setT(!t); setT(!t);
} }
function mouse_down(e) { //find the current element on row in the selected list (search_list)
function find_current(row, search_list)
let y_window = e.clientY; {
let y_target_offset = e.currentTarget.getBoundingClientRect().top; let current = null;
let row = Math.floor((y_window - y_target_offset) / cellHeight) + 1; for (let i = 0; i < search_list.length; i++)
let current_list = entries[e.currentTarget.id]; {
current = search_list[i];
if (e.button === 2) { if (current.start_point <= row && current.end_point >= row)
{
let current = null; break;
for (let i = 0; i < current_list.length; i++) {
current = current_list[i];
if (current.start_point <= row && current.end_point >= row) {
break;
}
current = null;
} }
current = null;
}
if (current != null) { return current;
let temp = [] }
for (let i = 0; i < current_list.length; i++) {
if (current_list[i] !== current) {
temp.push(current_list[i]);
}
}
entries[e.currentTarget.id] = temp; //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];
} else { for (let r = row; r < row + 2; r++)
{
for (let s = current.start_point; s < current.end_point; s++)
mouseDown = true; {
if (s === r)
if (e.target.id === "grab") { {
let entry = e.target.parentElement; free = false;
let rowStart = parseInt(window.getComputedStyle(entry).gridRowStart); break;
for (let i = 0; i < current_list.length; i++) {
let current = current_list[i];
if (current.start_point === row || current.end_point === row + 1) {
grabbed = current;
break;
}
}
if (row === rowStart) {
grabbedUp = true;
} else {
grabbedUp = false;
}
} else if (e.target.id === "entry") {
for (let i = 0; i < current_list.length; i++) {
let current = current_list[i];
if (current.start_point <= row && current.end_point >= row) {
selectedElement = current;
selectedListID = e.currentTarget.id;
break;
}
}
selectedOffsetTop = row - parseInt(window.getComputedStyle(e.target).gridRowStart);
selectedOffsetBottom = parseInt(window.getComputedStyle(e.target).gridRowEnd) - row;
} else {
if (row < 96) {
let free = true;
for (let i = 0; i < current_list.length; i++) {
let current = current_list[i];
for (let r = row; r < row + 2; r++) {
for (let s = current.start_point; s < current.end_point; s++) {
if (s === r) {
free = false;
break;
}
}
} }
} }
if (free) {
current_list.push(new CalenderEntry(row, row + 3));
setT(!t);
}
} }
} }
if (free)
{
list.push(new CalenderEntry(row, row + 3));
setT(!t);
}
} }
} }
function internal_to_time(internal) { //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 = find_current(row, current_list);
//check if the upper or lower resize bar was grabbed
if (row === rowStart)
{
grabbedUp = true;
} else
{
grabbedUp = false;
}
}
//if a whole element was clicked to move
else if (e.target.id === "entry")
{
selectedListID = e.currentTarget.id;
selectedElement = find_current(row, current_list);
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 -= 1
internal /= 4 internal /= 4
let integer = Math.floor(internal) let integer = Math.floor(internal)
@@ -184,13 +263,22 @@ export default function CalenderView(p) {
} }
let temp = [] let temp = []
for (let i = 2; i <= 96; i += 2) { for (let i = 2; i <= 96; i += 2)
{
temp.push(i); temp.push(i);
} }
//html of the calender view
return ( return (
<div style={{display: "flex", flexDirection: "row", justifyContent: "center", alignItems: "start"}}> // calender outer container, contains the calender view and resize buttons
<Button text={"-"} fontSize={25} onClick={() => {if(cellHeight - 5 >= 10) cellHeight -= 5; setT(!t);}} width={50} height={50}/> <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 id={t} style={{border: "5px solid #363636", borderRadius: 10}}>
<div style={{backgroundColor: "#363636"}}> <div style={{backgroundColor: "#363636"}}>
<div className={"wochen-tag-container"}> <div className={"wochen-tag-container"}>
@@ -202,14 +290,17 @@ export default function CalenderView(p) {
<div className={"wochen-tag font-big"}>Samstag</div> <div className={"wochen-tag font-big"}>Samstag</div>
</div> </div>
</div> </div>
{/*the viewport of the actual calender*/}
<div className={"calender-container"}> <div className={"calender-container"}>
<div className={"calender-view content"} style={{height: cellHeight * 96}}> {/*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} <div className={"spalte"} onMouseDown={mouse_down} onMouseUp={mouse_up} onMouseMove={mouse_move}
id={"mo"} style={{gridTemplateRows: `repeat(96, ${cellHeight}px)`}}> 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={{ {entries["mo"].map(d => (<div className={"entry"} style={{
width: "100%", width: "100%",
gridRowStart: d.start_point, gridRowStart: d.start_point,
@@ -217,16 +308,21 @@ export default function CalenderView(p) {
gridColumnStart: 0, gridColumnStart: 0,
gridColumnEnd: 0, gridColumnEnd: 0,
}} id={"entry"}> }} id={"entry"}>
{/*content of the entry / element*/}
{/*upper resize bar*/}
<div className={"resize-grab"} id={"grab"}></div> <div className={"resize-grab"} id={"grab"}></div>
<div style={{maxHeight: "60%"}} className={"no-pointer-events"}> <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>{internal_to_time(d.start_point) + " - " + internal_to_time(d.end_point)}</p>
<p>Moduel etc.</p> <p>Moduel etc.</p>
<p>Mehr Infos</p> <p>Mehr Infos</p>
<p>Raum</p> <p>Raum</p>
</div> </div>
{/*lower resize bar*/}
<div className={"resize-grab"} id={"grab"}></div> <div className={"resize-grab"} id={"grab"}></div>
</div>))} </div>))}
</div> </div>
{/*same as monday*/}
<div className={"spalte"} onMouseDown={mouse_down} onMouseUp={mouse_up} onMouseMove={mouse_move} <div className={"spalte"} onMouseDown={mouse_down} onMouseUp={mouse_up} onMouseMove={mouse_move}
id={"tu"} style={{gridTemplateRows: `repeat(96, ${cellHeight}px)`}}> id={"tu"} style={{gridTemplateRows: `repeat(96, ${cellHeight}px)`}}>
@@ -246,6 +342,7 @@ export default function CalenderView(p) {
<div className={"resize-grab"} id={"grab"}></div> <div className={"resize-grab"} id={"grab"}></div>
</div>))} </div>))}
</div> </div>
{/*same as monday*/}
<div className={"spalte"} onMouseDown={mouse_down} onMouseUp={mouse_up} onMouseMove={mouse_move} <div className={"spalte"} onMouseDown={mouse_down} onMouseUp={mouse_up} onMouseMove={mouse_move}
id={"we"} style={{gridTemplateRows: `repeat(96, ${cellHeight}px)`}}> id={"we"} style={{gridTemplateRows: `repeat(96, ${cellHeight}px)`}}>
@@ -266,6 +363,7 @@ export default function CalenderView(p) {
<div className={"resize-grab"} id={"grab"}></div> <div className={"resize-grab"} id={"grab"}></div>
</div>))} </div>))}
</div> </div>
{/*same as monday*/}
<div className={"spalte"} onMouseDown={mouse_down} onMouseUp={mouse_up} onMouseMove={mouse_move} <div className={"spalte"} onMouseDown={mouse_down} onMouseUp={mouse_up} onMouseMove={mouse_move}
id={"th"} style={{gridTemplateRows: `repeat(96, ${cellHeight}px)`}}> id={"th"} style={{gridTemplateRows: `repeat(96, ${cellHeight}px)`}}>
@@ -285,6 +383,7 @@ export default function CalenderView(p) {
<div className={"resize-grab"} id={"grab"}></div> <div className={"resize-grab"} id={"grab"}></div>
</div>))} </div>))}
</div> </div>
{/*same as monday*/}
<div className={"spalte"} onMouseDown={mouse_down} onMouseUp={mouse_up} onMouseMove={mouse_move} <div className={"spalte"} onMouseDown={mouse_down} onMouseUp={mouse_up} onMouseMove={mouse_move}
id={"fr"} style={{gridTemplateRows: `repeat(96, ${cellHeight}px)`}}> id={"fr"} style={{gridTemplateRows: `repeat(96, ${cellHeight}px)`}}>
@@ -304,6 +403,7 @@ export default function CalenderView(p) {
<div className={"resize-grab"} id={"grab"}></div> <div className={"resize-grab"} id={"grab"}></div>
</div>))} </div>))}
</div> </div>
{/*same as monday*/}
<div className={"spalte"} onMouseDown={mouse_down} onMouseUp={mouse_up} onMouseMove={mouse_move} <div className={"spalte"} onMouseDown={mouse_down} onMouseUp={mouse_up} onMouseMove={mouse_move}
id={"sa"} style={{gridTemplateRows: `repeat(96, ${cellHeight}px)`}}> id={"sa"} style={{gridTemplateRows: `repeat(96, ${cellHeight}px)`}}>
@@ -325,7 +425,9 @@ export default function CalenderView(p) {
</div> </div>
</div> </div>
{/*overlay with timeline*/}
<div className={"overlay"} style={{backgroundColor: "rgba(0, 0, 0, 0)"}}> <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={{ {temp.map(i => (<div style={{
width: "100%", width: "100%",
height: cellHeight * 2, height: cellHeight * 2,
@@ -338,42 +440,42 @@ export default function CalenderView(p) {
<p style={{ <p style={{
color: "gray", color: "gray",
marginTop: cellHeight -3, marginTop: cellHeight - 3,
marginRight: 120, marginRight: 120,
fontSize: 12, fontSize: 12,
textAlign: "center" textAlign: "center"
}}>{internal_to_time(i + 1)}</p> }}>{internal_to_time(i + 1)}</p>
<p style={{ <p style={{
color: "gray", color: "gray",
marginTop: cellHeight -3, marginTop: cellHeight - 3,
marginRight: 120, marginRight: 120,
fontSize: 12, fontSize: 12,
textAlign: "center" textAlign: "center"
}}>{internal_to_time(i + 1)}</p> }}>{internal_to_time(i + 1)}</p>
<p style={{ <p style={{
color: "gray", color: "gray",
marginTop: cellHeight -3, marginTop: cellHeight - 3,
marginRight: 120, marginRight: 120,
fontSize: 12, fontSize: 12,
textAlign: "center" textAlign: "center"
}}>{internal_to_time(i + 1)}</p> }}>{internal_to_time(i + 1)}</p>
<p style={{ <p style={{
color: "gray", color: "gray",
marginTop: cellHeight -3, marginTop: cellHeight - 3,
marginRight: 120, marginRight: 120,
fontSize: 12, fontSize: 12,
textAlign: "center" textAlign: "center"
}}>{internal_to_time(i + 1)}</p> }}>{internal_to_time(i + 1)}</p>
<p style={{ <p style={{
color: "gray", color: "gray",
marginTop: cellHeight -3, marginTop: cellHeight - 3,
marginRight: 120, marginRight: 120,
fontSize: 12, fontSize: 12,
textAlign: "center" textAlign: "center"
}}>{internal_to_time(i + 1)}</p> }}>{internal_to_time(i + 1)}</p>
<p style={{ <p style={{
color: "gray", color: "gray",
marginTop: cellHeight -3, marginTop: cellHeight - 3,
marginRight: 120, marginRight: 120,
fontSize: 12, fontSize: 12,
textAlign: "center" textAlign: "center"
@@ -384,7 +486,12 @@ export default function CalenderView(p) {
</div> </div>
</div> </div>
<Button text={"+"} fontSize={25} onClick={() => {cellHeight += 5; setT(!t)}} width={50} height={50}/> {/*the second resize button*/}
<Button text={"+"} fontSize={25} onClick={() =>
{
cellHeight += 5;
setT(!t)
}} width={50} height={50}/>
</div> </div>
) )
} }
-40
View File
@@ -19,46 +19,6 @@ export default function Home(p) {
<> <>
<div style={{height: 50}}></div> <div style={{height: 50}}></div>
<CalenderView/> <CalenderView/>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
<p>fdsfsdf</p>
</> </>
+1
View File
@@ -224,6 +224,7 @@ Calender View
height: 60px; height: 60px;
width: 1000px; width: 1000px;
gap: 5px; gap: 5px;
padding: 0 0 5px 0;
background-color: #363636; background-color: #363636;
} }