#import "../Helpers/code-snippets.typ": code

== Frontend
Das Frontend wurde mithilfe von Vue.js umgesetzt. Vue.js ist ein JavaScript-Framework, welches auf der Client-Seite läuft und für die Erstellung von Single-Page-Applications (SPA) verwendet wird. Vue.js ist relativ einfach zu erlernen und bietet viele Möglichkeiten, um eine moderne Webanwendung zu erstellen. Vue.js bietet eine sehr gute Dokumentation und eine grosse Community, was die Entwicklung von Webanwendungen erleichtert.

Um das CSS Styling zu vereinfachen, wurde das CSS-Framework Bootstrap verwendet. Bootstrap ist ein Open-Source-Framework, welches viele vorgefertigte CSS-Klassen und -Komponenten bietet.

Das Frontend besteht aus einer Startseite mit einer Liste der überwachten Websites, einer Seite zur Erstellung von neuen zu überwachenden Websites und einer Seite, auf welcher Details zu einer überwacheten Website angezeigt werden.
=== Startseite
#figure(
  image("../Images/03/start.png", width: 90%),
  caption: [ Startseite mit Liste überwachter Websites ]
)
Auf der Startseite sieht man alle überwachten Websites. Die Liste zeigt den benutzerdefinierten Namen der Website, die URL und den aktuellen Status (up/down) der Website an. Durch den Klick auf die Kachel einer Website kommt man zur Detailseite und durch den Klick auf das + Symbol kommt man zur Erstellungsseite.

Diese Seite ist im File `HomeView.vue` implementiert. Bei jedem Laden wird die Liste und der Status vom Backend abgerufen und angezeigt. Pro Website wird ein Kachel-Element erstellt, welches in `WebsiteItem.vue` implementiert ist.
=== Neue Website erstellen
#figure(
  image("../Images/03/create.png", width: 90%),
  caption: [ Neue zu überwachende Website erstellen ]
)
Auf dieser Seite kann durch Eingabe eines Namens und einer URL eine neue zu überwachende Website erstellt werden.

Das simple HTML Formular ist in `CreateView.vue` implementiert. Beim Absenden des Formulars wird ein POST-Request an das Backend gesendet, um die Website zu erstellen. Traefik verlangt dafür einen Basic Auth User und Passwort.
=== Website Details
#figure(
  image("../Images/03/details.png", width: 90%),
  caption: [ Details zu einer überwachten Website ]
)
Auf dieser Seite werden die Details einer überwachten Website angezeigt. Man sieht den Namen, eine History der letzten 30 Tage (oder weniger, falls die Website noch nicht so lange überwacht wird) und kann die Website löschen. In der History sieht man die prozentuale Verfügbarkeit und durchschnittliche Antwortzeit der Website aufgeteilt nach Kalendertagen. Je nach Verfügbarkeit wird die Zeile grün (100%), gelb (zwischen 99% und 100%) oder rot (unter 99%) eingefärbt.

Diese Seite ist im File `WebsiteView.vue` implementiert. Bei jedem Laden der Seite werden die letzen 43200 Monitoring-Einträge (30 Tage \* 24h \* 60 Minuten) vom Backend abgerufen. Danach werden die Daten nach Tag gruppiert und die prozentuale Verfügbarkeit und durchschnittliche Antwortzeit berechnet. Pro Tag wird dann eine Tabellenzeile erstellt, welche im Component `WebsiteDayItem.vue` implementiert ist.

Das Löschen einer Website wird durch einen DELETE-Request an das Backend durchgeführt. Traefik verlangt dafür einen Basic Auth User und Passwort.
=== Dockerfile
Beim Dockerfile haben wir uns für einen Multi-Stage-Build entschieden, dadurch erhalten wir ein viel kleineres Image und können den Vorteil von Vue.js, die ganze Applikation in den kleinen Ordner `dist` zu builden, optimal ausnutzen. In der ersten Stage wird zuerst das Node.js Image verwendet, um alle benötigten Node.js Modules zu installieren und die Applikation zu builden. In der zweiten und finalen Stage verwenden wir dann ein Nginx unprivileged Alpine Image, um das Image so klein wie möglich zu halten, aber doch noch gewisse Grundfunktionalitäten wie eine Shell zur Verfügung zu haben. Das unprivileged Image erhöht die Security, da der Hauptprozess nicht mit `root`, sondern mit dem eignen `nginx` User läuft. Wir kopieren den Inhalt des `dist` Ordners in den Nginx Webserver und konfigurieren den Webserver mit einer eigenen `nginx.conf` Datei. Zum Schluss wird der Port 8080 exposed und als Hauptprozess des Containers Nginx ohne Daemon gesetzt.
#figure(
  code(
    numbers: true,
    caption: "Dockerfile",
  )[```dockerfile
# build stage
FROM node:22.2.0-alpine as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# production stage
FROM nginxinc/nginx-unprivileged:1.26.0-alpine as production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 8080
CMD ["nginx", "-g", "daemon off;"]
```]
)