allow deleting accomplishment
Squashed commit of the following:
commit 846aa01f3bb2e88cc2141506dbad8fefce1cf75b
Author: Wojciech Kwolek <wojciech@kwolek.xyz>
Date: Mon Aug 31 21:02:58 2020 +0200
remove unimplemented edit link
commit d094e321c7e9d526646adad411d47fd03dc4d37b
Author: Wojciech Kwolek <wojciech@kwolek.xyz>
Date: Mon Aug 31 20:59:53 2020 +0200
implement deleting accomplishments
commit 5c33caba1baf0ad6a0c62cccba35209c7e28a71c
Author: Wojciech Kwolek <wojciech@kwolek.xyz>
Date: Mon Aug 31 17:33:12 2020 +0200
add edit buttons to the day view
commit 6cc826c5cbb0a0260f5745a8392c3bc92afb6c71
Author: Wojciech Kwolek <wojciech@kwolek.xyz>
Date: Mon Aug 31 16:38:35 2020 +0200
add __pycache__ to gitignore
commit 1593e4c6cfa1a45096421292152185579a449e53
Author: Wojciech Kwolek <wojciech@kwolek.xyz>
Date: Mon Aug 31 16:35:40 2020 +0200
extract a method for getting all day related data for a template
This commit is contained in:
parent
845f5dbe65
commit
d78e483ad2
|
|
@ -1,2 +1,3 @@
|
|||
node_modules/
|
||||
*.db
|
||||
__pycache__
|
||||
|
|
|
|||
|
|
@ -40,31 +40,35 @@ form input[type=password]:focus {
|
|||
}
|
||||
|
||||
form input[type=submit] {
|
||||
@apply w-full px-4 py-2 mt-2 font-bold rounded;
|
||||
@apply px-4 py-2 mt-2 font-bold rounded;
|
||||
}
|
||||
|
||||
form.auth-form input[type=submit] {
|
||||
@apply text-white bg-blue-500;
|
||||
@apply w-full text-white bg-blue-500;
|
||||
}
|
||||
|
||||
.green-btn {
|
||||
@apply text-white bg-green-500;
|
||||
}
|
||||
|
||||
.accomplishment .text {
|
||||
@apply flex-grow;
|
||||
}
|
||||
|
||||
.accomplishment .difficulty {
|
||||
@apply flex-shrink-0 pl-1 font-bold text-right;
|
||||
min-width: 3em;
|
||||
}
|
||||
|
||||
.accomplishment .difficulty-easy {
|
||||
.difficulty-easy {
|
||||
@apply text-green-700;
|
||||
}
|
||||
|
||||
.accomplishment .difficulty-medium {
|
||||
.difficulty-medium {
|
||||
@apply text-orange-700;
|
||||
}
|
||||
|
||||
.accomplishment .difficulty-hard {
|
||||
.difficulty-hard {
|
||||
@apply text-red-700;
|
||||
}
|
||||
|
||||
|
|
|
|||
106
app/main.py
106
app/main.py
|
|
@ -1,6 +1,6 @@
|
|||
from . import timeutils
|
||||
from flask import Blueprint, render_template, redirect, url_for
|
||||
from flask_login import current_user
|
||||
from flask import Blueprint, render_template, redirect, url_for, abort
|
||||
from flask_login import current_user, login_required
|
||||
from flask_wtf import FlaskForm
|
||||
from wtforms import StringField, SubmitField
|
||||
from wtforms.validators import DataRequired, Length
|
||||
|
|
@ -35,22 +35,45 @@ def handle_accomplishment_submission(form):
|
|||
return redirect(url_for('main.index'))
|
||||
|
||||
|
||||
def get_day_template_data(day_string):
|
||||
day_datetime = None
|
||||
if day_string == "today":
|
||||
day_datetime = timeutils.today()
|
||||
else:
|
||||
day_datetime = timeutils.from_str(day_string)
|
||||
|
||||
day_string_clean = timeutils.as_str(day_datetime)
|
||||
|
||||
accomplishments = list(reversed(
|
||||
Accomplishment.get_day(current_user.id, day_datetime)))
|
||||
total = sum(a.difficulty for a in accomplishments)
|
||||
|
||||
yesterday = timeutils.day_before(day_datetime)
|
||||
tomorrow = timeutils.day_after(day_datetime)
|
||||
if timeutils.is_future(tomorrow):
|
||||
tomorrow = None
|
||||
|
||||
return {
|
||||
"day": {
|
||||
"datetime": day_datetime,
|
||||
"string": day_string_clean,
|
||||
"fancy": timeutils.as_fancy_str(day_datetime),
|
||||
"is_today": timeutils.is_today(day_datetime)
|
||||
},
|
||||
|
||||
"links": {
|
||||
"yesterday": url_for('main.index', day=timeutils.as_str(yesterday)),
|
||||
"tomorrow": url_for('main.index', day=timeutils.as_str(tomorrow)) if tomorrow is not None else None
|
||||
},
|
||||
|
||||
"accomplishments": accomplishments,
|
||||
"total_xp": sum(a.difficulty for a in accomplishments),
|
||||
}
|
||||
|
||||
|
||||
@main.route('/', defaults={'day': 'today'}, methods=['GET', 'POST'])
|
||||
@main.route('/day/<day>')
|
||||
def index(day):
|
||||
day_datetime = None
|
||||
day_string = None
|
||||
is_today = False
|
||||
if day == "today":
|
||||
day_datetime = timeutils.today()
|
||||
day_string = "Today"
|
||||
is_today = True
|
||||
else:
|
||||
day_datetime = timeutils.from_str(day)
|
||||
if timeutils.is_today(day_datetime):
|
||||
return redirect('/')
|
||||
day_string = timeutils.as_fancy_str(day_datetime)
|
||||
|
||||
if not current_user.is_authenticated:
|
||||
return render_template('index.html')
|
||||
|
||||
|
|
@ -58,23 +81,50 @@ def index(day):
|
|||
if form.validate_on_submit():
|
||||
return handle_accomplishment_submission(form)
|
||||
|
||||
accomplishments = list(reversed(Accomplishment.get_day(
|
||||
current_user.id, day_datetime)))
|
||||
total = sum(a.difficulty for a in accomplishments)
|
||||
return render_template(
|
||||
'main/app.html',
|
||||
form=form,
|
||||
**get_day_template_data(day)
|
||||
)
|
||||
|
||||
tomorrow = timeutils.day_after(day_datetime)
|
||||
yesterday = timeutils.day_before(day_datetime)
|
||||
|
||||
if timeutils.is_future(tomorrow):
|
||||
tomorrow = None
|
||||
@main.route('/day/<day>/edit')
|
||||
@login_required
|
||||
def edit_day(day):
|
||||
form = NewAccomplishementForm()
|
||||
if form.validate_on_submit():
|
||||
return handle_accomplishment_submission(form)
|
||||
|
||||
return render_template(
|
||||
'main/app.html',
|
||||
form=form,
|
||||
day=day_string,
|
||||
accomplishments=accomplishments,
|
||||
total=total,
|
||||
tomorrow=timeutils.as_str(tomorrow),
|
||||
yesterday=timeutils.as_str(yesterday),
|
||||
is_today=is_today,
|
||||
edit=True,
|
||||
**get_day_template_data(day)
|
||||
)
|
||||
|
||||
|
||||
class DeleteForm(FlaskForm):
|
||||
submit = SubmitField('Delete')
|
||||
|
||||
|
||||
@main.route('/accomplishment/<accomplishment_id>/delete', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def delete_accomplishment(accomplishment_id):
|
||||
a = Accomplishment.query.get_or_404(accomplishment_id)
|
||||
if a.user_id != current_user.id:
|
||||
abort(403)
|
||||
|
||||
back_url = url_for(
|
||||
'main.edit_day', day=timeutils.as_str(timeutils.day(a.time)))
|
||||
|
||||
form = DeleteForm()
|
||||
if form.validate_on_submit():
|
||||
db.session.delete(a)
|
||||
db.session.commit()
|
||||
return redirect(back_url)
|
||||
|
||||
return render_template(
|
||||
'main/delete.html',
|
||||
form=form,
|
||||
accomplishment=a,
|
||||
cancel=back_url)
|
||||
|
|
|
|||
|
|
@ -22083,7 +22083,6 @@ form input[type=password]:focus {
|
|||
}
|
||||
|
||||
form input[type=submit] {
|
||||
width: 100%;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
padding-top: 0.5rem;
|
||||
|
|
@ -22094,6 +22093,7 @@ form input[type=submit] {
|
|||
}
|
||||
|
||||
form.auth-form input[type=submit] {
|
||||
width: 100%;
|
||||
--text-opacity: 1;
|
||||
color: #fff;
|
||||
color: rgba(255, 255, 255, var(--text-opacity));
|
||||
|
|
@ -22111,6 +22111,10 @@ form.auth-form input[type=submit] {
|
|||
background-color: rgba(72, 187, 120, var(--bg-opacity));
|
||||
}
|
||||
|
||||
.accomplishment .text {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.accomplishment .difficulty {
|
||||
flex-shrink: 0;
|
||||
padding-left: 0.25rem;
|
||||
|
|
@ -22119,19 +22123,19 @@ form.auth-form input[type=submit] {
|
|||
min-width: 3em;
|
||||
}
|
||||
|
||||
.accomplishment .difficulty-easy {
|
||||
.difficulty-easy {
|
||||
--text-opacity: 1;
|
||||
color: #2f855a;
|
||||
color: rgba(47, 133, 90, var(--text-opacity));
|
||||
}
|
||||
|
||||
.accomplishment .difficulty-medium {
|
||||
.difficulty-medium {
|
||||
--text-opacity: 1;
|
||||
color: #c05621;
|
||||
color: rgba(192, 86, 33, var(--text-opacity));
|
||||
}
|
||||
|
||||
.accomplishment .difficulty-hard {
|
||||
.difficulty-hard {
|
||||
--text-opacity: 1;
|
||||
color: #c53030;
|
||||
color: rgba(197, 48, 48, var(--text-opacity));
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "_skel.html" %}
|
||||
{% block title %}{% if is_today %}Home{% else %}{{ day }}{% endif %}{% endblock %}
|
||||
{% block title %}{{ day.fancy }}{% endblock %}
|
||||
{% block content %}
|
||||
<div class="max-w-lg mx-auto card">
|
||||
<div class="max-w-xl mx-auto card">
|
||||
<form method="POST" action="{{ url_for('main.index') }}">
|
||||
{{ form.csrf_token }}
|
||||
{{ form.text(placeholder="What did you accomplish today?", class_="placeholder-black", autofocus=True) }}
|
||||
|
|
@ -13,19 +13,40 @@
|
|||
</form>
|
||||
</div>
|
||||
<div class="max-w-lg mx-auto card">
|
||||
<h3 class="mb-4 text-2xl">{{ day }}</h3>
|
||||
{% for accomplishment in accomplishments %}
|
||||
<div class="flex justify-between my-1 ml-2 accomplishment">
|
||||
<div>{{ accomplishment.text }}</div>
|
||||
<div class="difficulty-{{ accomplishment.difficulty_class }} difficulty">{{ accomplishment.difficulty }} XP
|
||||
<div class="flex items-baseline justify-between mb-4">
|
||||
<div>
|
||||
<h3 class="text-2xl">{{ day.fancy }}</h3>
|
||||
</div>
|
||||
{% if edit %}
|
||||
<div><a href="{{ url_for('main.index', day=day.string) }}" class="link">done</a></div>
|
||||
{% else %}
|
||||
{% if accomplishments %}
|
||||
<div><a href="{{ url_for('main.edit_day', day=day.string) }}" class="link">edit</a></div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% for accomplishment in accomplishments %}
|
||||
<div class="flex ml-2 accomplishment">
|
||||
<div class="py-1 text">{{ accomplishment.text }}</div>
|
||||
<div class="py-1 {% if edit %} mr-2 {% endif %} difficulty-{{ accomplishment.difficulty_class }} difficulty">
|
||||
{{ accomplishment.difficulty }} XP
|
||||
</div>
|
||||
{% if edit %}
|
||||
<div class="flex-shrink-0 py-1 pl-2 text-sm italic border-l border-gray-300 border-solid">
|
||||
<div>
|
||||
<a class="text-red-700 underline hover:text-red-500"
|
||||
href="{{ url_for('main.delete_accomplishment', accomplishment_id=accomplishment.id) }}">delete</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<hr>
|
||||
{% else %}
|
||||
<div class="my-1 ml-2 text-sm accomplishment">
|
||||
{% if false %}
|
||||
<!-- TODO: random text if no accomplishments -->{% endif %}
|
||||
{% if is_today %}
|
||||
<!-- TODO: random text if no accomplishments -->
|
||||
{% endif %}
|
||||
{% if day.is_today %}
|
||||
<p>No accomplishments today... yet!</p>
|
||||
{% else %}
|
||||
<p>Nothing logged that day... but it's okay to take a break!</p>
|
||||
|
|
@ -33,14 +54,13 @@
|
|||
</div>
|
||||
{% endfor %}
|
||||
<div class="flex justify-end my-1 ml-2 accomplishment">
|
||||
<div><span class="pr-1 text-xs text-gray-700">total:</span> <span class="difficulty">{{ total }} XP</div>
|
||||
<div><span class="pr-1 text-xs text-gray-700">total:</span> <span class="difficulty">{{ total_xp }} XP</div>
|
||||
</div>
|
||||
<div class="flex justify-between mt-2 text-sm accomplishment">
|
||||
<div><a href="{{ url_for('main.index', day=yesterday) }}" class="text-blue-700">Previous day</a></div>
|
||||
{% if tomorrow %}<a href="{{ url_for('main.index', day=tomorrow) }}" class="text-blue-700">Next day</a>
|
||||
</div>{% endif %}
|
||||
<div><a href="{{ links.yesterday }}" class="text-blue-700">Previous day</a></div>
|
||||
{% if links.tomorrow %}<a href="{{ links.tomorrow }}" class="text-blue-700">Next day</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
{% extends "_skel.html" %}
|
||||
{% block content %}
|
||||
<div class="max-w-xl mx-auto text-center card">
|
||||
<p class="italic">
|
||||
{{ accomplishment.text }}
|
||||
</p>
|
||||
<p class="mt-2 font-bold difficulty-{{ accomplishment.difficulty_class }}">({{ accomplishment.difficulty }}
|
||||
XP)
|
||||
</p>
|
||||
</div>
|
||||
<div class="max-w-lg mx-auto text-center card">
|
||||
<h3 class="text-lg">Are you sure you want to remove this accomplishment?</h3>
|
||||
<form class="mt-2" method="POST">
|
||||
{{ form.csrf_token }}
|
||||
{{ form.submit(class_="hover:bg-red-500 bg-red-700 text-white") }}
|
||||
<a href="{{ cancel }}" class="block mt-2 text-sm text-blue-700 hover:text-blue-500">cancel</a>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
@ -25,6 +25,8 @@ def _suffix(d):
|
|||
def as_fancy_str(day_):
|
||||
if day_ is None:
|
||||
return None
|
||||
if is_today(day_):
|
||||
return "Today"
|
||||
return day_.strftime("%B {S}, %Y").replace('{S}', str(day_.day) + _suffix(day_.day))
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue