Skip to content

Commit 0d180ea

Browse files
committed
fix(roadmap-page): remove logs, lint fixes and small styling update
1 parent 90b76fb commit 0d180ea

4 files changed

Lines changed: 51 additions & 49 deletions

File tree

netlify/functions/sync-now.mts

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import { getStore } from '@netlify/blobs'
22
import { buildSnapshot } from '../../src/linear/build-snapshot.js'
33
import type { Context } from '@netlify/functions'
44

5-
export default async function handler(req: Request, _ctx: Context): Promise<Response> {
5+
export default async function handler(
6+
req: Request,
7+
_ctx: Context
8+
): Promise<Response> {
69
// Verify API_SECRET bearer token
710
const authHeader = req.headers.get('authorization') ?? ''
811
const token = authHeader.replace(/^Bearer\s+/i, '')
@@ -11,17 +14,14 @@ export default async function handler(req: Request, _ctx: Context): Promise<Resp
1114
if (!expected || token !== expected) {
1215
return new Response(JSON.stringify({ error: 'Unauthorized' }), {
1316
status: 401,
14-
headers: { 'Content-Type': 'application/json' },
17+
headers: { 'Content-Type': 'application/json' }
1518
})
1619
}
1720

18-
console.log('[sync-now] Manual sync triggered.')
19-
2021
const snapshot = await buildSnapshot()
2122

2223
const store = getStore('roadmap')
2324
await store.setJSON('roadmap-snapshot', snapshot)
24-
console.log(`[sync-now] Snapshot stored. generatedAt: ${snapshot.generatedAt}`)
2525

2626
// Purge CDN cache
2727
const siteId = process.env.NETLIFY_SITE_ID
@@ -32,27 +32,28 @@ export default async function handler(req: Request, _ctx: Context): Promise<Resp
3232
method: 'POST',
3333
headers: {
3434
Authorization: `Bearer ${apiToken}`,
35-
'Content-Type': 'application/json',
35+
'Content-Type': 'application/json'
3636
},
3737
body: JSON.stringify({
3838
site_id: siteId,
39-
paths: ['/developers/roadmap'],
40-
}),
39+
paths: ['/developers/roadmap']
40+
})
4141
})
42-
console.log(`[sync-now] CDN cache purge → ${res.status}`)
4342
} else {
44-
console.warn('[sync-now] NETLIFY_SITE_ID or NETLIFY_API_TOKEN not set — skipping CDN cache purge.')
43+
console.warn(
44+
'[sync-now] NETLIFY_SITE_ID or NETLIFY_API_TOKEN not set — skipping CDN cache purge.'
45+
)
4546
}
4647

4748
return new Response(
4849
JSON.stringify({ ok: true, generatedAt: snapshot.generatedAt }),
4950
{
5051
status: 200,
51-
headers: { 'Content-Type': 'application/json' },
52-
},
52+
headers: { 'Content-Type': 'application/json' }
53+
}
5354
)
5455
}
5556

5657
export const config = {
57-
path: '/api/sync',
58+
path: '/api/sync'
5859
}

netlify/functions/sync.mts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ export default async function handler() {
88

99
const store = getStore('roadmap')
1010
await store.setJSON('roadmap-snapshot', snapshot)
11-
console.log(`[sync] Snapshot stored. generatedAt: ${snapshot.generatedAt}`)
1211

1312
// Purge CDN cache so the next user request re-renders fresh HTML
1413
const siteId = process.env.NETLIFY_SITE_ID
@@ -19,21 +18,20 @@ export default async function handler() {
1918
method: 'POST',
2019
headers: {
2120
Authorization: `Bearer ${apiToken}`,
22-
'Content-Type': 'application/json',
21+
'Content-Type': 'application/json'
2322
},
2423
body: JSON.stringify({
2524
site_id: siteId,
26-
paths: ['/developers/roadmap'],
27-
}),
25+
paths: ['/developers/roadmap']
26+
})
2827
})
29-
console.log(`[sync] CDN cache purge → ${res.status}`)
3028
} else {
31-
console.warn('[sync] NETLIFY_SITE_ID or NETLIFY_API_TOKEN not set — skipping CDN cache purge.')
29+
console.warn(
30+
'[sync] NETLIFY_SITE_ID or NETLIFY_API_TOKEN not set — skipping CDN cache purge.'
31+
)
3232
}
33-
34-
console.log('[sync] Done.')
3533
}
3634

3735
export const config = {
38-
schedule: '0 */12 * * *',
36+
schedule: '0 */12 * * *'
3937
}

