Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
776eaec21b
126
app.py
126
app.py
@ -207,6 +207,10 @@ def habit_create():
|
||||
except ValueError:
|
||||
errors['list_query'] = 'Die Anzahl muss eine Zahl sein.'
|
||||
|
||||
# Check if unit is day and times is one
|
||||
if unit == 'Tag' and times != 1:
|
||||
errors['times'] = 'Die Anzahl muss 1 sein, wenn das Habit täglich ist.'
|
||||
|
||||
if errors:
|
||||
return render_template(
|
||||
'habit.html',
|
||||
@ -312,26 +316,107 @@ def profile_change():
|
||||
@app.route('/edit-habit')
|
||||
@login_required
|
||||
def edit_habit():
|
||||
habit_id = request.args.get("habit")
|
||||
#habit_id = request.get_json()["editHabitId"]
|
||||
|
||||
habit_id = int(request.args.get("habit"))
|
||||
habit = Habit.get(habit_id)
|
||||
|
||||
|
||||
units = ["Tag", "Woche", "Monat", "Jahr"]
|
||||
|
||||
return render_template(
|
||||
"edit-habit.html",
|
||||
title=habit.name
|
||||
title=habit.name,
|
||||
habit=habit.id,
|
||||
name=habit.name,
|
||||
note=habit.note,
|
||||
times=habit.times,
|
||||
unit=units[habit.unit],
|
||||
errors={}
|
||||
)
|
||||
'''
|
||||
|
||||
@app.route('/edit-habit', methods=['POST'])
|
||||
@login_required
|
||||
def edit_habit_change():
|
||||
#habit_id = request.get_json()["habitId"]
|
||||
|
||||
#habit = Habit.get(habit_id)
|
||||
|
||||
units = ["Tag", "Woche", "Monat", "Jahr"]
|
||||
name = request.form.get('name')
|
||||
note = request.form.get('note')
|
||||
times = request.form.get('times')
|
||||
unit = request.form.get('unit')
|
||||
list_id = request.form.get('habit')
|
||||
|
||||
habit = Habit.get(list_id)
|
||||
|
||||
# Check for errors
|
||||
errors = {}
|
||||
if not name:
|
||||
errors['name'] = 'Der Name ist erforderlich.'
|
||||
if not times:
|
||||
errors['times'] = 'Die Anzahl ist erforderlich.'
|
||||
if not note:
|
||||
note = ''
|
||||
if not unit:
|
||||
errors['unit'] = 'Die Einheit ist erforderlich.'
|
||||
if not list_id:
|
||||
errors['habit'] = 'Das Habit ist erforderlich.'
|
||||
|
||||
# Check if times is an integer
|
||||
try:
|
||||
print(times)
|
||||
times = int(times)
|
||||
|
||||
|
||||
# Check that times is greater than 0
|
||||
if times <= 0:
|
||||
errors['times'] = 'Die Anzahl muss größer als 0 sein.'
|
||||
except ValueError:
|
||||
errors['times'] = 'Die Anzahl muss eine Zahl sein.'
|
||||
|
||||
# Check that unit is valid
|
||||
if unit not in ['Tag', 'Woche', 'Monat', 'Jahr']:
|
||||
errors['unit'] = 'Die Einheit ist ungültig.'
|
||||
|
||||
# check if list_id is an int
|
||||
try:
|
||||
list_id = int(list_id)
|
||||
except ValueError:
|
||||
errors['list_query'] = 'Die Anzahl muss eine Zahl sein.'
|
||||
|
||||
if unit == 'Tag' and times != 1:
|
||||
errors['times'] = 'Die Anzahl muss 1 sein, wenn das Habit täglich ist.'
|
||||
|
||||
if errors:
|
||||
return render_template(
|
||||
"edit-habit.html"
|
||||
"edit-habit.html",
|
||||
title=habit.name,
|
||||
habit=habit.id,
|
||||
name=habit.name,
|
||||
note=habit.note,
|
||||
times=habit.times,
|
||||
unit=units[habit.unit],
|
||||
errors={}
|
||||
)
|
||||
'''
|
||||
|
||||
# Map unit to integer
|
||||
if unit == 'Tag':
|
||||
unit = 0
|
||||
elif unit == 'Woche':
|
||||
unit = 1
|
||||
elif unit == 'Monat':
|
||||
unit = 2
|
||||
elif unit == 'Jahr':
|
||||
unit = 3
|
||||
else:
|
||||
unit = 1
|
||||
|
||||
# Save habit to database
|
||||
print(name, note, times, unit)
|
||||
habit.name, habit.note, habit.times, habit.unit = name, note, times, unit
|
||||
|
||||
habit.update()
|
||||
# Back to index
|
||||
return redirect(url_for('index'))
|
||||
|
||||
@app.route('/check_password', methods=['POST'])
|
||||
@login_required
|
||||
def check_password():
|
||||
@ -483,6 +568,24 @@ def delete_habit():
|
||||
return {}
|
||||
|
||||
|
||||
@app.route('/delete-list', methods=['POST'])
|
||||
@login_required
|
||||
def delete_list():
|
||||
list_id = request.get_json()["listId"]
|
||||
|
||||
habit_list = HabitList.get(list_id)
|
||||
|
||||
if habit_list is None:
|
||||
return {"error": "List not found"}
|
||||
|
||||
# Check if habit belongs to user
|
||||
if current_user not in habit_list.get_users():
|
||||
return {"error": "List does not belong to user"}
|
||||
|
||||
habit_list.delete(current_user.id)
|
||||
return {}
|
||||
|
||||
|
||||
@app.route('/reorder', methods=['POST'])
|
||||
@login_required
|
||||
def reorder_habits():
|
||||
@ -549,11 +652,12 @@ def add_user():
|
||||
if not user:
|
||||
errors['email'] = 'E-Mail Adresse nicht gefunden.'
|
||||
|
||||
if user.id == current_user.id:
|
||||
if user and user.id == current_user.id:
|
||||
errors['email'] = 'Du kannst dich nicht selbst hinzufügen.'
|
||||
|
||||
# Check if user is already in the habit list
|
||||
already = False
|
||||
if user:
|
||||
for u in habit_list.get_users():
|
||||
if u.id == user.id:
|
||||
already = True
|
||||
@ -581,4 +685,4 @@ def add_user():
|
||||
|
||||
# Run the application
|
||||
if __name__ == '__main__':
|
||||
app.run(port=5000, debug=True)
|
||||
app.run(host="0.0.0.0", port=5000, debug=True)
|
||||
|
||||
@ -190,7 +190,7 @@ def update_slot(id: int, slot: int):
|
||||
|
||||
def update_habit(id: int, name: str, note: str, times: int, unit: int):
|
||||
now = datetime.now().isoformat()
|
||||
query = (f"UPDATE habits SET name = {name}, note = {note}, times = {times}, unit = {unit}, updated_at = '{now}' "
|
||||
query = (f"UPDATE habits SET name = '{name}', note = '{note}', times = {times}, unit = {unit}, updated_at = '{now}' "
|
||||
f"WHERE id = {id};")
|
||||
conn = con3()
|
||||
cursor = conn.cursor()
|
||||
|
||||
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@ -0,0 +1,3 @@
|
||||
pillow~=10.2.0
|
||||
flask~=3.0.0
|
||||
flask-login~=0.6.3
|
||||
20
templates/components/delete_list.html
Normal file
20
templates/components/delete_list.html
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
<div class="modal fade" id="listenModal" tabindex="-1" aria-labelledby="listenModal" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="listenModalLabel">Bestätige</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
Möchtest du diese Liste wirklich löschen?
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">abbrechen</button>
|
||||
<button type="button" class="btn btn-primary btn-danger" data-bs-dismiss="modal"
|
||||
onclick="deleteList(localStorage.getItem('selectedListId'));">Löschen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,4 +1,4 @@
|
||||
<div class="flex-fill col-md-8 col-12 card bg-light p-6 mb-6">
|
||||
<div class="flex-fill col-md-7 col-lg-8 col-12 card bg-light p-6 mb-6">
|
||||
|
||||
<!-- Listen erstellen -->
|
||||
<div class="row mb-3">
|
||||
@ -15,7 +15,7 @@
|
||||
<ul class="nav nav-tabs card-header-tabs" role="tablist">
|
||||
{% for habit_list in habit_lists %}
|
||||
|
||||
<li class="nav-item" role="presentation">
|
||||
<li class="nav-item" role="presentation" id="tab-{{ habit_list.id }}">
|
||||
<a class="nav-link {% if habit_list == habit_lists[0] %} active {% endif %}"
|
||||
id="simple-tab-{{habit_list.id}}"
|
||||
data-bs-toggle="tab" href="#simple-tabpanel-{{habit_list.id}}" role="tab"
|
||||
@ -63,6 +63,25 @@
|
||||
{% for habit_list in habit_lists %}
|
||||
<div class="tab-pane {% if habit_list == habit_lists[0] %} active {% endif %}"
|
||||
id="simple-tabpanel-{{habit_list.id}}" role="tabpanel" aria-labelledby="simple-tab-{{habit_list.id}}">
|
||||
|
||||
<!-- Beschreibung und Löschen von der Liste -->
|
||||
<div class="row mb-3">
|
||||
<div class="col">
|
||||
{{ habit_list.description }}
|
||||
</div>
|
||||
|
||||
<div class="col-2">
|
||||
<button type="button" class="btn btn-xs me-3" data-bs-toggle="modal"
|
||||
data-bs-target="#listenModal" style="width: 40px; height: 40px"
|
||||
onclick="{
|
||||
localStorage.setItem('selectedListId', {{ habit_list.id }});
|
||||
}">
|
||||
<!---onclick="setSelectedListId({{ habit_list.id }})"-->
|
||||
<i class="bi bi-trash3"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3 align-items-center">
|
||||
|
||||
<!-- Personen die zur Liste gehören -->
|
||||
@ -103,7 +122,7 @@
|
||||
{% for habit in habit_list.habits %}
|
||||
<li class="row d-flex align-items-center mb-2" id="habit-{{ habit.id }}">
|
||||
|
||||
<!-- Handle zum verschieben -->
|
||||
<!-- Handle zum Verschieben -->
|
||||
<div class="col-auto drag-handle" style="cursor: grab;">
|
||||
<i class="bi bi-grip-vertical"></i>
|
||||
</div>
|
||||
@ -172,5 +191,9 @@
|
||||
selectedHabitId = habitId;
|
||||
}
|
||||
|
||||
var selectedListId = null;
|
||||
|
||||
function setSelectedListId(listId) {
|
||||
selectedlistId = listId;
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
|
||||
<div class="flex-fill col-md-4 col-12 card bg-light mb-6">
|
||||
<div class="flex-fill col-md-5 col-lg-4 col-12 card bg-light mb-6">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">📅 Heatmap</h5>
|
||||
<div id="heatmap"></div>
|
||||
|
||||
@ -48,14 +48,6 @@
|
||||
});
|
||||
}
|
||||
|
||||
function sendHabitId(Id) {
|
||||
|
||||
var habitId = document.getElementById(Id);
|
||||
|
||||
// Make a POST request to /check with the habit id
|
||||
// axios.post('/edit-habit', {editHabitId: habitId})
|
||||
}
|
||||
|
||||
function deleteHabit(habitId) {
|
||||
// Make a POST request to /delete with the habit id
|
||||
|
||||
@ -76,6 +68,28 @@
|
||||
});
|
||||
}
|
||||
|
||||
function deleteList(listId) {
|
||||
// Make a POST request to /delete with the habit id
|
||||
|
||||
axios.post('/delete-list', {listId: listId}, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}).then(function (response) {
|
||||
// Handle the success response if needed
|
||||
console.log(response.data);
|
||||
|
||||
// Remove the habit from the DOM
|
||||
var habitElement = document.getElementById("simple-tabpanel-" + listId);
|
||||
habitElement.remove();
|
||||
var habitElement = document.getElementById("tab-" + listId);
|
||||
habitElement.remove();
|
||||
}).catch(function (error) {
|
||||
// Handle the error if needed
|
||||
console.error('Error:', error);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
document.addEventListener('DOMContentLoaded', (event) => {
|
||||
var elements = document.querySelectorAll('.task-list').values()
|
||||
|
||||
@ -2,6 +2,81 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
test
|
||||
{{ title }}
|
||||
<h1 class="mt-5">Habit Bearbeiten📋</h1>
|
||||
|
||||
<form action="/edit-habit" method="POST">
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Name der Gewohnheit</label>
|
||||
<input type="text" class="form-control {% if errors.get('name') %} is-invalid {% endif %}" id="name" name="name" value="{{name}}">
|
||||
<div class="invalid-feedback">
|
||||
{{ errors.get('name', '') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="note" class="form-label">Beschreibung</label>
|
||||
<input type="text" class="form-control {% if errors.get('note') %} is-invalid {% endif %}" id="note" name="note" value="{{note}}">
|
||||
<div class="invalid-feedback">
|
||||
{{ errors.get('note', '') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="mb-3 col-2">
|
||||
<label for="times" class="form-label">Häufigkeit</label>
|
||||
<input type="number" min="1" class="form-control {% if errors.get('times') %} is-invalid {% endif %}" id="times" name="times" value="{{times}}">
|
||||
<div class="invalid-feedback">
|
||||
{{ errors.get('times', '') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3 col-10">
|
||||
<label for="unit" class="form-label">Im Zeitraum</label>
|
||||
<select class="form-select {% if errors.get('unit') %} is-invalid {% endif %}" id="unit" name="unit">
|
||||
<option value="Tag">Tag</option>
|
||||
<option value="Woche">Woche</option>
|
||||
<option value="Monat">Monat</option>
|
||||
<option value="Jahr">Jahr</option>
|
||||
</select>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', (event) => {
|
||||
let selectedElement = document.getElementById('unit');
|
||||
|
||||
for (let option of selectedElement.options) {
|
||||
if (option.value == '{{ unit }}') {
|
||||
option.selected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<div class="invalid-feedback">
|
||||
{{ errors.get('unit', '') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="habit" id="habit" class="{% if errors.get('habit') %} is-invalid {% endif %}">
|
||||
<div class="invalid-feedback">
|
||||
{{ errors.get('list_query', '') }}
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Extracting the list-query from the URL
|
||||
var listQuery = new URLSearchParams(window.location.search).get('habit');
|
||||
|
||||
if ("{{ habit }}" != "") {
|
||||
listQuery = "{{ habit }}";
|
||||
|
||||
// Add the list_id to the URL
|
||||
var url = new URL(window.location.href);
|
||||
url.searchParams.set('habit', listQuery);
|
||||
// window.history.pushState({}, '', url);
|
||||
}
|
||||
|
||||
// Setting the list-query as the value of the hidden input field
|
||||
document.getElementById('habit').value = listQuery;
|
||||
});
|
||||
</script>
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
@ -27,8 +27,54 @@
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
@media (max-width: 1400px) {
|
||||
.day {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.day {
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
.day {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 770px) {
|
||||
.day {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 450px) {
|
||||
.day {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
.day {
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 350px) {
|
||||
.day {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@ -47,6 +93,15 @@
|
||||
{% include 'components/delete_button.html' %}
|
||||
{% endif %}
|
||||
|
||||
{% if current_user.is_authenticated %}
|
||||
{% include 'components/delete_list.html' %}
|
||||
{% endif %}
|
||||
|
||||
{% if not current_user.is_authenticated %}
|
||||
<script type="module" src="https://unpkg.com/@splinetool/viewer@1.0.55/build/spline-viewer.js"></script>
|
||||
<spline-viewer loading-anim-type="spinner-small-dark" url="https://prod.spline.design/4mCpd7DzpXgN2X9q/scene.splinecode"></spline-viewer>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
{% include 'components/scripts.html' %}
|
||||
|
||||
@ -44,7 +44,7 @@
|
||||
<a class="btn btn-outline-secondary" aria-current="page" href="{{ url_for('signup') }}">Signup</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="nav-item me-2">
|
||||
<li class="nav-item me-2 mb-2 mb-lg-0">
|
||||
<a class="btn text-white btn-primary" aria-current="page" href="{{ url_for('profile') }}">Profil</a>
|
||||
</li>
|
||||
<li class="nav-item me-2">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user