Merge branch '136-final-documentation-adjustments' into 'master'
Resolve "Final documentation adjustments" Closes #136 See merge request marcel.schwarz/2020ss-qbc-geofence-timetracking!121
This commit is contained in:
commit
e225fb0c43
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -1 +1,2 @@
|
|||||||
*.pptx filter=lfs diff=lfs merge=lfs -text
|
*.pptx filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.apk filter=lfs diff=lfs merge=lfs -text
|
||||||
|
@ -204,7 +204,7 @@
|
|||||||
Dieser Report zeigt eine Übersicht der geleisteten Arbeit jedes Gruppenmitglieds. Der vollständige Report ist separat angehängt. Dort kann jede Aktivität auf Issue Ebene genau nachvollzogen werden. Da lediglich die Issuenummern angegeben wurden, können die eigentlich dahinter liegenden Aufgaben auf GitLab\footnote{\url{https://gitlab.com/marcel.schwarz/2020ss-qbc-geofence-timetracking/-/issues?scope=all\&utf8=\%E2\%9C\%93\&state=all}} eingesehen werden.
|
Dieser Report zeigt eine Übersicht der geleisteten Arbeit jedes Gruppenmitglieds. Der vollständige Report ist separat angehängt. Dort kann jede Aktivität auf Issue Ebene genau nachvollzogen werden. Da lediglich die Issuenummern angegeben wurden, können die eigentlich dahinter liegenden Aufgaben auf GitLab\footnote{\url{https://gitlab.com/marcel.schwarz/2020ss-qbc-geofence-timetracking/-/issues?scope=all\&utf8=\%E2\%9C\%93\&state=all}} eingesehen werden.
|
||||||
|
|
||||||
\chapter{Projektfazit und Ausblick}
|
\chapter{Projektfazit und Ausblick}
|
||||||
Bei dem Projekt im Rahmen von Ubiquitous/Pervasive Computing konnten wir Bekanntes anwenden und Neues lernen. Wir alle konnten uns gut einbringen und zusammen auf unser gemeinsames Ziel hinarbeiten. Im Rückblick auf die vergangenen 5 Sprints lässt sich sagen, dass diese erfolgreich verlaufen sind. Die Verteilung der Aufgaben war gleichmäßig und funktionierte reibungslos. Die Idee des Projekts konnte vollständig umgesetzt werden, zudem konnten anfangs nicht geplante Features umgesetzt werden. Hierzu zählen z.B. tagesübergreifende Time Records. Wir alle sind mit dem Ergebnis unserer Arbeit zufrieden und können das Projekt als erfolgreich bezeichnen.\\
|
Bei dem Projekt im Rahmen von Ubiquitous/Pervasive Computing konnten wir Bekanntes anwenden und Neues lernen. Wir alle konnten uns gut einbringen und zusammen auf unser gemeinsames Ziel hinarbeiten. Im Rückblick auf die vergangenen fünf Sprints lässt sich sagen, dass diese erfolgreich verlaufen sind. Die Verteilung der Aufgaben war gleichmäßig und funktionierte reibungslos. Die Idee des Projekts konnte vollständig umgesetzt werden, zudem konnten anfangs nicht geplante Features umgesetzt werden. Hierzu zählen z.B. tagesübergreifende Time Records. Wir alle sind mit dem Ergebnis unserer Arbeit zufrieden und können das Projekt als erfolgreich bezeichnen.\\
|
||||||
|
|
||||||
Ebenso sehen wir ein großes Potential in der Weiterentwicklung unseres Endprodukts. Hier haben wir Ideen wie: Zuordnung der Benutzer in Gruppen, Benutzerprofile mit Daten über den Benutzer und dessen Tätigkeit oder auch Zuweisung von Kernarbeitszeit und Zeitrahmen, um Timetracking nur in einem festgelegten Zeitfenster zu erlauben. Mit ein paar Verbesserungen könnte unser Produkt von kleinen Unternehmen verwendet werden, die ein auf Vertrauen basiertes Zeitmeldesystem suchen.
|
Ebenso sehen wir ein großes Potential in der Weiterentwicklung unseres Endprodukts. Hier haben wir Ideen wie: Zuordnung der Benutzer in Gruppen, Benutzerprofile mit Daten über den Benutzer und dessen Tätigkeit oder auch Zuweisung von Kernarbeitszeit und Zeitrahmen, um Timetracking nur in einem festgelegten Zeitfenster zu erlauben. Mit ein paar Verbesserungen könnte unser Produkt von kleinen Unternehmen verwendet werden, die ein auf Vertrauen basiertes Zeitmeldesystem suchen.
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
\chapter{Android-App}
|
\chapter{Android-App}
|
||||||
\section{Technologiebeschreibung}
|
\section{Technologiebeschreibung}
|
||||||
\subsection{Android SDK}
|
\subsection{Android SDK}
|
||||||
Die Android-Entwicklung wurde, aufgrund der Ausgereiftheit und den Emulatoren, mit Android-Studio realisiert. Android-Studio verwaltet auch das SDK und unterstützt beim aktuell halten der Bibliotheken.\\
|
Die Android-Entwicklung wurde, aufgrund der Ausgereiftheit und den Emulatoren, mit Android-Studio realisiert. Android-Studio verwaltet auch das SDK und unterstützt beim aktuell Halten der Bibliotheken.\\
|
||||||
|
|
||||||
Das minimale API-Level, welches das Endgerät haben darf, wurde auf 23 "Marshmallow" festgelegt. Dadurch werden ca. 85\% der Geräte unterstützt und ist aktuell genug um gewisse Features, wie das neue Berechtigungssystem, zu unterstützen. Die Zielversion ist das aktuelle Android 10 mit API-Level 29. In dieser Version wurden erneut Berechtigungen geändert, wodurch im Code einige Anpassungen gemacht werden mussten (siehe: \ref{sec:Probleme})
|
Das minimale API-Level, welches das Endgerät haben darf, wurde auf 23 "Marshmallow" festgelegt. Dadurch werden ca. 85\% der Geräte unterstützt und ist aktuell genug um gewisse Features, wie das neue Berechtigungssystem, zu unterstützen. Die Zielversion ist das aktuelle Android 10 mit API-Level 29. In dieser Version wurden erneut Berechtigungen geändert, wodurch im Code einige Anpassungen gemacht werden mussten (siehe: \ref{sec:Probleme}).
|
||||||
|
|
||||||
\subsection{Kotlin}
|
\subsection{Kotlin}
|
||||||
Die Entscheidung fiel auf Kotlin als Programmiersprache, da die Sprache von Google für die Entwicklung von Android-Apps bevorzugt wird. Außerdem bietet dies die Gelegenheit, eine neue Programmiersprache zu erlernen. Dadurch musste jedoch viel Zeit investiert werden um zum einen die Sprache und zum anderen die Entwicklungsumgebung, sowie den Aufbau einer Android-App zu lernen. Dafür wurden zwei von insgesamt fünf Sprints eingeplant, weswegen die App nur die Grundfunktionen besitzt.
|
Die Entscheidung fiel auf Kotlin als Programmiersprache, da die Sprache von Google für die Entwicklung von Android-Apps bevorzugt wird. Außerdem bietet dies die Gelegenheit, eine neue Programmiersprache zu erlernen. Dadurch musste jedoch viel Zeit investiert werden um zum einen die Sprache und zum anderen die Entwicklungsumgebung, sowie den Aufbau einer Android-App zu lernen. Dafür wurden zwei von insgesamt fünf Sprints eingeplant, weswegen die App nur die Grundfunktionen besitzt.
|
||||||
@ -100,7 +100,7 @@ fun getUser(): Call<ValuesUser>
|
|||||||
@GET("accounts/search/findByUsername")
|
@GET("accounts/search/findByUsername")
|
||||||
fun getAccounts(@Query("username") username : String): Call<EmbeddedAccounts>
|
fun getAccounts(@Query("username") username : String): Call<EmbeddedAccounts>
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
Der Rückgabewert der Methoden ist immer vom Typ "Call". Wenn aus dem Body Werte gelesen werden sollen, muss eine Art Skelett-Klasse angelegt werden mit den relevanten Feldern. Die Klasse "ValuesUser" stellt Werte der Antwort bereit, wie z. B. den Vornamen.
|
Der Rückgabewert der Methoden ist immer vom Typ "Call". Wenn aus dem Body Werte gelesen werden sollen, muss eine Art Skelett-Klasse angelegt werden mit den, für die Anwendung relevanten, Feldern. Die Klasse "ValuesUser" stellt Werte der Antwort bereit, wie z. B. den Vornamen.
|
||||||
\begin{lstlisting}[language=Kotlin,caption=ValuesUser]
|
\begin{lstlisting}[language=Kotlin,caption=ValuesUser]
|
||||||
class ValuesUser(firstname: String) {
|
class ValuesUser(firstname: String) {
|
||||||
@SerializedName("firstname")
|
@SerializedName("firstname")
|
||||||
@ -227,13 +227,13 @@ context!!.getSharedPreferences("LOCATION", Context.MODE_PRIVATE)
|
|||||||
\begin{figure}[H]
|
\begin{figure}[H]
|
||||||
\centering
|
\centering
|
||||||
\includegraphics[width=0.4\linewidth]{img/android/btn_no_fence}
|
\includegraphics[width=0.4\linewidth]{img/android/btn_no_fence}
|
||||||
\caption{Nutzer hat noch keinen Geo-Daten}
|
\caption{Nutzer hat noch keine Geo-Daten}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
Um versehentliches Stoppen der Aufzeichnung zu verhindern, muss der Nutzer in einem Pop-Up-Dialog seine Aktion bestätigen.
|
Um versehentliches Stoppen der Aufzeichnung zu verhindern, muss der Nutzer in einem Pop-Up-Dialog seine Aktion bestätigen.
|
||||||
\begin{figure}[H]
|
\begin{figure}[H]
|
||||||
\centering
|
\centering
|
||||||
\includegraphics[width=0.4\linewidth]{img/android/confirm_stop}
|
\includegraphics[width=0.4\linewidth]{img/android/confirm_stop}
|
||||||
\caption{Bestätigungs Dialog zum stoppen}
|
\caption{Bestätigungsdialog zum stoppen}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
|
|
||||||
\section{Probleme und Lösungen}\label{sec:Probleme}
|
\section{Probleme und Lösungen}\label{sec:Probleme}
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
|
|
||||||
Die komplette Klasse ist durch die Lombok Integration sehr klein gehalten. Alles weitere wird durch Annotationen geregelt, einige Beispiele sind hier:
|
Die komplette Klasse ist durch die Lombok Integration sehr klein gehalten. Alles weitere wird durch Annotationen geregelt, einige Beispiele sind hier:
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item[] \textbf{@Entity} markiert die Klasse als Speicherbar in der Datenbank.
|
\item[] \textbf{@Entity} markiert die Klasse als speicherbar in der Datenbank.
|
||||||
\item[] \textbf{@ManyToOne} markiert das Attribut als Fremdschlüssenrelation aus einer anderen Tabelle.
|
\item[] \textbf{@ManyToOne} markiert das Attribut als Fremdschlüssenrelation aus einer anderen Tabelle.
|
||||||
\item[] \textbf{@Id} zeichnet den Primärschlüssel der Tabelle aus.
|
\item[] \textbf{@Id} zeichnet den Primärschlüssel der Tabelle aus.
|
||||||
\item[] \textbf{@Column} setzt spezielle Attribute für die Spalte in der Datenbank.
|
\item[] \textbf{@Column} setzt spezielle Attribute für die Spalte in der Datenbank.
|
||||||
@ -58,7 +58,7 @@
|
|||||||
\lstinputlisting[language=Java,caption=TimetrackAccount,firstline=11]{../backend/src/main/java/de/hft/geotime/entities/TimetrackAccount.java}
|
\lstinputlisting[language=Java,caption=TimetrackAccount,firstline=11]{../backend/src/main/java/de/hft/geotime/entities/TimetrackAccount.java}
|
||||||
|
|
||||||
\subsection{Sicherheit durch JWT}
|
\subsection{Sicherheit durch JWT}
|
||||||
Da wird die Web App im Laufe des Projekts auch öffentlich in Internet stellen mussten, war eine Art Authentifizierung so gut wie unumgänglich. Damit wir keine Probleme mit Session-Affinity haben, entschieden wir uns für eine Token-Based Authentifizierung. Bei der genauen Implementation handelt es sich hier um das Json Web Token, kurz JWT.
|
Da wird die Web App im Laufe des Projekts auch öffentlich in Internet stellen mussten, war eine Art Authentifizierung so gut wie unumgänglich. Damit wir keine Probleme mit Session-Affinity haben, entschieden wir uns für eine Token-Based Authentifizierung. Bei der genauen Implementation handelt es sich hier um das JSON Web Token, kurz JWT.
|
||||||
\begin{figure}[H]
|
\begin{figure}[H]
|
||||||
\centering
|
\centering
|
||||||
\includegraphics[width=\linewidth]{img/backend/jwt.io.png}
|
\includegraphics[width=\linewidth]{img/backend/jwt.io.png}
|
||||||
@ -106,7 +106,7 @@
|
|||||||
|
|
||||||
\lstinputlisting[language=Java,linerange={14-27,38-41,47-58},caption=RecordRepository,label=code:record-repository]{../backend/src/main/java/de/hft/geotime/repositories/RecordRepository.java}
|
\lstinputlisting[language=Java,linerange={14-27,38-41,47-58},caption=RecordRepository,label=code:record-repository]{../backend/src/main/java/de/hft/geotime/repositories/RecordRepository.java}
|
||||||
|
|
||||||
In diesem Repository befinden sich diverse verschiedene Methoden, wie Datenoperationen definiert werden können, ohne dass sie aktiv implementiert werden müssen. Es beginnt mit der Funktion "findAllByStartdateBetween". Dieser Name kann direkt als Java Hibernate Statement interpretiert werden und nimmt als Parameter zwei Datumsangaben entgegen und eine Page. Die zwei Datumsangaben werden aus dem Schlüsselwort "Between" abgeleitet. Damit es sich aber um echt vergleichbare Daten handelt, müssen diese nach einem bestimmten Schema geparsed werden. Dieses Schema ist in der "DateTimeFormat" Annotation angegeben. Als Rückgabe liefert diese Funktion dann eine Menge aller Einträge zwischen diesen Daten.\\
|
In diesem Repository befinden sich diverse verschiedene Methoden, wie Datenoperationen, die definiert werden können, ohne das sie aktiv implementiert werden müssen. Es beginnt mit der Funktion "findAllByStartdateBetween". Dieser Name kann direkt als Java Hibernate Statement interpretiert werden und nimmt als Parameter zwei Datumsangaben entgegen und eine Page. Die zwei Datumsangaben werden aus dem Schlüsselwort "Between" abgeleitet. Damit es sich aber um echt vergleichbare Daten handelt, müssen diese nach einem bestimmten Schema geparsed werden. Dieses Schema ist in der "DateTimeFormat" Annotation angegeben. Als Rückgabe liefert diese Funktion dann eine Menge aller Einträge zwischen diesen Daten.\\
|
||||||
|
|
||||||
Die nächste Funktion funktioniert nun ähnlich, nur dass dort über Eigenschaften mehrerer verlinkter Objekte gegangen werden kann. "findAllBy" ist wieder das selbe wie oben und zeigt an, dass eine Liste von Ergebnissen zurückgeliefert wird, aber "Account\_User\_Username" bedeutet nun folgendes: "Gehe zum Account des Records, dann zum User dieses Accounts und von diesem User dann den Username". Der gefundene Username wird dann mit dem Parameter der Funktion verglichen und die Ergebnisse entsprechend gefiltert. Weiter zeigt das "And" eine Verkettung eines weiteren Ausdrucks an. So können auch relativ komplexe Abfragen automatisch implementiert werden.\\
|
Die nächste Funktion funktioniert nun ähnlich, nur dass dort über Eigenschaften mehrerer verlinkter Objekte gegangen werden kann. "findAllBy" ist wieder das selbe wie oben und zeigt an, dass eine Liste von Ergebnissen zurückgeliefert wird, aber "Account\_User\_Username" bedeutet nun folgendes: "Gehe zum Account des Records, dann zum User dieses Accounts und von diesem User dann den Username". Der gefundene Username wird dann mit dem Parameter der Funktion verglichen und die Ergebnisse entsprechend gefiltert. Weiter zeigt das "And" eine Verkettung eines weiteren Ausdrucks an. So können auch relativ komplexe Abfragen automatisch implementiert werden.\\
|
||||||
|
|
||||||
@ -116,7 +116,7 @@
|
|||||||
|
|
||||||
Die Datei ist nicht vollständig abgedruckt, sondern nur ausschnittsweise, um die Grundkonzepte zu erläutern.
|
Die Datei ist nicht vollständig abgedruckt, sondern nur ausschnittsweise, um die Grundkonzepte zu erläutern.
|
||||||
\subsection{Projections}
|
\subsection{Projections}
|
||||||
Projections bieten nun noch weitere Möglichkeiten, Daten vor der Rückgabe noch zu transformieren und gegebenenfalls mit Zusatzdaten anzureichern. Eine Projektion ist ebenfalls durch ein Interface definiert und bring vor allem dann Vorteile, wenn mehrere Ressourcen gebündelt angefragt werden müssen, um beispielsweise eine Übersicht zu erstellen.
|
Projections bieten nun noch weitere Möglichkeiten, Daten vor der Rückgabe noch zu transformieren und gegebenenfalls mit Zusatzdaten anzureichern. Eine Projektion ist ebenfalls durch ein Interface definiert und bringt vor allem dann Vorteile, wenn mehrere Ressourcen gebündelt angefragt werden müssen, um beispielsweise eine Übersicht zu erstellen.
|
||||||
|
|
||||||
\lstinputlisting[language=Java,firstline=9,caption=RecordOverviewProjection,label=code:record-overview-projection]{../backend/src/main/java/de/hft/geotime/entities/projections/RecordOverviewProjection.java}
|
\lstinputlisting[language=Java,firstline=9,caption=RecordOverviewProjection,label=code:record-overview-projection]{../backend/src/main/java/de/hft/geotime/entities/projections/RecordOverviewProjection.java}
|
||||||
|
|
||||||
@ -300,7 +300,7 @@
|
|||||||
\item \textbf{"\_links"} zeigt weiterführende Links zu Ressourcen oder Informationen zum Paging an.
|
\item \textbf{"\_links"} zeigt weiterführende Links zu Ressourcen oder Informationen zum Paging an.
|
||||||
\item \textbf{"\_embedded"} enthält die Nutzdaten zur entsprechenden Ressource, aber auch weitere Einbettungen zu Sub-Ressourcen.
|
\item \textbf{"\_embedded"} enthält die Nutzdaten zur entsprechenden Ressource, aber auch weitere Einbettungen zu Sub-Ressourcen.
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
Zusätzlich dazu nutzt Spring bei der Generation der Repositories auch Teile der "Hypermedia as the Engine of Application State", kurz HATEOAS, Spezifikation. Das Listing \ref{code:main-route-api} zeigt hierfür den zusätzlichen Endpoint "profile". Unter diesem sind viele Spezifikationen zu finden, wie alle anderen Routen auf bestimmte Daten reagieren und auch antworten.
|
Zusätzlich dazu nutzt Spring bei der Generierung der Repositories auch Teile der "Hypermedia as the Engine of Application State", kurz HATEOAS, Spezifikation. Das Listing \ref{code:main-route-api} zeigt hierfür den zusätzlichen Endpoint "profile". Unter diesem sind viele Spezifikationen zu finden, wie alle anderen Routen auf bestimmte Daten reagieren und auch antworten.
|
||||||
|
|
||||||
Der "profile" Endpoint zeigt zusätzlich noch alle Projektionen an, die auf eine bestimmte Ressource angewendet werden können. Der Name der Projektion wird dann durch den URL-Parameter "projection=" angehängt.
|
Der "profile" Endpoint zeigt zusätzlich noch alle Projektionen an, die auf eine bestimmte Ressource angewendet werden können. Der Name der Projektion wird dann durch den URL-Parameter "projection=" angehängt.
|
||||||
|
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
\chapter{Entwicklungsumgebung}
|
\chapter{Entwicklungsumgebung}
|
||||||
Da wir uns für eine Full-Stack Application entschieden haben, war es wichtig, gleich zu Beginn die Entwicklungsumgebung so robust wie möglich zu gestalten. Weiter sollte das ganze Setup einfach unter Versionskontrolle gestellt werden können, um überall reproduzierbar zu sein.
|
Da wir uns für eine Full-Stack Application entschieden haben, war es wichtig, gleich zu Beginn die Entwicklungsumgebung so robust wie möglich zu gestalten. Weiter sollte das ganze Setup einfach unter Versionskontrolle gestellt werden können, um überall reproduzierbar zu sein.
|
||||||
\section{Versionsverwaltung}
|
\section{Versionsverwaltung}
|
||||||
Für die Versionsverwaltung haben wir das aktuell am weitesten verbreitete Tool Git benutzt. Dies war notwendig, damit wir unabhängig voneinander arbeiten können. Das Repository ist öffentlich auf der Plattform GitLab einsehbar. Die Adresse lautet \url{https://gitlab.com/marcel.schwarz/2020ss-qbc-geofence-timetracking}
|
Für die Versionsverwaltung haben wir das aktuell am weitesten verbreitete Tool Git benutzt. Dies war notwendig, damit wir unabhängig voneinander arbeiten können. Das Repository ist öffentlich auf der Plattform GitLab einsehbar. Die Adresse lautet \url{https://gitlab.com/marcel.schwarz/2020ss-qbc-geofence-timetracking}.
|
||||||
\subsection{GitLab}
|
\subsection{GitLab}
|
||||||
Die Entscheidung für GitLab fiel aber nicht ohne Grund. GitLab bietet auch sehr ausgeprägte Projektplanungsmöglichkeiten, die die Kollaboration sehr vereinfachen. Dazu zählen:
|
Die Entscheidung für GitLab fiel aber nicht ohne Grund. GitLab bietet auch sehr ausgeprägte Projektplanungsmöglichkeiten, die die Kollaboration sehr vereinfachen. Dazu zählen:
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item Issues. In den Issues werden alle Aufgaben für das Projekt abgelegt, die noch erledigt werden müssen oder eine weitere Betrachtung benötigen. Auch Bugfixes werden dort angelegt.
|
\item Issues. In den Issues werden alle Aufgaben für das Projekt abgelegt, die noch erledigt werden müssen oder eine weitere Betrachtung benötigen. Auch Bugfixes werden dort angelegt.
|
||||||
\item Issues werden in Merge Requests bearbeitet. Diese Merge Requests können genutzt werden, um über Code zu diskutieren und gegebenenfalls zu verbessern.
|
\item Issues werden in Merge Requests bearbeitet. Diese Merge Requests können genutzt werden, um über Code zu diskutieren und gegebenenfalls zu verbessern.
|
||||||
\item Code Ownership. Da wir die Teile der Anwendung nach Personen aufgeteilt haben, gibt es für jeden Teil der Anwendung mindestens ein Teammitglied, welches sich besonders gut mit diesen Themen auskennt. Diese Teammitglieder haben dadurch auch die Codeownership für diesen Teil des Codes.
|
\item Code-Ownership. Da wir die Teile der Anwendung nach Personen aufgeteilt haben, gibt es für jeden Teil der Anwendung mindestens ein Teammitglied, welches sich besonders gut mit diesen Themen auskennt. Diese Teammitglieder haben dadurch auch die Code-Ownership für diesen Teil des Codes.
|
||||||
\item Merge Request Approval. Wenn ein Issue mehrere Teile der Anwendung ändert, muss der jeweilige Codeowner dieses Teils dem Merge Request ebenfalls zustimmen. Ein Beispiel wäre hier die Implementation: "ein Datum im Frontend ändern", was aber zusätzlich die Anpassung des Datumsformates im Backend erfordert. Bei diesem Merge Request muss dann sowohl ein Codeowner des Frontends als auch des Backends zustimmen. Diese zusätzliche Sicherheitsschicht dient der Stabilität des Master Branches und der allgemeinen Codequalität.
|
\item Merge Request Approval. Wenn ein Issue mehrere Teile der Anwendung ändert, muss der jeweilige Codeowner dieses Teils dem Merge Request ebenfalls zustimmen. Ein Beispiel wäre hier die Implementation: "ein Datum im Frontend ändern", was aber zusätzlich die Anpassung des Datumsformates im Backend erfordert. Bei diesem Merge Request muss dann sowohl ein Codeowner des Frontends als auch des Backends zustimmen. Diese zusätzliche Sicherheitsschicht dient der Stabilität des Master-Branches und der allgemeinen Codequalität.
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
\subsection{Umgang mit Issues}
|
\subsection{Umgang mit Issues}
|
||||||
Die Issues sind die komplette Dokumentation der erledigten Aufgaben während des Projekts. In ihnen können alle Informationen abgelegt werden, die relevant sind. Beispiele sind hier Bugfixes, Features aber auch Definitionen von Design und Farbschema, die die Zustimmung mehrerer Gruppenmitglieder benötigen. Auch API Definitionen und Alignment-Meetings gehören bei uns dazu.
|
Die Issues sind die komplette Dokumentation der erledigten Aufgaben während des Projekts. In ihnen können alle Informationen abgelegt werden, die relevant sind. Beispiele sind hier Bugfixes, Features aber auch Definitionen von Design und Farbschema, die die Zustimmung mehrerer Gruppenmitglieder benötigen. Auch API-Definitionen und Alignment-Meetings gehören bei uns dazu.
|
||||||
|
|
||||||
Der Lebenszyklus eines Issues sieht wie folgt aus:
|
Der Lebenszyklus eines Issues sieht wie folgt aus:
|
||||||
\begin{enumerate}
|
\begin{enumerate}
|
||||||
@ -42,6 +42,6 @@
|
|||||||
\begin{lstlisting}[language=bash]
|
\begin{lstlisting}[language=bash]
|
||||||
docker-compose up --build -d
|
docker-compose up --build -d
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
im Rootverzeichnis der Anwendung ausgeführt werden. Es sei noch zu erwähnen, dass beim allerersten Start die Datenbankinitialisierung etwas länger brauchen kann und deshalb das backend mehrere Versuche braucht, bis die Verbindung aufgebaut werden kann.
|
im Root-Verzeichnis der Anwendung ausgeführt werden. Es sei noch zu erwähnen, dass beim allerersten Start die Datenbankinitialisierung etwas länger brauchen kann und deshalb das backend mehrere Versuche braucht, bis die Verbindung aufgebaut werden kann.
|
||||||
\section{Infrastruktur}
|
\section{Infrastruktur}
|
||||||
Die Infrastruktur, auf dem die Anwendung zur Zeit bereitgestellt ist, ist ein kleiner Linux Server bei Strato. Dieser Server hat ebenfalls eine Docker-Compose Installation und läuft auf Ubuntu 20.04 LTS. Gestartet wird es dann exakt gleich, wie im obigen Abschnitt erklärt. Natürlich ist Docker-Compose kein Deployment, welches in Produktion verwendet werden sollte, aber es reicht aktuell für unsere Zwecke aus. Nichts desto trotz ist die Anwendung aber auf eine sehr viel größere Skalierung bestens vorbereitet. Durch die Containerisierung ist unsere Anwendung komplett entkoppelt und könnte somit unabhängig skalieren. Einzig die SQL Datenbank müsste als Container entfernt werden und in ein eigenes Deployment verschoben werden.
|
Die Infrastruktur, auf dem die Anwendung zur Zeit bereitgestellt ist, ist ein kleiner Linux Server bei Strato. Dieser Server hat ebenfalls eine Docker-Compose Installation und läuft auf Ubuntu 20.04 LTS. Gestartet wird es dann exakt gleich, wie im obigen Abschnitt erklärt. Natürlich ist Docker-Compose kein Deployment, welches in Produktion verwendet werden sollte, aber es reicht aktuell für unsere Zwecke aus. Nichts desto trotz ist die Anwendung aber auf eine sehr viel größere Skalierung bestens vorbereitet. Durch die Containerisierung ist unsere Anwendung komplett entkoppelt und könnte somit unabhängig skalieren. Einzig die SQL Datenbank müsste als Container entfernt werden und in ein eigenes Deployment verschoben werden.
|
@ -1,7 +1,7 @@
|
|||||||
\chapter{Web-Frontend}
|
\chapter{Web-Frontend}
|
||||||
\section{Technologiebeschreibung}
|
\section{Technologiebeschreibung}
|
||||||
\subsection{Vue.js}
|
\subsection{Vue.js}
|
||||||
Vue.js\footnote{\url{https://vuejs.org/}} ist ein Javascript Framework, welches den Aufbau von Frontend Anwendungen erleichtert. Ein Hauptmerkmal hierbei ist die Kapselung der einzelnen Elemente in Komponenten, welche ihren eigenen HTML, Javascript und CSS code enthalten. Eine Komponente kann mehrere andere Komponenten einbinden, sowie diesen Daten mitgeben. Eingebundene Komponenten können an die übergeordnete Komponente Daten senden.
|
Vue.js\footnote{\url{https://vuejs.org/}} ist ein Javascript Framework, welches den Aufbau von Frontend-Anwendungen erleichtert. Ein Hauptmerkmal hierbei ist die Kapselung der einzelnen Elemente in Komponenten, welche ihren eigenen HTML, Javascript und CSS Code enthalten. Eine Komponente kann mehrere andere Komponenten einbinden, sowie diesen Daten mitgeben. Eingebundene Komponenten können an die übergeordnete Komponente Daten senden.
|
||||||
\subsection{Vuetify}
|
\subsection{Vuetify}
|
||||||
Vuetify\footnote{\url{https://vuetifyjs.com/de-DE/}} ist ein Designframework für Vue.js, das viele Elemente wie Menüleisten, Buttons und Dialogfenster bereitstellt. Ein bekanntes äquivalentes Framework ist Bootstrap. Das Designschema von Vuetify ist an Googles Material Design angelehnt. Nach Installation können die Elemente sehr einfach eingebunden und verwendet werden.
|
Vuetify\footnote{\url{https://vuetifyjs.com/de-DE/}} ist ein Designframework für Vue.js, das viele Elemente wie Menüleisten, Buttons und Dialogfenster bereitstellt. Ein bekanntes äquivalentes Framework ist Bootstrap. Das Designschema von Vuetify ist an Googles Material Design angelehnt. Nach Installation können die Elemente sehr einfach eingebunden und verwendet werden.
|
||||||
\section{Farbschema und Designsprache}
|
\section{Farbschema und Designsprache}
|
||||||
@ -68,7 +68,7 @@ export default {
|
|||||||
\subsection{Authentifizierung}
|
\subsection{Authentifizierung}
|
||||||
Wie schon im Backend beschrieben wurde, haben wir zur Authenfizierung JSON Web Token benutzt. Beim Login wurde das Token abgeholt und in den Sessionstorage geschrieben. Wir haben uns für den Sessionstorage entschieden, weil dieser beim Schließen des Browsertabs automatisch gelöscht wird. Der Logout Button entfernt ebenso das Token aus dem Storage.
|
Wie schon im Backend beschrieben wurde, haben wir zur Authenfizierung JSON Web Token benutzt. Beim Login wurde das Token abgeholt und in den Sessionstorage geschrieben. Wir haben uns für den Sessionstorage entschieden, weil dieser beim Schließen des Browsertabs automatisch gelöscht wird. Der Logout Button entfernt ebenso das Token aus dem Storage.
|
||||||
\subsection{Abrufen der Daten in Listen}
|
\subsection{Abrufen der Daten in Listen}
|
||||||
Zum Abrufen der Daten nutzen wir XMLHttpRequests. Diese geben vom Backend ein JSON Objekt zurück. Dies ermöglicht es uns, die JSON Funktionen von Java Script zu nutzen.
|
Zum Abrufen der Daten nutzen wir "XMLHttpRequests". Diese geben vom Backend ein JSON Objekt zurück. Dies ermöglicht es uns, die JSON Funktionen von Java Script zu nutzen.
|
||||||
\begin{lstlisting}[language=JavaScript,caption=Get Request]
|
\begin{lstlisting}[language=JavaScript,caption=Get Request]
|
||||||
var xhttp = new XMLHttpRequest();
|
var xhttp = new XMLHttpRequest();
|
||||||
var today;
|
var today;
|
||||||
@ -104,8 +104,8 @@ xhttp.send(JSONData);
|
|||||||
\item Kreisdiagramme
|
\item Kreisdiagramme
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item Verhältnis von Arbeitszeit zu Pausenzeit von allen Accounts des Benutzers.
|
\item Verhältnis von Arbeitszeit zu Pausenzeit von allen Accounts des Benutzers.
|
||||||
\item Verhältnis der Arbeitszeit je TimeTrack Account des Benutzers mit Angabe des Gesamtverdienstes.
|
\item Verhältnis der Arbeitszeit je Timetrack Account des Benutzers mit Angabe des Gesamtverdienstes.
|
||||||
\item Verhältnis des Verdienstes je TimeTrack Account des Benutzers.
|
\item Verhältnis des Verdienstes je Timetrack Account des Benutzers.
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
\item Säulendiagramme
|
\item Säulendiagramme
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
@ -166,7 +166,7 @@ export default {
|
|||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
|
||||||
Für die Kreisdiagramme war es notwendig, alle Zeiteinträge abzuholen, die Zeiten zu addieren und in die Datenfelder des Diagramms zu schreiben. Bei dem Kreisdiagramm, das die Accounts darstellt, war es notwendig, die Timetrack-Accounts des Benutzers abzufragen und für jeden ein Feld der addierten Zeit anzulegen und den Lohn in einer Variablen abzulegen.
|
Für die Kreisdiagramme war es notwendig, alle Zeiteinträge abzuholen, die Zeiten zu addieren und in die Datenfelder des Diagramms zu schreiben. Bei dem Kreisdiagramm, das die Accounts darstellt, war es notwendig, die Timetrack-Accounts des Benutzers abzufragen und für jeden ein Feld der addierten Zeit anzulegen und den Lohn in einer Variablen abzulegen.
|
||||||
\begin{lstlisting}[language=JavaScript, caption=Zuordnung der Zeit zu den TimeTrack Accounts]
|
\begin{lstlisting}[language=JavaScript, caption=Zuordnung der Zeit zu den Timetrack Accounts]
|
||||||
for (let index = 0; index < records.length; index++){
|
for (let index = 0; index < records.length; index++){
|
||||||
var record = records[index];
|
var record = records[index];
|
||||||
for (let indexAccs = 0; indexAccs < this.chartOptions.labels.length; indexAccs++) {
|
for (let indexAccs = 0; indexAccs < this.chartOptions.labels.length; indexAccs++) {
|
||||||
@ -200,7 +200,7 @@ for (let index = 0; index < records.length; index++){
|
|||||||
\end{figure}
|
\end{figure}
|
||||||
|
|
||||||
\subsection{Time Records}
|
\subsection{Time Records}
|
||||||
Auf der Time Records Seite kann man die eigenen Arbeitszeiten einsehen. Außerdem hat man die Möglichkeit, fehlerhafte Einträge zu verbessern oder zu löschen, indem man über den Stift hovert. Neue Einträge können erstellen werden, indem man den "+"-Button am Ende der Seite anklickt.
|
Auf der Time Records Seite kann man die eigenen Arbeitszeiten einsehen. Außerdem hat man die Möglichkeit, fehlerhafte Einträge zu verbessern oder zu löschen, indem man über den Stift hovert. Neue Einträge können erstellt werden, indem man den "+"-Button am Ende der Seite anklickt.
|
||||||
\begin{figure}[H]
|
\begin{figure}[H]
|
||||||
\centering
|
\centering
|
||||||
\includegraphics[width=\linewidth]{img/frontend/timerecords.PNG}
|
\includegraphics[width=\linewidth]{img/frontend/timerecords.PNG}
|
||||||
@ -238,11 +238,11 @@ for (let index = 0; index < records.length; index++){
|
|||||||
\begin{figure}[H]
|
\begin{figure}[H]
|
||||||
\centering
|
\centering
|
||||||
\includegraphics[width=\linewidth/2]{img/frontend/verwaltung.PNG}
|
\includegraphics[width=\linewidth/2]{img/frontend/verwaltung.PNG}
|
||||||
\caption{Nutzer Verwaltung}
|
\caption{Nutzerverwaltung}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
\section{Probleme und Lösungen}
|
\section{Probleme und Lösungen}
|
||||||
\subsection{Diagramme}
|
\subsection{Diagramme}
|
||||||
Beim Erstellen der Säulendiagramme sind wir auf den Fehler gestoßen, dass der erste Eintrag von links nicht richtig angezeigt wird. Dieser Fehler ist den Entwicklern von Apexcharts bekannt, aber noch nicht behoben. Wir haben das Problem behoben, indem wir die die Daten an der ersten Stelle entfernen. Dies führt zu einem kleinen Abstand, jedoch wird das Diagramm so optimal ohne fehlende Beschriftungen dargestellt.
|
Beim Erstellen der Säulendiagramme sind wir auf den Fehler gestoßen, dass der erste Eintrag von links nicht richtig angezeigt wird. Dieser Fehler ist den Entwicklern von Apexcharts bekannt, aber noch nicht behoben. Wir haben das Problem behoben, indem wir die Daten an der ersten Stelle entfernen. Dies führt zu einem kleinen Abstand, jedoch wird das Diagramm so optimal ohne fehlende Beschriftungen dargestellt.
|
||||||
\subsection{Custom Headers Chrome}
|
\subsection{Custom Headers Chrome}
|
||||||
Ein weiteres unserer Probleme war, dass Chrome sich geweigert hat, auf den selbst erstellten Header zuzugreifen. Dieses Problem konnten wir im Backend lösen, indem wir den Header zu den "Access-Control-Expose-Headers" hinzugefügt haben.
|
Ein weiteres unserer Probleme war, dass Chrome sich geweigert hat, auf den selbst erstellten Header zuzugreifen. Dieses Problem konnten wir im Backend lösen, indem wir den Header zu den "Access-Control-Expose-Headers" hinzugefügt haben.
|
||||||
\begin{lstlisting}[language=Java]
|
\begin{lstlisting}[language=Java]
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
\chapter{Projektplanung}
|
\chapter{Projektplanung}
|
||||||
\section{Ziel des Projekts}
|
\section{Ziel des Projekts}
|
||||||
Es sollte ein Projekt gebaut werden, das es ermöglicht, die Arbeitszeit über eine App zu tracken. Dies sollte aber nur möglich sein, wenn man sich in einem definierten Umkreis zu seinem Arbeitsplatz befindet. Des weiteren sollte es eine Website zur Verwaltung geben.
|
Es sollte ein Projekt gebaut werden, das es ermöglicht, die Arbeitszeit über eine App zu tracken. Dies sollte aber nur möglich sein, wenn man sich in einem definierten Umkreis zu seinem Arbeitsplatz befindet. Des Weiteren sollte es eine Website zur Verwaltung geben.
|
||||||
\section{Definition des Workflows}
|
\section{Definition des Workflows}
|
||||||
\subsection{Kommunikation}
|
\subsection{Kommunikation}
|
||||||
Zur Kommunikation haben wir für kurze Fragen, sowie das Vereinbaren von Treffen, WhatsApp genutzt. Für Besprechungen haben wir TeamSpeak verwendet.
|
Zur Kommunikation haben wir für kurze Fragen, sowie das Vereinbaren von Treffen, WhatsApp genutzt. Für Besprechungen haben wir TeamSpeak verwendet.
|
||||||
\subsection{Sprints}
|
\subsection{Sprints}
|
||||||
Wir haben die Projektzeit in 5 zweiwöchige Arbeitssprints und einen einwöchigen Vorbereitungssprint aufgeteilt. Die Enddaten der Sprints waren dabei an die Treffen mit Professor Knauth angepasst.
|
Wir haben die Projektzeit in fünf zweiwöchige Arbeitssprints und einen einwöchigen Vorbereitungssprint aufgeteilt. Die Enddaten der Sprints waren dabei an die Treffen mit Professor Knauth angepasst.
|
||||||
\subsection{Code-Owners}
|
\subsection{Code-Owners}
|
||||||
In unserem Git-Reposetory haben wir mit Code Ownership gearbeitet. Dazu haben wir 3 Ownerships eingeführt. Marcel Schwarz war Code-Owner für das Backend, Tobias Wieck für die Android App und Simon Kellner, sowie Tim Zieger für das Frontend. Wenn eine Änderung im jeweiligen Gebiet gemacht wurde, musste immer mindestens ein Code-Owner diese genehmigen.
|
In unserem Git-Repository haben wir mit Code-Ownership gearbeitet. Dazu haben wir drei Ownerships eingeführt. Marcel Schwarz war Code-Owner für das Backend, Tobias Wieck für die Android App und Simon Kellner, sowie Tim Zieger für das Frontend. Wenn eine Änderung im jeweiligen Gebiet gemacht wurde, musste immer mindestens ein Code-Owner diese genehmigen.
|
||||||
\section{Sprintziele}
|
\section{Sprintziele}
|
||||||
\subsection{Iteration 1}
|
\subsection{Iteration 1}
|
||||||
Das Ziel des ersten Sprints war die Erlernung der notwendigen Technologien und die Schnittstellendefinition.
|
Das Ziel des ersten Sprints war die Erlernung der notwendigen Technologien und die Schnittstellendefinition.
|
||||||
\subsection{Iteration 2}
|
\subsection{Iteration 2}
|
||||||
Im zweiten Sprint sollten die Designgrundlagen und Feature Scopes besprochen werden. Des weiteren sollte im Backend die Verbindung zwischen dem Backend und der Datenbank hergestellt werden. Im Frontend war geplant, weiter am Grundgerüst der Seite zu arbeiten und bei der App wurde die Einarbeitung weitergeführt.
|
Im zweiten Sprint sollten die Designgrundlagen und Feature Scopes besprochen werden. Des Weiteren sollte im Backend die Verbindung zwischen dem Backend und der Datenbank hergestellt werden. Im Frontend war geplant, weiter am Grundgerüst der Seite zu arbeiten und bei der App wurde die Einarbeitung weitergeführt.
|
||||||
\subsection{Iteration 3}
|
\subsection{Iteration 3}
|
||||||
Im Frontend sollte im dritten Sprint ein neues Designframework eingeführt werden und die
|
Im Frontend sollte im dritten Sprint ein neues Designframework eingeführt werden und die
|
||||||
Kommunikation mit dem Backend getestet werden. Der Plan fürs Backend war die Erstellung der Restcontroller. Bei der Android App sollte die Loginfunktionalität, sowie das Einlesen der Geo-Informationen realisiert werden.
|
Kommunikation mit dem Backend getestet werden. Der Plan für das Backend war die Erstellung der REST-Controller. Bei der Android App sollte die Login-Funktionalität, sowie das Einlesen der Geo-Informationen realisiert werden.
|
||||||
\subsection{Iteration 4}
|
\subsection{Iteration 4}
|
||||||
Für den vierten Sprint war im Backend geplant, die letzten Controller und Endpoints zu entwickeln. Im Frontend sollten die restlichen Seiten mitsamt Datenabholung aus dem Backend entwickelt werden. Für die App sollte der Geofence entwickelt und die Kommunikation mit dem Backend aufgebaut werden.
|
Für den vierten Sprint war im Backend geplant, die letzten Controller und Endpoints zu entwickeln. Im Frontend sollten die restlichen Seiten mitsamt Datenabholung aus dem Backend entwickelt werden. Für die App sollte der Geofence entwickelt und die Kommunikation mit dem Backend aufgebaut werden.
|
||||||
\subsection{Iteration 5}
|
\subsection{Iteration 5}
|
||||||
|
BIN
other-artifacts/app-release.apk
(Stored with Git LFS)
Normal file
BIN
other-artifacts/app-release.apk
(Stored with Git LFS)
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user