Skip to content

Commit bd83df9

Browse files
committed
First batch of UI changes needed in issues dashboard and annotations UI
based on product feedback
1 parent f47a699 commit bd83df9

File tree

8 files changed

+93
-36
lines changed

8 files changed

+93
-36
lines changed

apps/web/src/actions/evaluationsV2/annotate.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export const annotateEvaluationV2Action = withEvaluation
2828
providerLog: providerLog,
2929
commit: ctx.commit,
3030
workspace: ctx.workspace,
31+
currentUser: ctx.user,
3132
}).then((r) => r.unwrap())
3233

3334
return result

apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/issues/_components/LastSeenCell/index.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
differenceInMonths,
1010
differenceInYears,
1111
format,
12+
isSameDay,
1213
} from 'date-fns'
1314
import { Tooltip } from '@latitude-data/web-ui/atoms/Tooltip'
1415

@@ -34,8 +35,19 @@ function getRelativeTimeText(createdAt: Date, lastSeenDate: Date | null) {
3435
const now = new Date()
3536

3637
const ageText = formatTimeDistance(createdAt, now)
37-
const lastSeenText = formatTimeDistance(dateToUse, now)
3838

39+
// If last seen is today, show "today" instead of hours
40+
let lastSeenText: string
41+
if (dateToUse && isSameDay(dateToUse, now)) {
42+
lastSeenText = 'today'
43+
} else {
44+
lastSeenText = formatTimeDistance(dateToUse, now)
45+
}
46+
47+
// Format: "today / X old" or "X ago / Y old"
48+
if (lastSeenText === 'today') {
49+
return `today / ${ageText} old`
50+
}
3951
return `${lastSeenText} ago / ${ageText} old`
4052
}
4153

apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/runs/_components/RunsList/Item.tsx

Lines changed: 66 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
'use client'
22

3+
import { memo, useMemo } from 'react'
34
import { formatDuration } from '$/app/_lib/formatUtils'
45
import { relativeTime } from '$/lib/relativeTime'
56
import { useActiveRuns } from '$/stores/runs/activeRuns'
6-
import { Run } from '@latitude-data/constants'
7+
import {
8+
EvaluationConfiguration,
9+
EvaluationType,
10+
HumanEvaluationMetric,
11+
Run,
12+
} from '@latitude-data/constants'
713
import { Button } from '@latitude-data/web-ui/atoms/Button'
8-
import { Icon } from '@latitude-data/web-ui/atoms/Icons'
14+
import { Icon, IconProps } from '@latitude-data/web-ui/atoms/Icons'
915
import { Text } from '@latitude-data/web-ui/atoms/Text'
1016
import { Tooltip } from '@latitude-data/web-ui/atoms/Tooltip'
1117
import { cn } from '@latitude-data/web-ui/utils'
12-
import { memo } from 'react'
18+
import { getEvaluationMetricSpecification } from '$/components/evaluations'
1319

