Web-Technologien¶
Herzlich willkommen zur WebTech-Veranstaltung im Sommersemester 2025!
Grober Inhalt¶
In dieser Veranstaltung lernen Sie, was das World Wide Web ist und wie man eigene Webseiten und -anwendungen realisiert. Sie lernen die Protokolle und Sprachen http
, HTML
, CSS
, JavaScript
und TypeScript
kennen und machen sich mit Angular
, Node.js
und REST
vertraut. Zentrales Thema ist der sogenannte MEAN-Stack, d.h. Sie lernen die Entwicklung mithilfe von MongoDB, Express.js, Angular und Node.js kennen. Allerdings verwenden wir statt MongoDB
hier als Datenbank PostgreSQL
, um dichter an unserem Datenbankmodul im Studiengang zu sein. Der Stack heißt komischerweise trotzdem MEAN
(und nicht PEAN
).
Nachfolgend der vorläufige Wochenplan (wird eventuell angepasst).
Woche | Themen (Vorlesung) | Übung | Aufgabe (Stand) | Abgabe Übung bis | |
---|---|---|---|---|---|
1. | 07.-11.04.2025 | Einführung und Organisatorisches | Übung 0 | - | - |
2. | 14.-18.04.2025 | HTML | Übung 1 | Idee | 22.04.2025 |
3. | 21.-25.04.2025 | CSS (Eigenschaften und Selektoren | Übung 2 | - | 29.04.2025 |
4. | 28.-02.05.2025 | CSS (Grid) | Übung 3 | Konzept | 06.05.2025 |
5. | 05.-09.05.2025 | RWD (responsive Webdesign) | Übung 4 | - | 13.05.2025 |
6. | 12.-16.05.2025 | JavaScript (DOM) | Übung 5 | Datenmodell | 20.05.2025 |
7. | 19.-23.05.2025 | Angular (Einführung und Komponenten) | Übung 6 | Schnittstelle | 27.05.2025 |
8. | 26.-30.05.2025 | Templates (Bindings) | Übung 7 | Frontend (c+r) | 03.06.2025 |
9. | 02.-06.06.2025 | Angular (Routing und Services) | Übung 8 | Frontend (u+d) | 10.06.2025 |
10. | 09.-13.06.2025 | Node.js + Express (REST-Server MongoDB) | Übung 9 | Frontend fertig | 17.06.2025 |
11. | 16.-20.06.2025 | Angular (Anbindung ans Backend) | Übung 10 | Backend ( c ) | 24.06.2025 |
12. | 23.-27.06.2025 | Nutzerverwaltung und Material | - | Backend (r + u) | 01.07.2025 |
13. | 30.-04.07.2025 | Signals | - | Backend (d + fertig) | 08.07.2025 |
14. | 07.-11.07.2025 | Wiederholung | - | fertig stellen | 15.07.2025 |
15. | 14.-18.07.2025 | - | Fragen | - | - |
16. | 21.-25.07.2025 | - | Fragen | Abgabe 1.PZ 23.7.2025, Gespräche 24.7.2025 | |
Abgabe 2.PZ 23.9.2025, Gespräche 24.9.2025 (evtl. auch 25.9.2025) | - |
Die Erfahrung zeigt, dass die Mehrheit der Abgeben im 2.PZ erfolgt. Sie sollten allerdings bedenken, dass es zwischen dem 1. und dem 2.PZ keine Konsultationen gibt.
Organisatorisches¶
Zur erfolgreichen Durchführung der Veranstaltung müssen Sie die Übungen lösen und zu den jeweiligen Fristen per Git auf einen Server (GitHub oder GitLab) laden. Am Ende des Semesters ist eine Aufgabe abzugeben. Diese Aufgabe wird bewertet. Die Bewertung entspricht dann der Modulnote.
Hier sind die Übungen beschrieben, die Sie in jeder Woche ausführen sollen. Damit Sie dies erfolgreich erledigen können, ist jeweils angegeben, welche Themen Sie dafür durcharbeiten müssen. Das Durcharbeiten der jeweiligen Themen entspricht jeweils einer Vorlesung. Diese wird also selbständig durchgeführt.
Für die Kommunikation untereinander verwenden wir Slack. Dort können Sie alle inhaltlichen und organisatorischen Fragen stellen. Ich fände es gut, wenn ich dort möglichst wenig Fragen - zumindest die inhaltlichen - beantworten müsste, sondern eine Art internes Diskussionsforum entsteht. Es ist sehr gewünscht, dort Fragen zu stellen und noch mehr gewünscht, diese von Ihnen dort beantwortet zu sehen. Damit wäre allen geholfen und ich kann besser erkennen, wo noch Nachhol- bzw. Erläuterungsbedarf bei den meisten besteht.
Code aus der Vorlesung¶
Code aus HTML-Vorlesung
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Erste HTML-Seite</title>
</head>
<body>
<header>
<h1>Willkommen zu meiner ersten HTML-Seite!</h1>
<h2>etwas kleinere Überschrift</h2>
<h3>noch kleiner</h3>
<h6>am kleinsten</h6>
</header>
<main>
<p id="p1" class="rotHG gelbFont kursiv">hier ist ein Absatz. </p>
<a href="https://www.htw-berlin.de">HTW Berlin</a>
<a href="./html/seite1.html">Seite 1</a>
<img src="./images/fiw.jpg" alt="FIW-Logo" width="200" />
<!--
kommentar
kommentar
-->
<ul>
<li>erster Punkt</li>
<li>zweiter Punkt</li>
</ul>
<ol>
<li><h1>eins</h1></li>
<li>zwei</li>
<li>drei
<ul>
<li>Unterpunkt 1</li>
<li>Unterpunkt 2</li>
</ul>
</li>
<li>vier</li>
</ol>
<table>
<thead>
<tr>
<th>Spalte 1</th>
<th>Spalte 2</th>
<th>Spalte 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>eins eins</td>
<td>eins zwei</td>
<td>eins drei</td>
</tr>
<tr>
<td>zwei eins</td>
<td>zwei zwei</td>
<td>zwei drei</td>
</tr>
<tr>
<td>drei eins</td>
</tr>
<tr>
<td></td>
<td>vier zwei</td>
<td>vier drei</td>
</tr>
</tbody>
</table>
</main>
<footer>
<input type="text" />
<input type="password" />
<input type="checkbox" />
<input type="radio" />
<input type="button" value="Login" />
<input type="datetime-local" />
<input type="range" min="0" max="100" value="10" />
<input type="color">
</footer>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Seite</title>
</head>
<body>
<h4>Seite 1</h4>
<a href="../index.html">zurück zur index.html</a>
<img src="../images/htw.jpg" alt="HTW-Logo" width="200"/>
</body>
</html>
Code aus CSS-Vorlesung
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cascading</title>
<!-- Einbinden von CSS per externer css-Datei-->
<link rel="stylesheet" href="../styles/mystyles.css">
<style>
h1 {
text-transform: lowercase; /* CSS-Kommentare */
font-style: italic;
}
ol {
color: blue;
}
.fgYellow {
color: yellow;
}
/*
.bgBrown {
background-color: brown;
}
*/
.freigewaehlt {
font-size: 2em;
}
#firstH2 {
text-decoration: underline;
}
article p {
color: red;
}
section>p {
color: green;
}
a {
text-decoration: none;
}
a:hover {
background-color: blue;
color: white;
}
p::first-letter {
font-size: 3em;
}
</style>
</head>
<body>
<header>
<h1 style="background-color: rgb(50, 140, 140); color: rgb(249, 245, 245);">Cascading Style Sheets - CSS</h1>
</header>
<main>
<section>
<h2 id="firstH2">Section 1</h2>
<article>
<p class="fgYellow bgBrown freigewaehlt">Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quae.</p>
<p class="fgYellow bgBrown">Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quae.</p>
</article>
<article class="bgBrown">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quae.</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quae.</p>
</article>
<p>direktes Kind einer section</p>
</section>
<section>
<h2>Section 2</h2>
<article>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quae.</p>
hallo ballo
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quae.</p>
</article>
<article>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quae.</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quae.</p>
</article>
</section>
<ol>
<li>item 1
<ul>
<li>subitem</li>
<li>subitem</li>
<li>subitem</li>
</ul>
</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
<li>item 5</li>
</ol>
</main>
<aside>
<h2>Aside</h2>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quae.</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quae.</p>
</aside>
<footer>
<p>
<a href="./02_boxmodel.html">Boxmodel</a> ·
<a href="./03_rangfolge.html">Rangfolge</a>
<a href="https://www.htw-berlin.de">HTW Berlin</a>
</p>
</footer>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Box-Model</title>
<style>
* {
box-sizing: content-box; /* Standard */
}
img {
border: 1px solid black;
margin: 100px;
}
div {
width: 322px;
padding: 30px;
border: 5px solid gray;
margin: 0;
}
</style>
</head>
<body>
<header>
<h1>Box-Model</h1>
</header>
<main>
<img src="../images/fiw.jpg" alt="fiw logo" style="width:350px"/>
<div>Das FIW-Logo hat eine Breite von 350px (width:350px).
Der Inhalt dieser Box hat eine Breite von 320px.
Dazu kommt padding von 10px (auf beiden Seiten)
und ein Rahmen mit der Breite von 5px. Macht zusammen
350px.
</div>
</main>
<footer>
<p><a href="./01_cascading.html">Einführung</a> · <a href="./03_rangfolge.html">Rangfolge</a></p>
</footer>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Reihenfolge Selektoren</title>
<style>
a:link {
color: blue;
}
.link {
color: green;
}
#navigation a {
color: red;
}
li a {
color: magenta;
}
</style>
</head>
<body>
<header>
<h1>Reihenfolge Wirkung Selektoren</h1>
</header>
<main>
<h4>Test</h4>
<ul id="navigation">
<li><a href="./01_cascading.html" class="link">Einführung</a></li>
<li><a href="./02_boxmodel.html" class="link">Boxmodel</a></li>
</ul>
<h4>Prinzip</h4>
<dl>
<dt><em>Kategorie A</em></dt>
<dd>erhält den Wert 1, wenn CSS-Definitionen direkt im style-Attribut eines HTML-Elementes notiert sind</dd>
<dt><em>Kategorie B</em></dt>
<dd>erhält den Wert 1 bei Selektoren für Elemente mit id-Attributen</dd>
<dt><em>Kategorie C</em></dt>
<dd>Anzahl der von einem Selektor betroffenen Klassen und Pseudoklassen</dd>
<dt><em>Kategorie D</em></dt>
<dd>Anzahl der von einem Selektor betroffenen Elementnamen und Pseudo-Elemente</dd>
</dl>
<ol>
<li>Bei der Reihenfolge der Sortierung gilt: A > B > C > D, also z.B. 1 0 0 0 vor (größer als) 0 1 2 2.</li>
<li>Bei Gleichheit gilt die letzte Definition</li>
</ol>
</main>
<footer>
<p><a href="./02_boxmodel.html">Boxmodel</a> · <a href="./01_cascading.html">Einführung</a></p>
</footer>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>display</title>
<style>
p {
color: red;
}
p.ex1 {
display: none;
}
p.ex2 {
display: inline;
}
p.ex4 {
display: inline-block;
}
</style>
</head>
<body>
<header>
<nav>
<ul>
<li><a href="./02_boxmodel.html">Boxmodel</a></li>
<li><a href="./01_cascading.html">Cascading</a></li>
<li><a href="#">Display</a></li>
<li><a href="./05_grid">Grid</a></li>
</ul>
</nav>
</header>
<main>
<h1>The display Property</h1>
<h2>display: none:</h2>
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam semper diam at erat pulvinar, at pulvinar felis blandit. <p class="ex1">none!</p> Vestibulum volutpat tellus diam, consequat gravida libero rhoncus ut.
</div>
<h2>display: inline:</h2>
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam semper diam at erat pulvinar, at pulvinar felis blandit. <p class="ex2">inline!</p> Vestibulum volutpat tellus diam, consequat gravida libero rhoncus ut.
</div>
<h2>display: block:</h2>
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam semper diam at erat pulvinar, at pulvinar felis blandit. <p class="ex3">block!</p> Vestibulum volutpat tellus diam, consequat gravida libero rhoncus ut.
</div>
<h2>display: inline-block:</h2>
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam semper diam at erat pulvinar, at pulvinar felis blandit. <p class="ex4">neue Zeile und dann inline!</p> Vestibulum volutpat tellus diam, consequat gravida libero rhoncus ut.
</div>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/display?retiredLocale=de">Gibt noch sehr viele andere</a></li>
<li><a href="./index.html">Zurück</a></li>
</ul>
</main>
<footer>
</footer>
</body>
</html>
Code aus der Layout/RWD-Vorlesung
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS-Grid</title>
<style>
.orange {
background-color: orange;
opacity: 0.5;
border: 2px solid gray;
border-radius: 5px;
padding: 30px;
}
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(4, 1fr);
}
.one {
/* grid-column-start: 1;
grid-column-end: 3; */
grid-column: 1/3;
/* grid-row-start: 2;
grid-row-end: 4; */
grid-row: 2 / 4;
}
.two {
grid-column: 2;
grid-row: 2;
}
</style>
</head>
<body>
<header>
<h1>CSS-Grid</h1>
</header>
<main class="wrapper">
<div class="one orange">One</div>
<div class="two orange">Two</div>
<div class="three orange">Three</div>
<div class="four orange">Four</div>
<div class="five orange">Five</div>
<div class="six orange">Six</div>
</main>
<footer>
<p><a href="https://www.w3schools.com/cssref/pr_grid.php">grid</a></p>
<p><a href="https://www.w3schools.com/cssref/pr_grid-template-columns.php">grid-template-columns</a></p>
<p><a href="https://css-tricks.com/introduction-fr-css-unit/">fr - fraction</a></p>
<p><a href="./index.html">Zurück</a></p>
</footer>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div {
width: 100vw;
height: 100vh;
text-align: center;
background-color: red;
padding-top: 20%;
padding-bottom: 20%;
font-size: medium;
}
@media (min-width: 800px) {
div {
background-color: blue;
color: white;
}
}
@media (min-width: 1200px) {
div {
background-color: green;
color: yellow;
font-style: italic;
}
}
</style>
</head>
<body>
<div>Ändern Sie die Breite des Browsers, um den Effekt zu sehen.</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Responsive Webdesign</title>
<style>
.small {
display: grid;
grid-template-columns: 1fr;
column-gap: 2%;
row-gap: 2%;
}
@media (min-width: 800px) {
.medium {
display: grid;
grid-template-columns: 1fr 1fr;
}
}
@media (min-width: 1200px) {
.large {
display: grid;
grid-template-columns: repeat(4, 1fr);
}
}
</style>
</head>
<body>
<main class="small medium large">
<p>
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata
sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et
ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore
eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet,
</p>
<p>
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata
sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et
ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore
eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet,
</p>
<p>
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata
sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et
ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore
eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet,
</p>
<p>
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata
sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et
ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore
eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet,
</p>
</main>
</body>
</html>
Code aus der Bootstrap-Vorlesung
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-4Q6Gf2aSP4eDXB8Miphtr37CMZZQ5oXLH2yaXMJ2w8e2ZtHTl7GptT4jmndRuHDT" crossorigin="anonymous">
<title>Bootstrap</title>
<style>
.my-bg {
background-color: red;
}
</style>
</head>
<body>
<main role="main">
<div class="p-5 mb-4 bg-warning rounded-3">
<div class="container-fluid py-5">
<h1 class="display-5 fw-bold">Jetzt mit Bootstrap!</h1>
<p class="col-md-8 fs-4">Wir verwenden jetzt Bootstrap und schauen uns mal die Anwendung ein wenig genauer an. Das Grundprinzip besteht darin, HTML-Elementen Klassen zuzuordnen. </p>
<p><a class="btn btn-secondary btn-lg" href="https://getbootstrap.com/docs/5.3/examples/" role="button">Bootstrap Beispiele »</a></p>
</div>
</div>
<a class="btn btn-secondary my-bg">Hallo</a>
<div class="container">
<h2>Formular mit Validierung, ob Eingabe erfolgte (nur mit CSS - kein JavaScript!)</h2>
<p>Hier wird z.B. die Klasse <code>.was-validated</code> verwendet, um zu überprüfen, ob in den Textfeldern und der Checkbox eine Eingabe erfolgt ist.</p>
<form class="was-validated">
<div class="form-group">
<label for="uname">Username:</label>
<input type="text" class="form-control" id="uname" placeholder="Enter username" name="uname" required>
<div class="valid-feedback">Korrekt</div>
<div class="invalid-feedback">Feld bitte ausfüllen!</div>
</div>
<div class="form-group">
<label for="pwd">Password:</label>
<input type="password" class="form-control" id="pwd" placeholder="Enter password" name="pswd" required>
<div class="valid-feedback">Korrekt</div>
<div class="invalid-feedback">Feld bitte ausfüllen!</div>
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" name="remember" required> Ich habe die Datenschutzerklärung gelesen und stimme ihr zu.
<div class="valid-feedback">Korrekt</div>
<div class="invalid-feedback">Hier bitte bestätigen!</div>
</label>
</div>
<button type="submit" class="btn btn-primary">Login</button>
</form>
</div>
</main>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-4Q6Gf2aSP4eDXB8Miphtr37CMZZQ5oXLH2yaXMJ2w8e2ZtHTl7GptT4jmndRuHDT" crossorigin="anonymous">
<title>Grid</title>
<style>
div div {
padding: 10px;
}
</style>
</head>
<body>
<main class="container pt-5 ">
<h2>Wichtig ist, dass die Spaltenanzahl in einer Zeile 12 ergibt</h2>
<div class="row">
<div class="col-1" style="background-color: lightgrey;">
<h3>col-3</h3>
<p>Diesem <div> wurde die Klasse <code>col-3</code> zugewiesen</p>
</div>
<div class="col-6" style="background-color: darkgrey;">
<h3>col-4</h3>
<p>Diesem <div> wurde die Klasse <code>col-4</code> zugewiesen</p>
</div>
<div class="col-1" style="background-color: grey;">
<h3>col-5</h3>
<p>Diesem <div> wurde die Klasse <code>col-5</code> zugewiesen</p>
</div>
</div>
</main>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-4Q6Gf2aSP4eDXB8Miphtr37CMZZQ5oXLH2yaXMJ2w8e2ZtHTl7GptT4jmndRuHDT" crossorigin="anonymous">
<title>Grid</title>
<style>
div div {
padding: 10px;
margin-top: 5px;
margin-bottom: 5px;
}
.row div:nth-child(odd) {
background-color: lightgrey;
color: black;
}
.row div:nth-child(even) {
background-color: grey;
color: white;
}
</style>
</head>
<body>
<main class="container pt-5 ">
<h2>Jetzt responsiv - ändern Sie die Monitorbreite</h2>
<div class="row">
<div class="col-12 col-sm-6 col-md-4 col-lg-3 col-xl-2">
<ul>
<li>xs: <code>col-12</code> 1/1</li>
<li>sm: <code>col-sm-6</code> 1/2</li>
<li>md: <code>col-md-4</code> 1/3</li>
<li>lg: <code>col-lg-3</code> 1/4</li>
<li>xl: <code>col-xl-2</code> 1/6</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-4 col-lg-3 col-xl-2">
<ul>
<li>xs: <code>col-12</code> 1/1</li>
<li>sm: <code>col-sm-6</code> 2/2</li>
<li>md: <code>col-md-4</code> 2/3</li>
<li>lg: <code>col-lg-3</code> 2/4</li>
<li>xl: <code>col-xl-2</code> 2/6</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-4 col-lg-3 col-xl-2">
<ul>
<li>xs: <code>col-12</code> 1/1</li>
<li>sm: <code>col-sm-6</code> 1/2</li>
<li>md: <code>col-md-4</code> 3/3</li>
<li>lg: <code>col-lg-3</code> 3/4</li>
<li>xl: <code>col-xl-2</code> 3/6</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-4 col-lg-3 col-xl-2">
<ul>
<li>xs: <code>col-12</code> 1/1</li>
<li>sm: <code>col-sm-6</code> 2/2</li>
<li>md: <code>col-md-4</code> 1/3</li>
<li>lg: <code>col-lg-3</code> 4/4</li>
<li>xl: <code>col-xl-2</code> 4/6</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-4 col-lg-6 col-xl-2">
<ul>
<li>xs: <code>col-12</code> 1/1</li>
<li>sm: <code>col-sm-6</code> 1/2</li>
<li>md: <code>col-md-4</code> 2/3</li>
<li>lg: <code>col-lg-6</code> 1/2</li>
<li>xl: <code>col-xl-2</code> 5/6</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-4 col-lg-6 col-xl-2">
<ul>
<li>xs: <code>col-12</code> 1/1</li>
<li>sm: <code>col-sm-6</code> 2/2</li>
<li>md: <code>col-md-4</code> 3/3</li>
<li>lg: <code>col-lg-6</code> 2/2</li>
<li>xl: <code>col-xl-2</code> 6/6</li>
</ul>
</div>
</div>
</main>
</body>
</html>
Code aus der JavaScript-Vorlesung
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript</title>
</head>
<body>
<h1>JavaScript</h1>
<main>
<h4>Eigenschaften</h4>
<ul>
<li>Skriptsprache (aus Performanzgründen aber compiliert - z.B. V8 in Chrome, SpiderMonkey in Firefox)</li>
<li>dynamische Typisierung</li>
<li>keine unterschiedlichen Referenztypen</li>
<li>Vererbung durch <code>prototype</code></li>
<li>Objekteigenschaften und -funktionen können einfach dem Objekt hinzugefügt werden</li>
</ul>
<h4>Nützliche Links</h4>
<ul>
<li><a href="https://www.ecma-international.org/publications-and-standards/standards/ecma-262/">ECMA-262</a></li>
<li><a href="https://dom.spec.whatwg.org/">Document Object Model (DOM)</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide">JavaScript Guide</a></li>
<li><a href="https://www.w3schools.com/js/default.asp">JavaScript Tutorial</a></li>
<li><a href="https://learnjavascript.online/">Learn JavaScript</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference">JavaScript Reference</a></li>
</ul>
<h4>Ergebnisliste</h4>
<ul id="ulresult">
<li id="liresult1"></li>
</ul>
<input type="text" id="input" oninput="inputFunc()" onfocus="changeColor('yellow')" onblur="changeColor('white')" placeholder="Name"/>
<button type="button" onclick="helloFIW()">Klick Mich!</button>
</main>
<script>
function changeColor(color) {
let inputElement = document.querySelector('#input')
console.log('changeColor() : ', inputElement)
inputElement.style.backgroundColor = color
}
function inputFunc() {
let inputElement = document.getElementById('input')
console.log(inputElement.value)
let li1 = document.getElementById('liresult1')
li1.textContent = inputElement.value
li1.style.color = "red"
}
function helloFIW(name='World') {
const mark = "!"
console.log(`Hello ${name}${mark}`)
}
function test(a, b) {
return a + b;
}
let test2 = (a, b) => a + b
let test1 = test;
console.log("3+4=" + test(3,4));
console.log("3+4=" + test1(3,4));
console.log("3+4=" + test2(3,4));
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<title>Javascript</title>
<style>
div#output {
height: 300px;
}
</style>
</head>
<body class="container" onload="setBackgroundColorDiv()">
<h1>JavaScript-Objekte</h1>
<div id="output">
</div>
<div class="my-3">
<div class="row">
<div class="col-2">
<label for="hueIP" class="form-label">Hue (Farbton)</label>
</div>
<div class="col-2">
<input type="text" class="form-range" id="hueOP" value="50">
</div>
<div class="col-8">
<input type="range" class="form-range" min="0" max="360" id="hueIP" oninput="setNewColor()" value="50">
</div>
</div>
<div class="row">
<div class="col-2">
<label for="satIP" class="form-label">Saturation (Sättigung)</label>
</div>
<div class="col-2">
<input type="text" class="form-range" id="satOP" value="50">
</div>
<div class="col-8">
<input type="range" class="form-range" min="0" max="100" id="satIP" oninput="setNewColor()" value="50">
</div>
</div>
<div class="row">
<div class="col-2">
<label for="lightIP" class="form-label">Lightness (Helligkeit)</label>
</div>
<div class="col-2">
<input type="text" class="form-range" id="lightOP" value="50">
</div>
<div class="col-8">
<input type="range" class="form-range" min="0" max="100" id="lightIP" oninput="setNewColor()" value="50">
</div>
</div>
</div>
<script>
function setBackgroundColorDiv() {
let colorHSL = {
hue: 50,
saturation: 50,
lightness: 50,
getColor: () => `hsl(${colorHSL.hue}, ${colorHSL.saturation}%, ${colorHSL.lightness}%)`
}
let div = document.getElementById('output');
let cHSLJSON = JSON.stringify(colorHSL) ;
console.log('json : ', cHSLJSON);
let cHSLObj = JSON.parse(cHSLJSON);
console.log('objekt : ', cHSLObj);
div.style.backgroundColor = colorHSL.getColor();
}
function setNewColor() {
let colorHSL = {
hue: document.querySelector('#hueIP').value,
saturation: document.querySelector('#satIP').value,
lightness: document.querySelector('#lightIP').value,
getColor: () => `hsl(${colorHSL.hue}, ${colorHSL.saturation}%, ${colorHSL.lightness}%)`
}
document.getElementById('hueOP').value = colorHSL.hue;
document.getElementById('satOP').value = colorHSL.saturation;
document.getElementById('lightOP').value = colorHSL.lightness;
let div = document.getElementById('output');
div.style.backgroundColor = colorHSL.getColor();
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<title>Javascript</title>
<style>
div#output {
height: 300px;
}
</style>
</head>
<body class="container">
<h1>Formular auslesen</h1>
<h4>Kommentare</h4>
<form id="form" onsubmit="return false;">
<div class="form-floating mb-3">
<input type="text" class="form-control" id="input1" placeholder="Kommentar 1" onchange="fixeInput()" />
<label for="input1">Kommentar 1</label>
</div>
</form>
<script>
let nr = 1;
function fixeInput() {
/*
let curInputId = "input" + nr;
let curInputElement = document.getElementById(curInputId);
console.log(curInputElement.value);
curInputElement.disabled = "true";
let newDiv = document.createElement('div');
newDiv.classList.add("form-floating", "mb-3");
nr++;
let newInputId = "input"+nr;
let newInput = document.createElement('input');
newInput.classList.add("form-control");
newInput.placeholder = "Kommentar " + nr;
newInput.id = newInputId;
newInput.addEventListener("change", fixeInput);
let newLabel = document.createElement('label');
newLabel.for = newInputId;
newLabel.textContent = "Kommentar " + nr;
newDiv.appendChild(newInput);
newDiv.appendChild(newLabel);
let form = document.getElementById('form');
form.appendChild(newDiv);
newInput.focus();
*/
nr++;
let curInputId = "input" + nr;
let kommentar = "Kommentar " + nr;
let form = document.getElementById('form');
form.innerHTML += `
<div class="form-floating mb-3">
<input class="form-control" id=${curInputId} placeholder=${kommentar} onchange="fixeInput()" />
<label for=${curInputId}>${kommentar}</label>
</div> `
document.querySelector(`#${curInputId}`).focus()
}
</script>
</body>
</html>
Zugang zum Repo mit allen Code-Beispielen aus der Vorlesung
Die Vorlesungsbeispiele finden Sie unter https://gitlab.rz.htw-berlin.de/freiheit/wete25
- beim ersten Mal clonen:
git clone https://gitlab.rz.htw-berlin.de/freiheit/wete25.git
- dann immer nur noch pullen:
git pull
Semesteraufgabe¶
Am Ende des Kurses geben Sie eine Webanwendung ab. Diese wird bewertet und bildet die Modulnote für "WebTech" (es gibt also keine Klausur o.ä.). Überlegen Sie sich früh, was Sie implementieren wollen. Ihrer Kreativität sind keine Grenzen gesetzt. Es können 2 Studentinnen gemeinsam ein Projekt durchführen und abgeben. Sie erhalten dann (höchstwahrscheinlich) die gleiche Note. Es muss an den Commits erkennbar sein, welchen Anteil am Ergebnis jede der beiden Studentinnen hatte. Beachten Sie auch dringend die Regeln zum Umgang mit KI in den folgenden Mindestanforderungen!
Mindestanforderungen
Folgende Anforderungen werden an Ihr Projekt gestellt:
- das Frontend soll mit Angular entwickelt werden,
- das Backend mit Node.js,
- es soll eine Datenbank (MongoDB, kann aber auch MySQL oder PostgreSQL oder MariaDB - aber nicht Firebase) verwendet werden,
- es soll CRUD implementiert sein, d.h. Sie benötigen
- eine Komponente zur Erstellung und Speicherung eines Datenbankeintrages (Create),
- eine Komponente zur Änderung eines Datenbankeintrages (Update),
- eine Komponente zur Anzeige aller Datenbankeinträge (Read),
- eine Komponente zum Löschen eines Datenbankeintrages (Delete).
- wenn Sie die Anwendung alleine umsetzen, dann genügen 3 der 4 CRUD-Funktionalitäten
- wenn Sie die Anwendung zu zweit entwickeln, dann
- sollen alle 4 CRUD-Funktionalitäten umgesetzt werden und
- Login (Username + Passwort) und
- ich schaue mir die Commit-Hiostorie im Git genauer an, um sicherzugehen, dass beide Studentinnen gleich viel an der Anwendung mitentwickelt haben
Datenbankeinträge können Bücher, CDs, ToDos, Einkaufslisten, Vorlesungen, Kühlschrankinhalte usw. sein - wie gesagt, Ihrer Kreativität sind keine Grenzen gesetzt. Backend, Frontend und Datenbank müssen sich schon von dem unterscheiden, was wir in der Vorlesung und in der Übung gemacht haben (und somit vom Skript).
Die Anwendung soll in einem Git-Dienst (GitHub, GitLab, ...) verfügbar sein. Aus der Commit-Historie muss die fortlaufende Entwicklung Ihrer Anwendung sichtbar sein! Typisch sind 50-100 Commits über einen Zeitraum von mehreren Wochen (ohne Commits für die Readme).
Verwenden Sie ein CSS-Framework, wie z.B. Materialize, Bootstrap o.ä.! Ihre Anwendung soll "modern" aussehen und responsive sein.
Erstellen Sie eine informative (ausführliche) README-Datei (README.md
). Diese Datei sollte beinhalten:
- Eine Beschreibung Ihrer Anwendung. Am besten mit Screenshots, so dass sie Ihren Kommilitoninnen aus den nächsten Jahren hilft, ein Verständnis dafür zu entwickeln, was mögliche Semesteraufgaben sein können.
- Eine Anleitung zur Installation Ihrer Anwendung.
Super wäre es, wenn Sie die Datenbank, die Sie verwenden, per Skript vorausfüllen, d.h. es wäre schön, wenn zum Testen der Anwendung nur das Frontend und das Backend gestartet werden müssten und alles andere automatisch passieren würde. Super wäre es auch, wenn Sie Ihre Anwendung deployen würden.
Wenn alle Anforderungen kritiklos erfüllt sind, ist die Note schonmal eine 1.7
(bei leichter Kritik 2.0
). Es zeigte sich jedoch in den letzten Jahren, dass es wirklich herausragende Lösungen gab, die dann auch mit einer 1.3
und einige (wenige) sogar mit einer 1.0
bewertet werden konnten. Die Erwartungen für solche Lösungen lassen sich nicht formulieren, denn sie gehen ja "über die Erwartungen hinaus" ;-).
Nach Abgabe vereinbaren wir ein Online-Meeting, in dem Sie mir Ihre Anwendung nochmal zeigen können und ich Ihnen Fragen zu Ihrem Code stellen werde. Ist keine Prüfung, sondern eher ein fachliches Gespräch.
Beachten Sie folgende Regeln zum Umgang mit KI :
- Die Nutzung von KI bei der Erstellung der Semesterabgabe ist grundsätzlich erlaubt.
- In der
README.md
muss es ein Verzeichnis der verwendeten KI-Werkzeuge geben (stichpunktartig, wofür welche KI verwendet wurde). - Ihren Code müssen Sie erklären und einfache Änderungen und Ergänzungen durchführen können. Wenn Sie mehrere/alle Fragen im Gespräch nicht beantworten können, gilt die Arbeit als Täuschungsversuch.
Abgabe- und Gesprächstermine¶
Die Lösung für die Semesteraufgabe pushen Sie in Ihr Respository. In einem Gespräch führen Sie die Lösung vor und wir unterhalten uns über Ihre Lösung. Dafür stehen verschiedene Termine zur Verfügung.
-
- Prüfungszeitraum: 23.7.2025 Abgabe und 24.7.2025 Gespräch
-
- Püfungszeitraum: 23.9.2025 Abgabe und 24.9.2025 (evtl. auch 25.9.2025) Gespräch
Bitte tragen Sie sich in Moodle in den von Ihnen gewünschten Gesprächstermin ein! Wenn Sie im 1.PZ abgeben, tragen Sie sich im LSF zum ersten PZ zur Prüfung ein, ansonsten im 2.PZ.
Einige READMEs früherer Abgaben¶
AnimeWatchList deployed
🌸 AnimeWatchlist¶
AnimeWatchlist is a simple and intuitive platform for managing your personal anime collection. It helps you organize titles by watch status, search and filter your list, and easily update entries as your progress changes.
Designed for efficiency and clarity, it streamlines your tracking experience — whether you're planning, watching, pausing, or completing an anime.
📸 Screenshots¶
✨ Features¶
-
📋 Add, edit, and delete anime entries
-
📂 Sort and filter by title, category, season, status, and more
-
🔍 Search bar with real-time filtering
-
🔄 Status selection via dropdown (e.g., Watching, Planned, Paused, Dropped, Finished)
-
📊 Pagination and sorting support with Angular Material
-
💾 Backend integration for persistent data storage
⚙️ Installation¶
Prerequisites¶
Before you begin, make sure the following programs are installed:
- Git
- Node.js
- Angular CLI — Install it globally via:
Initialize Git Repository¶
If you don't have a Git repository yet, initialize it by running:
Clone Repositories
Clone both the backend and frontend repositories:
git clone https://gitlab.rz.htw-berlin.de/s0549057/anime-watchlist-backend.git
git clone https://gitlab.rz.htw-berlin.de/s0549057/anime-watchlist-frontend.git
Navigate to the backend directory and install all dependencies:
Create a.env
file in the root directory of the project with the following variables
PGUSER=your_username
PGHOST=psql.f4.htw-berlin.de
PGDATABASE=anime_watchlist
PGPASSWORD=your_password
PGPORT=5432
To start the backend:
Use--watch
for restarting the application automatically!
Install and Start Frontend
Navigate to the frontend directory and install all dependencies:
To start the frontend:
Access the Application
- Frontend: Open your browser and go to http://localhost:4200 to view the frontend.
🚀 Deployment¶
This application is deployed and accessible at:
👉 https://anime-watchlist-frontend.vercel.app
📦 Tech Stack¶
Technologies used in the project:
Client (Frontend): Angular CLI (for building a dynamic and responsive user interface as well managing the Angular application)
UI Components:
Angular Material (for modern and consistent UI elements)
Bootstrap (for responsive and mobile-first design)
Server (Backend): Node.js (used for the backend logic and API services)
🗺 Roadmap¶
The application can be expanded to allow the addition of anime movies alongside anime series. Unlike series, anime movies do not have seasons or episode counts; instead, they are defined by parts and release years. This distinction will be made using an Angular Material stepper. Depending on whether "Anime-Serie" or "Anime-Film" is selected in the first step, the corresponding form will be displayed in the second step.
Additionally, the application can be enhanced by implementing user registration and login functionality. Registered users will be able to add their own animes and manage their personalized list.
Another potential feature is the ability for users to upload images for each anime.
whispery - Dein digitales Tagebuch
whispery – Dein digitales Tagebuch ✨¶
whispery ist eine moderne Webanwendung zum Führen eines digitalen Tagebuchs.
Nutzer:innen können sich registrieren, anmelden und persönliche Einträge erstellen, bearbeiten oder löschen – begleitet von Emotionen in Emoji-Form.
Inhaltsverzeichnis¶
- Features
- Technologien
- Screenshots
- Installation & Nutzung
- Datenbankstruktur
- Deployment
- Bekannte Einschränkungen
- KI-Nutzung
- Autorin
Features¶
- 📓 Tagebucheinträge erstellen, anzeigen, bearbeiten und löschen (CRUD)
- 🔐 Registrierung & Login mit Passwort-Hashing (bcryptjs) und Token-Authentifizierung (JWT)
- 🔓 Logout mit Token-Entfernung
- 😊 Gefühle durch Emojis ausdrücken
- 📅 Datum wird automatisch pro Eintrag gespeichert
- 💾 Speicherung aller Einträge in einer MongoDB-Datenbank (MongoDB Atlas)
- 🪄 Nutzerfreundliche Popups bei Aktionen
- 🎨 Responsive Design mit Bootstrap
Technologien¶
- Frontend: Angular
- Backend: Node.js, Express
- Datenbank: MongoDB (Atlas)
- CSS-Framework: Bootstrap
- Deployment: Netlify (Frontend), Render (Backend)
Screenshots¶
Begrüßungsseite von whispery mit Möglichkeit zur Registrierung oder Login:¶
Das Formular zur Registrierung eines neuen Accounts:¶
Popup nach erfolgreicher Registrierung:¶
Fehlermeldung bei bereits registrierter E-Mail-Adresse:¶
Validierungshinweis für ein sicheres Passwort:¶
Fehlermeldung bei falscher E-Mail:¶
Fehlermeldung bei falschem Passwort:¶
Eingabemaske zur Erstellung eines neuen Tagebucheintrags:¶
Popup nach dem erfolgreichen Speichern eines neuen Eintrags:¶
Übersicht aller vorhandenen Tagebucheinträge:¶
Bearbeitungsansicht eines bestehenden Eintrags:¶
Popup nach erfolgreicher Bearbeitung eines Eintrags:¶
Bestätigungsdialog zum Löschen eines Eintrags:¶
Popup nach erfolgreichem Löschen eines Eintrags:¶
Popup nach dem Ausloggen des Users:¶
Installation & Nutzung¶
Voraussetzungen¶
- Node.js
- Angular CLI
- MongoDB Atlas Zugang
Projekt klonen¶
git clone https://github.com/Fuerueze/whispery-frontend.git
git clone https://github.com/Fuerueze/whispery-backend.git
Backend starten¶
Erstelle im Ordner whispery-backend
eine Datei namens .env
mit folgendem Inhalt:
Trage hier deine eigenen Werte ein!
MONGO_URI=<deine eigene MongoDB-Verbindungs-URL>
JWT_SECRET=<dein eigenes geheimes JWT-Passwort>
PORT=5001
Erklärungen zu den Variablen¶
MONGO_URI
: Deine eigene MongoDB-Verbindung, z. B. über MongoDB AtlasJWT_SECRET
: Ein beliebiger geheimer String, der zur Signierung der Tokens verwendet wirdPORT
: Optional – falls nicht gesetzt, wird automatisch5001
verwendet
Backend starten¶
Frontend starten¶
Anwendung im Browser öffnen:¶
Datenbankstruktur¶
Die folgende Struktur zeigt das Datenmodell der Anwendung:
Sammlung: users
¶
Sammlung: diaryentries
¶
{
"_id": "ObjectId",
"title": "string",
"content": "string",
"emoji": "string",
"date": "ISODate",
"user": "ObjectId (Referenz auf User)",
"__v": 0
}
Deployment¶
- Frontend (Netlify): https://whispery-tagebuch.netlify.app
- Backend (Render): https://whispery-backend.onrender.com
Bekannte Einschränkungen¶
Hinweis:
Im aktuellen Deployment über Netlify (Frontend) und Render (Backend) funktioniert die Registrierung und der Login derzeit nicht wie erwartet.
Es erfolgt keine Rückmeldung bei Klick auf "Registrieren" oder "Einloggen".
Lokal funktioniert alles korrekt.
Eine Lösung wird in Kürze nachgereicht.
KI-Nutzung¶
Tool | Zweck |
---|---|
ChatGPT | Planung, Codeoptimierung, README |
DeepSeek | Codeoptimierung |
VerseLogic
VerseLogic¶
VerseLogic ist eine Webanwendung zur Unterstützung des Songwriting-Prozesses.
Das Projekt verwendet:
- Frontend: Angular (Version 19.0.2)
- Backend: Node.js (Version 22.11.0)
Installation & Setup¶
Voraussetzungen¶
- Node.js
- Angular CLI (falls nicht installiert:
npm install -g @angular/cli
) - Git (zum Klonen des Repositories)
- PostgreSQL-Datenbank
Repository klonen¶
Befehl zum Klonen des Repositories:
Abhängigkeiten installieren¶
Frontend:
Backend:Anwendung starten¶
Datenbank initialisieren:¶
Bevor die Anwendung gestartet werden kann, muss eine .env-Datei erstellt werden, in der die Verbindungsdaten zu einer Datenbank hinterlegt sind.
Backend starten:¶
Tabellen erstellen:¶
Um die Tabellen zu initialisieren, rufe im Browser folgenden Link auf:
http://localhost:3000/init
Frontend starten:¶
Öffne ein neues Terminalfenster und führe folgende Befehle aus, um das Frontend zu starten.
Sobald das Backend und Frontend laufen, ist die Anwendung unter http://localhost:4200/
erreichbar.
Hauptfunktionen¶
- User-Authentifizierung: Registrierung & Login
- Song-Erstellung: Benutzer können neue Songs mit Namen & Sprache erstellen
- Song-Verwaltung:
- Songs auflisten, nach Name & Status filtern
- Songs löschen oder bearbeiten
- Song-Editor:
- Lyrics-Ansicht: Texte schreiben & speichern, inkl. Link zu einer Reimmaschine
- Tabs-Ansicht: Tabs erstellen und bearbeiten sowie Songstruktur hinzufügen
- Einstellungsansicht: Song-Details konfigurieren (Titel, Status, Sprache)
Screenshots¶
Login
Registrierung
Startseite
Songansicht - Lyrics
Songansicht - Tabs
Songansicht - Settings
Verwendete Tools¶
- ChatGPT: Unterstützung bei Verständnisfragen, Generierung von Lösungsansätzen
- Codepen: Entwicklung und Gestaltung der Login/Register-Seite
To-Do / Nächste mögliche Features¶
- KI-gestützte Song-Generierung
- Notenschreibsystem für andere Instrumente als Gitarre
- Möglichkeit, Audioinhalte hinzuzufügen
- Export der Lyrics & Tabs als PDF
TeilEs
WebTech2025¶
Was ist TeilEs?¶
Warum kaufen, wenn man es sich auch leihen kann!?
TeilEs ist eine Plattform auf der du ganz einfach mit anderen Dinge teilen kann.
Du sparst Geld, handelst nachhaltig und kommst mit anderen in Kontakt.
Suche und finde oder biete etwas an, was du gerne teilen möchtest. Natürlich alles kostenlos.
Inhalt¶
- Was ist TeilEs
- Installationsanleitung
- Screenshots der Anwendung
- Verwendung von KI-Werkzeugen
- API Dokumentation
- Weiteres
- Entwicklungsteam
Installationsanleitung¶
Voraussetzung und Technologien¶
- Node.js (verwendete Version 22.14.0)
- Angular CLI (verwendete Version 19.2.1) - Installation über npm install -g @angular/cli
- Bootstrap
- MongoDB (lokal oder als Cloud-Service) - Datenbank startet automatisch
Installation¶
1. Repository clonen:
2. Dependencies installieren
3. Backend starten
Backend läuft auf dem PORT 3000
4. Frontend starten
Frontend läuft auf dem PORT 4200
5. Anwendung im Browser starten
Screenshots der Anwendung¶
Home¶
Login¶
Produktliste mit aktiver Suche¶
Produktdetails mit Kontaktaufnahme des Anbieters¶
Chat | Benachrichtigung einer eingegangenen Nachricht¶
Übersicht der eigenen Anzeigen¶
Verwendung von KI-Werkzeugen und deren Einsatz¶
ChatGPT (OpenAI): - Unterstützung bei der Implementierung des Codes für den Chat sowie Bildupload (Bildupload nicht final implementiert) - zur Fehleranalyse, z.B. Chat: Namensanzeige des Chatpartner war fehlerhaft und um Tippfehler zu finden - Erstellung der GeoDaten (nicht final implementiert)
API Dokumentation¶
Dieses Projekt verwendet Swagger zur Dokumentation der API.
Lokal : http://localhost:3000/api-docs/#/
Weiteres¶
Verwendete Software:¶












