diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6769e21 --- /dev/null +++ b/.gitignore @@ -0,0 +1,160 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..1377d8c --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +Zappster_app.iml \ No newline at end of file diff --git a/.idea/Zappster_app.iml b/.idea/Zappster_app.iml new file mode 100644 index 0000000..286f873 --- /dev/null +++ b/.idea/Zappster_app.iml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..b9c87af --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..0688661 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..393d2d6 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..8325952 Binary files /dev/null and b/README.md differ diff --git a/create_db.py b/create_db.py new file mode 100644 index 0000000..c4df5ff --- /dev/null +++ b/create_db.py @@ -0,0 +1,39 @@ +# import the sqlite3 library to work with SQLite databases in Python +import sqlite3 + +# connect and open the database file database.db, the database will be created when it does not exists +conn = sqlite3.connect('database.db') +print("Opened database successfully") + +# drop table if exists: +conn.execute('DROP TABLE IF EXISTS card;') +conn.execute('DROP TABLE IF EXISTS wish;') + +# create a new table card with two columns: +# cardid - title +conn.execute('CREATE TABLE card (cardid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, title TEXT)') +print("Table card created successfully") + +# insert four rows in the newly created table +conn.execute("INSERT INTO card (title) VALUES ('Greetings')") +conn.execute("INSERT INTO card (title) VALUES ('Happy valentine''s day')") +conn.execute("INSERT INTO card (title) VALUES ('Happy Birthday')") +conn.execute("INSERT INTO card (title) VALUES ('Happy Birthday')") +conn.execute("INSERT INTO card (title) VALUES ('Happy Birthday')") +conn.execute("INSERT INTO card (title) VALUES ('I love you')") +conn.execute("INSERT INTO card (title) VALUES ('Happy Birthday')") +conn.execute("INSERT INTO card (title) VALUES ('Merry Christmas')") +conn.execute("INSERT INTO card (title) VALUES ('Congratulations')") +print("Cards inserted successfully") + +# create a second table wish: +# wishid - uid - sender - message - cardid +conn.execute('CREATE TABLE wish (wishid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,uid TEXT, sender TEXT, message TEXT, cardid INTEGER)') +# there are no wishes already sent, so the table stays empty +print("Table wish created successfully") + +# commit all changes to the database, otherwise they will be lost +conn.commit() + +# close the connection +conn.close() diff --git a/database.db b/database.db new file mode 100644 index 0000000..9c4c724 Binary files /dev/null and b/database.db differ diff --git a/flask_app.py b/flask_app.py new file mode 100644 index 0000000..60be3e3 --- /dev/null +++ b/flask_app.py @@ -0,0 +1,112 @@ +import secrets +import sqlite3 +import string +import os.path + +from flask import Flask, jsonify, request, render_template + +app = Flask(__name__) + + +def generate_uid(db_id): + alphabet = string.ascii_lowercase + string.digits + return f"{db_id}-" + ''.join(secrets.choice(alphabet) for _ in range(4)) + + +def dict_factory(cursor, row): + dic = dict() + for idx, col in enumerate(cursor.description): + dic[col[0]] = row[idx] + return dic + + +def db_connect(): + connection = sqlite3.connect('database.db') + connection.row_factory = dict_factory + cursor = connection.cursor() + return cursor, connection + + +@app.route('/') +def home(): + print(os.getcwd()) + return render_template("index.html") + + +@app.route('/about') +def about(): + return render_template("base.html") + + +@app.route('/cards') +def list_cards(): + cur, conn = db_connect() + cards = cur.execute('SELECT * FROM card;').fetchall() + conn.close() + return render_template("cards.html", cards=cards) + + +@app.route('/wish/') +def wish_form(card_id): + cur, conn = db_connect() + card = cur.execute(f'SELECT * FROM card WHERE cardid={card_id};').fetchall() + conn.close() + return render_template("send_wish.html", card=card[0]) + + +@app.route('/wish_insert', methods=['POST']) +def wish_insert(): + sender = request.form.get("sender") + message = request.form.get("message") + card_id = request.form.get("card_id") + + cur, conn = db_connect() + + max_id = cur.execute('select MAX(wishid) as wishid from wish;').fetchone()['wishid'] + if max_id is None: + db_id = 1 + else: + db_id = max_id + 1 + uid = generate_uid(db_id) + + card = cur.execute('SELECT * FROM card WHERE cardid' + '=' + str(card_id) + ';').fetchone() + conn.execute( + f"INSERT INTO wish (uid, sender, message, cardid) VALUES (\'{uid}\', \'{sender}\', \'{message}\', {card_id})") + conn.commit() + conn.close() + return render_template("confirm_wish.html", card=card) + + +@app.route('/get_wish') +def get_wish(): + return render_template("get_wish.html") + + +@app.route('/show_wish', methods=['POST']) +def result_wish(): + uid = request.form.get("uuid") + cur, conn = db_connect() + personal_card = cur.execute(f"SELECT * FROM wish WHERE uid=\'{uid}\';").fetchone() + conn.close() + return render_template("show_wish.html", card=personal_card) + + +# extra route for our API to request the personal message +# use the http get method in the web request +@app.route('/api/get_wish', methods=['GET']) +def get_personal_wish(): + # the function has one parameter, the unique code + # get the value of this parameter + code = request.args.get('code') + + # connect and open the database file database.db + cur, conn = db_connect() + # read the associated personal wish, you will need an extra integer field code in your wish table! + wish = cur.execute(f"SELECT * FROM wish WHERE code={code}").fetchall() + conn.close() + # there's only one wish because the code is unique + response = jsonify(wish[0]) + + # allow cross-domain Ajax requests, more info in later years + response.headers.add("Access-Control-Allow-Origin", "*") + return response diff --git a/read_db.py b/read_db.py new file mode 100644 index 0000000..8d43bbb --- /dev/null +++ b/read_db.py @@ -0,0 +1,20 @@ +import sqlite3 + +# connect and open the database file database.db +conn = sqlite3.connect('database.db') +print("Opened database successfully") + +# use the opened connection to read all cards into a cursor +cursor = conn.execute("SELECT cardid, title from card") +# loop over all rows in the cursor and print the cardid and title column +for row in cursor: + print("CARDID = ", row[0], "TITLE = ", row[1]) + +cursor = conn.execute("SELECT * from wish") +# loop over all rows in the cursor and print the cardid and title column +for row in cursor: + print(row) + +# close the connection +print("Operation done successfully") +conn.close() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..591be0e --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +Flask~=2.1.2 \ No newline at end of file diff --git a/static/1.jpg b/static/1.jpg new file mode 100644 index 0000000..1773192 Binary files /dev/null and b/static/1.jpg differ diff --git a/static/2.jpg b/static/2.jpg new file mode 100644 index 0000000..9f01cc4 Binary files /dev/null and b/static/2.jpg differ diff --git a/static/3.jpg b/static/3.jpg new file mode 100644 index 0000000..fef7a85 Binary files /dev/null and b/static/3.jpg differ diff --git a/static/4.jpg b/static/4.jpg new file mode 100644 index 0000000..a6c901b Binary files /dev/null and b/static/4.jpg differ diff --git a/static/5.jpg b/static/5.jpg new file mode 100644 index 0000000..8de44ea Binary files /dev/null and b/static/5.jpg differ diff --git a/static/6.jpg b/static/6.jpg new file mode 100644 index 0000000..a0fbb4c Binary files /dev/null and b/static/6.jpg differ diff --git a/static/7.jpg b/static/7.jpg new file mode 100644 index 0000000..9dacaa1 Binary files /dev/null and b/static/7.jpg differ diff --git a/static/8.jpg b/static/8.jpg new file mode 100644 index 0000000..ac40433 Binary files /dev/null and b/static/8.jpg differ diff --git a/static/9.jpg b/static/9.jpg new file mode 100644 index 0000000..17cbcc1 Binary files /dev/null and b/static/9.jpg differ diff --git a/static/style.css b/static/style.css new file mode 100644 index 0000000..f70c4af --- /dev/null +++ b/static/style.css @@ -0,0 +1,5 @@ +#title { + font-size: 5em; + text-decoration: underline; + text-align: center; +} \ No newline at end of file diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..cb2aa3f --- /dev/null +++ b/templates/base.html @@ -0,0 +1,56 @@ + + + + + + + + + + + + {% block title %} {% endblock %} + + + +
+ {% block content %} {% endblock %} +
+ + + + + + + + diff --git a/templates/cards.html b/templates/cards.html new file mode 100644 index 0000000..ec4101a --- /dev/null +++ b/templates/cards.html @@ -0,0 +1,24 @@ + +{% extends 'base.html' %} + + +{% block title %} AR Greeting Cards {% endblock %} + +{% block content %} +

