LPM-140 The Sprinting Update Adds sprint support across the web UI (board + issue detail), TUI kanban, CLI/REPL, and the Beads-backed storage layer. Changes: Introduces sprint entities in storage and exposes sprint operations via IssueService. Updates web board to support backlog vs. sprint columns, sprint selection, and sprint creation routes. Updates TUI kanban to show backlog + sprint columns and adds sprint selection/creation actions.
109 lines
3.6 KiB
Plaintext
109 lines
3.6 KiB
Plaintext
package components
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/LazyBachelor/LazyPM/internal/models"
|
|
)
|
|
|
|
type IssueDetailProps struct {
|
|
Issue *models.Issue
|
|
}
|
|
|
|
templ IssueDetail(props IssueDetailProps) {
|
|
<h2 class="text-2xl font-bold m-2">
|
|
{ props.Issue.Title }
|
|
</h2>
|
|
<div class="flex gap-2 flex-wrap">
|
|
@StatusBadge(props.Issue.Status)
|
|
@TypeBadge(props.Issue.IssueType)
|
|
@PriorityBadge(props.Issue.Priority)
|
|
</div>
|
|
if props.Issue.Description != "" {
|
|
<div class="mt-4">
|
|
<h3 class="text-sm font-semibold opacity-70 mb-1">Description</h3>
|
|
<p class="whitespace-pre-wrap text-sm">{ props.Issue.Description }</p>
|
|
</div>
|
|
}
|
|
<div class="divider my-2"></div>
|
|
<div class="grid grid-cols-2 gap-2 text-sm">
|
|
<div class="bg-base-200 rounded-lg p-2">
|
|
<span class="text-xs opacity-70 block">Created</span>
|
|
<p>{ props.Issue.CreatedAt.Format("Jan 2, 2006") }</p>
|
|
</div>
|
|
<div class="bg-base-200 rounded-lg p-2">
|
|
<span class="text-xs opacity-70 block">Updated</span>
|
|
<p>{ props.Issue.UpdatedAt.Format("Jan 2, 2006") }</p>
|
|
</div>
|
|
<div class="flex flex-row gap-1 bg-base-200 rounded-lg p-2">
|
|
<span class="text-xs opacity-70 block">Created by</span>
|
|
<p class="text-xs opacity-70">{ props.Issue.CreatedBy }</p>
|
|
</div>
|
|
<a
|
|
class="btn btn-primary btn-sm flex flex-row gap-1 items-center justify-center"
|
|
hx-get={ "/issues/" + props.Issue.ID + "/assignee" }
|
|
hx-target="#modal-container"
|
|
hx-swap="innerHTML"
|
|
>
|
|
if props.Issue.Assignee == "" {
|
|
<span>Unassigned (click to assign) </span>
|
|
} else {
|
|
<span>Assignee: { props.Issue.Assignee }</span>
|
|
}
|
|
</a>
|
|
</div>
|
|
}
|
|
|
|
templ StatusBadge(status models.Status) {
|
|
switch status {
|
|
case "open":
|
|
<span class="badge badge-info badge-sm whitespace-nowrap">Open</span>
|
|
case "in_progress":
|
|
<span class="badge badge-warning badge-sm whitespace-nowrap">In Progress</span>
|
|
case "ready_to_sprint":
|
|
<span class="badge badge-primary badge-sm whitespace-nowrap">Ready to sprint</span>
|
|
case "closed":
|
|
<span class="badge badge-success badge-sm whitespace-nowrap">Closed</span>
|
|
case "blocked":
|
|
<span class="badge badge-error badge-sm whitespace-nowrap">Blocked</span>
|
|
case "deferred":
|
|
<span class="badge badge-ghost badge-sm whitespace-nowrap">Deferred</span>
|
|
default:
|
|
<span class="badge badge-ghost badge-sm whitespace-nowrap">{ string(status) }</span>
|
|
}
|
|
}
|
|
|
|
templ TypeBadge(issueType models.IssueType) {
|
|
switch issueType {
|
|
case "bug":
|
|
<span class="badge badge-outline badge-error badge-sm whitespace-nowrap">Bug</span>
|
|
case "feature":
|
|
<span class="badge badge-outline badge-success badge-sm whitespace-nowrap">Feature</span>
|
|
case "task":
|
|
<span class="badge badge-outline badge-info badge-sm whitespace-nowrap">Task</span>
|
|
case "chore":
|
|
<span class="badge badge-outline badge-warning badge-sm whitespace-nowrap">Chore</span>
|
|
case "epic":
|
|
<span class="badge badge-outline badge-secondary badge-sm whitespace-nowrap">Epic</span>
|
|
default:
|
|
<span class="badge badge-outline badge-sm whitespace-nowrap">{ string(issueType) }</span>
|
|
}
|
|
}
|
|
|
|
templ PriorityBadge(priority int) {
|
|
switch priority {
|
|
case 0:
|
|
<span class="badge badge-ghost badge-sm whitespace-nowrap">Irrelevant</span>
|
|
case 1:
|
|
<span class="badge badge-ghost badge-sm whitespace-nowrap">Low</span>
|
|
case 2:
|
|
<span class="badge badge-info badge-sm whitespace-nowrap">Normal</span>
|
|
case 3:
|
|
<span class="badge badge-warning badge-sm whitespace-nowrap">High</span>
|
|
case 4:
|
|
<span class="badge badge-error badge-sm whitespace-nowrap">Critical</span>
|
|
default:
|
|
<span class="badge badge-ghost badge-sm whitespace-nowrap">{ fmt.Sprintf("P%d", priority) }</span>
|
|
}
|
|
}
|