Skip to content

Commit 02172e2

Browse files
committed
first commit
0 parents  commit 02172e2

22 files changed

+670
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/xpauld00_src.zip
2+
/xpauld00_tz02.pdf
3+
/__pycache__

Readme.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Readme súbor pre ITU projekt
2+
Meno a priezvisko: Daniel Paul
3+
Login: xpauld00
4+
5+
Popis a použitie:
6+
Program bol vytvorený návrhovým vzorom MVC a implementuje VOIP bez samotnej funkcionality komunikácie tak, ako je to zamýšlané v predmete ITU. Pre funkčnosť databáze je mať potrebné pripojenie k internetu, pretože je zahostovaná na platforme Heroku.
7+
8+
Pred spustením je potrebné si stiahnuť používané knižnice pomocou príkazu v adresári do ktorého ste rozbalili skomprimovaný súbor:
9+
pip install -r requirements.txt (Python 2), or pip3 install -r requirements.txt (Python 3)
10+
11+
Príklad spustenia (v adresári do ktorého ste rozbalili skomprimovaný súbor):
12+
python app.py
13+
14+
Po spustení začne bežať lokálny server s aplikáciou, na ktorý sa dá pripojiť cez webový prehliadač pomocou IP adresy v konzoli.

Templates/contacts.html

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{% for contact in contained %}
2+
<div class="row border border-dark" id="contactRow{{contact.id}}" style="background-color:rgb(116, 103, 128);" >
3+
<div class="col-sm-2">
4+
<img class="rounded-circle" style="float: left; margin-left: 20px; margin-top: 5px; margin-bottom: 5px;" src="{{contact.image_path}}" width="50" height="56"/>
5+
</div>
6+
<div class="col-sm-3" style="margin-top: 20px;">
7+
<a style="font-size:larger; font-weight: bold;">{{contact.name}}</a>
8+
</div>
9+
<div class="col-sm-7 callSection" id="callSection{{contact.id}}">
10+
11+
12+
<button class="rounded btn btn-danger btn-sm deleteContact" id="delete{{contact.id}}" contact_id="{{contact.id}}" style="margin-top: 5px; margin-bottom: 5px; text-align: center; font-size: xx-small; float: right;"></button>
13+
<img class="rounded-circle startCall" style="float: right; margin-top: 10px; margin-bottom: 5px; margin-right: 10px;" id="call{{contact.id}}" contact_id="{{contact.id}}" src="static/call.png" width="40" height="46"/>
14+
<img class="rounded-circle muteCall" style="float: right; margin-top: 10px; margin-bottom: 5px; margin-right: 20px; display: None;" id="mutecall{{contact.id}}" contact_id="{{contact.id}}" src="static/microphone.png" width="40" height="46"/>
15+
<img class="notifyButton rounded" style="float: right; margin-top: 10px; margin-right: 20px;" id="notify{{contact.id}}" contact_id="{{contact.id}}" src="/static/notify.png" width="40" height="46" />
16+
<div id="stopwatch{{contact.id}}" style="display: None; margin-top: 20px; margin-left: 35px;">00:00:00</div>
17+
18+
<select name="genre" style="width: 140px; margin-top: 15px;" id="timestamp{{contact.id}}" class="form-control" id="genre" required>
19+
<option>ASAP</option>
20+
<option>in 5 minutes</option>
21+
<option>in 10 minutes</option>
22+
<option>in 20 minutes</option>
23+
<option>in 30 minutes</option>
24+
<option>in 45 minutes</option>
25+
<option>in 1 hour</option>
26+
<option>in 2 hours</option>
27+
<option>in 3 hours</option>
28+
<option>later this day</option>
29+
<option>tomorrow</option>
30+
<option>this week</option>
31+
</select>
32+
33+
</div>
34+
</div>
35+
{% endfor %}
36+
{% for contact in not_contained %}
37+
<div class="row border border-dark" style="background-color:rgb(116, 103, 128);" >
38+
<div class="col-sm-2">
39+
<img class="rounded-circle" style="float: left; margin-left: 20px; margin-top: 5px; margin-bottom: 5px;" src="{{contact.image_path}}" width="50" height="56"/>
40+
</div>
41+
<div class="col-sm-4" style="margin-top: 20px;">
42+
<a style="font-size:larger; font-weight: bold;">{{contact.name}}</a>
43+
</div>
44+
<div class="col-sm-6" style="margin-top: 15px;" >
45+
<button class="rounded btn btn-success btn-sm addContact" id="add{{contact.id}}" contact_id="{{contact.id}}" style="margin-top: 5px; margin-bottom: 5px; text-align: center; font-size: xx-small; float: right;"></button>
46+
</div>
47+
</div>
48+
{% endfor %}