1420
export const RunsListItem = memo(
1521
({
@@ -27,6 +33,56 @@ export const RunsListItem = memo(
2733
stopRun?: ReturnType<typeof useActiveRuns>['stopRun']
2834
isStoppingRun?: boolean
2935
}) => {
36+
const iconProps = useMemo<IconProps>(() => {
37+
if (run.log?.error.code) {
38+
return { name: 'circleX', color: 'destructive' }
39+
}
40+
41+
const started = !!run.startedAt
42+
const ended = !!run.endedAt
43+
44+
if (!started && !ended) {
45+
return {
46+
name: 'circleDashed',
47+
color: 'foregroundMuted',
48+
className: 'stroke-[2.25]',
49+
}
50+
}
51+
52+
if (started && !ended) {
53+
return { name: 'loader', color: 'foregroundMuted', spin: true }
54+
}
55+
56+
const annotations = run.annotations ?? []
57+
58+
if (annotations.length === 0) {
59+
return { name: 'circleDashed', color: 'foregroundMuted' }
60+
}
61+
62+
const uiAnnotations = annotations.filter((annotation) => {
63+
const evaluation = annotation.evaluation
64+
const supportManual =
65+
getEvaluationMetricSpecification(evaluation).supportsManualEvaluation
66+
67+
if (!supportManual) return false
68+
69+
const config = evaluation.configuration as EvaluationConfiguration<
70+
EvaluationType.Human,
71+
HumanEvaluationMetric
72+
>
73+
return config.enableControls === true
74+
})
75+
76+
const uiAnnotation = uiAnnotations[0]
77+
78+
if (!uiAnnotation) return { name: 'circleDashed', color: 'success' }
79+
80+
const result = uiAnnotation.result
81+
return {
82+
name: result.hasPassed ? 'thumbsUp' : 'thumbsDown',
83+
color: result.hasPassed ? 'success' : 'destructive',
84+
}
85+
}, [run])
3086
return (
3187
<Tooltip
3288
asChild
@@ -48,34 +104,13 @@ export const RunsListItem = memo(
48104
}}
49105
>
50106
<div className='min-w-0 min-h-8 flex items-center justify-start gap-2.5 truncate'>
51-
{run.endedAt ? (
52-
<Icon
53-
name={
54-
run.log?.error.code
55-
? 'circleX'
56-
: run.annotations?.length
57-
? 'filledBadgeCheck'
58-
: 'circleCheck'
59-
}
60-
size='normal'
61-
color={run.log?.error.code ? 'destructive' : 'success'}
62-
className='flex-shrink-0'
63-
/>
64-
) : run.startedAt ? (
65-
<Icon
66-
name='loader'
67-
size='normal'
68-
color='foregroundMuted'
69-
className='flex-shrink-0 animate-spin'
70-
/>
71-
) : (
72-
<Icon
73-
name='circleDashed'
74-
size='normal'
75-
color='foregroundMuted'
76-
className='flex-shrink-0 stroke-[2.25]'
77-
/>
78-
)}
107+
<Icon
108+
size='normal'
109+
name={iconProps.name}
110+
color={iconProps.color}
111+
spin={iconProps.spin}
112+
className={cn('flex-shrink-0', iconProps.className)}
113+
/>
79114
<Text.H5
80115
color={run.log?.error.code ? 'destructive' : 'foreground'}
81116
animate={!run.endedAt}

apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/runs/_components/RunsList/index.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
'use client'
2-
31
import { RealtimeToggle } from '$/components/RealtimeToggle'
42
import { LogicTablePaginationFooter } from '$/components/TablePaginationFooter/LogicTablePaginationFooter'
53
import { useActiveRuns } from '$/stores/runs/activeRuns'

packages/core/src/events/events.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,10 +451,12 @@ export type EvaluationV2AnnotatedEvent = LatitudeEventGeneric<
451451
'evaluationV2Annotated',
452452
{
453453
workspaceId: number
454+
isNew: boolean
454455
evaluation: EvaluationV2
455456
result: EvaluationResultV2
456457
commit: Commit
457458
providerLog: ProviderLogDto
459+
userEmail?: string | null
458460
}
459461
>
460462

packages/core/src/lib/analytics/AnalyticsClient.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,9 @@ export class AnalyticsClient {
7575
// TODO: remove, it's very expensive to have a read operation on each analytics event
7676
const repo = new WorkspacesRepository(user.id)
7777
const result = await repo.find(this.workspaceId)
78+
7879
if (result.error) return undefined
80+
7981
const workspace = result.value
8082

8183
// Filtering out some expensive workspaces that are skewing our analytics...

packages/core/src/services/documents/tools/resolve/clientTools.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,4 +359,3 @@ describe('resolveClientToolDefinition', () => {
359359
})
360360
})
361361
})
362-

packages/core/src/services/evaluationsV2/annotate.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
} from '../../repositories'
2121
import { type Commit } from '../../schema/models/types/Commit'
2222
import { type Workspace } from '../../schema/models/types/Workspace'
23+
import { type User } from '../../schema/models/types/User'
2324
import { ProviderLogDto } from '../../schema/types'
2425
import { extractActualOutput } from './outputs/extract'
2526
import { createEvaluationResultV2 } from './results/create'
@@ -37,9 +38,11 @@ export async function annotateEvaluationV2<
3738
evaluation,
3839
resultScore,
3940
resultMetadata,
41+
currentUser,
4042
}: {
4143
workspace: Workspace
4244
commit: Commit
45+
currentUser?: User
4346
providerLog: ProviderLogDto
4447
evaluation: EvaluationV2<T, M>
4548
resultScore: number
@@ -161,11 +164,14 @@ export async function annotateEvaluationV2<
161164

162165
// TODO: We are stepping out of the db instance. This service should accept an instance of Transaction instead.
163166
const transaction = new Transaction()
167+
let alreadyExisted = false
164168
return await transaction.call(
165169
async () => {
166170
let result
167171

168-
if (existingResult.ok) {
172+
alreadyExisted = !!existingResult.ok
173+
174+
if (alreadyExisted) {
169175
const { result: updatedResult } = await updateEvaluationResultV2(
170176
{
171177
workspace,
@@ -197,6 +203,8 @@ export async function annotateEvaluationV2<
197203
publisher.publishLater({
198204
type: 'evaluationV2Annotated',
199205
data: {
206+
isNew: !alreadyExisted,
207+
userEmail: currentUser?.email || null,
200208
workspaceId: workspace.id,
201209
evaluation: evaluation,
202210
result: result,

0 commit comments

Comments
 (0)