subcategories and editing for tasks

This commit is contained in:
2026-02-10 19:31:57 +01:00
parent b2f26b66bb
commit 6902ff3373
7 changed files with 389 additions and 81 deletions

139
app.py
View File

@@ -108,7 +108,8 @@ def add_activity():
activity_id = db.activities.insert_one({
'user_id': get_user_id(),
'name': name,
'color': color
'color': color,
'subcategories': [] # Initialize empty list
}).inserted_id
# Add optional tasks
@@ -124,11 +125,100 @@ def add_activity():
return redirect(url_for('index'))
@app.route('/edit_activity/<activity_id>', methods=['GET', 'POST'])
def edit_activity(activity_id):
if not is_logged_in(): return redirect(url_for('login'))
user_id = get_user_id()
if request.method == 'POST':
name = request.form['name']
color = request.form.get('color', '#3498db')
subcats_str = request.form.get('subcategories', '')
# Parse comma-separated string into list
subcategories = [s.strip() for s in subcats_str.split(',') if s.strip()]
db.activities.update_one(
{'_id': ObjectId(activity_id), 'user_id': user_id},
{'$set': {'name': name, 'color': color, 'subcategories': subcategories}}
)
return redirect(url_for('index'))
activity = db.activities.find_one({'_id': ObjectId(activity_id), 'user_id': user_id})
if not activity: return "Activity not found", 404
return render_template('edit_activity.html', activity=activity)
@app.route('/start_timer_bg/<activity_id>', methods=['POST'])
def start_timer_bg(activity_id):
if not is_logged_in(): return jsonify({'error': 'auth'}), 401
user_id = get_user_id()
# Stop ANY running timer
db.time_entries.update_many(
{'user_id': user_id, 'end_time': None},
{'$set': {'end_time': datetime.now()}}
)
# Start new
start_time = datetime.now()
new_entry_id = db.time_entries.insert_one({
'user_id': user_id,
'activity_id': ObjectId(activity_id),
'start_time': start_time,
'end_time': None,
'note': '',
'subcategory': ''
}).inserted_id
# Auto-add templates
templates = db.tasks.find({
'user_id': user_id,
'activity_id': ObjectId(activity_id),
'is_template': True
})
for t in templates:
db.tasks.insert_one({
'user_id': user_id,
'name': t['name'],
'activity_id': ObjectId(activity_id),
'time_entry_id': new_entry_id,
'status': 'open',
'is_template': False,
'created_at': datetime.now(),
'comments': []
})
activity = db.activities.find_one({'_id': ObjectId(activity_id)})
return jsonify({
'status': 'success',
'start_time': start_time.isoformat(),
'activity_name': activity['name'],
'activity_color': activity.get('color', '#3498db')
})
@app.route('/update_active_entry', methods=['POST'])
def update_active_entry():
if not is_logged_in(): return redirect(url_for('login'))
user_id = get_user_id()
note = request.form.get('note', '')
subcategory = request.form.get('subcategory', '')
db.time_entries.update_one(
{'user_id': user_id, 'end_time': None},
{'$set': {'note': note, 'subcategory': subcategory}}
)
return redirect(url_for('index'))
@app.route('/toggle_timer/<activity_id>', methods=['POST'])
def toggle_timer(activity_id):
if not is_logged_in(): return redirect(url_for('login'))
user_id = get_user_id()
note = request.form.get('note', '')
subcategory = request.form.get('subcategory', '') # Get subcategory
# Check if this activity is currently running
current = db.time_entries.find_one({
@@ -150,14 +240,15 @@ def toggle_timer(activity_id):
{'$set': {'end_time': datetime.now()}}
)
# Start new
new_entry_id = db.time_entries.insert_one({
db.time_entries.insert_one({
'user_id': user_id,
'activity_id': ObjectId(activity_id),
'start_time': datetime.now(),
'end_time': None,
'note': note
}).inserted_id
'note': note,
'subcategory': subcategory # Store it
})
# Check for Task Templates and auto-add them
templates = db.tasks.find({
'user_id': user_id,
@@ -345,15 +436,37 @@ def logbook():
def log_entry_detail(entry_id):
if not is_logged_in(): return redirect(url_for('login'))
# Handle Note Update
# Handle Updates and Deletion
if request.method == 'POST':
new_note = request.form.get('note')
db.time_entries.update_one(
{'_id': ObjectId(entry_id), 'user_id': get_user_id()},
{'$set': {'note': new_note}}
)
flash('Session note updated')
return redirect(url_for('log_entry_detail', entry_id=entry_id))
action = request.form.get('action')
if action == 'delete':
db.time_entries.delete_one({'_id': ObjectId(entry_id), 'user_id': get_user_id()})
flash('Entry deleted')
return redirect(url_for('logbook'))
elif action == 'update':
new_note = request.form.get('note')
start_str = request.form.get('start_time')
end_str = request.form.get('end_time')
update_fields = {'note': new_note}
try:
if start_str:
update_fields['start_time'] = datetime.strptime(start_str, '%Y-%m-%dT%H:%M')
if end_str:
update_fields['end_time'] = datetime.strptime(end_str, '%Y-%m-%dT%H:%M')
except ValueError:
flash('Invalid date format')
return redirect(url_for('log_entry_detail', entry_id=entry_id))
db.time_entries.update_one(
{'_id': ObjectId(entry_id), 'user_id': get_user_id()},
{'$set': update_fields}
)
flash('Entry updated')
return redirect(url_for('log_entry_detail', entry_id=entry_id))
# Fetch Entry with Activity info
pipeline = [