1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177 |
- % !TeX spellcheck = de_DE
- % ---
- % Preamble
- % ---
- \documentclass[12pt]{report}
- \usepackage{defaultPreamble}
- \bibfilename{Gruppenbericht.bib}
- %
- % ---
- % Document Body
- % ---
- \begin{document}
- \pagenumbering{arabic}
- %
- % Deckblatt
- \setcounter{page}{0} % setze seitenzähler auf 0 -> alle Seitenzahlen <1 werden nicht angezeigt
- {\centering
- \clear % Select ClearSans for the title page
- \vspace*{2\baselineskip}
- %
- {\large Technische Hochschule}\\
- \vspace{0.3ex}
- {\large Georg-Simon Ohm Nürnberg}\\
- \vspace{0.3ex}
- {\large Fakultät Elektrotechnik Feinwerktechnik Informationstechnik}\\
- \vspace{2.5ex}
- %
- {\large Projekt OHM News}\\
- \vspace{3.5ex}
- %
- {\Large\b{Projektstudienarbeit}}\\
- \vspace{0.3ex}
- {\Large\b{B-ME 5}}\\
- \vspace{4.5ex}
- {\Large\b{OHM News - See only what matters}}\\
- \vspace{3.5ex}
- %
- {\large Wintersemester 2018/2019}\\
- \vspace{10\baselineskip}
- %
- \begin{table}[h]
- \centering \large
- \begin{tabular}{rl}
- \rule{0pt}{14pt}\b{Senta Mandutz} & \b{Edwina Barbalan} \\
- Matrikel-Nr.: 3022812 & Matrikel-Nr.: 3064088 \\
- \rule{0pt}{14pt}\b{Vivianne Pham} & \b{Xenia Gr\"unzinger} \\
- Matrikel-Nr.: 2928261 & Matrikel-Nr.: 3046080 \\
- \rule{0pt}{14pt}\b{Erik R\"ommelt} & \\
- Matrikel-Nr.: 2843345 & \\
- \end{tabular}
-
- \end{table}
-
- } % Need 1 empty line above for centering
- %
- \newpage % Seitenumbruch nach Titelblatt
- \paragraph{\Large Projekt-Roadmap}$~~$\\
- %
- \begin{table}[h]
- \centering%\small
- \begin{tabularx}{\textwidth}{|X|X|X|}
- \hline
- \rule{0pt}{14pt}\b{Tätigkeit} & \b{Dokument} & \b{Beteiligung} \\
- \hline
- \rule{0pt}{14pt}Entwicklung & Modaldialog für Login & Xenia, Erik \\
- Entwicklung & Einbindung zu Buefy & Xenia, Edwina \\
- Entwicklung & Autocompleted Taginput & Xenia, Senta \\
- Entwicklung & Frontend Suche & Xenia\\
- Entwicklung & Router Komponente & Edwina \\
- Entwicklung & Frontend Bookmarks & Edwina \\
- Entwicklung & Desktopansicht & Edwina \\
- Design und Ausformulierung & Video & Vivianne, Edwina \\
- Design und Ausformulierung & PowerPoint Präsentation & Edwina \\
- Entwicklung & Frontend Abonnieren (nur Darstellung)& Xenia\\
- Gestaltung & Erstellung von Plakaten & Xenia \\
- Organisation und Leitung & Projekt Ohm News & Alle \\
- Formulierung & Pflichtenheft & Alle \\
- Konzeption & Rollengruppen & Alle \\
- Dokumentation RESTful API & Digital mit Swagger.io & Erik \\
- Entwicklung & RESTful API mit JavaScript & Erik, Senta \\
- Entwicklung & Überarbeitung Server-Skripte & Erik \\
- Entwicklung & Überarbeitung DB-Skripte & Erik, Senta \\
- Entwicklung & Login-Logik mit JavaScript & Erik \\
- Entwicklung & Rollenkonzept & Erik \\
- Entwicklung & Frontend mit Vue.js, Buefy & Erik, Senta, Xenia, Edwina\\
- \rule{0pt}{14pt}Entwicklung & Datenbank mit MongoDB & Senta, Erik \\
- \hline
- \end{tabularx}
- \caption{Projekt-Roadmap Tabelle}
- \end{table}
- %
- % Inhaltsverzeichnis
- \newpage
- \tableofcontents
- %
- % Bericht
- \newpage % Seitenumbruch nach Titelblatt
- \section*{1. Einleitung}
- \phantomsection\addcontentsline{toc}{section}{1. Einleitung}
- In der heutigten Zeit werden die meisten Menschen tagtäglich mit einer Vielzahl an Reizen und Informationen überflutet. Dabei ist es nicht immer einfach den Blick auf das Wesentliche zu halten. Häufig werden wir durch Werbung, irrelevante Mails, Social Media Beiträge und weiteres schnell abgelenkt. So geht es auch vielen Studierenden und Angehörigen der Technischen Hochschule Nürnberg.\\
- Für uns war das Anlass genug. Es sollte doch eine Möglichkeit zur qualitativen Verbesserung der Informationsflut im Studienalltag geben. Auf der einen Seite müssen die Hochschulangehörigen entlastet werden, damit die Konzentration für die relevanten Themen gesteigert werden kann und auf der anderen Seite sollte genügend Freiraum für die individuellen Interessen bestehen.\\
- Im Folgenden wird die Entwicklung einer Idee zur Lösung dieser Problematik, über deren Ausarbeitung in Form eines Konzeptes bis hin zur praktischen Entwicklung eines lauffähigen Prototypen detailliert beschrieben.
- %
- \section*{2. Vorwort zur Projektidee}
- \phantomsection\addcontentsline{toc}{section}{2. Vorwort zur Projektidee}
- Die erste Konzeptversion zu der Projektidee von dem Projekt ''Ohm Management App'', dass im Verlauf der ersten Projektphase in ''OHM-News - See only what matters'' umbenannt wurde, wurde von Erik Römmelt erstellt. Nach gemeinsamer Überarbeitung durch Prof.Dr. Matthias Hopf, dem zukünftig betreuenden Professor und Erik Römmelt wurde die zu Projektbeginn gegebene Version des Projektkonzeptes ausformuliert.
- %
- \section*{3. Projektidee}
- \phantomsection\addcontentsline{toc}{section}{3. Projektidee}
- Die Projektidee basiert darauf, dass eine plattformunabhängige App für Studierende an der TH Nürnberg entwickelt werden soll, die Kurznachrichten filtert und in einem Nachrichtenfeed anzeigt. Das Filtern funktioniert durch Tags. Es können beim Nachrichten erstellen mehrere, jedoch mindestens eine eingegeben werden. Diese werden bei einer Überschneidung bei der Suche durch eine logische UND-Verknüpfung eingeschränkt. Angezeigt werden die Nachrichten abhängig von ihrer Priorität und Aktualität. \\
- Dazu können in einer Dateiablage von Professoren und Befugten wichtige Links oder andere Dateien gesammelt werden oder als Referenz darauf verwiesen werden. Damit es den Status ''Befugte'' gibt, muss es zudem eine Rollenverteilung geben, wem welche Rechte zu stehen oder beispielsweise wer nur Nachrichten empfangen kann.
- Zudem ist eine Speicherung einzelner Nachrichten aus dem Feed möglich, welche im Nachhinein in den Bookmarks oder auch Lesezeichen einsehbar sind.\\
- Des Weiteren können Push-Benachrichtigungen angezeigt werden, sodass das Risiko, wichtige Nachrichten zu übersehen, minimiert wird.
- Zuletzt gibt es noch ein Nutzerprofil. Hier können Daten zur Person eingetragen und angezeigt werden wie zum Beispiel das Profilbild, deren Status an der technischen Hochschule oder die Matrikelnummer.
- Für den Optimalfall einer Übernahme der App von der Hochschule soll modulorientiert und wartungsaufwandsarm gearbeitet werden, um die spätere Verwaltung zu erleichtern. Auch wird Wert gelegt auf eine nutzerfreundliche und möglichst intuitive Bedienoberfläche.
- %
- \subsection*{3.1. Technische Umsetzung}
- \phantomsection\addcontentsline{toc}{subsection}{3.1. Technische Umsetzung}
- Zur Umsetzung des Projektes fiel die Zielsetzung auf die Entwicklung einer progressiven Web-App. Aufgrund ihrer Plattformunabhängigkeit und Kompatibilität mit den TH-Servern (VPN und Eduroam) und laut Erfahrungen von Professor Dr. Hopf stellt dies eine gute Lösung und sichere Wahl dar. Ebenfalls, was die Datenschutzvorkehrungen der Hochschule betrifft. \\
- Es werden die Codesprachen HTML, CSS und JavaScript verwendet und als Frameworks Vue.js, Bootstrap und node.js. \\
- Als Datenbank dient MongoDB und das zugehörige Framework mongoose.
- %
- \section*{4. Projektorganisation}
- \phantomsection\addcontentsline{toc}{section}{4. Projektorganisation}
- Wöchentlich fand ein Treffen, zum Austausch und zur Besprechung zurückliegender und anstehender Aufgaben, statt. An diesem Treffen nahmen in der Regel alle Mitglieder dieser Projektgruppe und der Projektbetreuer Prof.Dr. Matthias Hopf teil. Konnten Teammitglieder, gleich welcher Gründe, an einem Treffen nicht teilnehmen, so haben alle sich unverzüglich über Absprachen und den neu anstehenden Aufgaben selbstständig erkundigt.
- %
- \subsection*{4.1. Trello}
- \phantomsection\addcontentsline{toc}{subsection}{4.1. Trello}
- Zu Beginn des Projekts wurde entschieden, dass zur Verbesserung des Arbeitsablaufs ein Organisationstool hilfreich wäre. So fiel ist Trello in Gespräch gekommen.\\
- Trello ist ein graphisch sehr gut aufbereitetes Projektmanagement-Tool in Form von Kanban-Boards. In der kostenfreien Version, ist es möglich ''unbegrenzt [viele] Boards, Listen, Karten, Mitglieder, Checklisten und Anhänge'' hinzuzufügen und zu nutzen\cite{trello:price}. Zur typografischen Gestaltung der Karten, um zum Beispiel eine Liste einzufügen ist die Nutzung von einigen Markdown-Markup Elementen möglich.\\
- Dem Projekt zugute kommend ist die sehr einfache Bedienbarkeit, Plattform unabhängige Verfügbarkeit, sowie die gute Übersichtlichkeit der Boards. Nachteilig ist, dass es nur sehr eingeschränkt die Zeitkomponente abbilden kann. Dies ist nur über die sogenannten ''Plugins'' möglich, wobei in der kostenfreien Version nur ein Plugin je Board zugleich genutzt werden kann. So kann einem Board entweder die Funktion ''Gantt-Diagramme nutzen'' oder ''Storypoints den Karten hinzufügen'' verwendet werden.\\
- Diese Einschränkung führte zur der Entscheidung gegen die Nutzung von Trello im Team.
- %
- \subsection*{4.2. Bitrix24}
- \phantomsection\addcontentsline{toc}{subsection}{4.2. Bitrix24}
- Nach dem Ausschluss von Trello begann die Umsicht nach einem anderen Tool, dass kostenfrei mit einer Gruppe von fünf Personen genutzt werden kann. Und es sollte die Funktionen Gantt-Diagramme erstellen, Aufgaben an Mitglieder verteilen und den Gewichtungs-Punkte oder ''Storypoints'' an Aufgaben zuweisen erfüllen.\\
- Bitrix24 hat diese Anforderungen erfüllt, war jedoch bereits auf den ersten Blick deutlich unübersichtlicher und komplexer in der Handhabung. Da es sich bei Bitrix24 in erster Linie um ein umfangreiches CRM-System handelt, mit vielen weiteren Funktionen wie ''Aufgabenverwaltung für Gruppen'', ''Projektplanung und -management'' und ''Team-Chat''\cite{bitrix:feature}.\\
- Auch nach der Deaktivierung und Ausblendung sämtlicher Funktionen, die die Nutzung von Bitrix24 komplizierter machten, blieb die Benutzeroberfläche noch unübersichtlich. Was die Umsetzung der Aufgaben als Kanban-Karten mit Gewichtungs-Punkten und der zeitlichen Darstellung der Aufgaben in einem Gantt-Diagramm betrifft, so war dies sehr angenehm und vollends zufriedenstellend möglich.\\
- So wurden zahlreiche organisatorische Fristen, sowie Aufgaben organisatorischer und entwicklungs-technischer Natur in Bitrix24 erfasst und anschließend in einem wöchentlichen Treffen vorgestellt. Im Weiteren wurde die Nutzung und Pflege des Tools an alle Mitglieder übertragen.\\
- Es stellte sich am Ende des ersten Projektabschnittes heraus, dass das Tool Bitrix24 aufgrund der komplexen und unübersichtliche Benutzeroberfläche kaum genutzt wurde.
- %
- \section*{5. Entwicklerblog}
- \phantomsection\addcontentsline{toc}{section}{5. Entwicklerblog}
- Die Wiki Blogeinträge in dem hochschulinternen github Repository dienen dazu, die Projektfortschritte transparent zu gestalten und eine kurze prägnante Zusammenfassung für Professoren und Studierende zu gewährleisten. Einzusehen sind die Beiträge auf der git efi Seite \cite{gitefi}.
- %
- \subsection*{5.1. Protokollierung}
- \phantomsection\addcontentsline{toc}{subsection}{5.1. Protokollierung}
- Für die Protokollierung wurden in regelmäßigen Intervallen Dokumentationen über die Tätigkeiten aller Teammitglieder geführt und diese folglich in Schrift festgehalten. Enthalten sind die Aufgabenaufteilung und die bisherige Umsetzung aller Projektteilnehmer in einer bestimmten Zeit, welche anschließend gebündelt zusammengefasst wurden.
- %
- \subsection*{5.2. Blogentwurf}
- \phantomsection\addcontentsline{toc}{subsection}{5.2. Blogentwurf}
- Da das git efi nicht nur für Professoren sondern auch Studierenden der Fakultät efi zugänglich ist, werden die Vorgänge des Projekts in kurzen Sätzen und möglichst verständlich wiedergegeben. So können sich auch Studierende außerhalb des Fachgebietes ein ungefähres Bild von dem Fortschritt der OHM News-App machen. Nach dem Umformulieren und Reduzieren auf die Kernaussagen wurden Einträge in kontinuierlichen Abständen auf dem Hochschul github\cite{gitefi} zum Abrufen hochgeladen. Diese berufen sich auf etwa ein Monats-Abstände oder kürzer. Bei neuen Einträgen wird Professor Dr. Hopf informiert, sodass er stets den Verlauf des Projektes nachvollziehen kann. In zeitlich chronologischer Reihenfolge aufgelistet, vereinfacht dies den Überblick. Insgesamt wurden im Laufe des OHM News-App Projektes sechs Wiki Blogeinträge erstellt.
- %
- \section*{6. Pflichtenheft}
- \phantomsection\addcontentsline{toc}{section}{6. Pflichtenheft}
- Das Pflichtenheft hat die Gruppe gemeinsam zusammengestellt. Dabei sollte der Datenzugriff per MongoDB erzeugt werden, alternativ könnte auch eine Schnittstelle zur Verfügung gestellt werden. Die Grafische UI der PWA sollte einen Login, ein Menü, eine Suche, ein Profil, einen Filter nach Hashtags, ein Dashboard, Einstellungen, das Nachrichtfeld und ein Formular zum Verfassen von Nachrichten umfassen. Ein Abhängigkeitsdiagramm soll erstellt werden. Die Anwendungslogik sollte im Bereich des Routings, der Darstellung und Speicherung von Nachrichten und dem LDAP-Login umgesetzt werden. Codetests sollten durchgeführt werden und das Rollenkonzept der Nutzer sollte festgelegt werden.\\
- Des Weiteren sollte ein Anwendungsname gefunden und ein Logo erstellt werden. Ein UX Konzept sollte aufgestellt werden. Wenn es zeitlich noch möglich wäre, hätte man die Funktionen umsetzen sollen um die Datenbankabrufe zu filtern und Kanälen zu folgen. Ebenso hätte man die Anzeigekriterien festlegen können.
- %
- \section*{7. Konzepterstellung}
- \phantomsection\addcontentsline{toc}{section}{7. Konzepterstellung}
- Der erste Schritt zur Definition eines Layoutentwurfs war die Erstellung von Scribbles. Unter einem Scribble versteht man einen groben ersten Entwurf, der zur Ideenfindung beitragen soll. Nach Festlegung der grundsätzlichen Projektidee, zeichnete jedes unserer Teammitglieder Scribbles für verschiedene Seiten der App, die wir im Anschluss zusammen diskutierten. Wichtig war uns hierbei, dass jedes Teammitglied erst eigene Ideen entwickelte, um so viele verschiedene Aspekte zu sammeln.\cite{scrib} \\
- Wir versuchten alle Ideen zu vereinen und einigten uns auf einen Layoutentwurf, welcher im Anschluss in einem detaillierten Screendesign umgesetzt wurde. In Abbildung \ref{layout} ist das Screendesign für die Startseite zu sehen. Wir legten vor allem den Fokus auf die Startseite, da diese der erste Baustein der App werden sollte. Die Navigation auf die anderen Seiten erfolgt über eine Leiste am unteren Displayrand. Die weiteren Seiten legten wir zu Beginn fest, arbeiteten diese allerdings erst mit der Zeit detaillierter aus. Ein genauer Aufbau der App wird unter 9.1. beschrieben. \\
- \begin{figure}[H]
- \centering
- \includegraphics[width=4.5cm]{../grafiken/Layout}
- \caption{Layoutentwurf der Startseite}
- \label{layout}
- \end{figure}
- Bevorstehende Implementierungen von Funktionalitäten sollten, wenn bereits im Vorfeld möglich, ebenfalls in den Layoutentwürfen berücksichtigt werden. Änderungen sind natürlich auch zu einem späteren Zeitpunkt möglich, erhöhen allerdings den Aufwand. Deswegen wurde versucht, möglichst viele Funktionalitäten bereits in die Layoutentwürfe miteinzubeziehen.\\\\
- Wir einigten uns im Projektteam darauf die App gemäß den Material Design Richtlinien von Google zu gestalten. Material Design ist eine von Google entwickelte Designvorgabe, die auf materienartigen Flächen basiert und dadurch zu einem sehr minimalistischen \mbox{Design} führt. Ziel dieser Designsprache ist unter anderem eine intuitive Benutzeroberfläche. Die Richtlinien wurden bei der Erstellung des Screendesigns berücksichtigt. \cite{md,md2}
- %
- \section*{8. Namensfindung}
- \phantomsection\addcontentsline{toc}{section}{8. Namensfindung}
- Zu Anfang haben wir uns für den Titel OHM-Management entschieden, mit dem Wissen, dass es höchstwahrscheinlich nicht dabei bleibt, da das Wort Management mit unserer angestrebten Funktionalität der App nur einschränkend passte.
- Die Verwendung des Wortstammes Kommunikation war für unsere Benennung auch nicht zutreffend, insofern der Austausch von Information nur in eine Richtung erfolgt.
- Zusätzlich gestaltete sich die Namensfindung etwas schwierig, da wir sozusagen eine App für die TH-Nürnberg entwickelten, die man auch in Verbindung mit dem OHM-Zeichen kennt. Diesbezüglich wollten wir uns bei der Benennung auch an dieses anlehnen. Um dies tun zu können, mussten wir uns erst einmal informieren, ob es ähnliche Namen bereits gibt die man aus diesem Grund dementsprechend nicht verwenden kann.
- %
- \subsection*{8.1. Recherche}
- \phantomsection\addcontentsline{toc}{subsection}{8.1. Recherche}
- Bevor also der erste Schritt in Richtung Namensfindung gemacht werden konnte, recherchierten wir über bereits vorhandene Namen, die von der TH-Nürnberg genutzt werden. Neben Namen wie InfoTHek, OHMdoc und OHM-Shop, welche für unser Thema eher irrelevant wirkten, fanden wir auch den Titel OHM-News. Dies war ein Online Journal, welches jedoch, wie sich später rausgestellt hatte, eingestellt wurde.
- %
- \subsection*{8.2. Brainstorming}
- \phantomsection\addcontentsline{toc}{subsection}{8.2. Brainstorming}
- In der Zwischenzeit setzten wir jedoch die Ideensammlung weiter fort und präsentierten in der Gruppe einzelne Namensvorschläge. Hieraus entstand eine Liste an kreativen Gedanken. Unsere Favoriten :
- \begin{itemize}
- \item \b{ON AIR}
- \begin{itemize}
- \item \b{O}HM \b{N}ews \b{A}pp for \b{I}nformation and \b{R}ediscovery/\b{R}ecommendations
- \item \b{O}HM \b{N}ews Stream for \b{A}ctivities, \b{I}nformation and \b{R}ecommendations
- \end{itemize}
- %
- \item \b{ON STREAM}
- %
- \begin{itemize}
- \item \b{O}HM \b{N}ews \b{Stream}
- \end{itemize}
- %
- \item \b{OHM News}
- %
- \item \b{TH i s}
- %
- \item \b{INFOhm}
- \end{itemize}
- Alle Vorschläge waren sehr durchdacht und kreativ. Jedoch hatten einige nicht ganz die Wirkung die wir uns erhofften, denn wir waren der Meinung, dass man das Wort On Air eher mit einem Radiosender verbindet. Ebenfalls der Nachteil bei der Idee On Stream war es, dass man stark an Streaming Dienste wie zum Beispiel Netflix erinnert wird.
- %
- \subsection*{8.3. Ergebnis}
- \phantomsection\addcontentsline{toc}{subsection}{8.3. Ergebnis}
- Nach langem Überlegen kamen wir auf den Namen OHM News zurück und dieser überzeugte uns im Endeffekt alle. Dieser Titel war recht kurz, er ist leicht zu verstehen ohne viel nachzudenken, man verbindet ihn auf Anhieb mit der TH-Nürnberg auf Grund des Wortes OHM und er verweist auf die Funktionalität die unsere App bereitstellt, die da wären Neuigkeiten, sprich News, für die Studenten der Hochschule bereitzustellen.
- %
- \subsection*{8.4. Claim}
- \phantomsection\addcontentsline{toc}{subsection}{8.4. Claim}
- Parallel zur Namensfindung, befassten wir uns auch mit dem Claim unseres Produktes. Da ein Claim die Funktion unserer App auf den Punkt bringen soll, und dabei kurz, leicht zu merken und aussagekräftig sein sollte, entschieden wir uns für eine Formulierung der Art ''nur relevante Themen werden angezeigt''. Nach einer kurzen Denkphase kamen wir auf den Claim ''See only what matters'', beziehungsweise ''Only see what matters'' vor. Dies kam bei uns allen sehr gut an, jedoch wussten wir nicht, welche von den beiden Optionen die erhoffte Bedeutung am besten hervorbringt. Sie haben zwar die selbe Bedeutung, trotz alle dem empfanden wir, dass die Betonung des Wortes „Only“ auf zwei verschiedene Faktoren des Satzes liegt. Nach reichlicher Überlegung entschieden wir uns also für die Formulierung ''See only what matters'' als Claim für unsere App.
- %
- \section*{9. Corporate Design}
- \phantomsection\addcontentsline{toc}{section}{9. Corporate Design}
- Um das ganze Konzept stimmig zu gestalten, wurde ein Corporate Design erstellt.
- Wichtigste Grundlage hierfür ist das Farbkonzept. Da die App im Hochschulrahmen verwendet werden soll, wurde für die Grundfarbe der Blauton des Hochschullogos gewählt, umso eine Zugehörigkeit zu symbolisieren. Ergänzend zu diesem Blauton werden noch zwei dezente Grautöne verwendet, wie in Abbildung \ref{farbschema} zu sehen ist. \\
- %
- \begin{figure}[H]
- \centering
- \includegraphics[width=12cm]{../grafiken/Farbschema_CD}
- \caption{Farbkonzept}
- \label{farbschema}
- \end{figure}
- \noindent
- Auch ein Logo ist wichtig, um einen gewissen wiedererkennungswert für die App zu schaffen. Da wir uns in der Gruppe für den App-Namen ''Ohm-News'' entschieden haben, war der erster Gedanke eine Zeitung für das Logo herzunehmen (siehe Abbildung \ref{logo1}). Die Grafik war allerdings schwierig in das Produkt einzubinden, weil sie sehr detailreich ist. \\
- %
- \begin{figure}[H]
- \centering
- \includegraphics[width=4cm]{../grafiken/Logo1_CD}
- \caption{Erster Logoentwurf}
- \label{logo1}
- \end{figure}
- \noindent Ein zweiter etwas minimalistischer Entwurf ist in Abbildung \ref{logo2} zu sehen, für welchen sich das Projektteam schlussendlich auch entschied. Es zeigt ein Globussymbol mit dem Hochschullogo im Zentrum, um auch hier wieder die Verbindung zur Hochschule schaffen. \\
- %
- \begin{figure}[H]
- \centering
- \includegraphics[width=4cm]{../grafiken/Logo2_CD}
- \caption{Finales Logo}
- \label{logo2}
- \end{figure}
- %
- \noindent Das Logo wurde dann auch zu einem App Icon erweitert. In Abbildung \ref{icons} ist das Icon für Android sowie IOS Geräte zu sehen. Das Android Icon wurde analog den Material-Design Richtlinien gestaltet und besitzt deshalb einen leichten Schatten. Bei dem IOS Icon wurde das Logo lediglich auf einen einfarbigen Hintergrund gesetzt. \\
- %
- \begin{figure}[H]
- \centering
- \includegraphics[width=10cm]{../grafiken/Icons_CD}
- \caption{App Icons}
- \label{icons}
- \end{figure}
- %
- \section*{10. Erstellung der Mockups}
- \phantomsection\addcontentsline{toc}{section}{10. Erstellung der Mockups}
- Auf Basis des Screendesigns wurden erste Mockups erstellt, welche mittels HTML und CSS umgesetzt wurden. Um die Elemente entsprechend den Material-Design Richtlinien zu gestalten, wurde das CSS-Framework Bootstrap mit eingebunden, das eine Auswahl an vordefinierten Gestaltungselementen und Stilen in Form von CSS-Stylesheets bereitstellt. Dazu gehören Elemente wie Buttons, Formulare, Navigationszeilen und viele mehr. Wir verwendeten Bootstrap Dateien, die auf Material Design abgestimmt sind. So wird ein einheitliches Design gewährleistet und die Styles müssen nicht selbst erstellt werden. Ein weitere Vorteil von Bootstrap, ist, dass es ein responsives Webdesign unterstützt und man deshalb plattformunabhängig entwickeln kann. Dafür sorgt ein Grid-Layout, welches den Benutzerbildschirm in 12 Spalten teilt und die Elemente, je nach verfügbarer Auflösung, anzeigt. Im ersten Projektabschnitt legten wir den Fokus besonders auf eine mobile Ansicht. Eine Desktopansicht wird ebenfalls unterstüzt, kann allerdings noch stark optimiert werden. \cite{bootstrap} \\
- Durch die Ergänzung von eigenen CSS-Dateien konnten Änderungen an den vordefinierten Stilen vorgenommen werden. Sowohl unsere als auch die von Bootstrap bereitgestellten Dateien, wurden auf Grundlage von Less-Stylesheets erstellt. Dabei wird auf effiziente Weise CSS generiert. Variablen sowie Funktionen sind möglich und Vererbung wird durch \mbox{verschachtelte} Selektoren dargestellt. \cite{less} \\
- Wir habe für jeden Menüpunkt eine HTML-Seite erstellt, welche im Unterpunkt genauer beschrieben werden.
-
- \subsection{Buefy}
-
- Bei der Gestaltung von Weboberflächen verwendet man in der Regel ein CSS-Framework. Im ersten Projektabschnitt haben wir uns für das Framework Bootstrap entschieden, \mbox{das} eine Umsetzung entsprechend der Material Design Richtlinien ermöglicht. Es stellt auch JavaScript-Erweiterungen, wie z.B. Modale,
- bereit, welche allerdings nicht konkret auf das, in der App verwendete, JavaScript-Framework Vue.js abgestimmt sind. Deswegen \mbox{entschieden} wir uns ein alternatives, konkret für Vue.js konzipierte, Css-Framework zu verwenden. Der Vorteil darin besteht, dass es neben vordefinierten Styles ebenfalls Oberflächen Komponenten für Vue bereitstellt.
- Die Wahl fiel auf Buefy, das auf dem Framework Bulma \mbox{basiert}.([1])\\
-
- Die Einbindung von Buefy erforderte zunächst eine Anpassung aller bereits bestehenden Komponenten, da Bootstrap und Buefy zum Teil gleiche Klassennamen verwenden und somit nicht zusammen genutzt werden können. In diesem Zug habe wir uns von Material-Design losgelöst und dessen Richtlinien in der Gestaltung nur noch zum Teil berücksichtigt.
- In den weiteren Gliederungspunkten werden einige Komponenten von Buefy näher \mbox{erläutert}.
-
- Um unseren Code einfacher und kompakter zu halten, standen wir vorerst vor der Entscheidung welches Open-Source-Tool wir verwenden wollen. Anfangs war unsere Aufmerksamkeit auf das Material-Framework „Vuetify“ gerichtet. Das Ziel dessen ist es, den Nutzern alles zur Verfügung zu stellen, was zum Aufbau umfangreicher und ansprechender Webanwendungen erforderlich ist mit der Verwendung von Material Design-Spezifikationen und Vue \textsuperscript{1}. Letztendlich entschieden wir uns jedoch dazu Buefy zu verwenden. Die Vorteile liegen hierbei darin, dass man es vollständig oder als einzelne Komponenten auf einer normalen Webseite importieren und Vue.js als Ersatz für jQuery verwenden kann \textsuperscript{2}.
- %
- \section*{10.1. Aufbau der App}
- \phantomsection\addcontentsline{toc}{subsection}{10.1. Aufbau der App}
- %
- \begin{figure}[H]
- \begin{minipage}[t]{5cm}
- \vspace{0pt}
- \centering
- \includegraphics[width=4cm]{../grafiken/Homescreen_MU}
- \caption{Startseite}
- \label{abbildung_homescreen}
- \end{minipage}
- \hfill
- \begin{minipage}[t]{11cm}
- \vspace{0pt}
- Auf der Startseite der App gelangt der Nutzer als erstes auf einen Newsfeed. Der Newsfeed besteht aus einzelnen Nachrichten in Form von Karten und soll für jeden Nutzer nur \mbox{relevante} Nachrichten anzeigen. Jede Nachricht besitzt einen oder \mbox{mehrere} Tags. Eine Nachricht wird für einen Nutzer als relevant eingestuft, wenn dieser mindestens einen Tag aus der Nachricht abonniert hat. Somit erhält jeder Nutzer eine individuelle Startseite. Zusätzlich befindet sich auf der Nachrichtenkarte oben rechts ein Icon, welches die Nachricht zu einer Fakultät zuordnet. Unten rechts kann das Lesezeichen-Icon geklickt werden, um eine Nachricht zu speichern. Auf diese Weise können die Studierenden wichtige Informationen schnell wiederfinden.\\\\
- Im Header ist die Suche zu finden, in der Tags explizit gefiltert werden können. Der \mbox{Header} ist von jeder Seite aus zugängig. Im Footer befindet sich die Navigationszeile, von wo aus der Nutzer auf die weiteren Seiten gelangt.
- \end{minipage}
- \end{figure}
- %
- \begin{figure}[H]
- \begin{minipage}[t]{5cm}
- \vspace{0pt}
- \centering
- \includegraphics[width=5cm]{../grafiken/Links_MU}
- \caption{Infoseite}
- \label{abbildung_infoseite}
- \end{minipage}
- \hfill
- \begin{minipage}[t]{11cm}
- \vspace{0pt}
- Der zweiten Menüpunkt, der durch ein Globus-Icon dargestellt wird, soll eine Informationsseite beinhalten. Das Konzept hierfür ist allerdings noch nicht konkret ausgearbeitet, da wir uns zuerst auf die Mitteilungsfunktionen konzentrieren wollten. Aktuell wird ein Empty State angezeigt.\\
- Dieser Menüpunkt wurde im zweiten Projektabschnitt zu einer erweiterten Suche.
- \end{minipage}
- \end{figure}
- %
- \medskip
- \begin{figure}[H]
- \begin{minipage}[t]{5cm}
- \vspace{0pt}
- \centering
- \includegraphics[width=5cm]{../grafiken/CreateMessage_MU}
- \caption{Formular}
- \label{abbildung_createmsg}
- \end{minipage}
- \hfill
- \begin{minipage}[t]{10cm}
- \vspace{0pt}
- Über das Plus-Icon, in der Mitte der Navigationszeile, gelangt man zu einem Formular. Hier können neue Nachrichten erstellt werden. Nachrichten sollen nur von ausgewählten Nutzergruppen, wie Fakultäten, Studienbüro und ähnlichen gesendet werden können.
- Für eine Nachricht wird ein Betreff, mindestens ein Tag und der Nachrichteninhalt benötigt. Es soll eine Auswahl an vordefinierten Tags geben, damit am Ende nicht jeder Verfasser wahllos Tags setzten kann und \mbox{Duplikate} vermieden werden. Dieser Menüpunkt ist der einzige in dem keine Navigationszeile angezeigt wird. Nach Absenden einer Nachricht, gelangt man zurück auf die Startseite. Über den Button 'Abbrechen' wird man auf den vorherigen Menüpunkt zurückgeleitet.
- \end{minipage}
- \end{figure}
- %
- \begin{figure}[H]
- \begin{minipage}[t]{5cm}
- \vspace{0pt}
- \centering
- \includegraphics[width=5cm]{../grafiken/Gespeicherte_MU}
- \caption{Gespeicherte}
- \label{abbildung_gespeichert}
- \end{minipage}
- \hfill
- \begin{minipage}[t]{11cm}
- \vspace{0pt}
- Der nächste Menüpunkt wird über das Lesezeichen-Icon erreicht und zeigt die gespeicherten Nachrichten an. Diese Seite ist ähnlich aufgebaut wie der Newsfeed der Startseite, beinhaltet allerdings nur die vom Nutzer gespeicherten Nachrichten.
- \end{minipage}
- \end{figure}
- %
- \medskip
- \begin{figure}[H]
- \begin{minipage}[t]{5cm}
- \vspace{0pt}
- \centering
- \includegraphics[width=5cm]{../grafiken/Profil_MU}
- \caption{Profil}
- \label{abbildung_profil}
- \end{minipage}
- \hfill
- \begin{minipage}[t]{11cm}
- \vspace{0pt}
- Der letzte Menüpunkt ist das Profil. \\
- Oben sieht man zuerst das Profilbild, hier verwendeten wir die runde Form anstatt der üblichen Quadratischen. Darunter sieht man dann die im Vorfeld angegebene Information des Benutzers. Am Ende der sogenannten Karte befinden sich zwei Knöpfe, die Anzeigen wie vielen Kanälen man folgt und wie viele Beiträge man bis jetzt gespeichert hat. Auf der Karte rechts oben im Eck findet man den Bearbeitungs-Knopf, in Form eines kleinen Stiftes, dies ermöglicht dem Benutzer, die Seite gemäß seinen Wünschen anzupassen.\\
- Die Profilkarte an sich blieb relativ gleich, was sich im zweiten Projektabschnitt geändert hat war das bearbeiten des Modals, welches sich öffnet, wenn man sich die Abonnierten Kanäle anzeigen lassen will. Dazu klickt man hierfür auf einen „b-button“ welches daraufhin ein „b-modal“ öffnet. Dort werden alle abonnierten Elemente aufgelistet. Sobald man auf den „Gespeichert“-Button klickt, wird man mittels router.push auf die Bookmark-Seite geleitet, auf der man alle gespeicherten Nachrichten findet.
- \end{minipage}
- \end{figure}
- %
- \section*{11. Single-Page Entwicklung}
- \phantomsection\addcontentsline{toc}{section}{11. Single-Page Entwicklung}
- Neben klassischen Webanwendungen gibt es ebenfalls Single-Page Webanwendungen. Bei klassischen Webapplikationen gibt es mehrere untereinander verlinkte HTML-Dokumente, die dann gemeinsam eine komplette Anwendung ausmachen. Der Nachteil hierbei ist, dass die Seite beim Wechsel durch die erneute Kommunikation mit dem Server neu heruntergeladen werden muss. SPA’s jedoch bestehen nur aus einer HTML-Datei. Dies bewirkt, dass neue oder veränderte Daten dynamisch geladen werden und somit die Kommunikation zwischen Server und Client verringert wird. Es ermöglicht dem Benutzer, nach dem einmaligen laden der Seite, diese auch weiterhin im offline Modus zu steuern. Sollte also die Interaktion mit dem Server unterbrochen werden, werden die zwischengespeicherten Daten einfach aus dem Webbrowser verwendet.\cite{spa:1}\cite{spa:2}
- %
- \subsection*{11.1. Warum Vue.js?}
- \phantomsection\addcontentsline{toc}{subsection}{11.1. Warum Vue.js?}
- Neben dem Vue.js Framework gibt es noch weitere wie zum Beispiel react.js, angular.js, meteor.js und viele mehr. Warum wir uns jedoch für das Vue.js Framework entschieden haben, werden wir Ihnen nun erläutern. Vue.js das jüngste von den drei größten Frameworks, es hat jedoch den Vorteil, dass es aus den Fehlern der Vorgänger lernen konnte und diese schon im Vorfeld überdenken und ausmerzen konnte. Da es auf Sprachen wie HTML, CSS und JavaScript aufbaut, lässt es sich problemlos in schon bestehende Projekte einbauen.
- Die Syntax ist hierbei, im Vergleich zu anderen, besser lesbar. Hierfür werden nämlich sogenannte ''Single File Components'' verwendet.\cite{vue:warum} Sogenannte Komponenten sind wiederverwendbare Vue-Instanzen mit einem Namen, die als benutzerdefiniertes Element in einer Vue-Stamminstanz verwendet werden. Wie so eine erstellte Komponente aussieht, werden wir Ihnen im folgenden erörtern.
- %
- \subsection*{11.2. Vue.js in vorhandene Mockups einbinden}
- \phantomsection\addcontentsline{toc}{subsection}{11.2. Vue.js in vorhandene Mockups einbinden}
- Nach reichlicher Recherche und dem einlesen in das uns vorher unbekannte Framework, war es an der Zeit unsere HTML-Seiten in Vue-Komponenten umzuwandern. Wir setzten uns erstmal zusammen und erstellten die Startseite.
- Im Folgenden wird der Aufbau der Home-Komponente näher erläutert. In Listing 1 ist der dazugehörige Quellcode zu sehen. Nicht enthalten sind zur Komponente zugehörige Methoden. Die Home-Komponente wird in unserem Projekt als HomeRouter betitelt.
- %
- \begin{center}
- \begin{lstlisting}[caption={HomeRouter-Komponente},captionpos=b]
- const HomeRouter = {
- template: `
- <div id="om-msg-cards">
- <MsgCard
- v-for="id in messagelist.slice().reverse()"
- :key="id"
- :msg="messages[id] || {}"
- ></MsgCard>
- </div>`,
- //Restliche Komponente
- ...
- \end{lstlisting}
- \end{center}
- %
- Im Newsfeed, welcher der Hauptbestand der Startseite ist, wird eine Liste von Nachrichten dynamisch generiert, sodass jeder Nutzer später einmal eine individuelle Ansicht erhält, abhängig von den Tags, die dieser abonniert. \\
- Jede Komponente besitzt ein Template in Form eines Strings, welcher HTML-Code \mbox{beinhaltet}. Die Komponente HomeRouter ist verschachtelt und enthält die Komponente MsgCard. Der Quellcode für diese Komponete ist in Listing 2 zu sehen.
- %
- \begin{center}
- \begin{lstlisting}[caption={MsgCard-Komponente},captionpos=b]
- Vue.component('MsgCard', {
- template: `<div class="om-card card">
- <h6 class="msg-head">
- <b>{{ msg.subject }}</b>
- <img src="favicon.ico" width=20px height=20px>
- </h6>
- {{ msg.message }}<br><br>
- <a href="#">{{ msg.tag }}</a></p>
- <div class="om-card-footer"> <div class="om-user-line">
- <i class="material-icons">account_circle</i>
- Erstellt von {{ msg.user }}</div>
- <i class="material-icons">bookmark_border</i>
- </div></div>`,
- props: ['msg']
- });
- \end{lstlisting}
- \end{center}
- %
- Eine MsgCard stellt eine einzelne Nachricht in Form einer Karte dar. In der HomeRouter-Komponete geht eine For-Schleife alle vorhandenen Nachrichten-Ids durch. Dabei werden der MsgCard-Komponente alle relevanten Informationen übergeben, die für eine Darstellung benötig wird. Am Ende stellt die App eine fortlaufende Liste mit allen Nachrichten dar.\\\\
- Da wir nun ein bisschen geübter im Umgang mit Vue waren, teilten wir uns die restlichen Seiten auf. Dabei gingen wir ähnlich vor, wie bei der Home-Komponente.
- %
- \subsection*{11.3. Routing}
- \phantomsection\addcontentsline{toc}{subsection}{11.3. Routing}
- Vue.js bietet eine Reihe von Funktionen, mit denen Sie wiederverwendbare Webkomponenten erstellen können. Routing ist eine dieser Methoden. Der Benutzer kann somit zwischen den Seiten wechseln, ohne diese erneut zu aktualisieren. Dies ermöglicht dem Benutzer eine einfache und dynamische Navigation durch die Webanwendung. Wir werden Ihnen nun, anhand unseres Codes erklären, wie ein Vue.js-Router funktioniert.\cite{vue:router} \\
- Zunächst richten wir hierfür die Navigation über die Navigationsbar ein, die wir mittels einem Router-Link-Element erstellt haben. Dieser gibt an, auf welche der angegebenen JS-Datei zugegriffen wird sobald man auf das ausgewählte Item klickt.
- %
- \begin{center}
- \begin{lstlisting}[caption={Navbar},captionpos=b]
- <nav class="nav nav-tabs nav-justified om-nav" v-if="$route.path !=='/createMessage' ">
- <router-link to="/home" class="nav-item nav-link">
- <i class="material-icons">home</i></router-link>
- <router-link to="/files" class="nav-item nav-link">
- <i class="material-icons">language</i></router-link>
- <router-link to="/createMessage" class="nav-item nav-link outlined">
- <i class="material-icons">add_circle</i></router-link>
- <router-link to="/bookmark" class="nav-item nav-link">
- <i class="material-icons">bookmark</i></router-link>
- <router-link to="/profil" class="nav-item nav-link">
- <i class="material-icons">person</i></router-link>
- </nav>
- \end{lstlisting}
- \end{center}
- %
- Im Folgenden werden Komponenten definiert und dann in ein neues Array von Objekten, so genannte Routen, eingefügt. Zu beachten ist die Zuordnung eines URL-Pfads zu der dazugehörigen Komponente. Daraufhin wird ein Vue-Router definiert, der an ein neues Vue-Objekt übergeben wird. Wenn nun beispielsweise ''/home'' geladen ist, wird die Home-Komponente in der Router-Ansicht gerendert und aufgerufen. Die erste Zeile mit dem ''/'' steht für die Startseite, auf die man gelangt, sobald man die App öffnet.\cite{vue:router3} \\
- %
- \begin{center}
- \begin{lstlisting}[caption={Routing},captionpos=b]
- const routes = [
- { path: "/", component: HomeRouter },
- { path: "/home", component: HomeRouter },
- { path: "/files", component: FileRouter },
- { path: "/createMessage", component: CreateMsgRouter },
- { path: "/bookmark", component: BookmarkRouter },
- { path: "/profil", component: ProfilRouter },
- ];
- const router = new VueRouter({
- routes
- });
- var app = new Vue({
- router,
- el: '#api',
- methods: {
- ...
- },
- });
- \end{lstlisting}
- \end{center}
- Zu Anfang entschieden wir uns dafür, das Routing auf die index.html Seite zu setzen. Nun jedoch waren wir der Meinung, dass es besser wäre diese in eine eigene Komponente einzubinden.
- Komponenten sind wiederverwendbare Vue-Instanzen mit einem Namen, in diesem Fall „nav-router“. Wir können diese Komponente nun als benutzerdefiniertes Element in einer mit new Vue erstellten Root-Vue-Instanz verwenden, welches auf der index.html Seite liegt.
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=8cm] {../grafiken/Navbar_2.png}
- \caption{Navigationsbar}
- \label{abbildung_2}
- \end{figure}
- \end{center}
- Nun konnten wir die Navigationsleiste einfacher bearbeiten. Die erste Herausforderung war es, den aktiven Router-Link dementsprechend hervorzuheben. Hierfür gibt es die buefy.css Datei, in der man derartige Änderungen vornehmen kann. Es wird nun beim Verwenden der App geschaut, welcher Link momentan aktiv ist. Dieser wird dann in einer etwas dunkleren Farbe und mit einer Kante am unteren Rand der Navigationsleiste markiert.
-
- %
- \section*{12. Service Worker}
- \phantomsection\addcontentsline{toc}{section}{12. Service Worker}
- Der ServiceWorker ist eine JavaScript Datei, die üblicherweise im root-Verzeichnis der Webanwendung liegt. Für die Funktionsweise ist die Namensgebung der Datei nicht maßgebend. Damit der ServiceWorker überhaupt funktionieren kann, wird eine SSL-Verbindung benötigt. Ist eine sicher Verbindung gegeben, kann der ServiceWorker (im Weiteren auch mit ''SW'' abgekürzt) nach erfolgreichem Laden der Webseite im Browser des Clients registriert werden. Nachdem der SW zeitlich unabhängig, also asynchron im Browser läuft, muss bei der Entwicklung und Umsetzung des ServiceWorker-Codes darauf geachtet werden, dass in Promises geschrieben wird. Da Promises ein wenig schwieriger nachzuvollziehen sind und insbesondere das Problem der sogenannten Callback-Hell nicht lösen, bietet es dich an den SW in Async/Await Struktur zu schreiben. Diese basiert auf dem asynchronen Prinzip der Promises und lässt sich dennoch lesen wie synchrone Funktionen.\\
- Zunächst wird der ServiceWorker, nach dem vollständigen Laden der Webanwendung, versuchen sich im Browser des Clients zu registrieren. Schlägt die Registrierung fehl, ist dies ein Anzeichen dafür, dass der genutzte Browser keine ServiceWorker unterstützt. Es folgen zwei Code Umsetzungen, beide dienen der Registrierung:\\
- %
- \begin{center}
- \begin{lstlisting}[caption={Register, Promise/Then-Codestruktur},captionpos=b]
- /* Promise / Then */
- if ('serviceWorker' in navigator) {
- window.addEventListener('load', function() {
- navigator.serviceWorker.register('/serviceWorker.js').then(function(registration) {
- // Registration was successful
- }, function(err) {
- // registration failed
- });
- });
- }
- \end{lstlisting}
- \end{center}
- %
- \begin{center}
- \begin{lstlisting}[caption={Register, Async/Await-Codestruktur},captionpos=b]
- /* Async / Await */
- const registerServiceWorker = async () => {
- try {
- const registration = await navigator.serviceWorker.register('/serviceWorker.js', {scope: '/'});
- // Registration successful
- } catch (err) {
- // Registration failed
- }
- return;
- }
- if ('serviceWorker' in navigator) {
- window.addEventListener('load', registerServiceWorker());
- }
- \end{lstlisting}
- \end{center}
- %
- Einmal in der Promise.then Schreibweise und einmal in der Async/Await Schreibweise.\\
- Nach erfolgreicher Registrierung, folgt das ServiceWorker Event Installation. Dabei wird eine neue ServiceWorker Version im Browser angelegt und ein Abbild der festgelegten Dateien, hier als Beispiel nur die ''index.html'' (siehe filesToCache), im sogenannten ''Local Storage'' mittels Cache-Managements (auch Cache API genannt) gespeichert. Diese beiden Code Blöcke zeigen den Install-Vorgang:
- %
- \begin{center}
- \begin{lstlisting}[caption={Install, Promise/Then-Codestruktur},captionpos=b]
- /* Promise / Then */
- const cacheName = 'appname-v1-0';
- const filesToCache = [ '/index.html' ];
- self.addEventListener('install', function(event) {
- console.log('[ServiceWorker] Install');
- event.waitUntil(
- caches.open(cacheName).then(function(cache) {
- console.log('[ServiceWorker] Caching app shell');
- return cache.addAll(filesToCache);
- })
- );
- });
- \end{lstlisting}
- \end{center}
- %
- \begin{center}
- \begin{lstlisting}[caption={Install, Async/Await-Codestruktur},captionpos=b]
- /* Async / Await */
- const installNewCache = async (event) => {
- const cacheName = 'appname-v1-0';
- const filesToCache = [ '/index.html' ];
- const cacheStatic = await caches.open(cacheName);
- cacheStatic.addAll(filesToCache);
- console.log('[ServiceWorker] Cache static files.');
- return;
- }
- self.addEventListener('install', event => {
- // don't wait
- self.skipWaiting();
- // cache static files
- event.waitUntil(installNewCache());
- console.log('[ServiceWorker] Install');
- });
- \end{lstlisting}
- \end{center}
- %
- Anschließend folgt die Aktivierung. Hier wird aufgeräumt und zwar die alten ServiceWorker Versionen. Es sollte immer nur eine ServiceWorker Version je Webanwendung im Browser registriert und installiert sein.
- %
- \begin{center}
- \begin{lstlisting}[caption={Activate, Promise/Then-Codestruktur},captionpos=b]
- /* Promise / Then */
- self.addEventListener('activate', function(event) {
- // ServiceWorker activated
- event.waitUntil(
- caches.keys().then(function(cacheKeyList) {
- return Promise.all(
- cacheKeyList.map(function(cacheKeyList) {
- if (cacheWhitelist.indexOf(cacheKeyList) === -1) {
- // Old Cache removed
- return caches.delete(cacheKeyList);
- }
- })
- );
- })
- );
- return self.clients.claim();
- });
- \end{lstlisting}
- \end{center}
- %
- \begin{center}
- \begin{lstlisting}[caption={Activate, Async/Await-Codestruktur},captionpos=b]
- /* Async / Await */
- const cacheCleanUp = async () => {
- const cacheKeyList = await caches.keys();
- const deletions = cacheKeyList
- .filter(key => key.startsWith(appPrefix) && !cacheKeyList.includes(key))
- .map(key => {
- caches.delete(key)
- // Old Cache removed
- });
- for (const success of deletions) {
- await success;
- }
- return;
- }
- self.addEventListener('activate', event => {
- event.waitUntil(cacheCleanUp());
- clients.claim();
- // ServiceWorker activated
- });
- \end{lstlisting}
- \end{center}
- %
- Als letzter Schritt bleibt nur noch der 'fetch'. Das ist jenes Event in dem der ServiceWorker neue, aktuelle Dateien aus dem Netzwerk bezieht und die Dateiversionen im Cache, lokalen Speicher aktualisiert. Hier gibt es verschiedene Vorgehensweisen. Wir haben uns entschieden, das der ServiceWorker nur jene API GET-Anfragen speichern soll. Dies dient der Vermeidung doppelter und korrupter Datensätze. Im Weiteren soll überprüft werden, ob die angefragten Dateien mit den gespeicherten Dateien übereinstimmt. Falls nicht, gibt es keine gespeicherten Daten und eine Netzwerkanfrage wird zwingend benötigt. Andernfalls zeige die gespeicherten Daten an und tätige anschließend eine Anfrage ans Netzwerk. Wenn aktuellere Daten aus dem Netzwerk empfangen werden, so aktualisiere die gespeicherten Dateien und zeige die aktuelleren Daten an. Zusätzlich wird noch ein wenig der Ursprung der Anfrage überprüft.
- %
- \begin{center}
- \begin{lstlisting}[caption={Fetch, Promise/Then-Codestruktur},captionpos=b]
- /* Promise / Then */
- self.addEventListener('fetch', function(event) {
- /* We should only cache GET requests */
- if (event.request.method !== 'GET') {
- /* If we don't block the event as shown below,
- then the request will go to the network as usual. */
- console.log('[ServiceWorker] Fetch event ignored.',
- event.request.method, event.request.url);
- return;
- }
- event.respondWith(
- caches.match(event.request)
- .then(function(response) {
- return fetch(event.request)
- .then(function(response) {
- // Check if response is valid, status is 200, response type is basic
- // (indicates request is from origin, means that requests to third party
- // assets aren't cached as well.
- if(!response || response.status !== 200 || response.type !== 'basic') {
- return response;
- }
- caches.open(CACHE_NAME)
- .then(function(cache) {
- // We have to clone the response here because request bodies can only
- // be read once. Placing a response in the cache counts as a read.
- cache.put(event.request, response.clone());
- });
- // Cache hit - return response
- if (response) return response;
- return response;
- });
- })
- .catch(function(err) {
- // Report a lack of connectivity to the user.
- });
- });
- \end{lstlisting}
- \end{center}
- %
- \begin{center}
- \begin{lstlisting}[caption={Fetch, Async/Await-Codestruktur},captionpos=b]
- /* Async / Await */
- self.addEventListener('fetch', event => {
- /* We should only cache GET requests */
- if (event.request.method !== 'GET') {
- /* If we don't block the event as shown below,
- then the request will go to the network as usual. */
- console.log('[ServiceWorker] Fetch event ignored.',
- event.request.method, event.request.url);
- return;
- }
- event.respondWith(async function update() {
- try {
- var requestURL = new URL(event.request.url);
- // Start the network request as soon as possible.
- const networkPromise = fetch(requestURL);
- const cachedResponse = await caches.match(event.request);
- const networkResponse = await networkPromise;
- // Check if response is valid, status is 200, response type is basic
- // (indicates request is from origin, means that requests to third party
- // assets aren't cached as well.
- if (!networkResponse || networkResponse.status !== 200
- || networkResponse.type !== 'basic') return networkResponse;
- const cache = await caches.open(staticCacheKey);
- // We have to clone the response here because request bodies can only
- // be read once. Placing a response in the cache counts as a read.
- cache.put(event.request, networkResponse.clone());
- if (cachedResponse) return cachedResponse;
- // ServiceWorker fetch
- return networkResponse;
- } catch (err) {
- // Report a lack of connectivity to the user.
- }
- }());
- });
- \end{lstlisting}
- \end{center}
- %
- Die Bildausschnitte mit dem Code wurden teils von mir erstellt, teils stammen diese von dieser Internetseite\cite{dev:codeSource}\cite{sw:cacheThenNetwork}.
- %
- \pagebreak
- \section*{13. ''Add-To-Homescreen''-Funktion}
- \phantomsection\addcontentsline{toc}{section}{13. ''Add-To-Homescreen''-Funktion}
- Für die Implementierung der ''Add-to-Homescreen''-Funktionalität sind für Android, iOS und die diversen Browser unterschiedliche Schritte nötig.\\
- Bei Android genügt es eine manifest.json Datei im root-Verzeichnis der App abzulegen. Diese Manifest-Datei enthält Meta-Informationen von App-Icon, über App-Name, über die Start-URL bis hin zu der Theme-Farbe für den Hintergrund des App-Icons oder dem Navigationsmenü im Browser. Wenn ein Nutzer im Abstand von 5 Minuten (Standard-Einstellung) die Webseite zweimalig aufruft, so wird dieser gefragt, ob er die App zum Homescreen hinzufügen möchte. Ab da kann er diese über das App-Icon als auch über den Browser starten.\\
- Für iOS müssen die Meta-Informationen im Bereich des Head-Elements, der index.html eingefügt werden. So wird dort das Aussehen von mehreren App-Icon Versionen definiert. Dies wird benötigt, da die meisten Apple-Geräte unterschiedliche Density (Pixel per Inch) haben. Des Weiteren werden Konfigurationseinstellungen aktiviert oder deaktiviert, als auch das Aussehen des Ladescreens für iOS Geräte festgelegt.\\
- Auch die Windows-Mobilgeräte muss in der index.html Datei im Head-Bereich mittels Meta-Informationen mitgeteilt werden, wie der Ladebildschirm oder das Appicon aussehen soll (vgl.\cite{dev:homescreen}).
- %
- \section{Desktopansicht}
- Da unsere Anwendung eine Progressive Web App ist, ist ein Aspekt davon, dass man diese sowohl auf dem Smartphone und Tablett als auch am Computer oder Laptop mit dem Internetbrowser verwenden kann. Da es jedoch nicht üblich ist die App Ansicht im Browser zu benutzen, musste die Anwendung überarbeitet werden. Demzufolge wurde je nach verwendetem Gerät und Größe die Ansicht angepasst und dementsprechend verändert.
-
-
- \subsection{Bulma Elemente}
- Um dies umsetzen zu können, wurden Elemente von Bulma verwendet. Bulma ist ein freies und Open-Source Frontend-CSS-Framework, welches auf Flexbox basiert \textsuperscript{3}. HTML und CSS basierende, gestalterische Vorlagen werden hierfür benutzt um zum Beispiel Formulare, Buttons, Navigations- und andere Oberflächengestaltungselemente zu erzeugen.
- Um nun die Desktopansicht anzupassen, werden dem notwendigen Inhalt der verschiedenen Seiten Klassen gegeben, sogenannte „Column Sizes“ (Spaltengrößen). Sobald die Fenstergröße ein bestimmtes Maß erreicht hat, wird entschieden welche Ansicht angezeigt wird. \\
-
- \lstset{
- basicstyle=\ttfamily,
- columns=fullflexible,
- frame=single,
- breaklines=true,
- postbreak=\mbox{\textcolor{red}{$\hookrightarrow$}\space},
- }
- \begin{lstlisting}
- const ProfilRouter = {
- template: `
- <div>
- <div class="column pull-right-sm is-four-fifths-desktop">
- ...
- </div>
- \end{lstlisting}
- Es wird also veranlasst, dass der Inhalt ab der Mindestgröße des Desktops nur noch auf vier Fünftel der Browserbreite angezeigt wird und zusätzlich auf die rechte Seite geschoben wird. Solange die Breite unter dem Mindestmaß bleibt, also alles bis zur Desktopgröße wie zum Beispiel das Tablet oder Smartphone-Format, wird nichts am Inhalt geändert.
-
-
- \subsection{Navigationsleiste wird zum Menü}
- Die meisten Apps besitzen für gewöhnlich eine Navigationsleiste, die das schnelle und unkomplizierte Erreichen der Seiten ermöglicht. Diese liegt teilweise unten am Bildschirm, da man dort am schnellsten mit dem Finger hinkommt. Deswegen bauten wir unsere App auch dementsprechend auf. Wenn man jedoch nun auf die Desktopversion umsteigt, wirkt diese Variante weder praktisch noch optisch anregend. Aufgrund dessen entschieden wir uns für die Verwendung einer einfachen Auflistung der Navigationselemente in Form eines Menüs auf der linken Seite. Somit hat man immer noch den schnellstmöglichen und direkten Zugriff auf die verschiedenen Seiten und man verläuft sich nicht in lästigen „Sackgassen“.
-
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=17cm] {../grafiken/Desktopansicht.png}
- \caption{App-Ansicht vs. Desktopansicht}
- \label{abbildung_4}
- \end{figure}
- \end{center}
- Um die Navigationsleiste umzustellen, wurden zum Teil sogenannte „Responsive Helpers“ verwendet. Zunächst wurde der Inhalt der Navigations-Komponente teilweise dupliziert und im Anschluss personalisiert. Dem ersten Element wird die Klasse „is-hidden-desktop“ gegeben und somit wird ausgesagt, dass es während der Appansicht sozusagen versteckt wird. Beim zweiten Element ist es die Klasse „is-hidden-touch“, also alles ab der Tabletgröße abwärts wird nicht auf der Desktopansicht zu sehen sein. Ebenfalls wird aus der „navbar“ ein „menu“ mit einer Liste (menu-list), in der die Router-Links aufgelistet sind. Ein weiteres Extra sind hier die Beschriftungen der jeweiligen Seiten, für die in der Navigationsleiste unten in der Appansicht kein Platz war.
- Und so sieht nun die fertige Navigations-Komponente in Form von Code aus: \\
-
- \lstset{
- basicstyle=\ttfamily,
- columns=fullflexible,
- frame=single,
- breaklines=true,
- postbreak=\mbox{\textcolor{red}{$\hookrightarrow$}\space},
- }
- \begin{lstlisting}
- Vue.component('nav-router', {
- template: ` <div>
- <nav class="navbar is-fixed-bottom is-expanded is-primary is-hidden-desktop}" role="navigation" aria-label="main navigation">
- <div class="navbar-brand is-expanded is-light">
- <router-link to="/home" class="navbar-item is-primary is-expanded has-text-centered is-hidden-desktop">
- <i class="material-icons">home</i>
- </router-link>
- ...
- </nav>
-
- <div class="is-fullheight">
- <div class="column is-sidebar-menu is-hidden-touch">
- <aside class="menu is-medium">
- <ul class="menu-list">
- <li><router-link to="/home">
- <i class="material-icons">home</i> Home
- </router-link></li>
- ...
- </ul>
- </aside>
- </div>
- </div>
- </div>`,
- \end{lstlisting}
-
-
-
- \section*{14. Erstellung der API-Schnittstelle}
- \phantomsection\addcontentsline{toc}{section}{14. Erstellung der API-Schnittstelle}
- Nachdem Server und die Clientseite der PWA funktionsfähig waren, war es noch relevant, dass zwischen diesen beiden kommuniziert werden kann. Dafür verwendet man die API.\cite{api} API steht für ''Application Programming Interface'' und diese Programmierschnittstelle kann wie in diesem Projekt zum Zugriff auf die Datenbank verwendet werden. Dabei handelt es sich in diesem Fall um einen RESTful Webservice.\cite{rest} \\
- %
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.3\textwidth]{../grafiken/ajax.png}
- \caption{Ajax Modell einer Webanwendung. Quelle: nach Haischt, Daniel; https://de.wikipedia.org/wiki/Ajax\_(Programmierung)\#/media/File:Ajax-vergleich.svg}
- \label{ajax}
- \end{figure}
- %
- \noindent Das asynchrone Datenübertragungskonzept AJAX wurde zur Kommunikation zwischen Browser und Server verwendet.\cite{ajax1} \cite{ajax2} \cite{ajax3} Dabei werden wie in Abbildung \ref{ajax} zu sehen ist HTTP Requests von dem Browser an den Server geschickt. Diese werden daraufhin von dem Server verarbeitet und es werden entweder Daten zurückgegeben oder ein HTTP Response mit einer Rückmeldung. Mit der Verwendung von AJAX hat man einige Vorteile, zum Beispiel, dass man die Seite nicht neu laden muss, damit die neuen Inhalte erscheinen und dass der Browser bereits weiter Requests schicken kann, ohne auf die Responses des Servers warten zu müssen. Da die gesamte PWA des Projekts in JavaScript geschrieben ist, ist es zudem vorteilhaft, dass die AJAX-Engine in JavaScript geschrieben wird. Die Daten aus der Datenbank werden im JSON-Format transportiert.\\
- \\
- Um die Funktionsweise einer derartigen Schnittstelle zu verstehen, wurde der Code einer PWA die Professor Matthias Hopf geschrieben und der Gruppe zur Verfügung gestellt hat, analysiert. Dieser war jedoch etwas zu komplex für einen Einsteiger in das Thema. Deswegen wurde auf simplere Beispiele in Tutorials zurückgegriffen. Diese Beispiele konnten nun auf das eigene Projekt übertragen und getestet werden. Nach einer ausführlichen Erläuterung durch Professor Hopf anhand eines Beispiels im Projektzusammenhang, war ein grundsätzliches Verständnis über die Schnittstelle vorhanden. Nun konnte die konkrete Umsetzung der API beginnen.\\
- Die erste Methode die umgesetzt wurde war ''list\_messages''. Diese zeigt nun alle Nachrichten der Datenbank auf der Startseite der PWA an. Dazu musste zuerst vom Server die IDs aller Nachrichten abgefragt werden. Man schreibt eine API Funktion, die ein GET Request an den Server schickt. Dieser sucht nach den IDs per find Anfrage in der Datenbank und antwortet mit einem HTTP Response, der das Array mit den IDs enthält. Auf der Client Seite wird nun für jede ID per GET Request alle Informationen der Nachricht angefragt. Der Server sucht die gefragten Information und schickt diese zurück mit dem dazugehörigen Nachrichtentext an den Browser.\\
- %
- \begin{center}
- \begin{lstlisting}[caption={''list\_messages''-Methode},captionpos=b]
- list_messages: function () {
- $.ajax({url: "api/ids", method: "GET"})
- .done(jd => {
- _messagelist.splice(0, _messagelist.length);
- _messagelist.push.apply(_messagelist, jd);
- console.log("jd: "+jd);
- for (var e in jd) {
- if (!_messages[jd[e]]) {
- get_insert_message(jd[e]);
- }
- }
- }).fail(function (e, f, g) {
- console.log("err: " + e + f + g);
- });
- }
- \end{lstlisting}
- \end{center}
- %
- Was für Vorgänge beim Senden einer Nachricht in einer API getätigt werden, ist im Folgenden aufgeführt. Hierfür muss die Mongodb heruntergeladen und angebunden sein.\\
- In der Server.js Datei wird durch die ''App.post''-Methode eine Nachricht erstellt. Dabei wird in ''createMsg'' die Funktion aufgerufen, in einen String umgewandelt und die Nachricht anschließend in der Datenbank gespeichert. Mit der POST-Methode können Nachrichten in die Datenbank gespeichert werden und anhand von einer GET-Methode angezeigt werden.\\
- Nun müssen in der createMsg.js alle Werte einsetzbar gestaltet werden. Wichtig dabei ist, sich an das vorgegebene Mongo Schema zu halten. Durch die ajax-Methode ''post'' können große Datenmengen an den Server geschickt werden. Zuletzt soll die Konsole auch einen Error anzeigen, falls der Abruf der Funktion erfolglos war. \\
- In Abbildung \ref{sys} kann man diese Vorgänge nachverfolgen. Diese beiden Funktionen haben am Ende funktioniert und können zusammen verwendet werden. \\
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.7\textwidth]{../grafiken/system.png}
- \caption{Erstellen einer Nachricht und Anzeigen aller Nachrichten}
- \label{sys}
- \end{figure}
- %
- \section*{15. Aufsetzung des Servers}
- \phantomsection\addcontentsline{toc}{section}{15. Aufsetzung des Servers}
- Zunächst muss ein http port eingerichtet werden. Über einen lokalen Server über node.js ist die Ohm News-App abrufbar. Mit der createServer Methode
- %
- \begin{center}
- \begin{lstlisting}[caption={''list\_messages''-Methode},captionpos=b]
- http.createServer(app).listen(http_port, function () {
- console.log("Express http server listening on port " + http_port);
- });
- \end{lstlisting}
- \end{center}
- %
- lässt sich ein Server aufsetzen. Hier wird auch der Listener für den Port impliziert und auf der Konsole ausgegeben, wenn die Verbindung erfolgreich war. \\
- Um die wichtigsten Fehlermeldungen und Bugs auszugeben, wird für unsere node.js App der Logger ''Morgan'' verwendet. Zusätzlich wird eine try-catch Funktion eingeordnet, da Zertifikat und Schlüssel noch nicht zertifiziert sind (siehe SSL und Keys) und somit vorerst ein Fehler angezeigt wird.
- %
- \subsection*{15.1. SSL und Keys}
- \phantomsection\addcontentsline{toc}{subsection}{15.1. SSL und Keys}
- Um die Applikation für die Nutzer sicher zu gestalten und eine Verschlüsselung sensibler Daten zu gewährleisten, sorgt ein SSL(Secure Socket Layer). Dadurch wird ein sicherer Kanal zwischen Web-Server und Client bereitgestellt und aus der http- wird eine https-Verbindung.
- \setlength{\parindent}{0cm}
- Übergangsweise werden ein selbst verifizierter Schlüssel und Zertifikat erstellt, welche später durch echte ausgetauscht werden. In einem neu erstellten Ordner ''keys'' werden das Zertifikat und der Schlüssel platziert.
- %
- \section*{16. Datenbankanbindung}
- \phantomsection\addcontentsline{toc}{section}{16. Datenbankanbindung}
- Für diese Anwendung wird eine Datenbank benötigt, weil die geschriebenen Nachrichten gespeichert werden müssen. Später sollen auch User mit ihren Userinformationen gespeichert werden. Im Falle dieses Projekts wurde sich für eine MongoDB entschieden.\\
- MongoDB ist eine dokumentenorientierte NoSQL Datenbank. Diese ist für diese Anwendung sinnvoll, da sie im Vergleich zu SQL Datenbanken flexibler handhabbar ist und somit auch viele Einstellungen noch im Nachhinein geändert werden können.\cite{mongo} \\
- Um den Umgang mit MongoDB zu vereinfachen wurde Mongoose, eine Object Data Modeling Bibliothek, verwendet.\cite{mongoose} \\
- Da man zu Beginn des Projekts noch nicht mit NoSQL Datenbanken gearbeitet hatte, mussten zuerst Tutorials und Erklärungen gelesen werden. Anhand von Beispieltests mit einer lokalen Datenbank konnte die grundsätzliche Funktionsweise bald verstanden werden. Daraufhin wurde das grobe Schema für eine Nachricht aufgebaut. Eine Nachricht sollte einen Betreff, eine Nachricht, den schreibenden User und die Tags beinhalten wie man in Listing \ref{lst:json} an einer beispielhaften JSON-Datei sehen kann. Die Datenbank musste konfiguriert und gestartet werden.
- %
- \begin{center}
- \lstset{language=xml}
- \begin{lstlisting}[caption={Nachricht im JSON-Format},captionpos=b,label=lst:json]
- {
- "messages": [{
- "subject": "Test"
- "message": "Hallo Welt!"
- "tag": "#OHM_News"
- "user": "User1"
- }]
- }
- \end{lstlisting}
- \lstsetdefault
- \end{center}
- %
- Die serverseitigen Codeteile zur API und der Code für die Datenbank sind momentan zur Vereinfachung in der server.js Datei. Später sollen diese zur Übersichtbarkeit und Wartbarkeit ausgelagert werden. Das Schema für die Nachricht und die Konfiguration der Datenbank sind zu diesem Zweck bereits in eigenen js-Dateien zu finden.\\
- Sobald all das lokal funktioniert hat, wurde die Portierung auf einen Server der Hochschule vorgenommen.\\
-
- In dem zweiten Abschnitt unseres Projekts sollten zusätzliche Funktionen wie das Suchen nach Tags und das Einloggen umgesetzt werden. Dafür musste der bisherige Aufbau der Datenbank erweitert und abgeändert werden. Die dafür benötigten Schemata wurden in der neu erstellten db.js Datei definiert.
- Um nach Tags suchen zu können wurde eine Collection in der Datenbank benötigt, die alle verwendbaren Tags beinhaltet. Folglich musste ein Schema für die Daten in dieser Collection erstellt werden. Dieses Schema legt fest, dass jedes gespeicherte Tag zwingend einen Namen benötigt. Da dieser eindeutig also unique ist, sollte das für die Identifikation bei der Suche genügen. \\
- Um das Rollenkonzept und die Login-Funktion umsetzen zu können, musste eine weitere Collection in der Datenbank erstellt werden. Jeder Hochschulangehörige soll sich in der Anwendung anmelden können und es sollten die wichtigsten Daten zu dem jeweiligen Benutzer in der User Collection gespeichert oder aktualisiert werden. Dabei wurde vorgesehen, dass eine ID zur Identifikation und als Primärschlüssel erstellt wird. Informationen wie Name, Emailadresse, Typ (Art von Nutzer z.B.: author, admin), Geschlecht, Rollen (Bereiche, die für den Nutzer erlaubt sind), Passwort, sowie Hash und Salt des angemeldeten Nutzers sollten wie in Abbildung \ref{fig:pic2} zu sehen ist in der Datenbank hinterlegt werden. Zusätzlich wurde im User Schema die Session-ID, ein Array an ID von allen vom Nutzer gespeicherten Nachrichten und ein Array an vom Nutzer abonnierten Tags angelegt.
-
- \begin{figure}[h]
- \centering
- \includegraphics[width=0.85\textwidth]{../grafiken/pr2}
- \caption{User im JSON-Format, Quelle: eigene Darstellung}
- \label{fig:pic2}
- \end{figure}
-
- \subsection{Erstellen der Test-Datenbank}
-
- Um die neuen Funktionen beim Erstellen gut testen zu können, war es aus dem und anderen Gründen (schneller, einfacher, zuverlässiger) eine lokale Test-Datenbank zu erstellen. Damit nicht jedes Gruppenmitglied eine solche Datenbank selbst erstellen und befüllen musste, wurde ein Skript geschrieben, das diese beiden Funktionen übernehmen sollte.\\
- Das in mong.js gespeichert Skript wechselt zu der Datenbank namens „omdb“ oder legt, falls sie noch nicht existiert diese an. Als erster Schritt werden nun alle Collections und deren Inhalte aus der Datenbank mit Hilfe der 'deleteMany()'-Funktion gelöscht, damit die Testdaten nicht mehrfach gespeichert werden. Daraufhin werden drei weitere Skripte für die jeweiligen Collections geladen.\\
- Das erste Skript namens mong\_msg.js beinhaltet acht Bespielnachrichten, die in Betreff, Nachricht, Nutzer und Tags mit Platzhaltertexten befüllt sind.
- In mong\_tag.js werden elf Beispieltags in die Tag-Collection eingefügt. Diese werden später benötigt, um die Autocomplete-Funktion in der Suche und der Nachrichtenerstellung testen zu können.
- Als drittes muss nach die User-Collection befüllt werden, um die Login-Funktion testen zu können. Dazu werden zwei Beispielnutzer erstellt. Der Erste bekommt den Namen „Test Author“ und soll einen Nutzer mit Schreiberlaubnis darstellen. Der Zweite mit dem Namen „Test Admin“ soll Administrationsaufgaben übernehmen können. \\
- Die Daten werden jeweils mit 'insert()' in die Collections geschrieben, wodurch die Collections falls sie noch nicht existieren erstellt werden. In Abbildung \ref{fig:pic3} ist zu sehen wie eine Nachricht aus der Testdatenbank aussieht.
-
- \begin{figure}[h]
- \centering
- \includegraphics[width=\textwidth]{../grafiken/pr3}
- \caption{Nachricht mit Text aus Testdatenbank, Quelle: eigene Darstellung}
- \label{fig:pic3}
- \end{figure}
-
-
-
- \subsection{Autocomplete-Funktion}
-
- Wenn in der Anwendung eine Nachricht erstellt werden soll, kann der Nutzer Tags zu der Nachricht hinzufügen. Um nicht zu viele oder zu viele ähnliche Tags setzen zu können, war vorgesehen, dass nur eine bestimmte Liste an Tags verwendet werden kann, die von dem Administrator verwaltet werden kann. Diese Tags sind in der Tag-Collection der Datenbank gespeichert. Nun soll bei der Nachrichtenerstellung im Eingabefeld für die Tags eine Autocomplete-Funktion eingefügt werden, die die Tags aus der Datenbank als Auswahl lädt. \\
- Dazu muss vorerst das globale Array data mit den Tags befüllt werden. Dafür wird die Methode 'list\_tags()' aufgerufen, die mittels AJAX-Aufruf die IDs aller Tags aus der Datenbank abfragt und als Array zurückschickt. Durch dieses Array wird daraufhin iteriert. Die IDs werden anschließend an die globale Funktion 'get\_insert\_tag(id)' übergeben. Dort holt ein AJAX-Aufruf mit der jeweiligen Tag-ID den Namen aus der Datenbank und lädt (push) diesen auf das data-Array.\\
- Wenn nun der Nutzer eine Eingabe in das Tag-Feld tätigt, wird die 'filteredDataArray()'-Methode aufgerufen. Diese durchsucht nun das data-Array mit der 'filter()'-Funktion nach dem eingegebenen Wort und gibt dieses an das Autocomplete-Input-Feld von Buefy [1] zurück. Dort werden die gefilterten Daten aus dem Array wie in Abbildung \ref{fig:pic4} zu sehen ist unter dem Eingabefeld angezeigt.
-
- \begin{figure}[h]
- \centering
- \includegraphics[width=0.75\textwidth]{../grafiken/pr4}
- \caption{Autocomplete-Funktion, Quelle: eigene Darstellung}
- \label{fig:pic4}
- \end{figure}
-
- \section{Suche}
- \subsection{Frontend der Suchfunktion}
-
- Eine der zentralen Funktionen von Ohm-News ist das Suche von Nachrichten. Auf diese Weise ist es für Studierende möglich Informationen schnell zu finden. Eine Möglichkeit der Suche bietet das Suchfeld im Header, welches von jeder Seite aus zugänglich ist. Es handelt sich hierbei um eine Freitextsuche. \
-
- Um die Eingabe zu erleichtern werden Tags über die Autocomplete Komponente von Buefy vorgeschlagen (vgl. Listing 3). Diese Komponente weist gewisse Ähnlichkeiten zu der Taginput Komponente auf und verwendet ebenfalls die Methode filteredDataArray( ) (vgl. S.8, Listing 2). Bei Bestätigung der Sucheingabe wird die Methode search( ) aufgerufen.
-
- \begin{lstlisting}[caption=Template zur search Komponente]
- Vue.component('search',{
- template: `
- <form class="om-searchbar" @submit.prevent="search()">
- <b-field>
- <b-autocomplete
- v-model="searchtext"
- :data="filteredDataArray"
- @keydown.native.enter="search"
- placeholder="suche..."
- icon="magnify"
- @select="option => selected = option">
- </b-autocomplete>
- <button class="clearButton" @click="clear">x</button>
- </b-field>
- </form>`,
- \end{lstlisting}
-
- Sobald die Suche gestartet wird, wird die globale Variable ''\_isSearchActive'' auf true gesetzt. Die Suchergebnisse werden auf gleiche Weise wie die Nachrichten auf der Startseite geladen. Der Server schickt eine Liste der Message-Ids zu allen Suchergebnissen. Im Anschluss werden die einzelnen Nachrichten zu den entsprechenden Ids angefordert und in msgCard Komponenten dargestellt. \newpage Die Ergebnisseite unterscheidet sich optisch von der Startseite durch einen Link oben links, der die Suche beendet und zurück zur Startseite navigiert (siehe Abbildung 3)\\
-
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=6cm]{../grafiken/3}
- \caption{Darstellung der Suchergebnise}
- \label{Abbildung 3}
- \end{figure}
- \end{center}
-
- Möchte der Nutzer konkret nach einem bestimmten Bestandteil einer Nachricht, wie dem Betreff oder einem Tag filtern, kann die erweiterte Suche verwendet werden (siehe Ab-bildung 4). Diese ist in der Navigationszeile als Menüpunkt zu finden und läuft parallel zu der Suche im Header. In einem Dropdown Menü kann die Art der Suche ausgewählt werden. Daraufhin wird das entsprechende Eingabefeld dargestellt. Die Freie Suche entspricht der Suche im Header und filtert aus allen Bestandteilen der Nachricht. Die Suche nach Betreff, Nachrichtentext, Tags oder User sollte Ergebnisse zu den entsprechenden Nachrichtenfeldern liefern, konnte allerdings aus Zeitgründen nicht mehr im Backend umgesetzt werden. Bei der Suche nach Tags wird wie im Header die Autokomplete-Komponente verwendet. Die Ergebnisse, werden, anders wie bei der Suche im Header, auf der Menüseite unter dem Formular angezeigt.\\
-
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=6cm]{../grafiken/4}
- \caption{Erweiterte Suche}
- \label{Abbildung 4}
- \end{figure}
- \end{center}
-
-
- \subsection{Backend der Suchfunktion}
-
- Im Header der Anwendung befindet sich ein Eingabefeld für Suchanfragen. Die Idee war, dass der Nutzer hier die Nachrichten im Dashboard nach bestimmten Suchbegriffen filtern kann. Dazu sollte sowohl eine freie Suche als auch eine Suche nach den vorgegebenen Tags implementiert werden. Für die Tag-Suche wurde die bereits erklärte Autocomplete-Funktion verwendet.
-
- \subsubsection{Allgemein: Text Index}
-
- Um die Text Suche in der MongoDB verwenden zu können, muss man einen Text Index für die zu durchsuchende Collection erstellen. Eine Collection kann jedoch nur einen Text Index haben. Mit der 'createIndex()'-Funktion kann man eines oder mehrere Felder als Text Index setzen. Wenn man eine Collection, die einen Text Index besitzt, mit dem \$text-Operator durchsucht, bekommt man die gefilterten Datensätze, die den Suchbegriff im Text Index haben. Dabei wird mit einer logischen Oder-Verknüpfung zwischen den durch Leerzeichen und Satzzeichen getrennt Worte des Suchbegriffs gesucht. [2] [3]
-
- \subsubsection{Einfache Suche}
-
- Die Suchfunktion in der Anwendung ist mit dem vorhandenen Eingabefeld im Header verknüpft. In der search.js-Datei befindet sich du dazugehörige Vue-Komponente. In dem Autocomplete-Feld von Buefy wird wie bei der Tageingabe beim Nachrichten erstellen die 'filteredDataArray()'-Methode aufgerufen, um die Tags aus der Datenbank als Vorschläge angezeigt zu bekommen. Zusätzlich soll nun durch den @keydown.native.enter-Event beim Drücken der Eingabe-Taste die Methode 'search()' aufgerufen werden. In dieser Methode wird ein AJAX-Aufruf gestartet, der mittels GET-Methode den Inhalt des Eingabefelds an den Server schickt. Dort wird mit diesem Mongoose-Aufruf die Datenbank durchsucht:\\
- \\
- model.Messages.find(\{\\
- \begingroup
- \leftskip4em
- \$text: \{\\
- \endgroup
- \begingroup
- \leftskip4em
- \$search: \\req.params.phrase\\
- \endgroup
- \begingroup
- \rightskip4em
- \}\\
- \endgroup
- \begingroup
- \rightskip4em
- \})\\
- \endgroup
- \\
- In der Collection Messages wird nach dem Text Index gesucht der den Suchbegriff („phrase“) beinhaltet, die über AJAX übergeben wurde, also die Sucheingabe ist. Damit bei dieser Datenbankabfrage etwas gefunden werden kann, muss dem Schema der Messages-Collection der passende Text Index angefügt werden. Dafür setzt mit der Wildcard „\$**“ alle Felder der Nachricht als Text Index:\\
- \begin{center} messageSchema.index({ "\$**": 'text' });\\ \end{center}
- Sobald die Suchergebnisse in der Datenbank gefunden wurden, werden die IDs der jeweiligen Nachrichten zurück an die 'search()'-Methode geschickt. Die gefilterten IDs werden nun wie bei der Erstellung des Dashboards durchiteriert. Für jede ID wird die globale Funktion \\'get\_insert\_message(id)' aufgerufen. Dort wird ein AJAX-Aufruf gestartet, der die gesamte Nachricht zu der jeweiligen ID aus der Datenbank zurückerhält und diese daraufhin im Dashboard anzeigt.
-
- \subsubsection{Erweiterte Suche}
-
- Da die Router-Komponente File nicht wie ursprünglich geplant als Dateiablage umgesetzt wurde, sollte an dieser Stelle dem Nutzer die Möglichkeit gegeben werden eine ausführlichere Suche durchzuführen. Hier befindet sich auf der Benutzeroberfläche wie in Abbildung \ref{fig:pic5} zu sehen ist ein Drop-Down-Menü mit dem der Nutzer zwischen den verschiedenen Suchformen wechseln kann. Dabei kann man zwischen den folgenden Suchoptionen wählen: freie Suche, Suche nach einem bestimmten Betreff, Tags, Nachrichteninhalten oder Autoren. Unter dem Auswahlmenü befindet sich das Eingabefeld für den gesuchten Begriff. Aus zeitlichen Gründen konnte an dieser Stelle nur testweise die Suche nach bestimmten Tags umgesetzt werden. Die Schwierigkeit dabei war, in der Datenbank nur einzelne Felder zu durchsuchen, da der zuvor erklärte Text Index in der Collection Messages auf alle Felder zugewiesen war und somit keine separate Suche umgesetzt werden konnte. Eine Umsetzungsmöglichkeit wäre die Nutzung einer weiteren Suchfunktion. Die bisher implementierte Suche bei den Tags entspricht von der Logik her der einfachen Suche und durchsucht alle Felder der Nachricht. Das Suchergebnis wird daraufhin direkt unter der Suchanfrage angezeigt.
-
- \begin{figure}[h]
- \centering
- \includegraphics[width=0.5\textwidth]{../grafiken/pr5}
- \caption{Benutzeroberfläche für die erweiterte Suche, Quelle: eigene Darstellung}
- \label{fig:pic5}
- \end{figure}
-
- \section{Nachrichten speichern}
- \subsection{Frontend für das Speichern von Nachrichten}
- Eines unserer Hauptfeatures ist zum einen das Speichern von Nachrichten. Diese Funktion hat den Vorteil, dass der Nutzer zu jeder Zeit einen Überblick über seine Nachrichten hat und diese auch persönlich ordnen kann, um zu vermeiden, dass man lange nach Nachrichten suchen muss. Um dies zu tun, wird auf das dafür vorgesehene Icon geklickt, welches sich mit dem Klick ändert, und zwar zu einem gefüllten Icon. Und so würde der Switch aussehen.
- \begin{figure}[h]
- \centering
- \includegraphics[width=0.75\textwidth]{../grafiken/Bookmark.png}
- \caption{Lesezeichen-Icon (nicht gespeichert/ gespeichert), Quelle: eigene Darstellung}
- \label{fig:pic6}
- \end{figure}
-
- \begin{lstlisting}
- Vue.component('MsgCard', {
- template: ` <div class="om-card card">
- ...
- <i id="bookmark-not-active" class="material-icons" :key="isActive" @click="myFilter(msg._id)" v-if="!isActive">bookmark_border</i>
-
- <i id="bookmark-active" class="material-icons" :key="isActive" @click="myFilter(msg._id)" v-else>bookmark</i>
- ...
- \end{lstlisting}
-
- \subsection{Backend für das Speichern von Nachrichten}
- Der Nutzer sollte wichtige Nachrichten speichern können, um sie zu einem späteren Zeitpunkt schnell und einfach finden zu können. Jede Nachricht im Dashboard hat in der rechten oberen Ecke ein Lesezeichen-Symbol. Beim Klicken auf dieses wird die zugehörige Nachricht gespeichert und kann in der Router-Komponente bookmark aufgerufen werden. \\
-
- In der Vue-Komponente msgCard der Anwendung gibt es ein Lesezeichen-Icon, das unausgefüllt ist und durch Anklicken wie in Abbildung \ref{fig:pic6} dargestellt ausgefüllt wird. Dazu wird mit @click die 'myFilter(Id)'-Methode aufgerufen. In dieser Methode wird über den booleschen Wert 'isActive' abgefragt ob diese Nachricht bereits gespeichert wurde. Falls sie bereits gespeichert ist, wird die ID der Nachricht aus dem globalen Array auth.bookmarks, das alle Lesezeichen des angemeldeten Nutzers aus der Datenbank beinhaltet, gelöscht. Zusätzlich wird der 'isActive'-Wert auf false gesetzt. Wenn die Nachricht noch nicht gespeichert wurde, wird die jeweilige ID in auth.bookmarks gespeichert und 'isActive' auf true gesetzt.\\
- \begin{lstlisting}
- data: function () {
- return {
- isActive: false,
- };
- },
- methods: {
- myFilter: function() {
- this.isActive = !this.isActive;
- },
- }
- });
- \end{lstlisting}
- In der BookmarkRouter-Komponente sollen nun alle Nachrichten, die von dem Nutzer gespeichert wurde, angezeigt werden. Dazu wird wie in home.js das MsgCard-Template geladen. Beim Laden der Nachrichten wird nun für jede im auth.bookmarks Array befindende ID die \\'get\_insert\_message(id)'-Funktion aufgerufen. Dabei werden per AJAX-Aufruf die IDs an den Server geschickt, um die gesamte Nachricht aus der Datenbank zu erhalten. Diese Nachrichten werden dann auf der Lesezeichen-Seite angezeigt.\\
- Damit das Lesezeichen-Icon beim Neuladen einer Seite oder beim Wechseln zwischen den Tabs die richtige Farbe (ausgefüllt/ unausgefüllt) hat, musste beim Laden der Nachrichten überprüft werden, ob die Nachricht bereits gespeichert ist. Dazu wurde das auth.bookmarks Array auf die Nachricht-ID untersucht und, falls vorhanden der Icon ausgefüllt. \\
- Aus zeitlichen Gründen konnte das auth.bookmarks Array nicht mit der Datenbank synchronisiert werden. Deshalb wurde beim Neuladen oder wechseln der Tabs auf einen leeren globalen Array zugegriffen, wodurch die IDs nicht abgefragt werden konnten.
-
-
-
- \section{Frontend der Abonnierfunktion}
-
- Das Ziel war auf der Startseite, alle Nachrichten anzuzeigen, die abonnierte Tags beinhalten, damit der Nutzer alle für ihn relevante Informationen auf den ersten Blick erfassen kann. Um einen Tag zu abonnieren, kann man zum einen über die Suche gehen. Sobald nach nur einem einzigen Tag gesucht wird erscheint oben rechts ein Button der die Abonnierfunktion anbietet (siehe Abbildung 5).
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=6cm]{../grafiken/5}
- \caption{Darstellung des Abonnierbuttons}
- \label{Abbildung 5}
- \end{figure}
- \end{center}
-
-
- In der Suchmethode wird geprüft, ob der Suchbegriff in dem Array der vordefinierten Tags vorhanden ist und der Button wird entsprechend sichtbar (vgl. S.14, Listing 4).
- Sobald der Tag abonniert wird ändert sich der Text auf dem Button und es besteht die Möglichkeit den Tag wieder zu deabonnieren. Das Backend hinter diesem Feature konnte allerdings aus Zeitgründen nicht vollständig implementiert werden.
- \newpage
-
- \begin{lstlisting}[caption=Abfrage in Suchmehtode]
- if(_taglist.indexOf(searchtext.replace(/#/g, '')) > -1){
- var btnString = "#" + searchtext.replace(/#/g, '') + " abonnieren";
- $("#btn-text").text(btnString);
- $("#subscribe-btn").css("visibility", "visible");
- }else{
- $("#subscribe-btn").css("visibility", "hidden");
- }
- \end{lstlisting}
-
-
-
-
-
- Eine weitere Möglichkeit besteht über den Tag-Link in einer Nachricht zu navigieren. Der Nutzer gelangt auf eine Seite, die alle Nachrichten zu diesem bestimmten Tag anzeigt und ebenfalls den Button oben rechts als Option einblendet. Im Hintergrund wird eine Suche nach dem Tag angestoßen, der Mechanismus ist somit derselbe.
-
-
-
- %
- \section*{17. Plakatgestaltung}
- \phantomsection\addcontentsline{toc}{section}{17. Plakatgestaltung}
- \subsection{Plakatgestaltung - Erste Projektabschnitt}
- Zu dem Plakat für die OHM News App wurde eine Ideensammlung in Form von Skizzen angefertigt.
- \begin{figure}[H]
- \centering
- \includegraphics[width=6.5cm, angle=90, scale=1.409]{../grafiken/IMG_Skizze1.jpg}\quad
- \includegraphics[width=6.5cm]{../grafiken/IMG_Skizze2.jpg}
- \includegraphics[width=6.5cm, angle=270, scale=1.409]{../grafiken/IMG_Skizze3.jpg}\quad
- \includegraphics[width=6.5cm, angle=270, scale=1.409]{../grafiken/IMG_Skizze4.jpg}
- \end{figure}
- %
- Die Umsetzung derer folgte in Form von ersten Entwürfen in Illustrator, welche der gesamten Gruppe vorgestellt wurden. \\
- Zu den hier unten aufgeführten Plakatentwürfen wurden jeweils zwei Versionen erstellt. Diese zwei kamen jedoch in die engere Auswahl und sollten noch weiter ausgearbeitet werden.
- \begin{figure}[H]
- \centering
- \includegraphics[width=6.5cm]{../grafiken/PDF_Plakat1.pdf}\quad
- \includegraphics[width=6.5cm]{../grafiken/PDF_Plakat2.pdf}
- \end{figure}
- %
- Bei der nächsten Vorauswahl an fünf OHM News Plakat-Versionen wurde daraufhin auf zwei reduziert, welche hier zu sehen sind.
- \begin{figure}[H]
- \centering
- \includegraphics[width=6.5cm]{../grafiken/PDF_Plakat3.pdf}\quad
- \includegraphics[width=6.5cm]{../grafiken/PDF_Plakat4.pdf}
- \end{figure}
- %
- Diese wurden weiter bearbeitet und Änderungen in Absprache mit der Projektgruppe vor\-genommen. Auch die Meinung von Professor Dr. Hopf beeinflusste die Plakatgestaltung.\\
- Einige Ansätze später und nach etlichem Experimentieren stand die Endauswahl bei diesen nächsten zwei Exemplaren. Besonderen Zeitaufwand nahm die Suche nach einer geeigneten Schrift für die zweite Version in Anspruch. Es gestaltete sich als äußerst schwierig, den künstlerischen leicht verspielten Ausdruck des Plakatlayouts mit der Seriösität des Hochschulcharakters in einer Schrift zu vereinen.
- \begin{figure}[H]
- \centering
- \includegraphics[width=6.5cm]{../grafiken/PDF_Plakat5.pdf}\quad
- \includegraphics[width=6.5cm]{../grafiken/PDF_Plakat6.pdf}
- \end{figure}
- %
- Zuletzt fiel die Wahl auf das linke mit blauem Verlauf versehene Plakat. Denn es vermittelt genau das, was der Slogan des Projektes aussagt. Der Fokus liegt auf der Nachrichtenbox, also das was wichtig ist, und der Rest verschwimmt im Hintergrund. \\
- Bei den wöchentlichen Treffen wurde im Allgemeinen der Fortschritt des Plakatdesigns analysiert und mit konstruktiver Kritik versehen. Dieses Feedback wurde im Rahmen des Möglichen umgesetzt und so kristallisierte sich die finale Version heraus. Nach gründlichem Finetuning und einer Umformatierung von DIN A3 auf DIN A1 wurde die Endfassung per Mail eingeschickt und schließlich ausgedruckt. Im Anhang ist sie in voller Auflösung aufzufinden.\\
- \subsection{Plakatgestaltung - Zweiter Projektabschnitt}
- Im Rahmen der Projektpräsentation wurden zwei Plakate erstellt. Das erste Plakat (siehe Abbildung 6, links) ist ein Werbeplakat und dient dazu den Kern des Projektes widerzuspiegeln, sowie Interesse für die Präsentation zu wecken. In Abbildung 6 (rechts) ist das technische Plakat zu sehen, welches einen groben Überblick über die verschiedenen Technologien der App gibt.
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=16cm]{../grafiken/6}
- \caption{Plakate}
- \label{Abbildung 6}
- \end{figure}
- \end{center}
-
- %
- \section*{18. PowerPoint Präsentation}
- \phantomsection\addcontentsline{toc}{section}{18. PowerPoint Präsentation}
- Als sich das Projekt für dieses Semester zum Ende hinneigte, war es an der Zeit sich für die Projektpräsentation vorzubereiten. Hierfür erstellte ich für die Gruppe eine PowerPoint Präsentation. Zunächst besprachen wir Gemeinschaftlich, wie diese ungefähr aussehen sollte. Wir waren alle einstimmig der Meinung, dass wir die Präsentation sehr einfach gestalten wollen, ohne zu lange Textpassagen mit einzubinden. Wir wollten es nämlich verhindern, dass das Publikum von zu vielen Faktoren in der Darstellung abgelenkt werden, zum Beispiel durch lesen von langem Fließtext. Durch den Gebrauch von bildlicher Veranschaulichung, versuchten wir es den Zuschauern zu ermöglichen, das Verständnis zu erleichtern.
- Auch hatten wir die Idee, eine fiktive Persona zu erstellen, zu dem der Betrachter einen Bezug finden kann und diese durch das vorgetragene Thema begleitet. Letztes Mal entschieden wir uns für Klaus den Studenten. Dieses Mal erstellten wir neben der Rolle des Studenten-/in auch die Persona des Professors und Admins. Somit konnten wir unsere Rollenverteilung bildlich aufzeigen.
-
- \section{Video}
- Um unser Projekt vorzustellen, wurde ein kurzes Werbe-Video angefertigt, welches für die kommenden Wochen im Foyer der TH-Nürnberg auf einem Großbildschirm gespielt wird. Dieser diente dazu, den Zuschauern einen kurzen Einblick in unsere App zu verschaffen und Ihr Interesse an unserem Projekt zu wecken. Die Aufgabe, ein Video ohne Audio-Erklärung zu erstellen war zunächst eine echte Herausforderung.
- Was jedoch letztendlich noch gemacht werden musste, war es, das Video abschließend noch stimmiger zu machen und dem Trailer noch den letzten Feinschliff zu verpassen. Dafür wurden lediglich neue Icons verwendet, die von der Form gut zusammenpassen. Außerdem wurden kurze Textausschnitte hinzugefügt um das allgemeine Verständnis unserer App zu erlangen ohne den Zuschauer unnötig mit zu viel Text und Informationen sozusagen zu erschlagen.
-
- \section{Pressefoto}
-
-
- F\"ur die Ank\"undigung der Abschlusspr\"asentationen hat die Gruppe zusätzlich ein Presse-foto erstellt (siehe Abbildung 7).
-
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=6cm]{../grafiken/7}
- \caption{Pressefoto}
- \label{Abbildung 7}
- \end{figure}
- \end{center}
-
-
- %
- \subsection*{18.1. Gestaltungselemente}
- \phantomsection\addcontentsline{toc}{subsection}{18.1. Gestaltungselemente}
- Da man jedoch, aus Urheberrechtlichen Gründen, nicht einfach wahllos Charaktere aus dem Internet benutzen kann, suchte ich nach einer Seite, auf der man solche Animationen erstellen kann. Ich bin auch direkt fündig geworden, trotz alle dem war es erstmal schwer etwas zu finden das man auch Gratis verwenden konnte.
- Dann bin ich auf die Seite www.Powtoon.com gestoßen. Dort fing ich als nächstes an, unseren sogenannten Klaus in all den Stimmungen, die wir für unsere Präsentation brauchten, zu gestalten. \\
- Wir entschieden im Vorfeld als Gruppe, dass sich unser Männchen so wenig wie möglich bewegen soll, aus dem gleichen Grund wie auch oben schon erwähnt und zwar um den Fokus nicht zu sehr darauf zu richten und das Publikum nicht zu sehr abzulenken. Nachdem das erledigt war, war es an der Zeit, die eben erstellten Videos von unserer Persona einzeln so zu kürzen und zu beschneiden, dass man sie gut auf die gewünschte Position einsetzen konnte. Als dieses erledigt wurde, besprach ich weitere Vorgehen einzeln mit den anderen Gruppenmitgliedern. Ich Informierte mich darüber, über welches Thema jeder einzelne vorträgt und wie sie sich ihren Präsentationsteil vorstellen. Diese Wünsche und Vorstellung setzte ich dann dementsprechend in unserer Präsentation um.
- Falls sie an dem Ergebnis interessiert sind, haben sie die Möglichkeit sich dies im Git-Repository im Ordner ''presentation'' anzusehen.
- %
- \section*{19. Weiterverwendung für Infoscreens}
- \phantomsection\addcontentsline{toc}{section}{19. Weiterverwendung für Infoscreens}
- Am Mittwoch, den 24.10.2018 fand das Info-Treffen mit Frau Fabi statt, welches von Prof.Dr. \mbox{Matthias} Hopf organisiert wurde. Dieses Treffen diente der Besprechung und Erörterung zukünftiger Nutzungsmöglichkeiten der Info-Screens, das sind geplante und teils bereits montierte Bildschirme zur Information-Bereitstellung für die Hochschulangehörigen auf dem Campusgelände. Frau Fabi ist Angehörige der Fakultät efi und in ihrer Funktion für die Dokumentenlenkung und Webredaktion an dem ''Tag''-basiertem Nachrichten-System unserer Webanwendung interessiert, welches zukünftig auch auf den Bildschirmen dargestellt werden könnten. Sie ließ auch das Interesse von Herr Pöhlau, dem Dekan der Fakultät efi bekunden.\\
- Außerdem informierte Frau Fabi uns, die Projektmitglieder und unseren Projektbetreuer, dass die Fakultät efi sicher die restlichen Info-Screens montieren werde und derzeit Besprechungen hinsichtlich weiterer Sicherheitsaspekte zu den Montagebereichen am Laufen sind. Ergänzend würden sie sich eine Softwarelösung wünschen, für die Ansteuerung und ''Befüllung'' der Monitore mit den Daten unserer App. Diese wird jedoch nicht mehr im Rahmen unseres Projektes umgesetzt werden. Die Umsetzung einer Softwarelösung wäre als Idee für ein zukünftiges Projekt denkbar, nach Aussage von Prof.Dr. Matthias Hopf.
- %
- \section*{20. Soll/Ist Vergleich auf Basis des Projektplanes}
- \phantomsection\addcontentsline{toc}{section}{20. Soll/Ist Vergleich auf Basis des Projektplanes}
- Zu Beginn des Semesters hat die Gruppe zusammen ein Pflichtenheft für den ersten Abschnitt des Projekts erstellt. Ziel war es den Datenzugriff zu ermöglichen und eine Schnittstelle zur Verfügung zu stellen. Es besteht eine Datenbankanbindung über den Server der Technischen Hochschule Nürnberg. Darüber hinaus sollten die folgenden Ziele im Bereich der grafischen Benutzerschnittstelle erreicht werden.\\
- Die Oberfläche der PWA sollte über eine Login Möglichkeit, eine Menüleiste, eine Suchoption, ein Profil, eine Filterfunktion, ein Dashboard als Hauptseite, ein Einstellungsmenü, Nachrichtenfelder und ein Formular zum Verfassen einer Nachricht verfügen. Die Login Funktion ist noch nicht implementiert und die Filterfunktion soll im nächsten Semester in das Suchfeld und die Profilanzeige eingebaut werden. Die restlichen Funktionen sind in der PWA grafisch umgesetzt worden. Es sollte zusätzlich ein Abhängigkeitsdiagramm erstellt werden. Allerdings war dies aufgrund fehlender komplexer Zusammenhänge noch nicht notwendig. Für die API-Schnittstelle wurde eine Dokumentation erstellt, um den Überblick zu bewahren. Im Bereich der Anwendungslogik wurde das Routing, die Darstellung der Nachrichten, die Speicherung der Nachrichten in der Datenbank und der LDAP-Login besonders behandelt. Das Routing sowie die Erstellung, Speicherung und Darstellung der Nachrichten funktioniert. Die Login Funktion wurde noch nicht näher betrachtet. Codetests wurden bisher noch keine durchgeführt. Das Rollenkonzept der Nutzer wurde bereits besprochen, allerdings noch nicht umgesetzt.\\
- Darüber hinaus gibt noch einige nachrangige Punkte. Dazu gehört die Festlegung des Anwendungsnamens, die Erstellung eines Logos, das UX-Konzept, das Filtern der Datenbankabrufe, das Festlegen der Anzeigekriterien und die Funktion einem Kanal zu folgen. Wie oben bereits erwähnt wird das Filtern der Abrufe im nächsten Semester umgesetzt. Auch die Anzeigekriterien und die Möglichkeit einem Kanal zu folgen wird erst zu einem späteren Zeitpunkt möglich sein.
- %
- \section*{21. Fazit}
- \phantomsection\addcontentsline{toc}{section}{21. Fazit}
- Im ersten Projektabschnitt ist viel Zeit ist in der Konzeptionsphase vergangen, da es ein sehr iterativer Prozess ist und deshalb mehrere Durchläufe bis zum Endentwurf nötig waren. Verschiedene Meinungen mussten mit einbezogen werden. Doch ein gutes Konzept erspart am Ende viel Änderungsarbeit. \\
- Für die weitere Erarbeitung der App haben sich die Projektmitglieder auf die Bereiche Front\-end, Datenbank, Sever und Service-Worker aufgeteilt. Diese Aufgaben\-verteilung hat gut funktioniert. Trotzdem ist unser Team sehr oft ins Stocken geraten, da sich die Aufgaben\-bereiche gerade am Anfang oft überschnitten haben. Hinzukommt, dass wir insgesamt \mbox{wenig} Erfahrung in diesen Bereichen hatten. Wir haben uns deshalb zu Beginn intensiv in die Themen eingearbeitet, was länger dauerte als erwartet. Zusätzlich mussten wir auf \mbox{fachliche} Unterstützung zurückgreifen.\\\\
- Alles in einem kann man trotzdem von einem erfolgreichen Projektabschnitt sprechen. Ein erster funktionierender Prototyp ist fertig und kann im nächsten Zug erweitert werden. Parallele individuelle Arbeiten sind einfacher möglich, da das Grundgerüst steht. Das Team hat sich in die Materie eingearbeitet und kann im zweiten Projektabschnitt schneller durchstarten. Die Idee und das Konzept für die App sind soweit ausgereift, sodass diese nur noch umgesetzt werden müssen. Abläufe innerhalb der Gruppe sind klarer geworden, allerdings gibt es noch einiges strukturelle Abläufe, die im zweiten Projektabschnitt weiter optimiert werden können.
- %
- % Literaturverzeichnis
- \newpage
- \section*{Quellen- und Literaturverzeichnis}
- \phantomsection\addcontentsline{toc}{section}{Quellen- und Literaturverzeichnis}
- \medskip
- %\nocite{*} % Alle Inhalte zur Ausgabe markieren, nicht nur jene die zitiert wurden.
- {\setstretch{1.0}%
- \printbibliography[heading=none]}
- %
- \end{document}
|