Skip to content

Commit f8dc241

Browse files
committed
time based sprint system
Signed-off-by: RAWx18 <rawx18.dev@gmail.com>
1 parent dd08ff1 commit f8dc241

File tree

2 files changed

+84
-35
lines changed

2 files changed

+84
-35
lines changed

frontend/src/modules/devspace/components/SprintPlanningModal.vue

Lines changed: 84 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@
2929
<div class="card-meta">
3030
<span class="id">#{{ element.id?.slice(0, 6) }}</span>
3131
<span class="points" v-if="element.storyPoints || element.estimatedHours">
32-
{{ element.storyPoints || element.estimatedHours }} pts
32+
{{ parseFloat(element.storyPoints) || parseFloat(element.estimatedHours) || 0 }} pts
3333
</span>
34+
<span class="points no-points" v-else>0 pts</span>
3435
</div>
3536
</div>
3637
</div>
@@ -63,6 +64,7 @@
6364
class="issue-list cycle-list"
6465
:animation="200"
6566
ghost-class="ghost-card"
67+
@change="handleCycleChange"
6668
>
6769
<template #item="{ element }">
6870
<div class="planning-card">
@@ -71,8 +73,9 @@
7173
<div class="card-meta">
7274
<span class="id">#{{ element.id?.slice(0, 6) }}</span>
7375
<span class="points" v-if="element.storyPoints || element.estimatedHours">
74-
{{ element.storyPoints || element.estimatedHours }} pts
76+
{{ parseFloat(element.storyPoints) || parseFloat(element.estimatedHours) || 0 }} pts
7577
</span>
78+
<span class="points no-points" v-else>0 pts</span>
7679
</div>
7780
</div>
7881
</div>
@@ -120,41 +123,96 @@ export default {
120123
const cycleIssues = ref([]);
121124
const saving = ref(false);
122125
const capacity = ref(20); // TODO: Fetch from settings or team capacity
126+
const updateTrigger = ref(0); // Force reactivity trigger
123127
124128
const totalPoints = computed(() => {
125-
return cycleIssues.value.reduce((sum, issue) => {
126-
return sum + (issue.storyPoints || issue.estimatedHours || 0);
129+
// Access updateTrigger to force recomputation
130+
updateTrigger.value;
131+
132+
console.log('[SprintPlanning] Computing total points for', cycleIssues.value.length, 'issues');
133+
const total = cycleIssues.value.reduce((sum, issue) => {
134+
const points = parseFloat(issue.storyPoints) || parseFloat(issue.estimatedHours) || 0;
135+
console.log('[SprintPlanning] Issue:', issue.title, 'Points:', points, 'storyPoints:', issue.storyPoints, 'estimatedHours:', issue.estimatedHours);
136+
return sum + points;
127137
}, 0);
138+
console.log('[SprintPlanning] Total calculated:', total);
139+
return Math.round(total * 10) / 10; // Round to 1 decimal place
128140
});
129-
130-
// Fetch data when modal opens
131-
watch(() => props.modelValue, async (val) => {
132-
if (val && props.cycle) {
133-
await fetchData();
134-
}
135-
});
141+
142+
const handleCycleChange = (event) => {
143+
console.log('[SprintPlanning] Cycle changed:', event);
144+
console.log('[SprintPlanning] Current cycle issues:', cycleIssues.value.length);
145+
// Force recomputation of totalPoints
146+
updateTrigger.value++;
147+
};
148+
149+
// Watch for changes in cycleIssues
150+
watch(cycleIssues, (newVal) => {
151+
console.log('[SprintPlanning] Cycle issues changed:', newVal.length, 'issues');
152+
console.log('[SprintPlanning] Issues:', newVal.map(i => ({ title: i.title, points: i.storyPoints || i.estimatedHours })));
153+
}, { deep: true });
136154
137155
const fetchData = async () => {
138156
try {
139-
// Fetch backlog issues (status=backlog or no cycle)
140-
// Ideally we filter by no assigned cycle, but backend might not stick strictly.
141-
// For now fetch all candidates.
142-
const allIssues = await DevtelService.listIssues(props.projectId, { status: ['backlog', 'todo'] }); // Adjust filters as needed
157+
console.log('[SprintPlanning] Fetching issues for project:', props.projectId);
158+
159+
// Fetch all issues from the project
160+
const response = await DevtelService.listIssues(props.projectId, {});
161+
162+
console.log('[SprintPlanning] Raw response:', response);
163+
164+
// Handle different response formats
165+
let allIssues = [];
166+
if (Array.isArray(response)) {
167+
allIssues = response;
168+
} else if (response && response.rows) {
169+
allIssues = response.rows;
170+
} else if (response && response.data) {
171+
allIssues = Array.isArray(response.data) ? response.data : response.data.rows || [];
172+
}
173+
174+
console.log('[SprintPlanning] All issues:', allIssues);
175+
console.log('[SprintPlanning] Sample issue:', allIssues[0]);
143176
144177
// Separate into those already in this cycle and others
145178
if (props.cycle) {
146-
// Assuming issue object has cycleId property
179+
// Issues already assigned to this cycle
147180
cycleIssues.value = allIssues.filter(i => i.cycleId === props.cycle.id);
148-
backlogIssues.value = allIssues.filter(i => i.cycleId !== props.cycle.id);
181+
// Backlog issues: no cycle assigned or in backlog/todo status
182+
backlogIssues.value = allIssues.filter(i =>
183+
!i.cycleId && (i.status === 'backlog' || i.status === 'todo')
184+
);
149185
} else {
150-
backlogIssues.value = allIssues;
186+
backlogIssues.value = allIssues.filter(i =>
187+
!i.cycleId && (i.status === 'backlog' || i.status === 'todo')
188+
);
151189
cycleIssues.value = [];
152190
}
191+
192+
console.log('[SprintPlanning] Backlog issues:', backlogIssues.value);
193+
console.log('[SprintPlanning] Cycle issues:', cycleIssues.value);
153194
} catch (e) {
154-
ElMessage.error('Failed to load issues for planning');
195+
console.error('[SprintPlanning] Failed to load issues:', e);
196+
ElMessage.error('Failed to load issues for planning: ' + e.message);
155197
}
156198
};
157199
200+
// Fetch data when modal opens
201+
watch(() => props.modelValue, async (val) => {
202+
if (val && props.cycle) {
203+
console.log('[SprintPlanning] Modal opened for cycle:', props.cycle);
204+
await fetchData();
205+
}
206+
}, { immediate: true });
207+
208+
// Also fetch on mount if already open
209+
onMounted(async () => {
210+
if (props.modelValue && props.cycle) {
211+
console.log('[SprintPlanning] Modal mounted, fetching data');
212+
await fetchData();
213+
}
214+
});
215+
158216
const handleClose = () => {
159217
visible.value = false;
160218
};
@@ -183,7 +241,8 @@ export default {
183241
capacity,
184242
totalPoints,
185243
handleClose,
186-
savePlan
244+
savePlan,
245+
handleCycleChange
187246
};
188247
}
189248
};
@@ -301,6 +360,11 @@ export default {
301360
color: var(--el-text-color-secondary);
302361
}
303362
363+
.card-meta .no-points {
364+
color: var(--el-text-color-placeholder);
365+
font-style: italic;
366+
}
367+
304368
.divider {
305369
display: flex;
306370
align-items: center;

frontend/src/modules/devspace/pages/BacklogPage.vue

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,5 @@
11
<template>
22
<div class="backlog-page devspace-page">
3-
<div class="page-header">
4-
<h1>Backlog</h1>
5-
<el-button type="primary" size="small">
6-
<i class="ri-add-line"></i>
7-
New Issue
8-
</el-button>
9-
</div>
10-
113
<!-- Bulk Actions Toolbar -->
124
<div class="bulk-actions" v-if="selectedIssues.length > 0">
135
<div class="selected-count">{{ selectedIssues.length }} selected</div>
@@ -415,13 +407,6 @@ const setupSocketListeners = () => {
415407
height: 100%;
416408
}
417409
418-
.page-header {
419-
display: flex;
420-
justify-content: space-between;
421-
align-items: center;
422-
margin-bottom: 16px;
423-
}
424-
425410
.bulk-actions {
426411
display: flex;
427412
align-items: center;

0 commit comments

Comments
 (0)