src/components/RoadmapBoard.astro

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,8 @@ for (const proj of uncategorised) {
267267

268268
<div class="board-outer">
269269
<div class="mobile-toggle-wrap">
270-
<button class="mobile-toggle-btn" aria-pressed="false">Full timeline</button>
270+
<button class="mobile-toggle-btn" aria-pressed="false">Full timeline</button
271+
>
271272
</div>
272273
<div class="board-scroll">
273274
<!--
@@ -280,10 +281,13 @@ for (const proj of uncategorised) {
280281
rows 3 … = one per project
281282
Every cell has explicit grid-column + grid-row to avoid auto-placement bugs.
282283
-->
283-
<div class="board" style={`--n-months: ${nMonths}; --n-quarters: ${nQuarters}; --now-pct: ${nowLeft}%`}>
284+
<div
285+
class="board"
286+
style={`--n-months: ${nMonths}; --n-quarters: ${nQuarters}; --now-pct: ${nowLeft}%`}
287+
>
284288
<!-- ── col 1, rows 1–2: "Project" label spans both header rows ── -->
285289
<div class="hd-label" style="grid-column: 1; grid-row: 1 / 3">
286-
Project
290+
Team / Project
287291
</div>
288292

289293
<!-- ── row 1: Quarter header cells (desktop: month-based spans) ── -->
@@ -429,7 +433,6 @@ for (const proj of uncategorised) {
429433
{proj.url ? (
430434
<a
431435
class="proj-name"
432-
href={proj.url}
433436
target="_blank"
434437
rel="noopener noreferrer"
435438
title={`Open ${proj.name} in Linear`}
@@ -702,7 +705,6 @@ for (const proj of uncategorised) {
702705

703706
a.proj-name:hover {
704707
color: var(--color-primary);
705-
text-decoration: underline;
706708
}
707709

708710
.proj-icon {
@@ -993,10 +995,9 @@ for (const proj of uncategorised) {
993995
if (isNaN(nowPct)) return
994996

995997
// Label column width varies between desktop (300px) and mobile quarter view (130px).
996-
const labelWidth = parseInt(
997-
getComputedStyle(board).gridTemplateColumns.split(' ')[0],
998-
10
999-
) || 300
998+
const labelWidth =
999+
parseInt(getComputedStyle(board).gridTemplateColumns.split(' ')[0], 10) ||
1000+
300
10001001
const timelineWidth = board.scrollWidth - labelWidth
10011002
const nowPxFromBoardLeft = labelWidth + (nowPct / 100) * timelineWidth
10021003

@@ -1005,19 +1006,21 @@ for (const proj of uncategorised) {
10051006
}
10061007

10071008
// Toggle between quarter view and full month view on mobile.
1008-
document.querySelectorAll<HTMLButtonElement>('.mobile-toggle-btn').forEach((btn) => {
1009-
btn.addEventListener('click', () => {
1010-
const outer = btn.closest('.board-outer')
1011-
if (!outer) return
1012-
const scroll = outer.querySelector<HTMLElement>('.board-scroll')
1013-
if (!scroll) return
1014-
const isFull = scroll.classList.toggle('board-scroll--full')
1015-
btn.textContent = isFull ? 'Quarter view' : 'Full timeline'
1016-
btn.setAttribute('aria-pressed', String(isFull))
1017-
// Re-centre after the grid repaints.
1018-
requestAnimationFrame(centreOnNow)
1009+
document
1010+
.querySelectorAll<HTMLButtonElement>('.mobile-toggle-btn')
1011+
.forEach((btn) => {
1012+
btn.addEventListener('click', () => {
1013+
const outer = btn.closest('.board-outer')
1014+
if (!outer) return
1015+
const scroll = outer.querySelector<HTMLElement>('.board-scroll')
1016+
if (!scroll) return
1017+
const isFull = scroll.classList.toggle('board-scroll--full')
1018+
btn.textContent = isFull ? 'Quarter view' : 'Full timeline'
1019+
btn.setAttribute('aria-pressed', String(isFull))
1020+
// Re-centre after the grid repaints.
1021+
requestAnimationFrame(centreOnNow)
1022+
})
10191023
})
1020-
})
10211024

10221025
// Run after the DOM (and layout) is ready.
10231026
if (document.readyState === 'loading') {
@@ -1032,13 +1035,17 @@ for (const proj of uncategorised) {
10321035
e.stopPropagation()
10331036
const isNowActive = !pin.classList.contains('ms-pin--active')
10341037
// Close any open tooltips first.
1035-
document.querySelectorAll('.ms-pin--active').forEach((p) => p.classList.remove('ms-pin--active'))
1038+
document
1039+
.querySelectorAll('.ms-pin--active')
1040+
.forEach((p) => p.classList.remove('ms-pin--active'))
10361041
if (isNowActive) pin.classList.add('ms-pin--active')
10371042
})
10381043
})
10391044

10401045
// Close tooltip when tapping outside.
10411046
document.addEventListener('click', () => {
1042-
document.querySelectorAll('.ms-pin--active').forEach((p) => p.classList.remove('ms-pin--active'))
1047+
document
1048+
.querySelectorAll('.ms-pin--active')
1049+
.forEach((p) => p.classList.remove('ms-pin--active'))
10431050
})
10441051
</script>

src/linear/build-snapshot.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,6 @@ async function withRetry<T>(
161161
// ---------------------------------------------------------------------------
162162

163163
async function fetchTeams(): Promise<TeamsQueryResult['teams']['nodes']> {
164-
console.log('[linear] Fetching teams...')
165164
const all: TeamsQueryResult['teams']['nodes'] = []
166165
let hasNextPage = true
167166
let endCursor: string | null = null
@@ -181,12 +180,10 @@ async function fetchTeams(): Promise<TeamsQueryResult['teams']['nodes']> {
181180
endCursor = result.teams.pageInfo.endCursor
182181
}
183182

184-
console.log(`[linear] Fetched ${all.length} teams.`)
185183
return all
186184
}
187185

188186
async function fetchViewProjects(viewId: string): Promise<ViewProjectNode[]> {
189-
console.log(`[linear] Fetching projects from view ${viewId}...`)
190187
const all: ViewProjectNode[] = []
191188
let hasNextPage = true
192189
let endCursor: string | null = null
@@ -213,7 +210,6 @@ async function fetchViewProjects(viewId: string): Promise<ViewProjectNode[]> {
213210
endCursor = result.customView.projects.pageInfo.endCursor
214211
}
215212

216-
console.log(`[linear] Fetched ${all.length} projects from view.`)
217213
return all
218214
}
219215

0 commit comments

Comments
 (0)