Skip to content

Commit 1c3d77f

Browse files
committed
remove sparklines, fix block averages to reflect filters
1 parent 253968b commit 1c3d77f

File tree

4 files changed

+180
-116
lines changed

4 files changed

+180
-116
lines changed

assets/app.js

Lines changed: 116 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,7 @@ const App = (() => {
6666
organizations: [],
6767
pullRequests: {
6868
incoming: [],
69-
outgoing: [],
70-
drafts: []
69+
outgoing: []
7170
},
7271
isDemoMode: false,
7372
};
@@ -146,8 +145,7 @@ const App = (() => {
146145
// Categorize PRs
147146
state.pullRequests = {
148147
incoming: [],
149-
outgoing: [],
150-
drafts: []
148+
outgoing: []
151149
};
152150

153151
for (const pr of prs) {
@@ -156,9 +154,8 @@ const App = (() => {
156154
pr.status_tags = getStatusTags(pr);
157155
pr.last_activity = generateMockActivity(pr);
158156

159-
if (pr.draft) {
160-
state.pullRequests.drafts.push(pr);
161-
} else if (pr.user.login === state.currentUser.login) {
157+
// Include drafts in incoming/outgoing based on author
158+
if (pr.user.login === state.currentUser.login) {
162159
state.pullRequests.outgoing.push(pr);
163160
} else {
164161
state.pullRequests.incoming.push(pr);
@@ -229,8 +226,7 @@ const App = (() => {
229226
// Extract unique organizations from PRs
230227
const allPRs = [
231228
...state.pullRequests.incoming,
232-
...state.pullRequests.outgoing,
233-
...state.pullRequests.drafts
229+
...state.pullRequests.outgoing
234230
];
235231

236232
const uniqueOrgs = [...new Set(allPRs.map(pr => pr.repository.full_name.split('/')[0]))].sort();
@@ -255,45 +251,17 @@ const App = (() => {
255251
// Update counts
256252
$('incomingCount').textContent = state.pullRequests.incoming.length;
257253
$('outgoingCount').textContent = state.pullRequests.outgoing.length;
258-
$('draftCount').textContent = state.pullRequests.drafts.length;
259-
260-
// Update blocked counts
261-
const incomingBlocked = state.pullRequests.incoming.filter(pr =>
262-
pr.status_tags?.includes('blocked on you')
263-
).length;
264-
const outgoingBlocked = state.pullRequests.outgoing.filter(pr =>
265-
pr.status_tags?.includes('blocked on you')
266-
).length;
267-
268-
const incomingBlockedEl = $('incomingBlockedCount');
269-
const outgoingBlockedEl = $('outgoingBlockedCount');
270-
271-
if (incomingBlocked > 0) {
272-
incomingBlockedEl.textContent = `${incomingBlocked} blocked on you`;
273-
show(incomingBlockedEl);
274-
} else {
275-
hide(incomingBlockedEl);
276-
}
277-
278-
if (outgoingBlocked > 0) {
279-
outgoingBlockedEl.textContent = `${outgoingBlocked} blocked on you`;
280-
show(outgoingBlockedEl);
281-
} else {
282-
hide(outgoingBlockedEl);
283-
}
284254

285-
// Update sparklines
286-
updateSparklines();
255+
// Update filter counts
256+
updateFilterCounts();
287257

288258
// Render PR lists
289-
renderPRList($('incomingPRs'), state.pullRequests.incoming);
290-
renderPRList($('outgoingPRs'), state.pullRequests.outgoing);
291-
renderPRList($('draftPRs'), state.pullRequests.drafts, true);
259+
renderPRList($('incomingPRs'), state.pullRequests.incoming, false, 'incoming');
260+
renderPRList($('outgoingPRs'), state.pullRequests.outgoing, false, 'outgoing');
292261

293262
// Update empty state
294263
const totalPRs = state.pullRequests.incoming.length +
295-
state.pullRequests.outgoing.length +
296-
state.pullRequests.drafts.length;
264+
state.pullRequests.outgoing.length;
297265

298266
const emptyState = $('emptyState');
299267
if (totalPRs === 0) {
@@ -303,57 +271,91 @@ const App = (() => {
303271
}
304272
};
305273

306-
const updateSparklines = () => {
307-
// Simple sparkline implementation
308-
const createSparkline = (data, width = 60, height = 20, color = '#10b981') => {
309-
if (!data.length) return '';
274+
const updateFilterCounts = () => {
275+
// Count stale and blocked on others PRs for each section
276+
const sections = [
277+
{ prs: state.pullRequests.incoming, prefix: 'incoming' },
278+
{ prs: state.pullRequests.outgoing, prefix: 'outgoing' }
279+
];
280+
281+
sections.forEach(({ prs, prefix }) => {
282+
const staleCount = prs.filter(pr => pr.status_tags?.includes('stale')).length;
283+
const blockedOthersCount = prs.filter(pr =>
284+
!pr.status_tags?.includes('blocked on you') && pr.status_tags?.length > 0
285+
).length;
310286

311-
const max = Math.max(...data, 1);
312-
const points = data.map((value, index) => {
313-
const x = (index / (data.length - 1)) * width;
314-
const y = height - (value / max) * height;
315-
return `${x},${y}`;
316-
}).join(' ');
287+
// Update checkbox labels with counts
288+
const staleLabel = $(`${prefix}FilterStale`)?.nextElementSibling;
289+
const blockedOthersLabel = $(`${prefix}FilterBlockedOthers`)?.nextElementSibling;
317290

318-
return `
319-
<svg width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
320-
<polyline
321-
fill="none"
322-
stroke="${color}"
323-
stroke-width="2"
324-
points="${points}"
325-
/>
326-
</svg>
327-
`;
328-
};
329-
330-
// Mock data for sparklines
331-
const incomingData = [3, 5, 2, 8, 4, 7, 6];
332-
const outgoingData = [2, 4, 6, 3, 7, 5, 8];
333-
const draftData = [1, 2, 1, 3, 2, 4, 3];
334-
335-
$('incomingSparkline').innerHTML = createSparkline(incomingData, 60, 20, '#6366f1');
336-
$('outgoingSparkline').innerHTML = createSparkline(outgoingData, 60, 20, '#10b981');
337-
$('draftSparkline').innerHTML = createSparkline(draftData, 60, 20, '#94a3b8');
291+
if (staleLabel) {
292+
staleLabel.textContent = `Stale (${staleCount})`;
293+
}
294+
295+
if (blockedOthersLabel) {
296+
blockedOthersLabel.textContent = `Blocked on Others (${blockedOthersCount})`;
297+
}
298+
});
299+
};
300+
301+
const updateAverages = (section, filteredPRs) => {
302+
// Calculate average age for filtered PRs
303+
if (filteredPRs.length === 0) {
304+
const avgElement = $(`${section}Average`);
305+
if (avgElement) avgElement.textContent = '';
306+
return;
307+
}
338308

339-
// Calculate averages
340-
const avgIncoming = Math.round(state.pullRequests.incoming.reduce((sum, pr) => sum + pr.age_days, 0) / state.pullRequests.incoming.length) || 0;
341-
const avgOutgoing = Math.round(state.pullRequests.outgoing.reduce((sum, pr) => sum + pr.age_days, 0) / state.pullRequests.outgoing.length) || 0;
309+
const avgAge = Math.round(filteredPRs.reduce((sum, pr) => sum + pr.age_days, 0) / filteredPRs.length) || 0;
310+
const avgElement = $(`${section}Average`);
342311

343-
if (avgIncoming > 0) $('incomingAverage').textContent = `avg ${avgIncoming}d`;
344-
if (avgOutgoing > 0) $('outgoingAverage').textContent = `avg ${avgOutgoing}d`;
312+
if (avgAge > 0 && avgElement) {
313+
avgElement.textContent = `avg ${avgAge}d open`;
314+
} else if (avgElement) {
315+
avgElement.textContent = '';
316+
}
345317
};
346318

347-
const renderPRList = (container, prs, isDraft = false) => {
319+
const renderPRList = (container, prs, isDraft = false, section = '') => {
348320
if (!container) return;
349321

350322
const orgSelect = $('orgSelect');
351323
const selectedOrg = orgSelect?.value;
352324

353-
// Filter by organization
325+
// Get section-specific filter states from cookies or default to true
326+
let showStale = true;
327+
let showBlockedOthers = true;
328+
329+
if (section === 'incoming') {
330+
showStale = getCookie('incomingFilterStale') !== 'false';
331+
showBlockedOthers = getCookie('incomingFilterBlockedOthers') !== 'false';
332+
// Update checkbox states from cookies
333+
if ($('incomingFilterStale')) $('incomingFilterStale').checked = showStale;
334+
if ($('incomingFilterBlockedOthers')) $('incomingFilterBlockedOthers').checked = showBlockedOthers;
335+
} else if (section === 'outgoing') {
336+
showStale = getCookie('outgoingFilterStale') !== 'false';
337+
showBlockedOthers = getCookie('outgoingFilterBlockedOthers') !== 'false';
338+
// Update checkbox states from cookies
339+
if ($('outgoingFilterStale')) $('outgoingFilterStale').checked = showStale;
340+
if ($('outgoingFilterBlockedOthers')) $('outgoingFilterBlockedOthers').checked = showBlockedOthers;
341+
}
342+
343+
// Apply filters
354344
let filteredPRs = prs;
345+
346+
// Filter by organization
355347
if (selectedOrg) {
356-
filteredPRs = prs.filter(pr => pr.repository.full_name.startsWith(selectedOrg + '/'));
348+
filteredPRs = filteredPRs.filter(pr => pr.repository.full_name.startsWith(selectedOrg + '/'));
349+
}
350+
351+
// Filter stale PRs
352+
if (!showStale) {
353+
filteredPRs = filteredPRs.filter(pr => !pr.status_tags?.includes('stale'));
354+
}
355+
356+
// Filter blocked on others PRs
357+
if (!showBlockedOthers) {
358+
filteredPRs = filteredPRs.filter(pr => pr.status_tags?.includes('blocked on you'));
357359
}
358360

359361
// Sort by priority
@@ -366,19 +368,24 @@ const App = (() => {
366368
});
367369

368370
container.innerHTML = sortedPRs.map(pr => createPRCard(pr, isDraft)).join('');
371+
372+
// Update average for this section with filtered PRs
373+
if (section === 'incoming' || section === 'outgoing') {
374+
updateAverages(section, filteredPRs);
375+
}
369376
};
370377

371378
const createPRCard = (pr, isDraft = false) => {
372-
const state = getPRState(pr, isDraft);
373-
const badges = buildBadges(pr, isDraft);
379+
const state = getPRState(pr, pr.draft);
380+
const badges = buildBadges(pr, pr.draft);
374381
const ageText = getAgeText(pr);
375382
const activityText = pr.last_activity ?
376383
` <span class="activity-text">• ${pr.last_activity.message} ${formatTimeAgo(pr.last_activity.timestamp)}</span>` : '';
377384
const reviewers = buildReviewers(pr.requested_reviewers || []);
378385
const needsAction = pr.status_tags?.includes('blocked on you');
379386

380387
return `
381-
<div class="pr-card" data-state="${state}" data-pr-id="${pr.id}" ${needsAction ? 'data-needs-action="true"' : ''}>
388+
<div class="pr-card" data-state="${state}" data-pr-id="${pr.id}" ${needsAction ? 'data-needs-action="true"' : ''} ${pr.draft ? 'data-draft="true"' : ''}>
382389
<div class="pr-header">
383390
<a href="${pr.html_url}" class="pr-title" target="_blank" rel="noopener">
384391
${escapeHtml(pr.title)}
@@ -512,8 +519,7 @@ const App = (() => {
512519
// Find PR in all sections
513520
const allPRs = [
514521
...state.pullRequests.incoming,
515-
...state.pullRequests.outgoing,
516-
...state.pullRequests.drafts
522+
...state.pullRequests.outgoing
517523
];
518524
const pr = allPRs.find(p => p.id.toString() === prId);
519525
if (!pr) return;
@@ -548,7 +554,7 @@ const App = (() => {
548554
if (response.ok) {
549555
showToast('PR merged successfully', 'success');
550556
// Remove PR from state
551-
['incoming', 'outgoing', 'drafts'].forEach(section => {
557+
['incoming', 'outgoing'].forEach(section => {
552558
const index = state.pullRequests[section].findIndex(p => p.id.toString() === prId);
553559
if (index !== -1) {
554560
state.pullRequests[section].splice(index, 1);
@@ -612,7 +618,7 @@ const App = (() => {
612618
if (response.ok) {
613619
showToast('PR closed', 'success');
614620
// Remove PR from state
615-
['incoming', 'outgoing', 'drafts'].forEach(section => {
621+
['incoming', 'outgoing'].forEach(section => {
616622
const index = state.pullRequests[section].findIndex(p => p.id.toString() === prId);
617623
if (index !== -1) {
618624
state.pullRequests[section].splice(index, 1);
@@ -802,8 +808,7 @@ const App = (() => {
802808
// Enhance demo PRs
803809
const allPRs = [
804810
...state.pullRequests.incoming,
805-
...state.pullRequests.outgoing,
806-
...state.pullRequests.drafts
811+
...state.pullRequests.outgoing
807812
];
808813

809814
allPRs.forEach(pr => {
@@ -842,6 +847,26 @@ const App = (() => {
842847
}
843848
if (loginBtn) loginBtn.addEventListener('click', initiateLogin);
844849

850+
// Setup filter event listeners for each section
851+
['incoming', 'outgoing'].forEach(section => {
852+
const staleFilter = $(`${section}FilterStale`);
853+
const blockedOthersFilter = $(`${section}FilterBlockedOthers`);
854+
855+
if (staleFilter) {
856+
staleFilter.addEventListener('change', (e) => {
857+
setCookie(`${section}FilterStale`, e.target.checked.toString(), 365);
858+
updatePRSections();
859+
});
860+
}
861+
862+
if (blockedOthersFilter) {
863+
blockedOthersFilter.addEventListener('change', (e) => {
864+
setCookie(`${section}FilterBlockedOthers`, e.target.checked.toString(), 365);
865+
updatePRSections();
866+
});
867+
}
868+
});
869+
845870
// Add event listener for PAT input Enter key
846871
const patInput = $('patInput');
847872
if (patInput) {
@@ -892,7 +917,8 @@ const App = (() => {
892917
showMainContent();
893918
} catch (error) {
894919
console.error('Error initializing app:', error);
895-
showToast('Failed to load data', 'error');
920+
const errorMessage = error.message || 'Unknown error';
921+
showToast(`Failed to load data: ${errorMessage}`, 'error');
896922
}
897923
};
898924

assets/demo-data.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -389,10 +389,7 @@ const DEMO_DATA = {
389389
repository: {
390390
full_name: 'my-company/infrastructure'
391391
}
392-
}
393-
],
394-
395-
drafts: [
392+
},
396393
{
397394
id: 12,
398395
number: 2134,

0 commit comments

Comments
 (0)