From e40bb75d7c181bac8eabda45e4dfc9f1f50a7016 Mon Sep 17 00:00:00 2001 From: samuellouiskwiatkowski-martin Date: Fri, 10 Nov 2023 18:34:28 -0500 Subject: [PATCH 1/4] Refactored the code so that we don't have so much redudant html. Also added a favicon. Also added the new logon page, but it is just a template right now. --- src/recommenderapp/app.py | 6 + src/recommenderapp/static/script.js | 3 +- .../templates/landing_page.html | 75 +++----- src/recommenderapp/templates/login.html | 54 ++++++ src/recommenderapp/templates/search_page.html | 152 +++++++--------- .../templates/shared/layout.html | 39 +++++ src/recommenderapp/templates/success.html | 162 +++++++----------- 7 files changed, 254 insertions(+), 237 deletions(-) create mode 100644 src/recommenderapp/templates/login.html create mode 100644 src/recommenderapp/templates/shared/layout.html diff --git a/src/recommenderapp/app.py b/src/recommenderapp/app.py index f9744700e..c9b9463a9 100644 --- a/src/recommenderapp/app.py +++ b/src/recommenderapp/app.py @@ -32,6 +32,12 @@ def landing_page(): """ return render_template("landing_page.html") +@app.route("/login") +def login_page(): + """ + Renders the login page. + """ + return render_template("login.html") @app.route("/search_page") def search_page(): diff --git a/src/recommenderapp/static/script.js b/src/recommenderapp/static/script.js index e3a08cc9e..32af9f3c4 100644 --- a/src/recommenderapp/static/script.js +++ b/src/recommenderapp/static/script.js @@ -1,5 +1,5 @@ $(document).ready(function () { - +console.log('hello') $(function () { $("#searchBox").autocomplete({ source: function (request, response) { @@ -127,6 +127,7 @@ $(document).ready(function () { // Function to handle Get Started button click function getStarted() { + console.log("Made it to this function!") // Navigate to the search page $("#loaderLanding").attr("class", "d-flex justify-content-center"); $("#centralDivLanding").hide(); diff --git a/src/recommenderapp/templates/landing_page.html b/src/recommenderapp/templates/landing_page.html index 41c52539a..cef441f12 100644 --- a/src/recommenderapp/templates/landing_page.html +++ b/src/recommenderapp/templates/landing_page.html @@ -1,54 +1,27 @@ - - - - - PopcornPicks - - - - - - - - - +{% extends 'shared/layout.html' %} - - - -
-




-

🎬 PopcornPicks🍿: Pick a Movie! 🎬

-


- Discover personalized movie recommendations by selecting up to 5 of your favorite films. -
- Create a watchlist and have it conveniently sent to your email. -
- Enjoy movies at your own pace, on your terms. -


-

- -
-
-
-
- -
+{% block maincontent %} +
+




+

🎬 PopcornPicks🍿: Pick a Movie! 🎬

+


+ Discover personalized movie recommendations by selecting up to 5 of your favorite films. +
+ Create a watchlist and have it conveniently sent to your email. +
+ Enjoy movies at your own pace, on your terms. +


+

+ +
+
+
+
+ +
+
+{% endblock %} - - - - - - diff --git a/src/recommenderapp/templates/login.html b/src/recommenderapp/templates/login.html new file mode 100644 index 000000000..4992bc0c0 --- /dev/null +++ b/src/recommenderapp/templates/login.html @@ -0,0 +1,54 @@ + + + + + PopcornPicks + + + + + + + + + + + + + +
+




+

🎬 PopcornPicks🍿: Pick a Movie! 🎬

+


+ Discover personalized movie recommendations by selecting up to 5 of your favorite films. +
+ Create a watchlist and have it conveniently sent to your email. +
+ Enjoy movies at your own pace, on your terms. +


+

+ +
+
+
+
+ +
+
+ + + + + + + diff --git a/src/recommenderapp/templates/search_page.html b/src/recommenderapp/templates/search_page.html index fb2fbb0ea..bc55c76ad 100644 --- a/src/recommenderapp/templates/search_page.html +++ b/src/recommenderapp/templates/search_page.html @@ -1,103 +1,79 @@ - - - - - - PopcornPicks - - - - - - - - - - - -
-
- -

🎬 Pick a Movie! 🎬

