From 138434974c00fdfc6bbdb82fd51dbe1dcfa95090 Mon Sep 17 00:00:00 2001 From: Apostolof Date: Sun, 17 Jan 2021 10:04:41 +0200 Subject: [PATCH] Add final report code --- UI/Report/1.0.introduction.tex | 7 +++ UI/Report/2.0.coverage.tex | 25 +++++++++ UI/Report/3.0.setup.tex | 80 +++++++++++++++++++++++++++ UI/Report/4.0.test_case.tex | 37 +++++++++++++ UI/Report/5.0.bugs.tex | 18 ++++++ UI/Report/6.0.unistall.tex | 36 ++++++++++++ UI/Report/TOC.tex | 1 + UI/Report/code_highlight_styling.tex | 28 ++++++++++ UI/Report/front_page.tex | 1 + UI/Report/report.tex | 58 +++++++++++++++++++ UI/Report/res/fwbLOGO.png | Bin 0 -> 18037 bytes 11 files changed, 291 insertions(+) create mode 100644 UI/Report/1.0.introduction.tex create mode 100644 UI/Report/2.0.coverage.tex create mode 100644 UI/Report/3.0.setup.tex create mode 100644 UI/Report/4.0.test_case.tex create mode 100644 UI/Report/5.0.bugs.tex create mode 100644 UI/Report/6.0.unistall.tex create mode 100644 UI/Report/TOC.tex create mode 100644 UI/Report/code_highlight_styling.tex create mode 100644 UI/Report/front_page.tex create mode 100644 UI/Report/report.tex create mode 100644 UI/Report/res/fwbLOGO.png diff --git a/UI/Report/1.0.introduction.tex b/UI/Report/1.0.introduction.tex new file mode 100644 index 0000000..87a7c99 --- /dev/null +++ b/UI/Report/1.0.introduction.tex @@ -0,0 +1,7 @@ +\section{Εισαγωγή} + +Η παρούσα εργασία εκπονήθηκε στα πλαίσια του μαθήματος ``Βάσεις Δεδομένων'' του ενάτου (9\textsuperscript{ου}) εξαμήνου του τμήματος Ηλεκτρολόγων Μηχανικών και Μηχανικών Υπολογιστών του Αριστοτέλειου Πανεπιστημίου Θεσσαλονίκης. Ζητούμενο του τρίτου παραδοτέου της εργασίας είναι υλοποίηση ενός συστήματος διεπαφής χρήστη (front end/UI) για τη βάση δεδομένων που σχεδιάστηκε και υλοποιήθηκε σε προηγούμενα παραδοτέα. + +Για το παραδοτέο αυτό έγινε ανάπτυξη κώδικα σε δύο μέρη. Το πρώτο μέρος αφορά ένα Restful API για τη βάση δεδομένων γραμμένο σε python, χρησιμοποιώντας κυρίως τα modules Django και Django Rest Framework, καθώς και άλλα λιγότερο σημαντικά modules. Το δεύτερο μέρος είναι η ανάπτυξη κώδικα σε Java, μίας εφαρμογής για Android smartphones η οποία αποτελεί τη γραφική διεπαφή. + +Όλος ο κώδικας αυτού καθώς και των προηγούμενων παραδοτέων, όπως και λοιπά αρχεία και βασικές πληροφορίες (README, SETUP, LICENSE) είναι διαθέσιμα στο \href{https://gitlab.com/Apostolof/flavours-without-borders}{online repository του project}. \ No newline at end of file diff --git a/UI/Report/2.0.coverage.tex b/UI/Report/2.0.coverage.tex new file mode 100644 index 0000000..bcde541 --- /dev/null +++ b/UI/Report/2.0.coverage.tex @@ -0,0 +1,25 @@ +\section{Κάλυψη προδιαγραφών} + +Στην τελική έκδοση της εφαρμογής υπάρχουν οι λειτουργίες της κύριας δραστηριότητας ενός πελάτη δηλαδή: +\begin{itemize} + \item Εύρεση καταστημάτων στον πλήρη χάρτη και φιλτράρισμα των αποτελεσμάτων με βάση το είδος καταστήματος, την απόσταση από την θέση του χρήστη ή τις θερμίδες των πιάτων που περιέχει + \item Πρόσβαση στα μενού των καταστημάτων, τα πιάτα και ποτά, τα συστατικά και τις κριτικές αυτών + \item Δημιουργία νέων κριτικών + \item Πρόταση προσθήκης νέου καταστήματος, πιάτου, ποτού και δίαιτας στη βάση + \item Προσθήκη νέων συστατικών στη βάση +\end{itemize} + +Όσων αφορά τις δυνατότητες τις οποίες έχει ένας διαχειριστής υλοποιήθηκαν οι εξής: +\begin{itemize} + \item Αποδοχή προτάσεων των χρηστών για νέα καταστήματα, πιάτα, ποτά και δίαιτες + \item Απευθείας προσθήκη νέου καταστήματος, πιάτου, ποτού και δίαιτας στη βάση +\end{itemize} + +Δεν υλοποιήθηκαν οι εξής λειτουργίες: +\begin{itemize} + \item Απόρριψη προτάσεων χρηστών (οι μη έγκυρες προτάσεις χρηστών παραμένουν στη βάση ως σκουπίδια) + \item Διαγραφή των σχολίων και κριτικών που έχουν κάνει οι ίδιοι οι χρήστες, αλλά και αφαίρεση τους από διαχειριστές + \item Αποκλεισμός (ban) χρηστών +\end{itemize} + +Η κατηγορία χρηστών που αφορά τους ιδιοκτήτες δεν υλοποιήθηκε. \ No newline at end of file diff --git a/UI/Report/3.0.setup.tex b/UI/Report/3.0.setup.tex new file mode 100644 index 0000000..74da8e4 --- /dev/null +++ b/UI/Report/3.0.setup.tex @@ -0,0 +1,80 @@ +\section{Στήσιμο API και εγκατάσταση εφαρμογής} + +Παρακάτω περιγράφονται η διαδικασία στησίματος της εφαρμογής API που είναι απαραίτητη για την λειτουργία της εφαρμογής Android καθώς και τα βήματα για το χτίσιμο της Android εφαρμογής στο περιβάλλον Android Studio και η εγκατάσταση της σε κινητό. + +Οι οδηγίες αυτές μπορούν να βρεθούν και στον \href{https://gitlab.com/Apostolof/flavours-without-borders/blob/master/UI/Database\%20API/SETUP.md}{οδηγό εγκατάστασης στο online repository} του κώδικα σε μία πιο συνοπτική έκδοση (στα αγγλικά). + +Αρχικά πρέπει να γίνει λήψη του κώδικα του project από το repository χρησιμοποιώντας το git: +\begin{lstlisting}[language=bash] +git clone https://gitlab.com/Apostolof/flavours-without-borders.git +\end{lstlisting} + +Έπειτα στήνεται η εφαρμογή API, ο κώδικας της οποία βρίσκεται στη διαδρομή: +\begin{quote} +\texttt{flavoursWithoutBorders/UI/Database API/} +\end{quote} + +Οι παρακάτω οδηγίες αφορούν Debian based, Linux συστήματα. Ωστόσο το λογισμικό θα πρέπει να λειτουργεί σε οποιοδήποτε λειτουργικό σύστημα, με μικρές αλλαγές στη διαδικασία εγκατάστασης. + +\subsection{Προαπαιτούμενα} + +Για να εκτελεστούν οι παρακάτω εντολές θα πρέπει το σύστημα στο οποίο δουλεύει ο αναγνώστης να έχει εγκατεστημένο το λογισμικό MySQL server και να υποστηρίζεται η εκτέλεση κώδικα python 3. Επίσης πρέπει να υπάρχει εγκατεστημένο το λογισμικό pip 3. + +Τέλος απαιτείται η εγκατάσταση των πακέτων \texttt{virtualenv}, \texttt{python3-dev} και \texttt{libmysqlclient-dev}, χρησιμοποιώντας τις εντολές: + +\begin{lstlisting}[language=bash] +apt install virtualenv +apt-get install python3-dev libmysqlclient-dev +\end{lstlisting} + +Αν είναι επιθυμητή η πρόσβαση στο API μέσω της δημόσιας IP του συστήματος στο οποίο εκτελείται το πρόγραμμα θα πρέπει να ανοίξει η πόρτα \texttt{8181} του router και να εξασφαλιστεί ότι κανένα firewall που τυχόν είναι εγκατεστημένο δεν θα αποκλείσει την επικοινωνία σε αυτή τη πόρτα. + +\subsection{Στήσιμο βάσης δεδομένων και προγράμματος API} + +Αρχικά πρέπει να γίνει απεγκατάσταση του πρόσθετου password\_validation της MySQL διότι προκαλεί προβλήματα στην δημιουργία χρηστών της βάσης. Για να γίνει αυτό, πρέπει να γίνει σύνδεση με τον root λογαριασμό στον server της MySQL: +\begin{lstlisting}[language=bash] +mysql -h localhost -u root -p +\end{lstlisting} +και απεγκατάσταση του πρόσθετου με την εντολή: +\begin{lstlisting}[language=SQL] +UNINSTALL PLUGIN validate_password; +\end{lstlisting} + +Τέλος πρέπει να εκτελεστεί το bash script που έχει γραφτεί και αναλαμβάνει το υπόλοιπο της εγκατάστασης, τρέχοντας τις εντολές: +\begin{lstlisting}[language=bash] +cd flavoursWithoutBorders/UI/Database\ API/ +./install.sh +\end{lstlisting} + +Το script θα ζητήσει την είσοδο μίας IP την οποία θα χρησιμοποιήσει για το στήσιμο του server. Αυτή μπορεί να είναι είτε η δημόσια (public IP) του συστήματος, αν έγινε προηγουμένως άνοιγμα της πόρτας 8181, είτε η τοπική (LAN IP). + +Το script δημιουργεί τη βάση \texttt{flavoursWithoutBorders}, δημιουργεί ένα εικονικό περιβάλλον (virtual environment) python 3, εγκαθιστά τοπικά όλα τα απαιτούμενα python modules, συνδέει την εφαρμογή API με την βάση δεδομένων και δημιουργεί έναν superuser. Τέλος ξεκινά τον server στον οποίο τρέχει το API. + +Όταν ο python server του API ξεκινήσει, ο αναγνώστης έχει πρόσβαση στο API μέσα από τις διευθύνσεις του admin panel και της λίστας διαθέσιμων εντολών του API. +\begin{lstlisting}[language=bash] +sensible-browser YOUR_IP:8181/admin/ +sensible-browser YOUR_IP:8181/api/ +\end{lstlisting} +όπου με τον όρο \texttt{YOUR\_IP} εννοείται η IP που επιλέχθηκε για χρήση σε προηγούμενο βήμα. + +\subsection{Χτίσιμο και εγκατάσταση της Android εφαρμογής} + +Για την εγκατάσταση της Android εφαρμογής δίνονται δύο επιλογές, το χτίσιμο της ή η χρήση του έτοιμου apk που διατίθεται μαζί με τον κώδικα. + +Για το χτίσιμο (build) της Android εφαρμογής απαιτείται η εγκατάσταση τουλάχιστον του Android SDK. Οδηγίες για τη διαδικασία δίνονται από την Google. Παρακάτω θα περιγραφεί η διαδικασία χρησιμοποιώντας το λογισμικό Android Studio. + +Μετά την εκκίνηση του λογισμικού, εμφανίζεται η οθόνη καλωσορίσματος. Αν υπάρχει ήδη ανοιχτό κάποιο project, το κλείνουμε μέσω της επιλογής του μενού File → Close Project. Από το μενού επιλέγεται το ``Open an existing Android Studio project''. Στο παράθυρο που εμφανίζεται, γίνεται επιλογή του φακέλου του project στη διαδρομή: +\begin{quote} +\texttt{flavoursWithoutBorders/UI/AndroidApp/flavoursWithoutBorders/} +\end{quote} + +Προσοχή στην ύπαρξη του \texttt{\textbf{flavoursWithoutBorders/}} στο τέλος του path! Η διαδρομή δεν λήγει στο \texttt{AndroidApp/}. + +Τέλος συνδέεται στο σύστημα με USB ένα Android smartphone και επιλέγεται από το μενού Run → Run 'app'. Στο μενού που εμφανίζεται επιλέγεται η σωστή συσκευή και γίνεται κλικ στο OK. + +Τονίζεται εδώ ότι κατά τη διαδικασία αυτή απαιτείται η λήψη πολλών, μεγάλου μεγέθους αρχείων, συνολικού μεγέθους αρκετών Gigabytes, κάτι που μπορεί να είναι αποτρεπτικό. Για το λόγο αυτό δίνεται ένα έτοιμο signed apk της εφαρμογής για εύκολη εγκατάσταση. Το apk μπορεί να βρεθεί στην διαδρομή: +\begin{quote} +\texttt{flavoursWithoutBorders/UI/release.apk} +\end{quote} + +Την πρώτη φορά που ανοίγει η εφαρμογή ζητείται από τον χρήστη η IP του API server. Θα πρέπει να δοθεί η IP η οποία χρησιμοποιήθηκε κατά το στήσιμο του server. \ No newline at end of file diff --git a/UI/Report/4.0.test_case.tex b/UI/Report/4.0.test_case.tex new file mode 100644 index 0000000..fba316c --- /dev/null +++ b/UI/Report/4.0.test_case.tex @@ -0,0 +1,37 @@ +\section{Σενάριο δοκιμής της εφαρμογής} + +Δημιουργία νέου λογαριασμού χρήστη: Ο χρήστης βρίσκεται στην αρχική οθόνη σύνδεσης σε υπάρχων λογαριασμό αλλά πατάει στο κείμενο ``or sign up'', εάν είναι συνδεδεμένος σε κάποιο λογαριασμό κάνει πρώτα Logout, συμπληρώνει τα στοιχεία του και μετά πατάει το κουμπί (SIGN UP). + +Σύνδεση χρήστη σε υπάρχων λογαριασμό: Ο χρήστης βρίσκεται στην αρχική οθόνη σύνδεσης σε υπάρχων λογαριασμό, συμπληρώνει το Username του ή το e-mail του και τον κωδικό του και πατάει το κουμπί (LOGIN). + +Εμφάνιση επιλογών της εφαρμογής: Ο χρήστης πατάει το πάνω αριστερά κουμπί ή κάνει ``Swipe Right'' από την αριστερή άκρη της οθόνης για την εμφάνιση των επιλογών. + +Πλοήγηση στα διαθέσιμα εστιατόρια της βάσης: Ο χρήστης κάνει εμφάνιση επιλογών πατάει το κουμπί ``Home'' και πλέον βρίσκεται στην οθόνη της λίστας των καταστημάτων. Ο χρήστης μπορεί να κάνει πλοήγηση στο χάρτη της εφαρμογής. Έπειτα εφαρμόζει κάποιο φίλτρο στα διαθέσιμα καταστήματα εάν αυτός/η επιθυμεί. Ο χρήστης επιλέγει ένα από τα διαθέσιμα καταστήματα της λίστας καταστημάτων. + +Πλοήγηση στο χάρτη της εφαρμογής: Ο χρήστης βρίσκεται στην οθόνη της λίστας των καταστημάτων και πατάει το 2ο κουμπί στην πάνω δεξιά μεριά της οθόνης ή κάνει ``Swipe Left'' από την δεξιά άκρη της οθόνης. Έπειτα μπορεί να επιστρέψει ξανά στη λίστα των καταστημάτων πατώντας το 2ο κουμπί στην πάνω δεξιά μεριά της οθόνης ή το φυσικό κουμπί ``Πίσω''. + +Φιλτράρισμα διαθέσιμων καταστημάτων: Ο χρήστης βρίσκεται στην λίστα καταστημάτων ή στον χάρτη προβολής των διαθέσιμων καταστημάτων και πατάει το 1ο κουμπί στην πάνω δεξιά μεριά της οθόνης. Κατά το φιλτράρισμα ο χρήστης μπορεί να επιλέξει 1. συγκεκριμένα είδη καταστημάτων ή 2. καταστήματα τα οποία έχουν απόσταση σε μέτρα από την θέση του μικρότερη ή ίση της τιμής που αυτός εισάγει στο αναδυόμενο παράθυρο (η εφαρμογή κάποιες φορές δεν ανακτά την θέση της συσκευής οπότε η λειτουργία αυτή ενδέχεται να μην δουλεύει πάντα) ή 3. καταστήματα τα οποία προσφέρουν πιάτα των οποίων οι θερμίδες δεν ξεπερνούν μια τιμή την οποία ο χρήστης εισάγει στο αναδυόμενο παράθυρο. + +Προσθήκη/Πρόταση προσθήκης νέου καταστήματος: Ο χρήστης βρίσκεται στην οθόνη της λίστας των καταστημάτων και πατάει το κουμπί (+). Έπειτα μετακινεί το στίγμα στο χάρτη στη θέση στην οποία βρίσκεται το κατάστημα, εισάγει το όνομα του καταστήματος, επιλέγει είδος καταστήματος και εισάγει το ωράριο λειτουργίας του, τέλος πατάει το κουμπί (ADD RESTAURANT). + +Προσθήκη/Πρόταση προσθήκης νέου πιάτου/ποτού σε κατάστημα: Ο χρήστης επιλέγει ένα κατάστημα έπειτα από πλοήγηση στα διαθέσιμα καταστήματα, μεταβαίνει στην καρτέλα FOOD/DRINK και και πατάει το κουμπί (+). Έπειτα εισάγει το όνομα του πιάτου/ποτού και μια περιγραφή του. Στην συνέχεια προσθέτει τα συστατικά τα οποία περιέχει το πιάτο/ποτό και τέλος πατάει το κουμπί (ADD FOOD/DRINK) + +Προσθήκη νέου συστατικού στη βάση: Ο χρήστης μεταβαίνει στην οθόνη της λίστας των συστατικών της βάσης αφού κάνει εμφάνιση επιλογών της εφαρμογής και πατήσει το κουμπί Ingredients. Έπειτα πατάει το κουμπί (+), εισάγει το όνομα του συστατικού και εάν αυτό περιέχει αλκοόλ, τέλος πατάει το κουμπί (ADD INGREDIENT). + +Προσθήκη/Πρόταση προσθήκης νέας δίαιτας στη βάση: Ο χρήστης μεταβαίνει στην οθόνη της λίστας των δίαιτων της βάσης αφού κάνει εμφάνιση επιλογών της εφαρμογής και πατήσει το κουμπί Diets. Έπειτα πατάει το κουμπί (+), εισάγει το όνομα της δίαιτας, μια περιγραφή της και την λίστα των απαγορευμένων συστατικών της δίαιτας. Τέλος πατάει το κουμπί (ADD DIET). + +Τροποποίηση της λίστας των δίαιτων που ακολουθεί ο χρήστης: Ο χρήστης μεταβαίνει στην οθόνη της λίστας των δίαιτων της βάσης και πατάει το κουμπί προσθήκης για τις δίαιτες τις επιθυμεί να ακολουθήσει. Για τις δίαιτες τις οποίες θέλει να σταματήσει να ακολουθεί πατάει το κουμπί της διαγραφής. + +Τροποποίηση της λίστας απαγορευμένων συστατικών του χρήστη: Ο χρήστης μεταβαίνει στην οθόνη της λίστας των συστατικών της βάσης και πατάει το κουμπί προσθήκης/διαγραφής για τα συστατικά τα οποία θέλει να προσθέσει/αφεραίσει από τη λίστα των απαγορευμένων του συστατικών + +Αξιολόγηση καταστήματος: Ο χρήστης επιλέγει ένα κατάστημα έπειτα από πλοήγηση στα διαθέσιμα καταστήματα, μεταβαίνει στην καρτέλα RATINGS και πατάει το κουμπί (+). Έπειτα επιλέγει την βαθμολογία αξιολόγησης (1-5) και την προσβασιμότητα σε ΑμΕΑ, επιλέγει προαιρετικά μια δίαιτα με βάση την οποία αξιολογεί το κατάστημα και εισάγει προαιρετικά ένα σχόλιο αξιολόγησης και τέλος πατάει το κουμπί (RATE) + +Αξιολόγηση πιάτου/ποτού καταστήματος: Ο χρήστης επιλέγει ένα κατάστημα έπειτα από πλοήγηση στα διαθέσιμα καταστήματα, μεταβαίνει στην καρτέλα FOOD/DRINK και επιλέγει το πιάτο/ποτό το οποίο επιθυμεί να αξιολογήσει, μεταβαίνει στην καρτέλα RATINGS και πατάει το κουμπί (+). Έπειτα επιλέγει την βαθμολογία αξιολόγησης (1-5) και το μέγεθος της μερίδας του πιάτου/ποτού και εισάγει προαιρετικά ένα σχόλιο αξιολόγησης, τέλος πατάει το κουμπί (RATE) + +Αποσύνδεση χρήστη: Ο χρήστης εκτελεί την εμφάνιση επιλογών και έπειτα πατάει το κουμπί (Logout) + +Αλλαγή ρόλου ενός χρήστη σε διαχειριστή: Ο sysadmin του συστήματος συνδέεται στην ιστοσελίδα διαχείρισης της βάσης Django Administration με διεύθυνση IP:8181/admin. Μεταβαίνει στην τροποποίηση του πίνακα Users και επιλέγει τον χρήστη του οποίου θέλει να αλλάξει τον ρόλο και αλλάζει το χαρακτηριστικό ``Role'' του χρήστη από ``Role object(0)'' σε ``Role object(1)''. + +Αποδοχή των προτάσεων προσθήκης καταστημάτων, πιάτων/ποτών και δίαιτων από διαχειριστές: Όταν ο διαχειριστής μεταβαίνει στις οθόνες της λίστας των καταστημάτων, λίστας των πιάτων/ποτών ενός καταστήματος ή της λίστας των δίαιτων της βάσης μπορεί να δει όλα τα αντικείμενα της λίστας, ακόμη και όσα δεν έχουν εγκριθεί. Για τα αντικείμενα τα οποία δεν έχουν εγκριθεί ακόμη υπάρχει ένα κουμπί έγκρισης το οποίο ο διαχειριστής μπορεί να πατήσει για όποια αντικείμενα θεωρεί πως είναι έγκυρα. + +Σημείωση: Για τις λειτουργίες προσθήκης οι όποιες αναφέρονται ως πρόταση προσθήκης, όταν οι ενέργειες εκτελούνται από απλούς χρήστες το αποτέλεσμα στην όψη των απλών χρηστών για τις νέες προτάσεις θα είναι διαθέσιμο όταν κάποιος διαχειριστής εγκρίνει αυτή την πρόταση. \ No newline at end of file diff --git a/UI/Report/5.0.bugs.tex b/UI/Report/5.0.bugs.tex new file mode 100644 index 0000000..16b36c7 --- /dev/null +++ b/UI/Report/5.0.bugs.tex @@ -0,0 +1,18 @@ +\section{Γνωστά bugs, μερικές υλοποιήσεις και άλλα προβλήματα} + +Παρακάτω παρατίθενται μερικά γνωστά bugs της εφαρμογής, features των οποίων η υλοποίηση δεν ολοκληρώθηκε και features τα οποία είναι κοινά σε εφαρμογές ή αναμενόμενο να υπάρχουν αλλά δεν υλοποιήθηκαν. Τα bugs και οι ελλείψεις αυτές θεωρήθηκαν εκτός του πεδίου εφαρμογής της εργασίας. + +Έλλειψη progress bars ή άλλης μορφής feedback για την πρόοδο των requests. Κατά την αναμονή απάντησης από τον server στα requests που κάνει η εφαρμογή δεν δίνεται κανένα οπτικό feedback για την εκκίνηση ή τη πρόοδο των requests. Αυτό μπορεί να οδηγήσει τον χρήστη εσφαλμένα στην εντύπωση ότι η εφαρμογή δεν λειτουργεί. + +Ελλιπής υλοποίηση των filters. Από τις τρεις μεθόδους φιλτραρίσματος των διαθέσιμων καταστημάτων που δίνονται από την εφαρμογή (με βάση τον τύπο, την απόσταση και τη διάθεση φαγητών με άνω όριο κάποιες θερμίδες) μόνο η μία λειτουργεί σωστά πάντα, το φιλτράρισμα με βάση τον τύπο. Το φιλτράρισμα με βάση την απόσταση λειτούργησε σωστά μόνο σε virtual device κατά το development και testing της εφαρμογής. Πιθανόν να λειτουργεί και σε πραγματικές συσκευές με έκδοση Android τουλάχιστον ίση με 8.0. Το φιλτράρισμα με βάση τη διάθεση φαγητών με άνω όριο κάποιες μερίδες δεν υλοποιήθηκε στη πλευρά του API (τουλάχιστον μέχρι τη παράδοση της εργασίας). + +Logout fails. Η λειτουργία της αποσύνδεσης χρήστη χρειάζεται να εκκινηθεί από τον χρήστη δύο φορές για να πετύχει. Ωστόσο κάποιες φορές δεν διαγράφονται τα αποθηκευμένα cookies, κάτι που προκαλεί προβλήματα στην μετέπειτα επανασύνδεσή του ή εγγραφή με νέο λογαριασμό. Στη περίπτωση αυτή πρέπει να γίνει διαγραφή των αποθηκευμένων δεδομένων μέσω των ρυθμίσεων του Android και της επιλογής ``clear data''. + +Ο τύπος χρήστη δεν ανανεώνεται. Σε περίπτωση που κάποιος χρήστης αλλάξει τύπο (απλός χρήστης που γίνεται moderator ή το αντίθετο) η εφαρμογή δεν αντιλαμβάνεται αυτόματα την αλλαγή. Για το λόγο αυτό πρέπει να γίνει αποσύνδεση και επανασύνδεση του χρήστη. Αν αυτό δεν πετύχει, πρέπει όπως και για τα logout fails να γίνει εκκαθάριση των δεδομένων της εφαρμογής. + +Μη εμφάνιση των προστιθέμενων εγγραφών των διαχειριστών απευθείας. Όταν ένας διαχειριστής προσθέτει ένα νέο κατάστημα, φαγητό, ποτό ή δίαιτα γίνεται απευθείας αποδεκτό από τη βάση. Ωστόσο για να εμφανιστεί στην εφαρμογή ο διαχειριστής πρέπει να φύγει από την οθόνη του αντικειμένου και να ξαναμπεί ώστε να φορτωθεί η αλλαγμένη λίστα εστιατορίων/φαγητών/ποτών/δίαιτων μετά από νέο request στον server. Στη περίπτωση της οθόνης με τη λίστα των εστιατορίων θα πρέπει είτε να κλείσει η εφαρμογή και να ανοίξει ξανά είτε να πατηθεί το κουμπί ``Clear filters'' από το μενού των φίλτρων (ακόμα και αν δεν υπάρχει κανένα φίλτρο σε εφαρμογή). +\begin{quote}{Roy Trenneman} +---Have you tried turning it off and on again? +\end{quote} + +Η απευθείας μετάβαση από τις δραστηριότητες με τις δίαιτες και τα υλικά στο προφίλ χρήστη αποτυγχάνει μερικές φορές. Συνήθως, όταν από την οθόνη με τις δίαιτες ή τα υλικά, μία δίαιτα ή ένα υλικό διαγραφεί από τη λίστα αυτών που ακολουθεί ή απαγορεύει ο χρήστης και έπειτα γίνει προσπάθεια απευθείας μετάβασης (μέσω του μενού επιλογών) στο προφίλ του, τότε η εφαρμογή αποτυγχάνει και κλείνει. \ No newline at end of file diff --git a/UI/Report/6.0.unistall.tex b/UI/Report/6.0.unistall.tex new file mode 100644 index 0000000..d0f8822 --- /dev/null +++ b/UI/Report/6.0.unistall.tex @@ -0,0 +1,36 @@ +\section{Απεγκατάσταση, επαναφορά συστήματος μετά το στήσιμο του API} + +Για την επαναφορά όλων των αλλαγών που έγιναν στο σύστημα κατά το στήσιμο του API πρέπει να ακολουθηθούν οι παρακάτω οδηγίες. + +\begin{enumerate} +\item + Διαγραφή των αρχείων που δημιουργήθηκαν από το Django. +\begin{lstlisting}[language=bash] +cd flavoursWithoutBorders/UI/Database\ API/ +rm -rf hyrieus/env +rm -rf hyrieus/flavoursAPI/hyrieus/migrations +\end{lstlisting} + +\item + Επαναφορά αλλαγών που έγιναν στο αρχείο settings.py από το script εγκατάστασης. +\begin{lstlisting}[language=bash] +git checkout -- hyrieus/flavoursAPI/settings.py +\end{lstlisting} + +\item + Επανεγκατάσταση του πρόσθετου password\_validation στον MySQL server. Σύνδεση ως root user: +\begin{lstlisting}[language=bash] +mysql -h localhost -u root -p +\end{lstlisting} + +και εκτέλεση της εντολής: +\begin{lstlisting}[language=SQL] +INSTALL PLUGIN validate_password SONAME 'validate_password.so'; +\end{lstlisting} + +\item + Διαγραφή της βάσης δεδομένων. +\begin{lstlisting}[language=bash] +mysql -h localhost -u root -p -e "DROP DATABASE IF EXISTS flavoursWithoutBorders;" +\end{lstlisting} +\end{enumerate} \ No newline at end of file diff --git a/UI/Report/TOC.tex b/UI/Report/TOC.tex new file mode 100644 index 0000000..67f93b1 --- /dev/null +++ b/UI/Report/TOC.tex @@ -0,0 +1 @@ +\tableofcontents \ No newline at end of file diff --git a/UI/Report/code_highlight_styling.tex b/UI/Report/code_highlight_styling.tex new file mode 100644 index 0000000..6292e1d --- /dev/null +++ b/UI/Report/code_highlight_styling.tex @@ -0,0 +1,28 @@ +\usepackage{color} + +\definecolor{codegreen}{rgb}{0,0.6,0} +\definecolor{codegray}{rgb}{0.5,0.5,0.5} +\definecolor{codepurple}{rgb}{0.58,0,0.82} +\definecolor{backcolour}{rgb}{0.95,0.95,0.92} +\definecolor{light-gray}{gray}{0.95} + +\lstdefinestyle{mystyle}{ + backgroundcolor=\color{light-gray}, + commentstyle=\color{codegreen}, + keywordstyle=\color{magenta}, + numberstyle=\tiny\color{codegray}, + stringstyle=\color{codepurple}, + basicstyle=\footnotesize\ttfamily, + breakatwhitespace=false, + breaklines=true, + captionpos=b, + keepspaces=true, + numbers=none, + numbersep=5pt, + showspaces=false, + showstringspaces=false, + showtabs=false, + tabsize=2 +} + +\lstset{style=mystyle} \ No newline at end of file diff --git a/UI/Report/front_page.tex b/UI/Report/front_page.tex new file mode 100644 index 0000000..2a8b21e --- /dev/null +++ b/UI/Report/front_page.tex @@ -0,0 +1 @@ +\maketitle diff --git a/UI/Report/report.tex b/UI/Report/report.tex new file mode 100644 index 0000000..2350d16 --- /dev/null +++ b/UI/Report/report.tex @@ -0,0 +1,58 @@ +\documentclass{article} +\usepackage{geometry} +\geometry{a4paper, top=2cm, bottom=2cm, left=2cm,right=2cm} +\usepackage{fontspec} +\setmainfont{Lato} +%\setmonofont{Consolas} +% \usepackage[nonumeralsign]{xgreek} +\usepackage{fancyhdr} +\usepackage{hyperref} +\usepackage{enumitem} +\usepackage{cite} +\usepackage{titlesec} +\usepackage{float} +\usepackage{booktabs} +\usepackage{array} +\usepackage{multirow} +\usepackage{graphicx} +\usepackage{amsmath} +\usepackage{listings} +\input{code_highlight_styling.tex} +%\usepackage[all]{hypcap} +%\usepackage{tikz} + +\restylefloat{table} +\hypersetup{colorlinks=true, linkcolor=black, urlcolor=blue, citecolor=blue} +\urlstyle{same} +\setlength{\parskip}{\baselineskip} +%\setlength{\parindent}{0pt} + +\title{\large ΤΜΗΜΑ ΗΛΕΚΤΡΟΛΟΓΩΝ ΜΗΧΑΝΙΚΩΝ ΚΑΙ ΜΗΧΑΝΙΚΩΝ ΥΠΟΛΟΓΙΣΤΩΝ \\ +\large ΑΡΙΣΤΟΤΕΛΕΙΟ ΠΑΝΕΠΙΣΤΗΜΙΟ ΘΕΣΣΑΛΟΝΙΚΗΣ \\ +\vspace{5cm} +\includegraphics[width=\textwidth]{res/fwbLOGO}\\ +\vspace{5cm} +\large Ομάδα 13 \\ +Τρίτο παραδοτέο} +\titleformat{\chapter} + {\normalfont\LARGE\bfseries}{\thechapter}{1em}{} + +\author{Φανάκης Απόστολος, 8261, apostolof@ece.auth.gr \\ +Τσάκωνας Γεώργιος Νικόλαος, 8252, tsakonag@ece.auth.gr \\ +Παπαδιάκος Χαράλαμπος, 8302, charaldp@ece.auth.gr} +\date{\today} + +\pagestyle{fancy} +\lhead{Βάσεις Δεδομένων 2019} + +\begin{document} + \input{front_page.tex} + \newpage + \input{TOC.tex} + \input{1.0.introduction.tex} + \input{2.0.coverage.tex} + \input{3.0.setup.tex} + \input{4.0.test_case.tex} + \input{5.0.bugs.tex} + \input{6.0.unistall.tex} +\end{document} diff --git a/UI/Report/res/fwbLOGO.png b/UI/Report/res/fwbLOGO.png new file mode 100644 index 0000000000000000000000000000000000000000..4443a7857ded59fe9ab1044650f5f8e5cab0b122 GIT binary patch literal 18037 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 E09E^&BLDyZ literal 0 HcmV?d00001