-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Gerard Clos <[email protected]>
- Loading branch information
Showing
31 changed files
with
2,402 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
'use server' | ||
|
||
import { createEvaluation } from '@latitude-data/core/services/evaluations/create' | ||
import { z } from 'zod' | ||
|
||
import { authProcedure } from '../procedures' | ||
|
||
export const createEvaluationAction = authProcedure | ||
.createServerAction() | ||
.input( | ||
z.object({ | ||
name: z.string(), | ||
description: z.string(), | ||
prompt: z.string().optional(), | ||
}), | ||
{ type: 'json' }, | ||
) | ||
.handler(async ({ input, ctx }) => { | ||
const result = await createEvaluation({ | ||
workspace: ctx.workspace, | ||
name: input.name, | ||
description: input.description, | ||
prompt: input.prompt ?? '', | ||
}) | ||
|
||
return result.unwrap() | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
'use server' | ||
|
||
import { EvaluationsRepository } from '@latitude-data/core/repositories' | ||
|
||
import { authProcedure } from '../procedures' | ||
|
||
export const fetchEvaluationsAction = authProcedure | ||
.createServerAction() | ||
.handler(async ({ ctx }) => { | ||
const evaluationsScope = new EvaluationsRepository(ctx.workspace.id) | ||
|
||
return await evaluationsScope.findAll().then((r) => r.unwrap()) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
apps/web/src/app/(private)/evaluations/_components/ActiveEvaluations/Empty/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { Button, Text } from '@latitude-data/web-ui' | ||
|
||
export default function EmptyActiveEvaluations({ | ||
onCreateEvaluation, | ||
}: { | ||
onCreateEvaluation: () => void | ||
}) { | ||
return ( | ||
<div className='w-full min-h-[400px] bg-secondary flex flex-col justify-center items-center p-4 gap-6 rounded-2xl'> | ||
<div className='w-[400px] text-center'> | ||
<Text.H5 color='foregroundMuted'> | ||
There are no evaluations yet. Create one to start reviewing your | ||
prompts. | ||
</Text.H5> | ||
</div> | ||
<Button fancy onClick={onCreateEvaluation}> | ||
Create your first evaluation | ||
</Button> | ||
</div> | ||
) | ||
} |
59 changes: 59 additions & 0 deletions
59
apps/web/src/app/(private)/evaluations/_components/ActiveEvaluations/Table/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { Evaluation } from '@latitude-data/core/browser' | ||
import { | ||
Table, | ||
TableBody, | ||
TableCell, | ||
TableHead, | ||
TableHeader, | ||
TableRow, | ||
Text, | ||
} from '@latitude-data/web-ui' | ||
|
||
export const ActiveEvaluationsTableRow = ({ | ||
evaluation, | ||
onSelect, | ||
}: { | ||
evaluation: Evaluation | ||
onSelect: () => void | ||
}) => { | ||
return ( | ||
<TableRow | ||
key={evaluation.id} | ||
className='cursor-pointer border-b-[0.5px] h-12 max-h-12 border-border' | ||
onClick={onSelect} | ||
> | ||
<TableCell> | ||
<Text.H4 noWrap>{evaluation.name}</Text.H4> | ||
</TableCell> | ||
<TableCell> | ||
<Text.H4>{evaluation.description}</Text.H4> | ||
</TableCell> | ||
</TableRow> | ||
) | ||
} | ||
|
||
export default function ActiveEvaluationsTable({ | ||
evaluations: evaluations, | ||
}: { | ||
evaluations: Evaluation[] | ||
}) { | ||
return ( | ||
<Table className='table-auto'> | ||
<TableHeader className='sticky top-0 z-10'> | ||
<TableRow> | ||
<TableHead>Name</TableHead> | ||
<TableHead>Description</TableHead> | ||
</TableRow> | ||
</TableHeader> | ||
<TableBody className='max-h-full overflow-y-auto'> | ||
{evaluations.map((template) => ( | ||
<ActiveEvaluationsTableRow | ||
key={template.id} | ||
evaluation={template} | ||
onSelect={() => {}} | ||
/> | ||
))} | ||
</TableBody> | ||
</Table> | ||
) | ||
} |
29 changes: 29 additions & 0 deletions
29
apps/web/src/app/(private)/evaluations/_components/ActiveEvaluations/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { Button, Text } from '@latitude-data/web-ui' | ||
import useEvaluations from '$/stores/evaluationsStore' | ||
|
||
import EmptyActiveEvaluations from './Empty' | ||
import ActiveEvaluationsTable from './Table' | ||
|
||
export default function ActiveEvaluations({ | ||
onCreateEvaluation, | ||
}: { | ||
onCreateEvaluation: () => void | ||
}) { | ||
const { data: evaluations } = useEvaluations() | ||
|
||
return ( | ||
<div className='w-full flex flex-col gap-4'> | ||
<div className='w-full flex flex-row justify-between items-center'> | ||
<Text.H4M>Your evaluations</Text.H4M> | ||
<Button fancy variant='outline' onClick={onCreateEvaluation}> | ||
Add evaluation | ||
</Button> | ||
</div> | ||
{evaluations?.length ? ( | ||
<ActiveEvaluationsTable evaluations={evaluations} /> | ||
) : ( | ||
<EmptyActiveEvaluations onCreateEvaluation={onCreateEvaluation} /> | ||
)} | ||
</div> | ||
) | ||
} |
108 changes: 108 additions & 0 deletions
108
apps/web/src/app/(private)/evaluations/_components/CreateEvaluationModal/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import { useCallback, useEffect, useMemo, useState } from 'react' | ||
|
||
import { | ||
ConfirmModal, | ||
Input, | ||
ReactStateDispatch, | ||
Text, | ||
TextArea, | ||
} from '@latitude-data/web-ui' | ||
import { ROUTES } from '$/services/routes' | ||
import useEvaluations from '$/stores/evaluationsStore' | ||
import { useRouter } from 'next/navigation' | ||
|
||
export type CreateEvaluationData = { | ||
title: string | ||
description: string | ||
prompt: string | ||
} | ||
|
||
export default function CreateEvaluationModal({ | ||
data: initialData, | ||
onClose, | ||
}: { | ||
data?: CreateEvaluationData | ||
onClose: ReactStateDispatch<number | null> | ||
}) { | ||
const [title, setTitle] = useState(initialData?.title ?? '') | ||
const [description, setDescription] = useState(initialData?.description ?? '') | ||
const [prompt, setPrompt] = useState(initialData?.prompt ?? '') | ||
|
||
useEffect(() => { | ||
if (!initialData) return | ||
setTitle(initialData?.title ?? '') | ||
setDescription(initialData?.description ?? '') | ||
setPrompt(initialData?.prompt ?? '') | ||
}, [initialData]) | ||
|
||
const { | ||
data: existingEvaluations, | ||
isLoading, | ||
createEvaluation, | ||
isCreating, | ||
} = useEvaluations({ | ||
onSuccessCreate: (_newEvaluation) => { | ||
router.push(ROUTES.evaluations.root) | ||
onClose(null) | ||
}, | ||
}) | ||
const router = useRouter() | ||
|
||
const onConfirm = useCallback(() => { | ||
createEvaluation({ | ||
name: title, | ||
description, | ||
prompt, | ||
}) | ||
onClose(null) | ||
}, [createEvaluation, onClose, title, description, prompt]) | ||
|
||
const titleError = useMemo<string | undefined>(() => { | ||
if (!title) return 'Please enter a name for your evaluation.' | ||
if (existingEvaluations?.find((e) => e.name === title)) | ||
return 'There is already an evaluation with this name. Please choose a different name.' | ||
return undefined | ||
}, [existingEvaluations, title]) | ||
|
||
return ( | ||
<ConfirmModal | ||
open={!!initialData} | ||
title='Create New Evaluation' | ||
description='Evaluations allow you to analyze logs and assign them metrics such as scores, categories, or boolean values.' | ||
onOpenChange={() => onClose(null)} | ||
onConfirm={onConfirm} | ||
confirm={{ | ||
label: 'Create evaluation', | ||
description: | ||
prompt && | ||
'A prompt is included with this template. You can edit it once you create the evaluation.', | ||
disabled: isLoading || isCreating || !!titleError, | ||
isConfirming: isCreating, | ||
}} | ||
> | ||
<div className='w-full flex flex-col gap-4'> | ||
<div className='w-full flex flex-col gap-4'> | ||
<Text.H5M>Name</Text.H5M> | ||
<Input | ||
value={title} | ||
errors={titleError ? [titleError] : undefined} | ||
onChange={(e) => setTitle(e.target.value)} | ||
placeholder='Enter title' | ||
className='w-full' | ||
/> | ||
</div> | ||
<div className='w-full flex flex-col gap-4'> | ||
<Text.H5M>Description</Text.H5M> | ||
<TextArea | ||
value={description} | ||
minRows={4} | ||
maxRows={6} | ||
onChange={(e) => setDescription(e.target.value)} | ||
placeholder='Describe what is the purpose of this evaluation' | ||
className='w-full' | ||
/> | ||
</div> | ||
</div> | ||
</ConfirmModal> | ||
) | ||
} |
50 changes: 50 additions & 0 deletions
50
apps/web/src/app/(private)/evaluations/_components/Evaluations.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
'use client' | ||
|
||
import { useState } from 'react' | ||
|
||
import { EvaluationTemplateWithCategory } from '@latitude-data/core/browser' | ||
|
||
import ActiveEvaluations from './ActiveEvaluations' | ||
import CreateEvaluationModal, { | ||
CreateEvaluationData, | ||
} from './CreateEvaluationModal' | ||
import EvaluationTemplates from './TemplateEvaluations' | ||
|
||
export default function Evaluations({ | ||
evaluationTemplates, | ||
}: { | ||
evaluationTemplates: EvaluationTemplateWithCategory[] | ||
}) { | ||
const [newEvaluationData, setNewEvaluationData] = | ||
useState<CreateEvaluationData>() | ||
|
||
return ( | ||
<div className='w-full flex flex-col items-center'> | ||
<div className='w-full max-w-screen-xl py-6 px-4 flex flex-col gap-10'> | ||
<ActiveEvaluations | ||
onCreateEvaluation={() => | ||
setNewEvaluationData({ | ||
title: 'New Evaluation', | ||
description: '', | ||
prompt: '', | ||
}) | ||
} | ||
/> | ||
<EvaluationTemplates | ||
evaluationTemplates={evaluationTemplates} | ||
onSelectTemplate={(template) => | ||
setNewEvaluationData({ | ||
title: template.name, | ||
description: template.description, | ||
prompt: template.prompt, | ||
}) | ||
} | ||
/> | ||
<CreateEvaluationModal | ||
data={newEvaluationData} | ||
onClose={() => setNewEvaluationData(undefined)} | ||
/> | ||
</div> | ||
</div> | ||
) | ||
} |
Oops, something went wrong.