-
✨Tip: Select Upto 5 movies to get a tailored watchlist✨
-
+{% extends 'shared/layout.html' %} +{% block maincontent %} +
+
+ +

🎬 Pick a Movie! 🎬

+
✨Tip: Select Upto 5 movies to get a tailored watchlist✨
+
-
-
- -
-

Selected Movie(s):

-
-
- - -
    -
    -
    - - -
    -
    -
    -
    -
    - -
    -
    - -
    -
    - -

    Recommended Movies:

    -
    -
      -
      -
      + +
      +
      + +
      +

      Selected Movie(s):

      +
      +
      + + +
        -
        -
        - - -
        +
        + +
        -
        -
        - -
        +
        +
        -
        +
        +
        - - + +

        Recommended Movies:

        +
        +
          +
          -
          -
          -
          -
          - - +
          +
          + +
          -


          - - - - - +
          +
          +
          +
          + +
          +
          +
          +
          +
          + + +
          +
          +
          +
          +
          +
          + + +
          +
          +
          +


          + +{% endblock %} diff --git a/src/recommenderapp/templates/shared/layout.html b/src/recommenderapp/templates/shared/layout.html new file mode 100644 index 000000000..83f6a502c --- /dev/null +++ b/src/recommenderapp/templates/shared/layout.html @@ -0,0 +1,39 @@ + + + + + + PopcornPicks + + + + + + + + {% block extracss %}{% endblock %} + + + + + + + + + {% block extrajs %}{% endblock %} + + + + + {% block maincontent %}{% endblock %} + + + {% block extra_html_scripts %}{% endblock %} + \ No newline at end of file diff --git a/src/recommenderapp/templates/success.html b/src/recommenderapp/templates/success.html index 24d44f7a9..49c7efca3 100644 --- a/src/recommenderapp/templates/success.html +++ b/src/recommenderapp/templates/success.html @@ -1,105 +1,73 @@ - - - - PopcornPicks - - - - - - - - - - - +{% extends 'shared/layout.html' %} - -
          -
          -
          - -
          -
          -

          Have your watchlist sent to your email!

          -
          -
          - -
          -
          - - - -
          -
          -
          -

          -
          -

          - Or -

          +{% block extrajs %} + +{% endblock %} + +{% block maincontent %} +
          +
          +
          +
          -

          - - +
          +

          Have your watchlist sent to your email!

          +
          +
          + +
          +
          + + + +
          +
          +

          +
          +

          + Or +

          +
          +

          + - - +
          + + + + +{% endblock %} - - - - - - + +{% endblock %} From 3e6659d0089971b754e170c26e38e3422aa91374 Mon Sep 17 00:00:00 2001 From: samuellouiskwiatkowski-martin Date: Mon, 13 Nov 2023 22:27:07 -0500 Subject: [PATCH 2/4] Added login page and signup page. Added lots of supporting code including js css html and python for this all to work. Now both features are fully functional. Also added logout button. Code should be ready to merge to main after review. --- src/recommenderapp/app.py | 108 ++++++++++++++++-- src/recommenderapp/db.py | 29 +++++ src/recommenderapp/static/login.css | 16 +++ src/recommenderapp/static/login.js | 22 ++++ src/recommenderapp/static/signup.css | 12 ++ src/recommenderapp/static/signup.js | 24 ++++ src/recommenderapp/templates/login.html | 86 ++++++-------- .../templates/shared/layout.html | 6 + src/recommenderapp/templates/signup.html | 40 +++++++ 9 files changed, 285 insertions(+), 58 deletions(-) create mode 100644 src/recommenderapp/db.py create mode 100644 src/recommenderapp/static/login.css create mode 100644 src/recommenderapp/static/login.js create mode 100644 src/recommenderapp/static/signup.css create mode 100644 src/recommenderapp/static/signup.js create mode 100644 src/recommenderapp/templates/signup.html diff --git a/src/recommenderapp/app.py b/src/recommenderapp/app.py index c9b9463a9..60e21ac8e 100644 --- a/src/recommenderapp/app.py +++ b/src/recommenderapp/app.py @@ -8,7 +8,7 @@ import json import sys -from flask import Flask, jsonify, render_template, request +from flask import Flask, jsonify, render_template, request, session, redirect from flask_cors import CORS from search import Search from utils import beautify_feedback_data, send_email_to_user @@ -17,35 +17,127 @@ #pylint: disable=wrong-import-position from src.prediction_scripts.item_based import recommend_for_new_user #pylint: enable=wrong-import-position - +import db app = Flask(__name__) app.secret_key = "secret key" cors = CORS(app, resources={r"/*": {"origins": "*"}}) +# Connect to the database +db.connect() +# Initialize the database for users +db.mutation_query(''' + CREATE TABLE IF NOT EXISTS users ( + email varchar(500), + password varchar(500) + ) + ''') + +def get_user(): + """ + Returns the user's email if a user is logged in, otherwise returns none + """ + ret = 'None' + if 'email' in session: + # An email is in the session + ret = session['email'] + return ret @app.route("/") def landing_page(): """ - Renders the landing page. + Renders the landing page with the user. """ - return render_template("landing_page.html") + return render_template("landing_page.html", user=get_user()) @app.route("/login") def login_page(): """ Renders the login page. """ - return render_template("login.html") + return render_template("login.html", user=get_user()) + +@app.route("/signup") +def signup_page(): + """ + Renders the signup page. + """ + return render_template("signup.html", user=get_user()) @app.route("/search_page") def search_page(): """ Renders the search page. """ - return render_template("search_page.html") - + return render_template("search_page.html", user=get_user()) + +@app.route('/processSignup', methods = ["POST","GET"]) +def processSignup(): + """ + Queries the database to see if the user already exists. If so it lets the javascript know + If not, the new user is added to the database + """ + ret = {} + # Below is how we create a dictionary of the data sent from the input form + form_fields = dict((key, request.form.getlist(key)[0]) for key in list(request.form.keys())) + print(form_fields) + + # query to see if user in the database already + user_query = f"SELECT * FROM users where email=?" + result = db.select_query(user_query, (form_fields["email"],)) + print(result) + print('blehhhhh') + result = result.fetchone() # get the first row + print(result) + if result is None: + # if email is not in the database then we add it + add_user_query = f"INSERT INTO users (email, password) VALUES (?,?)" + db.mutation_query(add_user_query, (form_fields["email"], form_fields["password"])) + ret["success"] = 1 # send a success indicator back to the javascript side + + # If user is in database, then send a failure indicator + else: + ret["success"] = 0 + + return ret + +@app.route('/processLogin', methods = ["POST","GET"]) +def processLogin(): + """ + Checks to see if the username name and password are valid + If so, the user is logged in via adding their email to the session data + Otherwise the javascript is told there was a mistake. + """ + ret = {} + # Below is how we create a dictionary of the data sent from the input form + form_fields = dict((key, request.form.getlist(key)[0]) for key in list(request.form.keys())) + print(form_fields) + + # query to see if user in the database + user_query = f"SELECT * FROM users where email=? and password=?" + result = db.select_query(user_query, (form_fields["email"], form_fields["password"])) + print(result) + print('blehhhhh') + result = result.fetchone() # get the first row + print(result) + if result is None: + # if email and password is not in the database then we add it then send failure indicator + ret["success"] = 0 + + # If email and password is in the database we log the user in + else: + session['email'] = form_fields["email"] # add the email to the users session + ret["success"] = 1 + return ret + +@app.route('/logout') +def logout(): + """ + Logs the current user out by poping their email from the current session + """ + session.pop('email', default=None) + return redirect('/') @app.route("/predict", methods=["POST"]) def predict(): @@ -103,7 +195,7 @@ def success(): """ Renders the success page. """ - return render_template("success.html") + return render_template("success.html", user=get_user()) if __name__ == "__main__": diff --git a/src/recommenderapp/db.py b/src/recommenderapp/db.py new file mode 100644 index 000000000..5f7f56fbc --- /dev/null +++ b/src/recommenderapp/db.py @@ -0,0 +1,29 @@ +# Reused code from previous project +import sqlite3 +from sqlite3 import Error +import os + +CON = None +def connect(): + ''' connect program to database file db.sqlite ''' + global CON + db_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'db.sqlite') + print(db_path) + try: + CON = sqlite3.connect(db_path, check_same_thread=False) + print("Connection to SQLite DB successful") + except Error as err: + print(f"The error '{err}' occurred when trying to connect to SQLite database") + + +def select_query(sql, args=()): + ''' select query to return items from database ''' + cur = CON.cursor() + return cur.execute(sql, args) + + +def mutation_query(sql, args=()): + ''' do a mutation on the database ''' + cur = CON.cursor() + cur.execute(sql, args) + CON.commit() \ No newline at end of file diff --git a/src/recommenderapp/static/login.css b/src/recommenderapp/static/login.css new file mode 100644 index 000000000..8dfbcad0f --- /dev/null +++ b/src/recommenderapp/static/login.css @@ -0,0 +1,16 @@ +#login-form { + margin: auto; /*so the form is in the center of it's container */ +} + +#Signup_text { + margin: auto; +} + +#login_alert { + margin: 0 auto; + padding-bottom: 5px; + padding-top: 5px; + margin-bottom: 10px; + margin-top: 10px; + display: none; +} \ No newline at end of file diff --git a/src/recommenderapp/static/login.js b/src/recommenderapp/static/login.js new file mode 100644 index 000000000..e737f09a3 --- /dev/null +++ b/src/recommenderapp/static/login.js @@ -0,0 +1,22 @@ +//Function for login in +function Login(){ + email = document.getElementById("inputemail").value + pass = document.getElementById("inputpassword").value + login_alert = document.getElementById("login_alert") + console.log(email) /* just for us to see outputs on the console for testing */ + console.log(pass) + $.ajax({ + url: "/processLogin", + type: 'POST', + data: {'email': email, 'password': pass, 'role': "user"}, + success:function(returned_data){ + if (returned_data['success'] === 1){ + window.location.href = "/" + } + else{ + login_alert.style.display = "flex"; + } + } + + }) +} diff --git a/src/recommenderapp/static/signup.css b/src/recommenderapp/static/signup.css new file mode 100644 index 000000000..9d4b052cf --- /dev/null +++ b/src/recommenderapp/static/signup.css @@ -0,0 +1,12 @@ +#signup-form { + margin: auto; /*so the form is in the center of it's container */ +} + +#failed_sign_in { + margin: 0 auto; + padding-bottom: 5px; + padding-top: 5px; + margin-bottom: 10px; + margin-top: 10px; + display: none; +} \ No newline at end of file diff --git a/src/recommenderapp/static/signup.js b/src/recommenderapp/static/signup.js new file mode 100644 index 000000000..f3dd919ec --- /dev/null +++ b/src/recommenderapp/static/signup.js @@ -0,0 +1,24 @@ +//Function for sign out +function Signup(){ + email = document.getElementById("inputemail").value + pass = document.getElementById("inputpassword").value + sign_alert = document.getElementById("failed_sign_in") + console.log(email) /* just for us to see outputs on the console for testing */ + console.log(pass) + $.ajax({ + url: "/processSignup", + type: 'POST', + data: {'email': email, 'password': pass, 'role': "user"}, // role will matter later + success:function(returned_data){ + if (returned_data['success'] === 1){ + // happens if the signup is valid + window.location.href = "/login" + } + else{ + // happens if the signup is not valid + //window.location.href = "/signup" + sign_alert.style.display = "flex"; + } + } + }) +} diff --git a/src/recommenderapp/templates/login.html b/src/recommenderapp/templates/login.html index 4992bc0c0..8619ab8f0 100644 --- a/src/recommenderapp/templates/login.html +++ b/src/recommenderapp/templates/login.html @@ -1,54 +1,40 @@ - - - - - PopcornPicks - - - - - - - - - +{% extends 'shared/layout.html' %} - - +{% block extracss %} + +{% endblock %} -
          -




          -

          🎬 PopcornPicks🍿: Pick a Movie! 🎬

          -


          - Discover personalized movie recommendations by selecting up to 5 of your favorite films. -
          - Create a watchlist and have it conveniently sent to your email. -
          - Enjoy movies at your own pace, on your terms. -


          -

          - +{% block extrajs %} + +{% endblock %} + +{% block maincontent %} +
          +




          +

          🎬 PopcornPicks🍿: Login to Your Account! 🎬

          + -
          -
          -
          - +
          +
          + +
          -
          - - - - - - - +
          +
          + + +
          +
          + + + Don't have an account with us? Click here to sign up. +
          +
          +
          +
          +
          + +
          +
          +{% endblock %} diff --git a/src/recommenderapp/templates/shared/layout.html b/src/recommenderapp/templates/shared/layout.html index 83f6a502c..020a8fed0 100644 --- a/src/recommenderapp/templates/shared/layout.html +++ b/src/recommenderapp/templates/shared/layout.html @@ -29,6 +29,12 @@ + {% if user == 'None' %} + Login + {% else %} +
          Welcome {{ user }}!
          + Logout + {% endif %}
          diff --git a/src/recommenderapp/templates/signup.html b/src/recommenderapp/templates/signup.html new file mode 100644 index 000000000..9e720c4bb --- /dev/null +++ b/src/recommenderapp/templates/signup.html @@ -0,0 +1,40 @@ +{% extends 'shared/layout.html' %} + +{% block extracss %} + +{% endblock %} + +{% block extrajs %} + +{% endblock %} + +{% block maincontent %} +
          +




          +

          🎬 PopcornPicks🍿: Signup for an Account! 🎬

          + +
          +
          + + +
          +
          +
          + + +
          +
          + +
          +
          + +
          + +
          +
          + +
          +
          +{% endblock %} \ No newline at end of file From 2b4c17e80334c7ce65c08c6995470483beb470d9 Mon Sep 17 00:00:00 2001 From: samuellouiskwiatkowski-martin Date: Wed, 15 Nov 2023 02:35:57 -0500 Subject: [PATCH 3/4] Removed excess bloat in the code. --- src/recommenderapp/app.py | 11 ----------- src/recommenderapp/templates/landing_page.html | 4 ++-- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/recommenderapp/app.py b/src/recommenderapp/app.py index 60e21ac8e..3bcdba286 100644 --- a/src/recommenderapp/app.py +++ b/src/recommenderapp/app.py @@ -81,21 +81,15 @@ def processSignup(): ret = {} # Below is how we create a dictionary of the data sent from the input form form_fields = dict((key, request.form.getlist(key)[0]) for key in list(request.form.keys())) - print(form_fields) - # query to see if user in the database already user_query = f"SELECT * FROM users where email=?" result = db.select_query(user_query, (form_fields["email"],)) - print(result) - print('blehhhhh') result = result.fetchone() # get the first row - print(result) if result is None: # if email is not in the database then we add it add_user_query = f"INSERT INTO users (email, password) VALUES (?,?)" db.mutation_query(add_user_query, (form_fields["email"], form_fields["password"])) ret["success"] = 1 # send a success indicator back to the javascript side - # If user is in database, then send a failure indicator else: ret["success"] = 0 @@ -112,15 +106,10 @@ def processLogin(): ret = {} # Below is how we create a dictionary of the data sent from the input form form_fields = dict((key, request.form.getlist(key)[0]) for key in list(request.form.keys())) - print(form_fields) - # query to see if user in the database user_query = f"SELECT * FROM users where email=? and password=?" result = db.select_query(user_query, (form_fields["email"], form_fields["password"])) - print(result) - print('blehhhhh') result = result.fetchone() # get the first row - print(result) if result is None: # if email and password is not in the database then we add it then send failure indicator ret["success"] = 0 diff --git a/src/recommenderapp/templates/landing_page.html b/src/recommenderapp/templates/landing_page.html index cef441f12..54fe8850a 100644 --- a/src/recommenderapp/templates/landing_page.html +++ b/src/recommenderapp/templates/landing_page.html @@ -13,8 +13,8 @@

          🎬 PopcornPicks🍿: Pick a Movie! 🎬




          From 6064f4b537b6d7ef4f65c613ca00ef83fbda540a Mon Sep 17 00:00:00 2001 From: samuellouiskwiatkowski-martin Date: Thu, 16 Nov 2023 19:03:27 -0500 Subject: [PATCH 4/4] Test --- src/recommenderapp/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/recommenderapp/app.py b/src/recommenderapp/app.py index 3bcdba286..3c70c6f00 100644 --- a/src/recommenderapp/app.py +++ b/src/recommenderapp/app.py @@ -123,7 +123,7 @@ def processLogin(): @app.route('/logout') def logout(): """ - Logs the current user out by poping their email from the current session + Logs the current user out by poping their email from current session """ session.pop('email', default=None) return redirect('/')