proiect finalizat
This commit is contained in:
Executable
+5
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
source venv/bin/activate
|
||||||
|
cd messenger_app
|
||||||
|
uvicorn app.main:app --reload
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
The 'api' package contains the logic behind the endpoints of the backend. The main version of the api is 'v1'.
|
||||||
|
"""
|
||||||
Binary file not shown.
@@ -6,6 +6,10 @@ from .signup import signup
|
|||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
"""
|
||||||
|
The 'auth' packages contains the router configuration for the 'Authentication' endpoints.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
@router.post("/login")
|
@router.post("/login")
|
||||||
async def login_router(login_info: Login):
|
async def login_router(login_info: Login):
|
||||||
|
|||||||
@@ -4,6 +4,15 @@ from database.queries.user import get_user_by_email
|
|||||||
|
|
||||||
|
|
||||||
async def login(login_info: Login):
|
async def login(login_info: Login):
|
||||||
|
"""
|
||||||
|
Verify user credentials
|
||||||
|
|
||||||
|
Args:
|
||||||
|
login_info (Login)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict : full user information besides password
|
||||||
|
"""
|
||||||
result = get_user_by_email(login_info.email)
|
result = get_user_by_email(login_info.email)
|
||||||
if not result:
|
if not result:
|
||||||
raise HTTPException(status_code=404, detail='User not in system.')
|
raise HTTPException(status_code=404, detail='User not in system.')
|
||||||
|
|||||||
@@ -4,6 +4,15 @@ from database.queries.user import get_user_by_email, create_user_db
|
|||||||
|
|
||||||
|
|
||||||
async def signup(user: User):
|
async def signup(user: User):
|
||||||
|
"""
|
||||||
|
Verify user credentials
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user (User)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict : full user information besides password
|
||||||
|
"""
|
||||||
result = get_user_by_email(user.email)
|
result = get_user_by_email(user.email)
|
||||||
if result:
|
if result:
|
||||||
raise HTTPException(status_code=409, detail='User already exists.')
|
raise HTTPException(status_code=409, detail='User already exists.')
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ from .get_conversation import get_conversation
|
|||||||
from .get_conversation_url import get_conversation_url
|
from .get_conversation_url import get_conversation_url
|
||||||
from app.models import Message
|
from app.models import Message
|
||||||
|
|
||||||
|
'''
|
||||||
|
The 'messages' packages contains the router configuration for the 'Messages' endpoints.
|
||||||
|
'''
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -3,6 +3,15 @@ from database.queries.messages import find_conversation_db
|
|||||||
|
|
||||||
|
|
||||||
async def get_conversation(conversation_url: str):
|
async def get_conversation(conversation_url: str):
|
||||||
|
"""
|
||||||
|
Retrieves the full context of the conversation
|
||||||
|
|
||||||
|
Args:
|
||||||
|
conversation_url (str)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
HTTP Status
|
||||||
|
"""
|
||||||
conversation = find_conversation_db(conversation_url)
|
conversation = find_conversation_db(conversation_url)
|
||||||
if conversation is None:
|
if conversation is None:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Conversation not found")
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Conversation not found")
|
||||||
|
|||||||
@@ -4,6 +4,16 @@ from fastapi import HTTPException
|
|||||||
|
|
||||||
|
|
||||||
async def get_conversation_url(id_user1: str, id_user2: str):
|
async def get_conversation_url(id_user1: str, id_user2: str):
|
||||||
|
"""
|
||||||
|
Retrieves the conversation identifier
|
||||||
|
|
||||||
|
Args:
|
||||||
|
id_user1 (str)
|
||||||
|
id_user2 (str)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
(str) : conversation_url
|
||||||
|
"""
|
||||||
if get_user_by_id(id_user1) is None or get_user_by_id(id_user2) is None:
|
if get_user_by_id(id_user1) is None or get_user_by_id(id_user2) is None:
|
||||||
raise HTTPException(status_code=404, detail="Users not in the system.")
|
raise HTTPException(status_code=404, detail="Users not in the system.")
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,15 @@ from database.queries.messages import send_message_db
|
|||||||
|
|
||||||
|
|
||||||
async def send(message: Message):
|
async def send(message: Message):
|
||||||
|
"""
|
||||||
|
Stores message in MongoDB
|
||||||
|
|
||||||
|
Args:
|
||||||
|
message (Message)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
HTTP Status
|
||||||
|
"""
|
||||||
success = send_message_db(message)
|
success = send_message_db(message)
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ from .update import update_user
|
|||||||
from .delete import delete_user
|
from .delete import delete_user
|
||||||
from .get_all import get_all_users
|
from .get_all import get_all_users
|
||||||
|
|
||||||
|
'''
|
||||||
|
The 'messages' packages contains the router configuration for the 'Messages' endpoints.
|
||||||
|
'''
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -4,6 +4,15 @@ from database.queries.user import get_user_by_email, create_user_db
|
|||||||
|
|
||||||
|
|
||||||
async def create_user(user: User):
|
async def create_user(user: User):
|
||||||
|
"""
|
||||||
|
Creates a user
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user (User)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
complete user information, including id, if successful
|
||||||
|
"""
|
||||||
result = get_user_by_email(user.email)
|
result = get_user_by_email(user.email)
|
||||||
if result:
|
if result:
|
||||||
raise HTTPException(status_code=409, detail='User already exists.')
|
raise HTTPException(status_code=409, detail='User already exists.')
|
||||||
|
|||||||
@@ -2,7 +2,16 @@ from fastapi import HTTPException
|
|||||||
from database.queries.user import get_user_by_id, delete_user_db
|
from database.queries.user import get_user_by_id, delete_user_db
|
||||||
|
|
||||||
|
|
||||||
async def delete_user(user_id: int):
|
async def delete_user(user_id):
|
||||||
|
"""
|
||||||
|
Deletes a user
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user_id (str)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
complete user information, including id, if successful
|
||||||
|
"""
|
||||||
user = get_user_by_id(user_id)
|
user = get_user_by_id(user_id)
|
||||||
if user is None:
|
if user is None:
|
||||||
raise HTTPException(status_code=404, detail='User not found')
|
raise HTTPException(status_code=404, detail='User not found')
|
||||||
|
|||||||
@@ -3,4 +3,13 @@ from database.queries.user import get_all_users_db
|
|||||||
|
|
||||||
async def get_all_users():
|
async def get_all_users():
|
||||||
users = get_all_users_db()
|
users = get_all_users_db()
|
||||||
|
"""
|
||||||
|
Gets all users from database
|
||||||
|
|
||||||
|
Args:
|
||||||
|
Nan
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A list of users, if exists
|
||||||
|
"""
|
||||||
return users
|
return users
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
The 'app' package contains de main API object plus all the routing. It also contains the 'models' for the API requests.
|
||||||
|
"""
|
||||||
Binary file not shown.
@@ -1,3 +1,10 @@
|
|||||||
from .user import User
|
from .user import User
|
||||||
from .message import Message
|
from .message import Message
|
||||||
from .login import Login
|
from .login import Login
|
||||||
|
|
||||||
|
'''
|
||||||
|
The 'models' package contains the schematics for the API body structures. In more detail:
|
||||||
|
- 'Login' model is used for the auth/login endpoint
|
||||||
|
- 'User' model is used for the auto/signup and users endpoints
|
||||||
|
- 'Message' model is used for the messages/send endpoint
|
||||||
|
'''
|
||||||
Binary file not shown.
Binary file not shown.
@@ -1,5 +1,4 @@
|
|||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
|
|
||||||
class Message(BaseModel):
|
class Message(BaseModel):
|
||||||
|
|||||||
@@ -1,4 +1,11 @@
|
|||||||
from .connection import MONGODB_CONFIG, MongoDbHandler
|
from .connection import MONGODB_CONFIG, MongoDbHandler
|
||||||
|
|
||||||
mongo_db_handler = MongoDbHandler(**MONGODB_CONFIG)
|
mongo_db_handler = MongoDbHandler(**MONGODB_CONFIG)
|
||||||
mongo_db_handler.connect()
|
mongo_db_handler.connect()
|
||||||
|
|
||||||
|
'''
|
||||||
|
The 'mongodb_database' package contains the definition of the 'MongoDbHandler' class which connects to the MongoDB
|
||||||
|
database used for storing the messages between the clients.
|
||||||
|
|
||||||
|
The object 'mongo_db_handler' is created inside this file and can be used throughout the lifetime of the application
|
||||||
|
'''
|
||||||
Binary file not shown.
@@ -1,4 +1,12 @@
|
|||||||
from .connection import POSTGRESQL_CONFIG, PostgreSQLHandler
|
from .connection import POSTGRESQL_CONFIG, PostgreSQLHandler
|
||||||
|
|
||||||
postgresql_db_handler = PostgreSQLHandler(**POSTGRESQL_CONFIG)
|
postgresql_db_handler = PostgreSQLHandler(**POSTGRESQL_CONFIG)
|
||||||
postgresql_db_handler.connect()
|
postgresql_db_handler.connect()
|
||||||
|
|
||||||
|
'''
|
||||||
|
The 'postgresql_database' package contains the definition of the 'PostgreSQlHandler' class which connects to the MongoDB
|
||||||
|
database used for storing information about the users and the existing chats
|
||||||
|
|
||||||
|
The object 'postgresql_db_handler' is created inside this file and can be used throughout the lifetime
|
||||||
|
of the application
|
||||||
|
'''
|
||||||
Binary file not shown.
@@ -0,0 +1,8 @@
|
|||||||
|
'''
|
||||||
|
The 'queries' package contains functions which are used by the API to execute database operations. This package contains
|
||||||
|
implementations for 'messages' and 'users' requirements. The list of the functions is:
|
||||||
|
- create_conversation_db()
|
||||||
|
- find_conversation_db()
|
||||||
|
- get_conversation_url_db()
|
||||||
|
- send_message_db
|
||||||
|
'''
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -5,6 +5,16 @@ from datetime import datetime
|
|||||||
|
|
||||||
|
|
||||||
def create_conversation_db(user1_id, user2_id):
|
def create_conversation_db(user1_id, user2_id):
|
||||||
|
"""
|
||||||
|
Creates the conversation identifier for two users.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user1_id (str): ID of first user.
|
||||||
|
user1_id (str): ID of second user.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Conversation identifier/URL
|
||||||
|
"""
|
||||||
current_datetime = datetime.now().strftime("%Y%m%d%H%M%S")
|
current_datetime = datetime.now().strftime("%Y%m%d%H%M%S")
|
||||||
unique_id = str(uuid.uuid4()).replace('-', '')
|
unique_id = str(uuid.uuid4()).replace('-', '')
|
||||||
conversation_url = f"{current_datetime}_{unique_id}"
|
conversation_url = f"{current_datetime}_{unique_id}"
|
||||||
@@ -20,6 +30,15 @@ def create_conversation_db(user1_id, user2_id):
|
|||||||
|
|
||||||
|
|
||||||
def find_conversation_db(conversation_url):
|
def find_conversation_db(conversation_url):
|
||||||
|
"""
|
||||||
|
Retrieves the conversation from MongoDB
|
||||||
|
|
||||||
|
Args:
|
||||||
|
conversation_url (str): conversation identifier
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dic: conversation
|
||||||
|
"""
|
||||||
collection = mongo_db_handler.get_collection()
|
collection = mongo_db_handler.get_collection()
|
||||||
query = {'name': conversation_url}
|
query = {'name': conversation_url}
|
||||||
result_set = collection.find_one(query)
|
result_set = collection.find_one(query)
|
||||||
|
|||||||
@@ -2,6 +2,15 @@ from database import postgresql_db_handler
|
|||||||
|
|
||||||
|
|
||||||
def get_user_by_id(user_id):
|
def get_user_by_id(user_id):
|
||||||
|
"""
|
||||||
|
Creates the conversation identifier for two users.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user_id (str): user id
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
User: information about the user if exists
|
||||||
|
"""
|
||||||
query = """
|
query = """
|
||||||
SELECT * FROM users WHERE id = %s;
|
SELECT * FROM users WHERE id = %s;
|
||||||
"""
|
"""
|
||||||
@@ -15,6 +24,15 @@ def get_user_by_id(user_id):
|
|||||||
|
|
||||||
|
|
||||||
def get_user_by_email(email):
|
def get_user_by_email(email):
|
||||||
|
"""
|
||||||
|
Creates the conversation identifier for two users.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
email (str): email of the user
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
User: information about the user if exists
|
||||||
|
"""
|
||||||
query = """
|
query = """
|
||||||
SELECT * FROM users WHERE email = %s;
|
SELECT * FROM users WHERE email = %s;
|
||||||
"""
|
"""
|
||||||
@@ -28,6 +46,17 @@ def get_user_by_email(email):
|
|||||||
|
|
||||||
|
|
||||||
def create_user_db(username, password, email):
|
def create_user_db(username, password, email):
|
||||||
|
"""
|
||||||
|
Creates used based on provided information
|
||||||
|
|
||||||
|
Args:
|
||||||
|
username (str)
|
||||||
|
password (str)
|
||||||
|
email (str)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Nothing
|
||||||
|
"""
|
||||||
query = """
|
query = """
|
||||||
INSERT INTO users (username, password, email)
|
INSERT INTO users (username, password, email)
|
||||||
VALUES (%s, %s, %s);
|
VALUES (%s, %s, %s);
|
||||||
@@ -37,6 +66,19 @@ def create_user_db(username, password, email):
|
|||||||
|
|
||||||
|
|
||||||
def update_user_db(user_id, new_username, new_password, new_email):
|
def update_user_db(user_id, new_username, new_password, new_email):
|
||||||
|
"""
|
||||||
|
Updates user based on the new information
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user_id (int)
|
||||||
|
new_username (str)
|
||||||
|
new_password (str)
|
||||||
|
new_email (str)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Nothing
|
||||||
|
"""
|
||||||
|
|
||||||
query = """
|
query = """
|
||||||
UPDATE users
|
UPDATE users
|
||||||
SET username = %s, password = %s, email = %s
|
SET username = %s, password = %s, email = %s
|
||||||
@@ -48,6 +90,15 @@ def update_user_db(user_id, new_username, new_password, new_email):
|
|||||||
|
|
||||||
|
|
||||||
def delete_user_db(user_id):
|
def delete_user_db(user_id):
|
||||||
|
"""
|
||||||
|
Deletes a user
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user_id: int
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Nothing
|
||||||
|
"""
|
||||||
query = """
|
query = """
|
||||||
DELETE FROM users WHERE id = %s;
|
DELETE FROM users WHERE id = %s;
|
||||||
"""
|
"""
|
||||||
|
|||||||
Executable
+5
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
source venv/bin/activate
|
||||||
|
cd messenger_gui
|
||||||
|
python main.py
|
||||||
@@ -1,2 +1,10 @@
|
|||||||
from .main import MainApplication
|
from .main_application import MainApplication
|
||||||
app = MainApplication()
|
app = MainApplication()
|
||||||
|
|
||||||
|
'''
|
||||||
|
The 'app' package contains all the UI and network components to run the application'. This package contains the
|
||||||
|
following packages:
|
||||||
|
- http (tools to make HTTP requests to the API)
|
||||||
|
- models (schematics for the HTTP requests and user info validation)
|
||||||
|
- views (UI design)
|
||||||
|
'''
|
||||||
@@ -1,3 +1,9 @@
|
|||||||
from .request_builder import RequestBuilder
|
from .request_builder import RequestBuilder
|
||||||
|
|
||||||
request_builder = RequestBuilder()
|
request_builder = RequestBuilder()
|
||||||
|
|
||||||
|
"""
|
||||||
|
The 'http' package contains the tools for making HTTP requests to the backend. This package contains:
|
||||||
|
- request_builder: class through which the request is build
|
||||||
|
- request_handler: object resulted from the builder and can be used to make requests.
|
||||||
|
"""
|
||||||
|
|||||||
@@ -2,6 +2,18 @@ from .request_handler import _HttpRequestHandler
|
|||||||
|
|
||||||
|
|
||||||
class RequestBuilder:
|
class RequestBuilder:
|
||||||
|
"""
|
||||||
|
A Builder for HTTP Request class
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
__url (str): URL at which the request is made
|
||||||
|
__headers (dict):
|
||||||
|
__body (dict):
|
||||||
|
__params (dict): Query params
|
||||||
|
__method (str): HTTP method (GET, POST, ...)
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.__url = ""
|
self.__url = ""
|
||||||
self.__headers = {}
|
self.__headers = {}
|
||||||
@@ -9,26 +21,27 @@ class RequestBuilder:
|
|||||||
self.__params = None
|
self.__params = None
|
||||||
self.__method = "GET"
|
self.__method = "GET"
|
||||||
|
|
||||||
def set_url(self, url=str):
|
def set_url(self, url):
|
||||||
self.__url = url
|
self.__url = url
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def set_headers(self, headers=dict):
|
def set_headers(self, headers):
|
||||||
self.__headers = headers
|
self.__headers = headers
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def set_body(self, body=dict):
|
def set_body(self, body):
|
||||||
self.__body = body
|
self.__body = body
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def set_params(self, params=dict):
|
def set_params(self, params):
|
||||||
self.__params = params
|
self.__params = params
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def set_method(self, method=str):
|
def set_method(self, method):
|
||||||
self.__method = method
|
self.__method = method
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
|
"""Based on the set parameters it returns a Request Handler object"""
|
||||||
return _HttpRequestHandler(url=self.__url, method=self.__method, body=self.__body,
|
return _HttpRequestHandler(url=self.__url, method=self.__method, body=self.__body,
|
||||||
params=self.__params, headers=self.__headers)
|
params=self.__params, headers=self.__headers)
|
||||||
|
|||||||
@@ -3,16 +3,26 @@ import requests
|
|||||||
|
|
||||||
|
|
||||||
class _HttpRequestHandler:
|
class _HttpRequestHandler:
|
||||||
|
"""
|
||||||
|
A Builder for HTTP Request class
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
url (str): URL at which the request is made
|
||||||
|
headers (dict):
|
||||||
|
body (dict):
|
||||||
|
params (dict): Query params
|
||||||
|
method (str): HTTP method (GET, POST, ...)
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, url, method="GET", params=None, headers=None, body=None):
|
def __init__(self, url, method="GET", params=None, headers=None, body=None):
|
||||||
self.url = url
|
self.url = url
|
||||||
self.method = method
|
self.method = method
|
||||||
self.headers = headers
|
self.headers = headers
|
||||||
print(body)
|
|
||||||
self.body = json.dumps(body)
|
self.body = json.dumps(body)
|
||||||
self.params = params
|
self.params = params
|
||||||
|
|
||||||
def make_request(self):
|
def make_request(self):
|
||||||
print(self.body)
|
"""Make HTTP request and returns the answer"""
|
||||||
response = requests.request(method=self.method, url=self.url,
|
response = requests.request(method=self.method, url=self.url,
|
||||||
params=self.params, data=self.body, headers=self.headers)
|
params=self.params, data=self.body, headers=self.headers)
|
||||||
return response
|
return response
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import json
|
import json
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from PIL import Image, ImageTk
|
|
||||||
from app.views.login import LoginView
|
from app.views.login import LoginView
|
||||||
from app.views.initial import InitialView
|
from app.views.initial import InitialView
|
||||||
from app.views.signup import SignupView
|
from app.views.signup import SignupView
|
||||||
@@ -52,6 +51,3 @@ class MainApplication(tk.Tk):
|
|||||||
self.current_logged_user['id'] = data['info']['id']
|
self.current_logged_user['id'] = data['info']['id']
|
||||||
self.current_logged_user['username'] = data['info']['username']
|
self.current_logged_user['username'] = data['info']['username']
|
||||||
self.current_logged_user['email'] = data['info']['email']
|
self.current_logged_user['email'] = data['info']['email']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
"""
|
||||||
|
The 'models' package contains schematics for the HTTP requests and validations for the information provided by the
|
||||||
|
user during the authentication. The package contains:
|
||||||
|
- http_models
|
||||||
|
- view_models
|
||||||
|
"""
|
||||||
@@ -1,2 +1,6 @@
|
|||||||
from .login import LoginRequestModel
|
from .login import LoginRequestModel
|
||||||
from .signup import SignupRequestModel
|
from .signup import SignupRequestModel
|
||||||
|
|
||||||
|
"""
|
||||||
|
The 'http_models' package contains the schematics for the body data when making HTTP requests
|
||||||
|
"""
|
||||||
@@ -1,2 +1,7 @@
|
|||||||
from .login import LoginModel
|
from .login import LoginModel
|
||||||
from .signup import SignupModel
|
from .signup import SignupModel
|
||||||
|
|
||||||
|
"""
|
||||||
|
The 'view models' package contains the validations for the information the user provides during the authentication
|
||||||
|
(login/sign up)
|
||||||
|
"""
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
"""
|
||||||
|
The 'views' package contains all the UI implementation of the app. The app contains the following views:
|
||||||
|
- InitialView
|
||||||
|
- LoginView
|
||||||
|
- SingUpView
|
||||||
|
- MainPageView
|
||||||
|
- ChatView
|
||||||
|
"""
|
||||||
@@ -5,6 +5,10 @@ from app.views.message import MessageView
|
|||||||
|
|
||||||
|
|
||||||
class ChatWindow(tk.Toplevel):
|
class ChatWindow(tk.Toplevel):
|
||||||
|
"""
|
||||||
|
This view is opened in a separate window and takes care of the communication between the two users. It receives
|
||||||
|
both the users' information and retrieves the conversation_url.
|
||||||
|
"""
|
||||||
def __init__(self, master=None, user_data=None, current_logged_user=None):
|
def __init__(self, master=None, user_data=None, current_logged_user=None):
|
||||||
super().__init__(master)
|
super().__init__(master)
|
||||||
|
|
||||||
@@ -48,6 +52,7 @@ class ChatWindow(tk.Toplevel):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def create_widgets(self, conversation):
|
def create_widgets(self, conversation):
|
||||||
|
"""Creates the UI of this view"""
|
||||||
# Create a frame for displaying messages
|
# Create a frame for displaying messages
|
||||||
self.messages_frame = tk.Frame(self)
|
self.messages_frame = tk.Frame(self)
|
||||||
self.messages_frame.pack()
|
self.messages_frame.pack()
|
||||||
@@ -70,6 +75,10 @@ class ChatWindow(tk.Toplevel):
|
|||||||
self.send_button.pack(side=tk.RIGHT)
|
self.send_button.pack(side=tk.RIGHT)
|
||||||
|
|
||||||
def update_chat(self):
|
def update_chat(self):
|
||||||
|
"""
|
||||||
|
This function is scheduled each second to make a request to the API to retrieve the latest chat between the
|
||||||
|
users
|
||||||
|
"""
|
||||||
self.messages_frame.destroy()
|
self.messages_frame.destroy()
|
||||||
self.messages_frame = tk.Frame(self)
|
self.messages_frame = tk.Frame(self)
|
||||||
self.messages_frame.pack()
|
self.messages_frame.pack()
|
||||||
@@ -85,7 +94,9 @@ class ChatWindow(tk.Toplevel):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def send_message(self):
|
def send_message(self):
|
||||||
|
"""At the submit button, the text is sent to the database"""
|
||||||
message = self.entry_widget.get()
|
message = self.entry_widget.get()
|
||||||
|
|
||||||
self.define_send_message_params(message, "text")
|
self.define_send_message_params(message, "text")
|
||||||
if not message:
|
if not message:
|
||||||
return
|
return
|
||||||
@@ -101,6 +112,7 @@ class ChatWindow(tk.Toplevel):
|
|||||||
self.update_chat()
|
self.update_chat()
|
||||||
|
|
||||||
def get_conversation_url(self):
|
def get_conversation_url(self):
|
||||||
|
"""Fetches the conversation_url"""
|
||||||
request_builder.set_url(self.url)
|
request_builder.set_url(self.url)
|
||||||
request_builder.set_body(self.body)
|
request_builder.set_body(self.body)
|
||||||
request_builder.set_headers(self.headers)
|
request_builder.set_headers(self.headers)
|
||||||
@@ -113,6 +125,7 @@ class ChatWindow(tk.Toplevel):
|
|||||||
return data['conversation_url']
|
return data['conversation_url']
|
||||||
|
|
||||||
def get_conversation(self):
|
def get_conversation(self):
|
||||||
|
"""Fetches the conversation between the users"""
|
||||||
request_builder.set_url(self.url)
|
request_builder.set_url(self.url)
|
||||||
request_builder.set_body(self.body)
|
request_builder.set_body(self.body)
|
||||||
request_builder.set_headers(self.headers)
|
request_builder.set_headers(self.headers)
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ import tkinter as tk
|
|||||||
|
|
||||||
|
|
||||||
class InitialView(tk.Frame):
|
class InitialView(tk.Frame):
|
||||||
|
"""
|
||||||
|
This class is the first rendered view of the application. This offers the options to Login or sign Up
|
||||||
|
"""
|
||||||
def __init__(self, master=None):
|
def __init__(self, master=None):
|
||||||
super().__init__(master)
|
super().__init__(master)
|
||||||
self.create_widgets()
|
self.create_widgets()
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ def hash_password(password):
|
|||||||
|
|
||||||
|
|
||||||
class LoginView(tk.Frame):
|
class LoginView(tk.Frame):
|
||||||
|
"""
|
||||||
|
This view takes care of the validation of the user in the system. This class receives the login information and
|
||||||
|
validates them. The response is shown to the user.
|
||||||
|
"""
|
||||||
def __init__(self, master=None):
|
def __init__(self, master=None):
|
||||||
super().__init__(master)
|
super().__init__(master)
|
||||||
self.form_frame = None
|
self.form_frame = None
|
||||||
@@ -27,6 +31,9 @@ class LoginView(tk.Frame):
|
|||||||
self.params = None
|
self.params = None
|
||||||
|
|
||||||
def create_widgets(self):
|
def create_widgets(self):
|
||||||
|
"""
|
||||||
|
Creates the layout of the view
|
||||||
|
"""
|
||||||
# Create a frame to hold the entry fields and labels
|
# Create a frame to hold the entry fields and labels
|
||||||
self.form_frame = tk.Frame(self)
|
self.form_frame = tk.Frame(self)
|
||||||
|
|
||||||
@@ -71,6 +78,10 @@ class LoginView(tk.Frame):
|
|||||||
self.master.change_to_initial_view()
|
self.master.change_to_initial_view()
|
||||||
|
|
||||||
def on_login(self):
|
def on_login(self):
|
||||||
|
"""
|
||||||
|
After login button pressed, the validation of the provided information starts and will redirect the
|
||||||
|
user to next view if everything is accepted
|
||||||
|
"""
|
||||||
# Retrieve values from entry fields
|
# Retrieve values from entry fields
|
||||||
email = self.email_entry.get()
|
email = self.email_entry.get()
|
||||||
password = self.password_entry.get()
|
password = self.password_entry.get()
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ from app.views.user_frame import UserFrame
|
|||||||
|
|
||||||
|
|
||||||
class MainPageView(tk.Frame):
|
class MainPageView(tk.Frame):
|
||||||
|
"""
|
||||||
|
This is the view from which the user will open a chat with anyone which is registered in the system. Each chat is
|
||||||
|
shown as a box with a photo, the username and the email.
|
||||||
|
"""
|
||||||
def __init__(self, master=None):
|
def __init__(self, master=None):
|
||||||
super().__init__(master)
|
super().__init__(master)
|
||||||
self.form_frame = None
|
self.form_frame = None
|
||||||
@@ -20,6 +24,7 @@ class MainPageView(tk.Frame):
|
|||||||
self.body = None
|
self.body = None
|
||||||
|
|
||||||
def create_widgets(self):
|
def create_widgets(self):
|
||||||
|
"""Takes care of the creation of the UI"""
|
||||||
# Create a main frame to center the user frame and button frame
|
# Create a main frame to center the user frame and button frame
|
||||||
main_frame = tk.Frame(self.master)
|
main_frame = tk.Frame(self.master)
|
||||||
main_frame.pack(expand=True)
|
main_frame.pack(expand=True)
|
||||||
@@ -57,6 +62,7 @@ class MainPageView(tk.Frame):
|
|||||||
self.master.change_to_initial_view()
|
self.master.change_to_initial_view()
|
||||||
|
|
||||||
def open_chat(self, user_data):
|
def open_chat(self, user_data):
|
||||||
|
"""Opens a chat in a different window"""
|
||||||
# Pass both the clicked user data and the current logged user info to ChatWindow
|
# Pass both the clicked user data and the current logged user info to ChatWindow
|
||||||
chat_window = ChatWindow(self, user_data, self.master.current_logged_user)
|
chat_window = ChatWindow(self, user_data, self.master.current_logged_user)
|
||||||
chat_window.mainloop() # Main loop for the new window
|
chat_window.mainloop() # Main loop for the new window
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ import base64
|
|||||||
|
|
||||||
|
|
||||||
class MessageView(tk.Frame):
|
class MessageView(tk.Frame):
|
||||||
|
"""
|
||||||
|
This view is the message that appears in main windows of the chat. This is configured to hold text and images.
|
||||||
|
"""
|
||||||
def __init__(self, master, message, current_logged_user, user_data, *args, **kwargs):
|
def __init__(self, master, message, current_logged_user, user_data, *args, **kwargs):
|
||||||
super().__init__(master, *args, **kwargs)
|
super().__init__(master, *args, **kwargs)
|
||||||
self.current_logged_user = current_logged_user
|
self.current_logged_user = current_logged_user
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ def hash_password(password):
|
|||||||
|
|
||||||
|
|
||||||
class SignupView(tk.Frame):
|
class SignupView(tk.Frame):
|
||||||
|
"""
|
||||||
|
This view takes care of the registration of the user in the system. This class receives the sing up
|
||||||
|
information and validates them. The response is shown to the user.
|
||||||
|
"""
|
||||||
def __init__(self, master=None):
|
def __init__(self, master=None):
|
||||||
super().__init__(master)
|
super().__init__(master)
|
||||||
self.form_frame = None
|
self.form_frame = None
|
||||||
@@ -27,6 +31,7 @@ class SignupView(tk.Frame):
|
|||||||
self.params = None
|
self.params = None
|
||||||
|
|
||||||
def create_widgets(self):
|
def create_widgets(self):
|
||||||
|
"""Creates the layout of the view"""
|
||||||
# Create a frame to hold the entry fields and labels
|
# Create a frame to hold the entry fields and labels
|
||||||
self.form_frame = tk.Frame(self)
|
self.form_frame = tk.Frame(self)
|
||||||
|
|
||||||
@@ -78,6 +83,10 @@ class SignupView(tk.Frame):
|
|||||||
self.master.change_to_initial_view()
|
self.master.change_to_initial_view()
|
||||||
|
|
||||||
def on_signup(self):
|
def on_signup(self):
|
||||||
|
"""
|
||||||
|
After sign up button pressed, the validation of the provided information starts and will redirect the
|
||||||
|
user to next view if everything is accepted
|
||||||
|
"""
|
||||||
# Retrieve values from entry fields
|
# Retrieve values from entry fields
|
||||||
username = self.username_entry.get()
|
username = self.username_entry.get()
|
||||||
email = self.email_entry.get()
|
email = self.email_entry.get()
|
||||||
|
|||||||
@@ -3,11 +3,13 @@ from PIL import Image, ImageTk
|
|||||||
|
|
||||||
|
|
||||||
class UserFrame(tk.Frame):
|
class UserFrame(tk.Frame):
|
||||||
|
"""
|
||||||
|
This class takes care of the aspect of the user blocks from the MainPageView.
|
||||||
|
"""
|
||||||
def __init__(self, master, user_data, current_logged_user, click_callback, *args, **kwargs):
|
def __init__(self, master, user_data, current_logged_user, click_callback, *args, **kwargs):
|
||||||
super().__init__(master, *args, **kwargs)
|
super().__init__(master, *args, **kwargs)
|
||||||
|
|
||||||
self.current_logged_user = current_logged_user
|
self.current_logged_user = current_logged_user
|
||||||
print(user_data)
|
|
||||||
|
|
||||||
self.user_data = {
|
self.user_data = {
|
||||||
'id': user_data[0],
|
'id': user_data[0],
|
||||||
@@ -45,7 +47,6 @@ class UserFrame(tk.Frame):
|
|||||||
# Bind the click event to the user frame
|
# Bind the click event to the user frame
|
||||||
user_frame.bind("<Button-1>", lambda event, user_data=self.user_data, current_logged_user=self.current_logged_user: self.on_user_click(user_data, current_logged_user))
|
user_frame.bind("<Button-1>", lambda event, user_data=self.user_data, current_logged_user=self.current_logged_user: self.on_user_click(user_data, current_logged_user))
|
||||||
|
|
||||||
|
|
||||||
# Pack the user frame
|
# Pack the user frame
|
||||||
user_frame.pack(side=tk.LEFT, padx=10, pady=10)
|
user_frame.pack(side=tk.LEFT, padx=10, pady=10)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user