Skip to content

Commit 8446440

Browse files
authored
Add tooltip to show when data was last updated (#28)
1 parent 386a2e6 commit 8446440

7 files changed

Lines changed: 82 additions & 60 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "daily-helper",
3-
"version": "2.1.1",
3+
"version": "2.2.0",
44
"private": true,
55
"scripts": {
66
"start": "vite",

src/components/AppBar.tsx

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@ import Tooltip from '@mui/material/Tooltip'
2424
import Typography from '@mui/material/Typography'
2525
import packageData from '../../package.json'
2626
import { settingsHandler } from '../helpers/settingsHandler'
27+
import { useRelativeTime } from '../hooks/useRelativeTime'
2728

2829
type AppBarElementProps = {
2930
handleReload: (teamName: string, isValidToken: boolean) => void
3031
loadingProgress: number
3132
isLoadingAnimationPlaying: boolean
33+
lastUpdated?: Date | null
3234
showDrawbar?: (marginTop?: number) => ReactElement | null
3335
drawbarName: string
3436
isDrawbarOpen: boolean
@@ -38,11 +40,13 @@ export default function AppBarElement({
3840
handleReload: initialHandleReload,
3941
loadingProgress,
4042
isLoadingAnimationPlaying,
43+
lastUpdated = null,
4144
showDrawbar,
4245
drawbarName,
4346
isDrawbarOpen,
4447
setIsDrawbarOpen,
4548
}: AppBarElementProps) {
49+
const relativeTime = useRelativeTime(lastUpdated)
4650
const [teamTabValue, setTeamTabValue] = useState(0)
4751
const [teamNames, setTeamNames] = useState(settingsHandler.loadTeamNames())
4852
const [isSettingsOpen, setIsSettingsOpen] = useState(false)
@@ -88,10 +92,10 @@ export default function AppBarElement({
8892

8993
return (
9094
<>
91-
<AppBar>
95+
<AppBar sx={{ overflow: 'visible' }}>
9296
<Toolbar
9397
ref={toolbarRef}
94-
sx={{ paddingBottom: isLoadingAnimationPlaying ? 0 : 0.5 }}
98+
sx={{ paddingBottom: 0.5 }}
9599
onKeyUp={({ code }: KeyboardEvent) => {
96100
code === 'Escape' && handleHideDrawbar()
97101
}}
@@ -149,7 +153,13 @@ export default function AppBarElement({
149153
isLoading={isLoadingAnimationPlaying}
150154
/>
151155

152-
<Tooltip title="Refresh pull requests">
156+
<Tooltip
157+
title={
158+
relativeTime
159+
? `Refresh pull requests · Updated ${relativeTime}`
160+
: 'Refresh pull requests'
161+
}
162+
>
153163
<IconButton
154164
edge="end"
155165
size="large"
@@ -162,7 +172,11 @@ export default function AppBarElement({
162172
</Toolbar>
163173

164174
{isLoadingAnimationPlaying && (
165-
<LinearProgress variant="determinate" value={loadingProgress} />
175+
<LinearProgress
176+
variant="determinate"
177+
value={loadingProgress}
178+
sx={{ position: 'absolute', bottom: 0, left: 0, right: 0 }}
179+
/>
166180
)}
167181
</AppBar>
168182
</>

src/helpers/dataFetcher.ts

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -501,38 +501,8 @@ async function fetchPullRequests({
501501
uniquePullRequests.set(pr.id, pr),
502502
)
503503

504-
const pullRequests = Array.from(uniquePullRequests.values()).map(
505-
(pr): PullRequest => ({
506-
id: pr.id,
507-
author: pr.author,
508-
title: pr.title,
509-
number: pr.number,
510-
url: pr.permalink,
511-
repositoryUrl: pr.repository.url,
512-
repositoryName: pr.repository.name,
513-
repositoryBaseRef: pr.repository.defaultBranchRef.name,
514-
baseRef: pr.baseRef.name,
515-
state: pr.state,
516-
isDraft: pr.isDraft,
517-
reviewDecision: pr.reviewDecision,
518-
createdAt: new Date(pr.createdAt),
519-
labels: pr.labels.nodes,
520-
reviews: formatReviews(pr.reviews.nodes),
521-
comments: calculateNumberOfComments(
522-
pr.comments.totalCount,
523-
pr.reviews.nodes,
524-
),
525-
requestedReviewers: getReviewers(pr.reviewRequests.nodes),
526-
contributors: getContributors(pr.commits.nodes, pr.author),
527-
assignees: pr.assignees.nodes,
528-
lastCommitChecks:
529-
includeChecks && pr.lastCommit?.nodes[0]
530-
? getLastCommitChecks(
531-
pr.lastCommit.nodes[0].commit,
532-
pr.baseRef.branchProtectionRule?.requiredStatusCheckContexts,
533-
)
534-
: null,
535-
}),
504+
const pullRequests = Array.from(uniquePullRequests.values()).map(pr =>
505+
normalizePR(pr, includeChecks),
536506
)
537507

538508
pullRequests.sort((a, b) => b.createdAt.valueOf() - a.createdAt.valueOf())
@@ -543,6 +513,43 @@ async function fetchPullRequests({
543513
return pullRequests
544514
}
545515

516+
function normalizePR(
517+
pr: GraphQL_PullRequest,
518+
includeChecks: boolean,
519+
): PullRequest {
520+
return {
521+
id: pr.id,
522+
author: pr.author,
523+
title: pr.title,
524+
number: pr.number,
525+
url: pr.permalink,
526+
repositoryUrl: pr.repository.url,
527+
repositoryName: pr.repository.name,
528+
repositoryBaseRef: pr.repository.defaultBranchRef.name,
529+
baseRef: pr.baseRef.name,
530+
state: pr.state,
531+
isDraft: pr.isDraft,
532+
reviewDecision: pr.reviewDecision,
533+
createdAt: new Date(pr.createdAt),
534+
labels: pr.labels.nodes,
535+
reviews: formatReviews(pr.reviews.nodes),
536+
comments: calculateNumberOfComments(
537+
pr.comments.totalCount,
538+
pr.reviews.nodes,
539+
),
540+
requestedReviewers: getReviewers(pr.reviewRequests.nodes),
541+
contributors: getContributors(pr.commits.nodes, pr.author),
542+
assignees: pr.assignees.nodes,
543+
lastCommitChecks:
544+
includeChecks && pr.lastCommit?.nodes[0]
545+
? getLastCommitChecks(
546+
pr.lastCommit.nodes[0].commit,
547+
pr.baseRef.branchProtectionRule?.requiredStatusCheckContexts,
548+
)
549+
: null,
550+
}
551+
}
552+
546553
async function fetchTeamRepositories(
547554
orgName: string,
548555
teamName: string,

src/helpers/time.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' })
22

3+
export function fromNowShort(date: Date): string {
4+
const seconds = Math.round((Date.now() - date.getTime()) / 1000)
5+
if (seconds < 10) return 'just now'
6+
if (seconds < 60) return 'less than a minute ago'
7+
return fromNow(date)
8+
}
9+
310
export function fromNow(date: Date): string {
411
const seconds = Math.round((Date.now() - date.getTime()) / 1000)
512
if (seconds < 60) return rtf.format(-seconds, 'second')

src/helpers/useOnScreen.ts

Lines changed: 0 additions & 23 deletions
This file was deleted.

src/hooks/useRelativeTime.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { useEffect, useState } from 'react'
2+
import { fromNowShort } from '../helpers/time'
3+
4+
export function useRelativeTime(date: Date | null): string {
5+
const [, setTick] = useState(0)
6+
7+
useEffect(() => {
8+
if (!date) return
9+
const id = setInterval(() => setTick(t => t + 1), 10_000)
10+
return () => clearInterval(id)
11+
}, [date])
12+
13+
return date ? fromNowShort(date) : ''
14+
}

src/views/DailyHelper/DailyHelper.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export default function DailyHelper() {
5252
const [isLoadingAnimationPlaying, setIsLoadingAnimationPlaying] = useState(
5353
!isInvalidToken && Boolean(orgName) && teamNames.length > 0,
5454
)
55+
const [lastUpdated, setLastUpdated] = useState<Date | null>(null)
5556
const [isDrawbarOpen, setIsDrawbarOpen] = useState(false)
5657
const [
5758
isPullRequestsWithoutLabelsHidden,
@@ -110,6 +111,7 @@ export default function DailyHelper() {
110111
})
111112
.then(pullRequests => {
112113
setPullRequests(pullRequests)
114+
setLastUpdated(new Date())
113115
setIsLoadingAnimationPlaying(false)
114116
})
115117
setShouldLoad(false)
@@ -256,6 +258,7 @@ export default function DailyHelper() {
256258
<AppBar
257259
loadingProgress={loadingProgress}
258260
isLoadingAnimationPlaying={isLoadingAnimationPlaying}
261+
lastUpdated={lastUpdated}
259262
handleReload={handleReload}
260263
showDrawbar={getDrawer({
261264
allLabels,

0 commit comments

Comments
 (0)