AR Greeting Cards

+
+

Please select one of our fancy AR cards:

+ +

+ + {% for card in cards %} + +

+

{{ card['title'] }}

+ + + +
+ {% endfor %} +

+{% endblock %} diff --git a/templates/confirm_wish.html b/templates/confirm_wish.html new file mode 100644 index 0000000..ccf312f --- /dev/null +++ b/templates/confirm_wish.html @@ -0,0 +1,18 @@ + +{% extends 'base.html' %} + + +{% block title %} New Wish confirmation {% endblock %} + +{% block content %} +

New Wish confirmation

+ +
+ +

{{ card }}

+ + + +

New wish was added to the database

+ +{% endblock %} diff --git a/templates/get_wish.html b/templates/get_wish.html new file mode 100644 index 0000000..4966b80 --- /dev/null +++ b/templates/get_wish.html @@ -0,0 +1,23 @@ + +{% extends 'base.html' %} + + +{% block title %} Add New Wish {% endblock %} + +{% block content %} +

Get your message

+ +
+ +

Please fill in this the code:

+ +

+

+
+ + +
+ +
+

+{% endblock %} \ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..6fb1e84 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,15 @@ + +{% extends 'base.html' %} + + +{% block title %} Home {% endblock %} + +{% block content %} +

AR Greeting Cards

+ +
+ +

The best place to send your friends interactive and suprising greating cards

+

surprise one of your friends now!!

+ +{% endblock %} diff --git a/templates/send_wish.html b/templates/send_wish.html new file mode 100644 index 0000000..d0806dc --- /dev/null +++ b/templates/send_wish.html @@ -0,0 +1,35 @@ + +{% extends 'base.html' %} + + +{% block title %} Add New Wish {% endblock %} + +{% block content %} +

Add New Wish

+ +
+ +

Please fill in this form:

+ +

+

+ +

{{ card }}

+
+ +
+ + +
+
+ + +
+
+ + +
+ +
+

+{% endblock %} \ No newline at end of file diff --git a/templates/show_wish.html b/templates/show_wish.html new file mode 100644 index 0000000..0dc8418 --- /dev/null +++ b/templates/show_wish.html @@ -0,0 +1,15 @@ + +{% extends 'base.html' %} + + +{% block title %} AR Greeting Cards {% endblock %} + +{% block content %} +

Your unique card

+
+ +
+ +

{{ card }}

+
+{% endblock %}