Skip to content

Commit

Permalink
[web] use pydantic schema for task table
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasjuhrich committed Aug 1, 2023
1 parent 50b0e01 commit 7e0408e
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 30 deletions.
4 changes: 2 additions & 2 deletions tests/frontend/test_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@ def task_request_ctx(app):
])
def test_task_object_creation(app, task: UserTask, session, task_request_ctx):
object = task_row(task)
assert object['user']['title'] is not None
assert object['user']['href'] is not None
assert object.user.title is not None
assert object.user.href is not None
59 changes: 33 additions & 26 deletions web/blueprints/task/__init__.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
import typing as t
from dataclasses import asdict
from typing import NoReturn

from flask import Blueprint, jsonify, url_for, abort, flash, redirect, request, \
render_template
from flask import Blueprint, url_for, abort, flash, redirect, request, render_template
from flask_login import current_user

from pycroft.exc import PycroftException
from pycroft.lib.task import cancel_task, task_type_to_impl, \
manually_execute_task, reschedule_task
from pycroft.model import session
from pycroft.model.facilities import Building
from pycroft.model.task import Task, TaskStatus
from pycroft.model.task import Task, TaskStatus, UserTask
from web.blueprints import redirect_or_404
from web.blueprints.access import BlueprintAccess
from web.blueprints.helpers.user import get_user_or_404
from web.blueprints.navigation import BlueprintNavigation
from web.blueprints.task.forms import RescheduleTaskForm
from web.blueprints.task.tables import TaskTable
from web.table.table import datetime_format
from web.blueprints.task.tables import TaskTable, TaskRow
from web.table.table import (
BtnColResponse,
TableResponse,
datetime_format_pydantic,
LinkColResponse,
)
from web.template_filters import datetime_filter

bp = Blueprint('task', __name__)
Expand All @@ -36,28 +41,27 @@ def format_parameters(parameters):
return parameters


def task_row(task: Task):
def task_row(task: UserTask) -> TaskRow:
task_impl = task_type_to_impl.get(task.type)
T = TaskTable
return {
"id": task.id,
"user": T.user.value(
return TaskRow(
id=task.id,
user=LinkColResponse(
href=url_for('user.user_show', user_id=task.user.id),
title=task.user.name
),
"name": task_impl.name,
"type": task.type.name,
"status": task.status.name,
"parameters": format_parameters(asdict(task.parameters)),
"errors": task.errors if task.errors is not None else list(),
"due": datetime_format(task.due, default='', formatter=datetime_filter),
"created": f"{task.created:%Y-%m-%d %H:%M:%S}",
"creator": T.creator.value(
name=task_impl.name,
type=task.type.name, # actually redundant, because we assume UserTask
status=task.status.name,
parameters=format_parameters(asdict(task.parameters)),
errors=task.errors if task.errors is not None else list(),
due=datetime_format_pydantic(task.due, default="", formatter=datetime_filter),
created=f"{task.created:%Y-%m-%d %H:%M:%S}",
creator=LinkColResponse(
href=url_for('user.user_show', user_id=task.creator.id),
title=task.creator.name
),
'actions': [
T.actions.single_value(
actions=[
BtnColResponse(
href=url_for(
'.cancel_user_task',
task_id=task.id,
Expand All @@ -67,7 +71,7 @@ def task_row(task: Task):
icon='fa-times',
btn_class='btn-link'
),
T.actions.single_value(
BtnColResponse(
href=url_for(
'.reschedule_user_task',
task_id=task.id,
Expand All @@ -77,7 +81,7 @@ def task_row(task: Task):
icon='fa-calendar-alt',
btn_class='btn-link'
),
T.actions.single_value(
BtnColResponse(
href=url_for(
'.manually_execute_user_task',
task_id=task.id,
Expand All @@ -88,14 +92,15 @@ def task_row(task: Task):
btn_class='btn-link'
)
] if task.status == TaskStatus.OPEN else None,
}
)


@bp.route("/user/<int:user_id>/json")
def json_tasks_for_user(user_id):
user = get_user_or_404(user_id)

return jsonify(items=[task_row(task) for task in user.tasks])
return TableResponse[TaskRow](
items=[task_row(t.cast(UserTask, task)) for task in user.tasks]
)


@bp.route("/user/json")
Expand All @@ -112,7 +117,9 @@ def json_user_tasks():
else:
tasks = tasks.all()

return jsonify(items=[task_row(task) for task in tasks])
return TableResponse[TaskRow](
items=[task_row(t.cast(UserTask, task)) for task in tasks]
)


def get_task_or_404(task_id) -> Task | NoReturn:
Expand Down
29 changes: 27 additions & 2 deletions web/blueprints/task/tables.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
from web.table.table import BootstrapTable, Column, DateColumn, \
MultiBtnColumn, LinkColumn
import typing as t
from pydantic import BaseModel

from web.table.table import (
BootstrapTable,
Column,
DateColumn,
MultiBtnColumn,
LinkColumn,
LinkColResponse,
DateColResponse,
BtnColResponse,
)
from web.blueprints.helpers.user import no_membership_change


Expand Down Expand Up @@ -34,3 +45,17 @@ def __init__(self, hidden_columns: set[str] = None, sort_order="asc", *a, **kw):
kw['table_args'] = table_args

super().__init__(*a, **kw)


class TaskRow(BaseModel):
id: int # seems unused, not sure
user: LinkColResponse
name: str
type: str
due: DateColResponse
creator: LinkColResponse
status: str # used by taskRowFormatter
actions: list[BtnColResponse]
created: str
parameters: dict[str, t.Any]
errors: list[str] # used by taskDetailFormatter

0 comments on commit 7e0408e

Please sign in to comment.