fix: Sprint-Zuordnung im Eingang sichtbarer machen.
All checks were successful
Deploy Development / deploy (push) Successful in 47s
Test Suite / pytest-backend (push) Successful in 2m52s
Test Suite / lint-backend (push) Successful in 3s
Test Suite / compose-smoke (push) Has been skipped
Test Suite / k6 /api/health Baseline (push) Successful in 18s
Test Suite / playwright-smoke (push) Successful in 13s
All checks were successful
Deploy Development / deploy (push) Successful in 47s
Test Suite / pytest-backend (push) Successful in 2m52s
Test Suite / lint-backend (push) Successful in 3s
Test Suite / compose-smoke (push) Has been skipped
Test Suite / k6 /api/health Baseline (push) Successful in 18s
Test Suite / playwright-smoke (push) Successful in 13s
Ziel-Sprint-Dropdown immer wenn Sprint existiert, Setup-Hinweis ohne Sprint, Planen fuer alle commit-faehigen Backlog-Status. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
00567bb097
commit
c19b6296ed
|
|
@ -10,6 +10,8 @@ import { computeDropPatches, computeMovePatches, sortByOrder } from '../utils/re
|
|||
import { useMinWidth } from '../hooks/useMinWidth.js'
|
||||
|
||||
const PLANNING_STATUSES = new Set(['planned', 'active', 'at_risk'])
|
||||
/** Backend erlaubt Convert für diese Status — UI war nur bei „Freigegeben“ sichtbar. */
|
||||
const COMMITTABLE_STATUSES = new Set(['accepted', 'triaged', 'new'])
|
||||
|
||||
export function BacklogSection({
|
||||
items,
|
||||
|
|
@ -137,8 +139,8 @@ export function BacklogSection({
|
|||
const modalTitle =
|
||||
modalMode?.kind === 'create' ? 'Backlog-Item anlegen' : 'Backlog-Item bearbeiten'
|
||||
|
||||
const acceptedItems = sortedItems.filter((item) => item.status === 'accepted')
|
||||
const selectedAccepted = acceptedItems.filter((item) => selectedIds.has(item.id))
|
||||
const committableItems = sortedItems.filter((item) => COMMITTABLE_STATUSES.has(item.status))
|
||||
const selectedCommittable = committableItems.filter((item) => selectedIds.has(item.id))
|
||||
|
||||
function toggleSelected(itemId) {
|
||||
setSelectedIds((prev) => {
|
||||
|
|
@ -163,14 +165,14 @@ export function BacklogSection({
|
|||
}
|
||||
|
||||
async function handleBulkPlan() {
|
||||
if (!selectedAccepted.length) return
|
||||
if (!selectedCommittable.length) return
|
||||
if (typeof onBulkConvert === 'function') {
|
||||
await onBulkConvert(
|
||||
selectedAccepted.map((item) => item.id),
|
||||
selectedCommittable.map((item) => item.id),
|
||||
convertOptions(),
|
||||
)
|
||||
} else {
|
||||
for (const item of selectedAccepted) {
|
||||
for (const item of selectedCommittable) {
|
||||
await onConvert(item.id, convertOptions())
|
||||
}
|
||||
}
|
||||
|
|
@ -195,10 +197,22 @@ export function BacklogSection({
|
|||
)}
|
||||
</div>
|
||||
|
||||
{showSprintPlanning && canManage && acceptedItems.length > 0 && (
|
||||
{sprintPlanningEnabled && canManage && !showSprintPlanning && (
|
||||
<div className="backlog-sprint-setup card-list-item">
|
||||
<p className="backlog-sprint-setup__title">
|
||||
<strong>Sprint-Planung:</strong> Lege zuerst einen Sprint an.
|
||||
</p>
|
||||
<p className="muted backlog-sprint-planning__hint">
|
||||
Plan → Sprint → „Sprint anlegen“ (optional „Sofort aktivieren“). Danach erscheint hier
|
||||
die Sprint-Auswahl zum Committen aus dem Eingang.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{showSprintPlanning && canManage && (
|
||||
<div className="backlog-sprint-planning card-list-item">
|
||||
<label className="backlog-sprint-planning__field">
|
||||
<span className="muted">Sprint-Ziel</span>
|
||||
<span className="muted">Ziel-Sprint</span>
|
||||
<select
|
||||
value={sprintTargetId}
|
||||
onChange={(e) => setSprintTargetId(e.target.value)}
|
||||
|
|
@ -207,33 +221,30 @@ export function BacklogSection({
|
|||
{planableSprints.map((cycle) => (
|
||||
<option key={cycle.id} value={cycle.id}>
|
||||
{cycle.title}
|
||||
{cycle.status === 'active' ? ' (aktiv)' : ''}
|
||||
{cycle.status === 'active' ? ' (aktiv)' : cycle.status === 'planned' ? ' (geplant)' : ''}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
{selectedAccepted.length > 0 && (
|
||||
{selectedCommittable.length > 0 && (
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary btn-sm"
|
||||
disabled={busy || !sprintTargetId}
|
||||
onClick={handleBulkPlan}
|
||||
>
|
||||
{selectedAccepted.length} Item{selectedAccepted.length === 1 ? '' : 's'} {convertLabel}
|
||||
{selectedCommittable.length} Item{selectedCommittable.length === 1 ? '' : 's'}{' '}
|
||||
{convertLabel}
|
||||
</button>
|
||||
)}
|
||||
<p className="muted backlog-sprint-planning__hint">
|
||||
Items markieren und in den gewählten Sprint committen — Planung unter Plan → Sprint.
|
||||
{committableItems.length === 0
|
||||
? 'Lege Backlog-Items an — dann per Checkbox markieren und in den Sprint committen.'
|
||||
: 'Checkbox am Item → „In Sprint planen“. Committen erzeugt ein Arbeitspaket mit Sprint-Zuweisung.'}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{sprintPlanningEnabled && canManage && acceptedItems.length > 0 && planableSprints.length === 0 && (
|
||||
<p className="muted backlog-sprint-planning__hint">
|
||||
Lege zuerst einen Sprint unter Plan → Sprint an, um Backlog-Items zu planen.
|
||||
</p>
|
||||
)}
|
||||
|
||||
{items.length === 0 && <EmptyState message="Backlog ist leer." />}
|
||||
|
||||
<ul className="item-list backlog-reorder-list">
|
||||
|
|
@ -262,7 +273,7 @@ export function BacklogSection({
|
|||
⋮⋮
|
||||
</span>
|
||||
)}
|
||||
{showSprintPlanning && canManage && item.status === 'accepted' && (
|
||||
{showSprintPlanning && canManage && COMMITTABLE_STATUSES.has(item.status) && (
|
||||
<label className="backlog-select-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
|
|
@ -304,14 +315,14 @@ export function BacklogSection({
|
|||
<PriorityBadge priority={item.priority} />
|
||||
{canManage && item.status !== 'converted' && (
|
||||
<>
|
||||
{item.status === 'accepted' && (
|
||||
{COMMITTABLE_STATUSES.has(item.status) && (
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary btn-sm"
|
||||
onClick={() => handleSingleConvert(item.id)}
|
||||
disabled={busy || (showSprintPlanning && !sprintTargetId)}
|
||||
>
|
||||
{convertLabel}
|
||||
{showSprintPlanning ? convertLabel : 'In Arbeitspaket umwandeln'}
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
|
|
|
|||
|
|
@ -670,6 +670,18 @@
|
|||
background: var(--jk-surface);
|
||||
}
|
||||
|
||||
.backlog-sprint-setup {
|
||||
margin-bottom: 16px;
|
||||
padding: 12px;
|
||||
border-left: 3px solid var(--jk-primary);
|
||||
background: var(--jk-surface-muted, rgba(0, 0, 0, 0.03));
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.backlog-sprint-setup__title {
|
||||
margin: 0 0 6px;
|
||||
}
|
||||
|
||||
.backlog-sprint-planning {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user