Templates/home.html

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<!DOCTYPE html>
2+
<html lang="en" dir="ltr">
3+
<head>
4+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
5+
<meta charset="utf-8">
6+
<link rel="shortcut icon" href="#" />
7+
<title>Wispr</title>
8+
</head>
9+
<body style="background-color: rgb(53, 51, 49);">
10+
11+
<div class="container border" style="margin-top: 150px; height: 70%; ">
12+
13+
<div class="row border border-dark" style="background-color: rgb(80, 28, 248);">
14+
<div class="col-sm-4">
15+
<img class="rounded-circle" style="float: left; margin-left: 20px; margin-top: 5px; margin-bottom: 5px;" src="{{user.image_path}}" width="60" height="66"/>
16+
</div>
17+
<div class="col-sm-4" style="text-align: center;">
18+
<h1 style="margin-top: 10px;" id="username_display">{{user.username}}</h1>
19+
</div>
20+
<div class="col-sm-4">
21+
<button class="rounded profile_show" style="font-size:xxx-large; float:right; margin-top: 5px; height: 60px; width: 150px; border: 0cm; background-color: rgb(80, 28, 248);"></button>
22+
</div>
23+
24+
25+
<div class="col-sm-12 border border-dark" id="profile_change" style="display: None; background-color: rgb(90, 85, 75); height:52vh;">
26+
<h2 style="color: aliceblue; text-align: center; margin-top: 20px;" >Edit profile</h2>
27+
<label style="font-weight: bold; color: aliceblue; margin-top: 80px;" >Username:</label>
28+
<input class="form-control" type="text" id="change_username" style="margin-top:1px; margin-bottom: 5px; width: 400px;" placeholder="{{user.username}}">
29+
<button class="rounded btn btn-success" id="save_changes">Save changes</button>
30+
</div>
31+
32+
<div class="col-sm-6 border border-dark profile_hide" style="background-color: rgb(105, 101, 94);">
33+
<input class="form-control" type="text" id="contactSearch" style="margin-top: 5px; margin-bottom: 5px;" placeholder="Search/Add contact" aria-label="Search">
34+
</div>
35+
36+
<div class="col-sm-6 border border-dark profile_hide" style="background-color:rgb(105, 101, 94);">
37+
<input class="form-control" id="notificationSearch" style="margin-top: 5px; margin-bottom: 5px;" type="text" placeholder="Search notification" aria-label="Search">
38+
</div>
39+
40+
<div class="col-sm-6 profile_hide" style="background-color: rgb(105, 101, 94); height:46vh; overflow-y:scroll" >
41+
42+
<!-- Search bar for contacts -->
43+
<!-- for contact in contacts -->
44+
<div id="place_for_contacts"></div>
45+
46+
47+
</div>
48+
<div class="col-sm-6 border border-dark profile_hide" style="background-color: rgb(105, 101, 94); height: 46vh; overflow-y:scroll;">
49+
<!-- Search bar for notifications -->
50+
<!-- MAYBE button for clearing notifications after date? -->
51+
<!-- for notification in notifications -->
52+
<div id="place_for_notifications"></div>
53+
54+
</div>
55+
</div>
56+
</div>
57+
<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
58+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script>
59+
<script src="{{url_for('static',filename='js.js')}}"></script>
60+
</body>
61+
</html>

Templates/notifications.html

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{% for notification in notifications %}
2+
<div class="row border border-dark" {% if notification.confirmed == 1 %} style="background-color:rgb(29, 177, 29);" {% else %} style="background-color:rgb(180, 179, 134);" {% endif %}>
3+
<div class="col-sm-9" style="margin-top: 6px;">
4+
{% if notification.from_user == 1 %}
5+
<a style="font-size:small; font-weight: bold;">You want to contact {{notification.contact.name}} {{notification.timestamp}}.</a>
6+
{% else %}
7+
<a style="font-size:small; font-weight: bold;">{{notification.contact.name}} wants to contact you {{notification.timestamp}}.</a>
8+
{% endif %}
9+
<p style="font-size:small; font-weight: bold;">Created: {{notification.date_created}} {{notification.time_created}}</p>
10+
</div>
11+
<div class="col-sm-3">
12+
<button class="rounded btn btn-danger btn-sm deleteNotification" id="delete{{notification.id}}" notification_id="{{notification.id}}" style="margin-top: 5px; margin-bottom: 5px; text-align: center; font-size: xx-small; float: right;"></button>
13+
{% if notification.from_user == 0 and notification.confirmed == 0 %}
14+
<button class="rounded btn btn-success btn-sm confirmNotification" id="confirm{{notification.id}}" notification_id="{{notification.id}}" style="margin-top: 5px; margin-bottom: 5px; text-align: center; font-size: xx-small;float: right;"></button>
15+
{% endif %}
16+
</div>
17+
18+
</div>
19+
{% endfor %}

