Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
69b3c257d1
72
app.py
72
app.py
@ -132,11 +132,13 @@ def index():
|
|||||||
habit_lists = current_user.get_habitLists()
|
habit_lists = current_user.get_habitLists()
|
||||||
name = "Hallo " + current_user.name
|
name = "Hallo " + current_user.name
|
||||||
heatmap_values, day = current_user.get_heatmap()
|
heatmap_values, day = current_user.get_heatmap()
|
||||||
|
heatmap_color = current_user.heatmap_color
|
||||||
else:
|
else:
|
||||||
habit_lists = []
|
habit_lists = []
|
||||||
name = "Bitte melde dich an."
|
name = "Bitte melde dich an."
|
||||||
heatmap_values = []
|
heatmap_values = []
|
||||||
day = None
|
day = None
|
||||||
|
heatmap_color = None
|
||||||
|
|
||||||
# Sort habits by whether they have been checked today and then by slot
|
# Sort habits by whether they have been checked today and then by slot
|
||||||
for habit_list in habit_lists:
|
for habit_list in habit_lists:
|
||||||
@ -146,7 +148,6 @@ def index():
|
|||||||
"Friday": "Freitag", "Saturday": "Samstag", "Sunday": "Sonntag"}
|
"Friday": "Freitag", "Saturday": "Samstag", "Sunday": "Sonntag"}
|
||||||
|
|
||||||
date = datetime.datetime.now().strftime("%d.%m.%Y %H:%M ") + days[datetime.datetime.now().strftime("%A")]
|
date = datetime.datetime.now().strftime("%d.%m.%Y %H:%M ") + days[datetime.datetime.now().strftime("%A")]
|
||||||
color = '255, 0, 255'
|
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
'index.html',
|
'index.html',
|
||||||
@ -155,7 +156,7 @@ def index():
|
|||||||
habit_lists=habit_lists,
|
habit_lists=habit_lists,
|
||||||
heatmap_values=heatmap_values,
|
heatmap_values=heatmap_values,
|
||||||
day=day,
|
day=day,
|
||||||
color=color,
|
color=heatmap_color,
|
||||||
errors={}
|
errors={}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -513,7 +514,8 @@ def save_profile_image(image_file):
|
|||||||
# Save the processed image
|
# Save the processed image
|
||||||
image_path = os.path.join(app.config['UPLOAD_FOLDER'], filename.replace(".gif", ".jpg"))
|
image_path = os.path.join(app.config['UPLOAD_FOLDER'], filename.replace(".gif", ".jpg"))
|
||||||
image.save(image_path, 'JPEG', quality=100)
|
image.save(image_path, 'JPEG', quality=100)
|
||||||
current_user.update_profile_image(image_path)
|
current_user.profile_image = image_path
|
||||||
|
current_user.update()
|
||||||
|
|
||||||
|
|
||||||
def save_profile_animated(image_file, filename):
|
def save_profile_animated(image_file, filename):
|
||||||
@ -522,7 +524,8 @@ def save_profile_animated(image_file, filename):
|
|||||||
gif_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
|
gif_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
|
||||||
image_file.save(gif_path)
|
image_file.save(gif_path)
|
||||||
|
|
||||||
current_user.update_profile_image(gif_path)
|
current_user.profile_image = gif_path
|
||||||
|
current_user.update()
|
||||||
|
|
||||||
|
|
||||||
@app.route('/upload', methods=['POST'])
|
@app.route('/upload', methods=['POST'])
|
||||||
@ -652,6 +655,67 @@ def users():
|
|||||||
errors={},
|
errors={},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@app.route('/users-edit')
|
||||||
|
@login_required
|
||||||
|
def edit_users():
|
||||||
|
habit_list_id = request.args.get('habit_list', current_user.get_habitLists()[0].id)
|
||||||
|
habit_list = HabitList.get(int(habit_list_id))
|
||||||
|
users = habit_list.get_users()
|
||||||
|
|
||||||
|
# Remove the current user from the list
|
||||||
|
users = [user for user in users if user.id != current_user.id]
|
||||||
|
|
||||||
|
return render_template(
|
||||||
|
'users-edit.html',
|
||||||
|
title='Teilnehmer bearbeiten',
|
||||||
|
habit_list=habit_list,
|
||||||
|
users=users,
|
||||||
|
errors={},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/user-delete', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def delete_user_from_list():
|
||||||
|
habit_list_id = request.form.get('habit_list_id')
|
||||||
|
habit_list = HabitList.get(int(habit_list_id))
|
||||||
|
|
||||||
|
habit_user_id = request.form.get('habit_user_id')
|
||||||
|
habit_user = User.get(int(habit_user_id))
|
||||||
|
|
||||||
|
users = habit_list.get_users()
|
||||||
|
|
||||||
|
# Remove the current user from the list
|
||||||
|
users = [user for user in users if user.id != current_user.id]
|
||||||
|
|
||||||
|
# Check for errors
|
||||||
|
errors = {}
|
||||||
|
if not habit_list_id:
|
||||||
|
errors['habit_list'] = 'Die Habitliste ist erforderlich.'
|
||||||
|
if not habit_list_id:
|
||||||
|
errors['habit_user'] = 'Ein User ist erforderlich.'
|
||||||
|
|
||||||
|
if errors:
|
||||||
|
return render_template(
|
||||||
|
'users-edit.html',
|
||||||
|
title='Teilnehmer bearbeiten',
|
||||||
|
habit_list=habit_list,
|
||||||
|
users=users,
|
||||||
|
errors={},
|
||||||
|
)
|
||||||
|
|
||||||
|
# delete user from habit list
|
||||||
|
id = int(habit_user_id)
|
||||||
|
habit_list.delete(id)
|
||||||
|
|
||||||
|
return render_template(
|
||||||
|
'users-edit.html',
|
||||||
|
title='Teilnehmer bearbeiten',
|
||||||
|
habit_list=habit_list,
|
||||||
|
users=users,
|
||||||
|
errors={},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/users', methods=['POST'])
|
@app.route('/users', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
|
|||||||
@ -27,11 +27,11 @@ def create_user_profile_image(user_id):
|
|||||||
return relative_destination_path
|
return relative_destination_path
|
||||||
|
|
||||||
|
|
||||||
def create_user(name: str, email: str, password: str, profile_image: str = None):
|
def create_user(name: str, email: str, password: str, heatmap_color: str, profile_image: str = None):
|
||||||
password = hashlib.sha256(password.encode()).hexdigest()
|
password = hashlib.sha256(password.encode()).hexdigest()
|
||||||
now = datetime.now().isoformat()
|
now = datetime.now().isoformat()
|
||||||
query = (f"INSERT INTO users (name, email, password, profile_image, created_at, updated_at) VALUES "
|
query = (f"INSERT INTO users (name, email, password, profile_image, heatmap_color, created_at, updated_at) VALUES "
|
||||||
f"('{name}', '{email}', '{password}', '{profile_image}', '{now}', '{now}');")
|
f"('{name}', '{email}', '{password}', '{profile_image}', '{heatmap_color}', '{now}', '{now}');")
|
||||||
conn = con3()
|
conn = con3()
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
cursor.execute(query)
|
cursor.execute(query)
|
||||||
@ -66,24 +66,15 @@ def get_user_by_email(email: str):
|
|||||||
return user
|
return user
|
||||||
|
|
||||||
|
|
||||||
def update_user(id: int, name: str, email: str, password: str):
|
def update_user(id: int, name: str, email: str, password: str, profile_image: str, heatmap_color: str):
|
||||||
now = datetime.now().isoformat()
|
now = datetime.now().isoformat()
|
||||||
if password:
|
if password:
|
||||||
query = (f"UPDATE users SET name = '{name}', email = '{email}', password = '{password}', updated_at = '{now}' "
|
query = (f"UPDATE users SET name = '{name}', email = '{email}', password = '{password}', "
|
||||||
|
f"profile_image ='{profile_image}', heatmap_color = '{heatmap_color}', updated_at = '{now}' "
|
||||||
f"WHERE id = {id};")
|
f"WHERE id = {id};")
|
||||||
else:
|
else:
|
||||||
query = f"UPDATE users SET name = '{name}', email = '{email}', updated_at = '{now}' WHERE id = {id};"
|
query = (f"UPDATE users SET name = '{name}', email = '{email}', profile_image ='{profile_image}', "
|
||||||
conn = con3()
|
f"heatmap_color = '{heatmap_color}', updated_at = '{now}' WHERE id = {id};")
|
||||||
cursor = conn.cursor()
|
|
||||||
cursor.execute(query)
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return cursor.lastrowid
|
|
||||||
|
|
||||||
|
|
||||||
def update_user_profile(id: int, profile_image: str):
|
|
||||||
now = datetime.now().isoformat()
|
|
||||||
query = f"UPDATE users SET profile_image = '{profile_image}', updated_at = '{now}' WHERE id = {id};"
|
|
||||||
conn = con3()
|
conn = con3()
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
cursor.execute(query)
|
cursor.execute(query)
|
||||||
@ -342,7 +333,7 @@ def accept_List(list_id: int, user_id: int):
|
|||||||
|
|
||||||
|
|
||||||
def remove_user(list_id: int, user_id: int):
|
def remove_user(list_id: int, user_id: int):
|
||||||
query = f"DELETE FROM habit_lists WHERE user_id = {user_id} AND list_id = {list_id};"
|
query = f"DELETE FROM habit_users WHERE user_id = {user_id} AND list_id = {list_id};"
|
||||||
conn = con3()
|
conn = con3()
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
cursor.execute(query)
|
cursor.execute(query)
|
||||||
|
|||||||
1
db/migrations/1709825341_delete_users_table.sql
Normal file
1
db/migrations/1709825341_delete_users_table.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
DROP TABLE users;
|
||||||
11
db/migrations/1709825360_create_users_table.sql
Normal file
11
db/migrations/1709825360_create_users_table.sql
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS users
|
||||||
|
(
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
email TEXT NOT NULL,
|
||||||
|
password TEXT NOT NULL,
|
||||||
|
profile_image TEXT NOT NULL,
|
||||||
|
heatmap_color TEXT NOT NULL,
|
||||||
|
created_at TEXT NOT NULL,
|
||||||
|
updated_at TEXT NOT NULL
|
||||||
|
);
|
||||||
@ -53,7 +53,7 @@ class HabitList:
|
|||||||
raw_users = get_users(self.id)
|
raw_users = get_users(self.id)
|
||||||
users = []
|
users = []
|
||||||
for user in raw_users:
|
for user in raw_users:
|
||||||
user = User(user[0], user[1], user[2], user[3], user[4])
|
user = User(user[0], user[1], user[2], user[3], user[4], user[5])
|
||||||
users.append(user)
|
users.append(user)
|
||||||
|
|
||||||
return users
|
return users
|
||||||
|
|||||||
@ -2,40 +2,39 @@ from datetime import datetime
|
|||||||
|
|
||||||
from flask_login import UserMixin
|
from flask_login import UserMixin
|
||||||
from db.SQLiteClient import (create_user, get_user, get_user_by_email, update_user, delete_user,
|
from db.SQLiteClient import (create_user, get_user, get_user_by_email, update_user, delete_user,
|
||||||
get_habitLists, get_heatmap_value, update_user_profile)
|
get_habitLists, get_heatmap_value)
|
||||||
|
|
||||||
|
|
||||||
class User(UserMixin):
|
class User(UserMixin):
|
||||||
def __init__(self, id: int, name: str, email: str, password: str = None, profile_image:str = None):
|
def __init__(self, id: int, name: str, email: str, password: str=None, profile_image:str=None, heatmap_color: str=None):
|
||||||
self.id = id
|
self.id = id
|
||||||
self.name = name
|
self.name = name
|
||||||
self.email = email
|
self.email = email
|
||||||
self.password = password
|
self.password = password
|
||||||
self.profile_image = profile_image
|
self.profile_image = profile_image
|
||||||
|
self.heatmap_color = heatmap_color
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create(name: str, email: str, password: str):
|
def create(name: str, email: str, password: str):
|
||||||
id, profile_image = create_user(name, email, password)
|
heatmap_color = "0, 255, 0"
|
||||||
return User(id=id, name=name, email=email, profile_image=profile_image)
|
id, profile_image = create_user(name, email, password, heatmap_color)
|
||||||
|
return User(id=id, name=name, email=email, profile_image=profile_image, heatmap_color=heatmap_color)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get(id: int):
|
def get(id: int):
|
||||||
user = get_user(id)
|
user = get_user(id)
|
||||||
return User(user[0], user[1], user[2], user[3], user[4]) if user else None
|
return User(user[0], user[1], user[2], user[3], user[4], user[5]) if user else None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_by_email(email: str):
|
def get_by_email(email: str):
|
||||||
user = get_user_by_email(email)
|
user = get_user_by_email(email)
|
||||||
return User(user[0], user[1], user[2], user[3], user[4]) if user else None
|
return User(user[0], user[1], user[2], user[3], user[4], user[5]) if user else None
|
||||||
|
|
||||||
|
|
||||||
# Updates: name, email, password
|
# Updates: name, email, password
|
||||||
def update(self):
|
def update(self):
|
||||||
update_user(self.id, self.name, self.email, self.password if self.password else None)
|
update_user(self.id, self.name, self.email, self.password if self.password else None, self.profile_image, self.heatmap_color)
|
||||||
|
|
||||||
def update_profile_image(self, profile_image: str):
|
|
||||||
update_user_profile(self.id, profile_image)
|
|
||||||
|
|
||||||
# Deletes the User
|
# Deletes the User
|
||||||
def delete(self):
|
def delete(self):
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Funktion zum Erstellen der Heatmap
|
// Funktion zum Erstellen der Heatmap
|
||||||
function createHeatmap(data, day, color) {
|
function createHeatmap(data, day) {
|
||||||
const heatmapContainer = document.getElementById('heatmap');
|
const heatmapContainer = document.getElementById('heatmap');
|
||||||
|
|
||||||
const days = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']
|
const days = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']
|
||||||
@ -18,7 +18,6 @@ function createHeatmap(data, day, color) {
|
|||||||
// console.log(i * 7 + j, data[i * 7 + j], Math.max(...data));
|
// console.log(i * 7 + j, data[i * 7 + j], Math.max(...data));
|
||||||
const opacity = data[i * 7 + j] / (Math.max(...data) <= 0 ? 1 : Math.max(...data)); // Berechne die Opazität basierend auf Aktivitätsanzahl
|
const opacity = data[i * 7 + j] / (Math.max(...data) <= 0 ? 1 : Math.max(...data)); // Berechne die Opazität basierend auf Aktivitätsanzahl
|
||||||
|
|
||||||
if (data[i * 7 + j]) {
|
|
||||||
const dayElement = document.createElement('div');
|
const dayElement = document.createElement('div');
|
||||||
dayElement.classList.add('day');
|
dayElement.classList.add('day');
|
||||||
dayElement.style.backgroundColor = `rgba(${color}, ${opacity})`;
|
dayElement.style.backgroundColor = `rgba(${color}, ${opacity})`;
|
||||||
@ -30,7 +29,6 @@ function createHeatmap(data, day, color) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function deleteHeatmap() {
|
function deleteHeatmap() {
|
||||||
const heatmapContainer = document.getElementById('heatmap');
|
const heatmapContainer = document.getElementById('heatmap');
|
||||||
@ -165,6 +163,7 @@ $(function () {
|
|||||||
$('[data-toggle="tooltip"]').tooltip()
|
$('[data-toggle="tooltip"]').tooltip()
|
||||||
|
|
||||||
})
|
})
|
||||||
|
console.log(activityData, day, color)
|
||||||
// Erstelle die Heatmap mit den simulierten Daten
|
// Erstelle die Heatmap mit den simulierten Daten
|
||||||
createHeatmap(activityData, day, color);
|
createHeatmap(activityData, day, color);
|
||||||
|
|
||||||
|
|||||||
@ -65,14 +65,14 @@
|
|||||||
id="simple-tabpanel-{{habit_list.id}}" role="tabpanel" aria-labelledby="simple-tab-{{habit_list.id}}">
|
id="simple-tabpanel-{{habit_list.id}}" role="tabpanel" aria-labelledby="simple-tab-{{habit_list.id}}">
|
||||||
|
|
||||||
<!-- Beschreibung und Löschen von der Liste -->
|
<!-- Beschreibung und Löschen von der Liste -->
|
||||||
<div class="row mb-3">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
{{ habit_list.description }}
|
{{ habit_list.description }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-1">
|
<div class="col-1">
|
||||||
<button type="button" class="btn btn-xs me-3" data-bs-toggle="modal"
|
<button type="button" class="btn btn-xs me-3" data-bs-toggle="modal"
|
||||||
data-bs-target="#listenModal" style="width: 40px; height: 40px"
|
data-bs-target="#listenModal"
|
||||||
onclick="{
|
onclick="{
|
||||||
localStorage.setItem('selectedListId', {{ habit_list.id }});
|
localStorage.setItem('selectedListId', {{ habit_list.id }});
|
||||||
}">
|
}">
|
||||||
@ -99,18 +99,27 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- Knopf für das Hinzufügen einer Person zur gemeinsamen Liste -->
|
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<a href="/users?habit_list={{habit_list.id}}" style="width: 40px; height: 40px; min-height: 3em;"
|
<!-- Knopf für das Hinzufügen einer Person zur gemeinsamen Liste -->
|
||||||
|
<a class="me-5" href="/users?habit_list={{habit_list.id}}" style="width: 40px; height: 40px; min-height: 3em;"
|
||||||
data-toggle="tooltip" data-placement="top" title="Benutzer einladen">
|
data-toggle="tooltip" data-placement="top" title="Benutzer einladen">
|
||||||
<i class="bi bi-person-fill-add" style="font-size: 24px;"></i>
|
<i class="bi bi-person-fill-add" style="font-size: 24px;"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
<!-- Knopf für das Bearbeiten von Personen zur gemeinsamen Liste -->
|
||||||
|
{% if habit_list.get_users()|length > 1 %}
|
||||||
|
<a href="/users-edit?habit_list={{habit_list.id}}" style="width: 40px; height: 40px; min-height: 3em;"
|
||||||
|
data-toggle="tooltip" data-placement="top" title="Benutzer bearbeiten">
|
||||||
|
<i class="bi bi-pencil"></i>
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="col"></div>
|
<div class="col"></div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="col-6"></div>
|
<div class="col-4"></div>
|
||||||
|
|
||||||
|
|
||||||
<!-- neue Gewohnheiten erstellen -->
|
<!-- neue Gewohnheiten erstellen -->
|
||||||
<a class="col-3 btn btn-primary" role="button" href="/habit?list={{ habit_list.id }}">
|
<a class="col-3 btn btn-primary" role="button" href="/habit?list={{ habit_list.id }}">
|
||||||
|
|||||||
@ -11,4 +11,5 @@
|
|||||||
const activityData = {{ heatmap_values }};
|
const activityData = {{ heatmap_values }};
|
||||||
const day = {{ day }};
|
const day = {{ day }};
|
||||||
const color = "{{ color }}";
|
const color = "{{ color }}";
|
||||||
|
console.log(activityData, day, color)
|
||||||
</script>
|
</script>
|
||||||
37
templates/users-edit.html
Normal file
37
templates/users-edit.html
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
{% extends 'index.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="card bg-light p-5 mt-5">
|
||||||
|
<h1 class="mb-5">
|
||||||
|
{{ title }}
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
|
||||||
|
{% for user in users %}
|
||||||
|
<form action="/user-delete" class="row" method="POST">
|
||||||
|
<div class="col">
|
||||||
|
<img src="{{ user.profile_image }}" class="avatar"/>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
{{ user.name }}
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
{{ user.email }}
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<label>
|
||||||
|
<input hidden="hidden" name="habit_list_id" value="{{ habit_list.id }}">
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input hidden="hidden" name="habit_user_id" value="{{ user.id }}">
|
||||||
|
</label>
|
||||||
|
<button type="submit" class="btn btn-primary btn-danger">
|
||||||
|
Löschen
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
Loading…
x
Reference in New Issue
Block a user