flask_template_codex/app/tasks/forms.py
2026-08-08 03:26:12 +02:00

146 lines
3.9 KiB
Python

from flask_wtf import FlaskForm
from flask_wtf.file import FileAllowed, FileField, FileRequired
from wtforms import (
BooleanField,
IntegerField,
SelectField,
StringField,
SubmitField,
TextAreaField,
)
from wtforms.fields import DateTimeLocalField
from wtforms.validators import (
DataRequired,
Length,
NumberRange,
Optional,
ValidationError,
)
from .models import TASK_PRIORITIES, TASK_STATUSES
STATUS_LABELS = {
"not_started": "Not started",
"in_progress": "In progress",
"done": "Done",
}
PRIORITY_LABELS = {
"urgent": "Urgent",
"important": "Important",
"normal": "Normal",
}
def not_blank(_form: FlaskForm, field: StringField) -> None:
if not field.data or not field.data.strip():
raise ValidationError("This field cannot be blank.")
class TaskForm(FlaskForm):
title = StringField(
"Task title",
validators=[not_blank, Length(max=200)],
)
description = TextAreaField(
"Notes",
validators=[Optional(), Length(max=5000)],
)
status = SelectField(
"Status",
choices=[(value, STATUS_LABELS[value]) for value in TASK_STATUSES],
default="not_started",
)
priority = SelectField(
"Priority",
choices=[(value, PRIORITY_LABELS[value]) for value in TASK_PRIORITIES],
default="normal",
)
due_date = DateTimeLocalField(
"Due date and time",
format="%Y-%m-%dT%H:%M",
validators=[Optional()],
)
submit = SubmitField("Save task")
class SubtaskForm(FlaskForm):
title = StringField(
"Next small step",
validators=[not_blank, Length(max=100)],
)
submit = SubmitField("Add step")
class ActionForm(FlaskForm):
submit = SubmitField()
def valid_chunk_plan(_form: FlaskForm, field: StringField) -> None:
if not field.data or not field.data.strip():
return
values = [value.strip() for value in field.data.split(",")]
if len(values) > 12:
raise ValidationError("Use at most 12 focus blocks.")
try:
minutes = [int(value) for value in values]
except ValueError as exc:
raise ValidationError(
"Use comma-separated whole minutes, such as 5, 5, 10."
) from exc
if any(value < 1 or value > 120 for value in minutes):
raise ValidationError("Each focus block must be 1 to 120 minutes.")
class FocusSettingsForm(FlaskForm):
timer_minutes = IntegerField(
"Countdown length in minutes",
validators=[Optional(), NumberRange(min=1, max=180)],
)
context = StringField(
"Helpful context",
validators=[Optional(), Length(max=100)],
)
chunk_plan = StringField(
"Focus blocks",
validators=[Optional(), Length(max=120), valid_chunk_plan],
)
submit = SubmitField("Save focus setup")
def parsed_chunks(self) -> list[int]:
if not self.chunk_plan.data or not self.chunk_plan.data.strip():
return []
return [
int(value.strip())
for value in self.chunk_plan.data.split(",")
]
class MarkdownImportForm(FlaskForm):
markdown_file = FileField(
"Markdown or text file",
validators=[
FileRequired(),
FileAllowed(["md", "markdown", "txt"], "Use a .md or .txt file."),
],
)
confirm = BooleanField(
"I reviewed the import format and want to add these tasks.",
validators=[DataRequired()],
)
submit = SubmitField("Import task list")
class BackupImportForm(FlaskForm):
backup_file = FileField(
"Steady JSON backup",
validators=[FileRequired(), FileAllowed(["json"], "Use a .json file.")],
)
replace_existing = BooleanField(
"Replace all of my existing tasks instead of merging"
)
confirm = BooleanField(
"I understand that restore may add or replace tasks and preferences.",
validators=[DataRequired()],
)
submit = SubmitField("Restore backup")