Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 8 additions & 40 deletions druks_panel/pages.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from druks import ui
from druks.workflows import SubjectStatus

from druks_panel.contracts import AdvisorAssessment, ModeratorSynthesis
from druks_panel.models import Decision
Expand Down Expand Up @@ -49,8 +48,8 @@ def _synthesis(decision: Decision) -> ui.Section:
)


def _human_call(decision: Decision, status: SubjectStatus) -> ui.Section:
"""The human gate: the form while the run waits, the record after."""
def _human_call(decision: Decision) -> ui.Section:
"""The human gate: the controls while the run waits, the record after."""
if decision.outcome:
return ui.Section(
title="The call",
Expand All @@ -64,42 +63,12 @@ def _human_call(decision: Decision, status: SubjectStatus) -> ui.Section:
ui.Quote(decision.outcome_note or "Nobody left a note."),
],
)
if status.is_parked:
return ui.Section(
title="The call",
blocks=[
ui.Form(
description="The run stays parked until you record the outcome.",
fields=[
ui.RadioField(
name="action",
label="Outcome",
options=[
ui.Option("Proceed", value="proceed"),
ui.Option("Revise", value="revise"),
ui.Option("Pass", value="pass"),
],
is_required=True,
),
ui.TextAreaField(
name="note",
label="Note",
rows=3,
help_text="What the record must say about this call.",
),
],
action=ui.Action(
label="Record the decision",
operation="record_outcome",
arguments={"decision_id": decision.id},
tone="primary",
),
)
],
)
return ui.Section(
title="The call",
blocks=[ui.Text("The run parks here after the moderator reports.")],
blocks=[
ui.Text("After the moderator reports, the run waits here for your call."),
ui.GateControls(decision),
],
)


Expand Down Expand Up @@ -187,13 +156,12 @@ async def new_decision():
@ui.page("/decisions/{decision_id}", subject=Decision)
async def decision(decision_id: int):
decision = await Decision.get(id=decision_id)
status = await decision.get_status()
assessments = [AdvisorAssessment.model_validate(item) for item in decision.assessments]
return ui.Page(
decision.title,
description=decision.question,
# The whole page follows: an operator watches each advisor land. A
# parked run publishes nothing, so a redraw cannot wipe the form below.
# parked run publishes nothing, so a redraw cannot wipe a half-written note.
follows=decision,
blocks=[
ui.Facts(
Expand Down Expand Up @@ -242,6 +210,6 @@ async def decision(decision_id: int):
),
),
_synthesis(decision),
_human_call(decision, status),
_human_call(decision),
],
)
26 changes: 3 additions & 23 deletions druks_panel/routes.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
from druks.workflows import WorkflowError
from fastapi import APIRouter, HTTPException, status
from fastapi import APIRouter, status

from druks_panel.models import Decision
from druks_panel.schemas import (
CreateDecisionRequest,
CreateDecisionResponse,
DecisionOutcomeRequest,
DecisionSummary,
)
from druks_panel.workflows import Deliberate, RecordDecision
from druks_panel.schemas import CreateDecisionRequest, CreateDecisionResponse, DecisionSummary
from druks_panel.workflows import Deliberate

# Every APIRouter declared here mounts under /api/panel.
router = APIRouter(prefix="/decisions")
Expand All @@ -34,17 +28,3 @@ async def create_decision(body: CreateDecisionRequest) -> CreateDecisionResponse
)
run_id = await Deliberate.start(subject=decision)
return CreateDecisionResponse(id=decision.id, run_id=run_id)


@router.post(
"/{decision_id}/outcome",
status_code=status.HTTP_202_ACCEPTED,
operation_id="record_outcome",
)
async def record_outcome(decision_id: int, body: DecisionOutcomeRequest) -> dict[str, str]:
decision = await Decision.get(id=decision_id)
try:
await RecordDecision.answer(decision, action=body.action, note=body.note)
except WorkflowError as error:
raise HTTPException(status.HTTP_409_CONFLICT, str(error)) from error
return {"result": "recorded"}
7 changes: 0 additions & 7 deletions druks_panel/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,6 @@ class CreateDecisionRequest(BaseModel):
context: str = Field(default="", max_length=4000)


class DecisionOutcomeRequest(BaseModel):
model_config = ConfigDict(str_strip_whitespace=True)

action: DecisionAction
note: str = Field(default="", max_length=2000)


class CreateDecisionResponse(Schema):
id: int
run_id: str
Expand Down
6 changes: 1 addition & 5 deletions druks_panel/workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,7 @@ async def run_multistep(self) -> dict[str, str]:
)

reply = await RecordDecision.wait(
input_request={
"presentation": "external",
"label": "Record the decision",
"url": f"/panel/decisions/{decision.id}",
}
input_request={"presentation": "in_app", "label": "Record the decision"}
)
await self.persist_outcome(action=reply.action, note=reply.note)
await self.announce("decision.recorded", action=reply.action)
Expand Down