app.py

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
from models import User, Contact, Notification
2+
from flask import Flask, render_template, request, redirect, url_for, session, jsonify
3+
from flask_login import login_user, logout_user, current_user, login_required
4+
from werkzeug.security import check_password_hash
5+
from commands import restart_tables, fill_database
6+
from extensions import db, login_manager
7+
from datetime import timedelta, datetime
8+
import random
9+
import string
10+
import time
11+
12+
13+
app = Flask(__name__)
14+
app.config['SECRET_KEY'] = "SECRET_KEY"
15+
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgres://bykujoxjexdrch:e1c8a3a18df8920af1e1609638f70a0380b97e7be75bf15e7c1f6618bb100468@ec2-54-217-224-85.eu-west-1.compute.amazonaws.com:5432/d15f1d6b486k51'
16+
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
17+
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(minutes=5)
18+
19+
db.init_app(app)
20+
login_manager.init_app(app)
21+
app.cli.add_command(restart_tables)
22+
app.cli.add_command(fill_database)
23+
24+
login_manager.login_view = 'app.login'
25+
26+
27+
@login_manager.user_loader
28+
def load_user(user_id):
29+
return User.query.get(user_id)
30+
31+
32+
''' HOME '''
33+
34+
35+
@app.route("/", methods=['GET', 'POST'])
36+
def home():
37+
user = User.query.first()
38+
return render_template("home.html", user=user)
39+
40+
41+
@app.route("/edit_profile", methods=['GET', 'POST'])
42+
def edit_profile():
43+
username = request.form.get("username")
44+
print(username)
45+
user = User.query.first()
46+
user.username = username
47+
db.session.commit()
48+
49+
return jsonify({'result': 'success', 'username': username})
50+
51+
52+
@app.route("/filter_contacts", methods=['GET', 'POST'])
53+
def filter_contacts():
54+
user = User.query.first()
55+
searchbox = request.form.get("text")
56+
contained = []
57+
not_contained = []
58+
contacts = Contact.query.filter(
59+
Contact.name.contains(str(searchbox))).all()
60+
for contact in contacts:
61+
if(contact in user.contacts):
62+
contained.append(contact)
63+
else:
64+
not_contained.append(contact)
65+
66+
return render_template('contacts.html', contained=contained, not_contained=not_contained)
67+
68+
69+
@app.route("/filter_notifications", methods=['GET', 'POST'])
70+
def filter_notifications():
71+
searchbox = request.form.get("text")
72+
notifications_time = Notification.query.filter(
73+
Notification.time_created.contains(str(searchbox))).all()
74+
notifications_date = Notification.query.filter(
75+
Notification.date_created.contains(str(searchbox))).all()
76+
77+
notifs = Notification.query.all()
78+
notif_list = []
79+
for notif in notifs:
80+
if str(searchbox) in notif.contact.name:
81+
notif_list.append(notif)
82+
83+
notifications = notifications_date + notifications_time + notif_list
84+
85+
return render_template('notifications.html', notifications=notifications)
86+
87+
88+
@ app.route("/deleteContact", methods=['GET', 'POST'])
89+
def deleteContact():
90+
user = User.query.first()
91+
contact = Contact.query.filter_by(
92+
id=int(request.form.get("contact_id"))).first()
93+
user.contacts.remove(contact)
94+
db.session.commit()
95+
return render_template('contacts.html', contained=user.contacts)
96+
97+
98+
@ app.route("/addContact", methods=['GET', 'POST'])
99+
def addContact():
100+
user = User.query.first()
101+
contact = Contact.query.filter_by(
102+
id=int(request.form.get("contact_id"))).first()
103+
user.contacts.append(contact)
104+
db.session.commit()
105+
return render_template('contacts.html', contained=user.contacts)
106+
107+
108+
@ app.route("/showall_contacts", methods=['GET', 'POST'])
109+
def showall_contacts():
110+
user = User.query.first()
111+
return render_template('contacts.html', contained=user.contacts)
112+
113+
114+
@ app.route("/showall_notifications", methods=['GET', 'POST'])
115+
def showall_notifications():
116+
notifications = Notification.query.all()
117+
return render_template('notifications.html', notifications=notifications)
118+
119+
120+
@ app.route("/createNotification", methods=['GET', 'POST'])
121+
def createNotification():
122+
123+
today = datetime.now()
124+
today_date = today.strftime("%d/%m/%Y")
125+
today_time = today.strftime("%H:%M:%S")
126+
user = User.query.first()
127+
contact = Contact.query.filter_by(
128+
id=int(request.form.get("contact_id"))).first()
129+
notification = Notification(
130+
from_user=1, date_created=today_date, time_created=today_time, timestamp=request.form.get("timestamp"), confirmed=0)
131+
db.session.commit()
132+
user.notifications.append(notification)
133+
contact.notifications.append(notification)
134+
db.session.commit()
135+
136+
notifications = Notification.query.all()
137+
return render_template('notifications.html', notifications=notifications)
138+
139+
140+
@ app.route("/confirmNotification", methods=['GET', 'POST'])
141+
def confirmNotification():
142+
notification = Notification.query.filter_by(
143+
id=int(request.form.get("notification_id"))).first()
144+
print(notification.confirmed)
145+
notification.confirmed = 1
146+
db.session.commit()
147+
notifications = Notification.query.all()
148+
return render_template('notifications.html', notifications=notifications)
149+
150+
151+
@ app.route("/deleteNotification", methods=['GET', 'POST'])
152+
def deleteNotification():
153+
notification = Notification.query.filter_by(
154+
id=int(request.form.get("notification_id"))).first()
155+
db.session.delete(notification)
156+
db.session.commit()
157+
notifications = Notification.query.all()
158+
return render_template('notifications.html', notifications=notifications)
159+
160+
161+
if __name__ == "__main__":
162+
app.run(debug=True)