Icons by Icons8: Visual Studio Code 2019, Mongo Db, Postman Inc, Figma, Affinity Designer, Affinity Photo, Trello, Google Docs, Zoom, Slack, Chat GPT
Fonts: Comfortaa https://fonts.google.com/specimen/Comfortaa¶
Bildnachweis: Teddy GR auf Unsplash¶
Game Vault
Game Vault👾¶
Description📜¶
Game Vault is your own personal database for storing games with your rating.
Key Features of Game Vault ⭐¶
- 🔍 Filter your games to easily find what you're looking for
- 🖥️ Responsive design for a seamless experience on desktops and laptops
- 🔐 Personal database – each user has their own secure game collection
How to Install 🚀¶
- Connect to the HTW Berlin network via OpenVPN
- In your terminal, run:
- Configurate your
.env
file:
Use of AI in This Project 🤖¶
We used Artificial Intelligence for the following points in this project: - Understanding concepts - Filter games by genres, publishers, platforms - Initializing Select2 - Building complex database structure with JOINS
Support 💬¶
If you have any questions, suggestions, or need assistance, please write us at damaris.liedtke@student.htw-berlin.de or julia.neubert@student.htw-berlin.de 🤝
Finanzverwaltung mit EasyFinance
Finanzverwaltung mit EasyFinance¶
Übersicht zur Webanwendung:¶
- Allgemeine Infos
- Projektstruktur
- Beschreibung der Anwendung mit Screenshots
- Datenmodell mit ER Diagramm und Konzept
- Technologien
- Verwendete KI
- Anleitung zur Installation
- Lizenz
- Kontakt
1. Allgemeine Infos: ¶
EasyFinance ist eine Webanwendung, die im Kurs Webtechnologien 2024/25 unter der Leitung von Prof. Freiheit von Maryam Mirza entwickelt wurde. Das Backend wurde mit Render deployed und ist unter https://backendwebtech.onrender.com erreichbar. Das Frontend ist mit Vercel deployed und die Anwendung ist unter https://frontend-webtech.vercel.app erreichbar. Hinweis: Weil das Backend über Render läuft und Render nach längerer Inaktivität einen Moment braucht, dauert es ca. 1min bis die Tabelle mit den Daten angezeigt wird.
Die Webanwendung wurde mit Angular, Node.js und PostgreSQL gebaut.
2. Projektstruktur ¶
Backend:
webtechnologien_backend/
│
├── controllers/
│ ├── kategorien.controller.js - Logik für CRUD-Operationen auf Kategorien
│ └── transaktion.controller.js - Logik für CRUD-Operationen auf Transaktionen
│
├── routes/
│ ├── kategorie.routes.js - Definiert die API-Routen für Kategorien
│ ├── transaktion.routes.js - Definiert die API-Routen für Transaktionen
│ └──root.js - Beispiel für eine einfache Route
│
│
├── db.js - Setzt die Verbindung zur PostgreSQL-Datenbank auf
├── initdb.js - Initialisiert die Datenbank und befüllt sie mit Beispieldaten
│
├── .env - Enthält Umgebungsvariablen, z. B. DB-Zugangsdaten (nicht hochladen!)
├── .gitignore - Definiert Dateien und Ordner, die von Git ignoriert werden sollen
├── package.json - Beschreibt das Projekt und die installierten Abhängigkeiten
├── package-lock.json - Speichert die exakte Version der Abhängigkeiten
└─ server.js - Startpunkt des Servers, konfiguriert Express und Bindet Routen ein
Frontend:
webtechnologien_frontend/
│
src/
│
├── app/ # Hauptordner für die Anwendungslogik
│ ├── header/ # Header-Komponente
│ │ ├── header.component.html
│ │ ├── header.component.ts
│ │ └── header.component.css
│ │
│ ├── footer/ # Footer-Komponente
│ │ ├── footer.component.html
│ │ ├── footer.component.ts
│ │ └── footer.component.css
│ │
│ ├── dialog-loeschen/ # Dialog zum Löschen
│ │ ├── dialog-loeschen.component.html
│ │ ├── dialog-loeschen.component.ts
│ │ └── dialog-loeschen.component.css
│ │
│ ├── main/ # Hauptkomponente
│ │ ├── main.component.html
│ │ ├── main.component.ts
│ │ └── main.component.css
│ │
│ ├── services/ # Dienste für Daten- und Backend-Logik
│ │ ├── backend-kategorien.service.ts # Service für Kategorien-Backend mit URL
│ │ ├── backend-transaktions.service.ts # Service für Transaktionen-Backend mit URL
│ │ ├── kategorien.ts
│ │ └── transaktion.ts
│ │
│ ├── transaktionen/ # Verwaltung und Anzeige von der Tabelle Transaktionen
│ │ ├── transaktionen.component.html
│ │ ├── transaktionen.component.ts
│ │ └── transaktionen.component.css
│ │
│ ├── transaction-dialog-hinzufuegen/ # Dialog zum Hinzufügen von Transaktionen
│ │ ├── transaction-dialog.component.html
│ │ ├── transaction-dialog.component.ts
│ │ └── transaction-dialog.component.css
│ │
│ ├── app.component.html # Root-Template der Anwendung
│ ├── app.component.ts # Root-Komponente der Anwendung
│ ├── app.component.css
│ ├── app.module.ts # Hauptmodul der Angular-Anwendung
│ ├── app.config.ts
│ └── app-routes.ts
│
│
├── styles.css # Globale CSS-Dateien der App
├── index.html # Startpunkt der Angular-Anwendung
├── main.ts # Einstiegspunkt/Bootstrap der Anwendung
├── .gitignore
├── angular.json # CLI-Konfiguration für das Projekt
├── package.json
├── package-lock.json
├── README.md
├── tsconfig.app.json
└── tsconfig.json
3. Beschreibung der Anwendung mit Screenshots: ¶
EasyFinance ist ein Prototyp, der dafür gedacht ist, sich leicht einen Überblick über die eigenen Finanzen machen zu können. Die Idee ist einfach Ausgaben und Einnahmen eintragen zu können und mit Wichtigkeitslabels unnötige Ausgaben direkt zu entdecken. So entsteht eine Übersicht wo leicht zu erkennen ist, wo eingespart werden könnte. Praktisch ist, dass hier auch Bar Einnahmen und Ausgaben erfasst werden können, was bei einem herkömmlichen Kontoauszug nicht erfasst wird.
Wenn die Anwendung weiterentwickelt werden sollte, wäre eine Registrierung und ein Login zum Datenschutz notwendig. Zudem müssten die Daten verschlüsselt werden.
3.1 Feature 1: Transaktion hinzufuegen¶
Um eine Transaktion hinzuzufügen klicke auf Transaktion hinzufügen. Es öffnet sich ein Dialog und du kannst alle benötigten Werte eingeben. Für die Transaktion gibt es ein Datepicker, sodass du schnell das passende Datum findest. Zudem gibt es Kategorien unter denen du per Drop Down auswählen kannst. In dem Drop Down Typ gibst du ein, ob es sich um eine Eingabe oder Ausgabe handelt. Ob es eine wichtige Ausgabe war, wird automatisch dann per Icon angezeigt, sobald du fertig bist. Du kannst die Transaktion auch abbrechen, falls du es dir anders überlegst.
Ein Hinweis im Dialogfenster erinnert daran, dass alle Felder ausgefüllt werden müssen. Erst wenn alle Felder in korrekter Form eingetragen wurden, kann eine Transaktion hinzugefügt werden. Das stellt sicher, dass keine fehlerhaften Transaktionen hinzugefügt werden.
Solange nicht alle Felder korrekt ausgefüllt sind, erscheint ein Hinweis.
Sobald alle Felder korrekt ausgefüllt wurden, verschwindet der Hinweis und es kann auf ok geklickt werden.
3.2 Feature 2: Transaktion löschen¶
Wenn mit der Maus über den Trash-Icon gehoovert wird, leuchtet das Icon in pinker Farbe auf. Sobald zum Löschen drauf geklickt wird, öffnet sich ein Dialog, sodass die Transaktion gelöscht werden kann. Der Dialog stellt sicher, dass nicht versehentlich etwas gelöscht wird.
3.3 Extra Feature:¶
Per Hinweis mit Ausrufezeichen-Icon lassen sich unnötige Ausgaben so schnell entdecken.
Damit erhält die Nutzer:in leicht einen Überblick, wo sie einfach einsparen könnte.
Ipad Ansicht mit Wichtigkeitslabel bei Sonnencreme
3.4 Responsives Design:¶
Das Design ist mit Bootstrap resposiv gestaltet, damit Transaktionen auch vom Smartphone oder Tablet verwaltet werden können. Damit die Übersicht der Transaktionen lesbar angezeigt wird, werden auf kleinen Bildschirmen nur die wichtigsten Spalten der Tabelle angezeigt. Die Kategorie und das Wichtigkeitslabel sind nur auf größeren Bildschirmen (ab Tabletgröße) sichtbar.
Transaktion hinzufügen - Ansicht auf dem Smartphone
Übersicht aller Transaktionen - Ansicht auf dem Smartphone
4. Datenmodell mit ER Diagramm und Konzept ¶
ER-Diagramm:¶
Konzept:¶
Die Webanwendung ist ein Prototyp zur Finanzverwaltung. Die eingegebenen Daten sind fiktiv und dienen nur zum Ausprobieren. Sie können von allen, die Zugriff auf die Seite haben verändert werden.
EasyFinance kann mit einer Registrierung und einem Login erweitert werden. Damit auch echte persönliche Daten eingegeben werden können, ist ein Login sowie eine Verschlüsselung der Datenbank zum Datenschutz notwendig.
Die Erweiterung könnte zudem noch eine weitere Bearbeiten-CRUD Operation sowie Filter für eine detaillierte Analyse beinhalten.
💻 5. Technologien: ¶
- Entwicklungsumgebung: IntelliJ IDEA 2024.2.4 (Ultimate Edition)
- Datenbank: PostgreSQL Version 16
- Backend: Node.js v22.11.0, Express 4.21.2, JavaScript
- Frontend: Angular Angular CLI version 19.2.0.
-
HTML, CSS, Typescript
-
Server für Backend und Datenbank: Render
- Server für Frontend: Vercel
🤖️ 6. Verwendete KI: ¶
- perplexity.ai
- Github Co-Pilot
- Backend: Controller und Routen teilweise mit Perplexity erstellt.
- Frontend: Teilweise mit Perplexity erstellt. Z.B. bei dem Datepicker.
- Frontend: Hinweis im Dialogfenster Transaktion hinzufügen mit Github Co-Pilot sowie Fehlermeldungen damit gefixt und Layout-Design.
🛠️ 7. Anleitung zur Installation: ¶
Wichtiger Hinweis¶
Die Datenabank wurde mit Render deployed und ist bis zum 06.04.2025 erreichbar. Danach wird sie von Server genommen. Es kann dann stattdessen die Datenbank von ocean der HTW verwendet werden. Dazu muss im Backend die .env Datei angepasst werden mit den Umgebungsvariablen und Anmeldeinformation der ocean Datenbank.
Das Backend ist unter https://backendwebtech.onrender.com erreichbar.
Die Frontend-Anwendung ist unter https://frontend-webtech.vercel.app erreichbar.
Voraussetzungen:¶
Node.js installiert haben. npm installiert haben.
Repository klonen (Frontend und Backend)¶
In das entsprechende Projektverzeichnis mit der Bash wechseln: Beispielweise:
Abhängigkeiten installieren¶
(Frontend und Backend)
VPN verbinden¶
Backend starten mit¶
Frontend starten mit¶
Sobald der Server läuft, öffne deinen Browser und gehe zuhttp://localhost:4200/
.
Die Applikation wird automatisch neu laden wenn du die source files veränderst.
Wenn du das Projekt nicht lokal starten, sondern direkt über den Browser aufrufen möchtest, dann gehe zu https://frontend-webtech.vercel.app.
Bauen¶
Um das Projekt zu deployen muss es vorher gebuildet werden. Das geht im Terminal mit:
Das kompiliert das Projekt und speichert die Build-Dateien im Verzeichnisdist/
.
Im dist Verzeichnis ist die fertige Version von der Webanwendung drin.
📝 8. Lizenz ¶
Dieses Projekt steht unter der MIT-Lizenz. Weitere Informationen findest du in der LICENSE-Datei.
Produktmanager
Produktmanager Frontend & Backend¶
Dieses Projekt ist eine Webanwendung zur Verwaltung von Produkten, die es ermöglicht, Produkte hinzuzufügen, zu aktualisieren, anzuzeigen und zu löschen. Es besteht aus einem Angular-Frontend und einem Node.js-Backend mit Verbindung zu einer PostgreSQL-Datenbank.
Funktionalitäten¶
Das Produktmanager-Projekt ermöglicht folgende Funktionen:
- Produkterstellung: Benutzer können neue Produkte mit Kategorien, Herstellerinformationen, Zutaten und Nährwertinformationen hinzufügen.
- Produktanzeige: Eine Liste aller vorhandenen Produkte wird angezeigt, mit Detailansichten für jedes Produkt.
- Produktbearbeitung: Bereits erstellte Produkte können aktualisiert werden.
- Produktlöschung: Benutzer können Produkte löschen.
- Datenverwaltung: Automatische Verbindung zu einer PostgreSQL-Datenbank.
- Benutzerfreundliche Oberfläche: Verwenden von Angular Material für ein ansprechendes und intuitives Design.
📦 Produktliste¶
Dies ist die Hauptansicht der Produktliste in der Anwendung.
➕ Produkt hinzufügen¶
Formular zum Hinzufügen eines neuen Produkts.
🔍 Produkt Details¶
Detailansicht eines spezifischen Produkts.
🔍 Produkt Bearbeiten¶
Detailansicht eines spezifischen Produkts.
Installation¶
Voraussetzungen¶
- Node.js (mindestens Version 16)
- npm (mit Node.js installiert)
- PostgreSQL Datenbank
Backend Setup¶
- Klone das Repository:
- Navigiere in das Backend-Verzeichnis:
- Installiere die Abhängigkeiten:
- Erstelle eine
.env
Datei im Backend-Verzeichnis mit folgendem Inhalt:
DB_USER=<DeinBenutzername>
DB_PASSWORD=<DeinPasswort>
DB_HOST=<DatenbankHost>
DB_NAME=produktmanager
DB_PORT=5432
- Starte den Server:
Frontend Setup¶
- Klone das Repository:
- Navigiere in das Frontend-Verzeichnis:
- Installiere die Abhängigkeiten:
- Starte das Frontend:
Deployment¶
Backend Deployment (Render)¶
- Stelle sicher, dass deine Umgebungsvariablen auf Render gesetzt sind (DB_USER, DB_PASSWORD, DB_HOST, DB_NAME, DB_PORT).
- Lade das Repository auf Render hoch und starte die Anwendung.
Frontend Deployment (Render)¶
- Stelle sicher, dass
angular.json
den richtigenoutputPath
(dist/frontend/browser
) definiert. - Stelle sicher, dass du
ng build
ausführst, bevor du deployst. - Lade die gebauten Dateien (
dist/frontend/browser
) auf Render hoch.
Verwendung¶
Das Frontend kann auf http://localhost:4200
aufgerufen werden. Das Backend läuft auf http://localhost:5000
.
Technologien¶
- Angular (Frontend)
- Angular Material
- Node.js (Backend)
- Express
- PostgreSQL
Quellen¶
- Wo ChatGPT unterstützt hat:
- Unterstützung bei der Erstellung von Angular-Komponenten.
- Hilfe beim Aufbau von Backend-Routen.
- Beratung bei der Verbindung mit der Datenbank.
- Unterstützung bei der Fehlerbehebung während des Deployments.
- Verbesserung der Projektstruktur und der Kommunikation zwischen Frontend und Backend.
- Optimierung der Datenverarbeitung und Validierung im Backend.
Viel Spaß beim Verwenden des Produktmanagers! 🚀