commands.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import click
2+
from flask.cli import with_appcontext
3+
from models import User, Contact, Notification
4+
from extensions import db
5+
6+
7+
@click.command(name='restart_tables')
8+
@with_appcontext
9+
def restart_tables():
10+
db.drop_all()
11+
db.create_all()
12+
13+
14+
@click.command(name='fill_database')
15+
@with_appcontext
16+
def fill_database():
17+
user = User(username="User", image_path="/static/profile.jpg")
18+
db.session.add(user)
19+
db.session.commit()
20+
c_jotaro = Contact(name="Jotaro", image_path="/static/jotaro.jpg")
21+
db.session.add(c_jotaro)
22+
c_dio = Contact(name="Dio", image_path="/static/dio.jpg")
23+
db.session.add(c_dio)
24+
c_joseph = Contact(name="Joseph", image_path="/static/joseph.jpg")
25+
db.session.add(c_joseph)
26+
c_polnareff = Contact(name="Polnareff", image_path="/static/polnareff.jpg")
27+
db.session.add(c_polnareff)
28+
c_yoshikage = Contact(name="Yoshikage", image_path="/static/yoshikage.jpg")
29+
db.session.add(c_yoshikage)
30+
c_zepelli = Contact(name="Zepelli", image_path="/static/zepelli.jpg")
31+
db.session.add(c_zepelli)
32+
db.session.commit()
33+
34+
user.contacts.append(c_jotaro)
35+
user.contacts.append(c_dio)
36+
user.contacts.append(c_joseph)
37+
user.contacts.append(c_polnareff)
38+
user.contacts.append(c_yoshikage)
39+
user.contacts.append(c_zepelli)
40+
db.session.commit()

extensions.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from flask_login import LoginManager
2+
from flask_sqlalchemy import SQLAlchemy
3+
4+
5+
login_manager = LoginManager()
6+
db = SQLAlchemy()

models.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from flask_login import UserMixin
2+
from extensions import db
3+
import pandas as pd
4+
5+
6+
class User(UserMixin, db.Model):
7+
id = db.Column(db.Integer, primary_key=True)
8+
username = db.Column(db.String(20), unique=True)
9+
image_path = db.Column(db.String(60))
10+
notifications = db.relationship('Notification', backref='user')
11+
contacts = db.relationship('Contact', backref='user')
12+
13+
14+
class Contact(db.Model):
15+
id = db.Column(db.Integer, primary_key=True)
16+
name = db.Column(db.String(60), unique=True)
17+
image_path = db.Column(db.String(60))
18+
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
19+
notifications = db.relationship('Notification', backref='contact')
20+
21+
22+
class Notification(db.Model):
23+
id = db.Column(db.Integer, primary_key=True)
24+
from_user = db.Column(db.Integer)
25+
timestamp = db.Column(db.String(14))
26+
confirmed = db.Column(db.Integer)
27+
time_created = db.Column(db.String(10))
28+
date_created = db.Column(db.String(10))
29+
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
30+
contact_id = db.Column(db.Integer, db.ForeignKey('contact.id'))

0 commit comments

Comments
 (0)