Skip to content

Commit

Permalink
feat(ui): introduce app templates
Browse files Browse the repository at this point in the history
  • Loading branch information
shhdgit committed Mar 27, 2024
1 parent fa479c4 commit 9c07d10
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 132 deletions.
164 changes: 164 additions & 0 deletions ui/src/modules/app_list/ModifyAppModel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import { Button, Chip, Code, Divider, Group, Modal, Stack, Text, TextInput, Title } from '@mantine/core'
import { getHotkeyHandler } from '@mantine/hooks'
import {
getListAppApplicationsGetQueryKey,
useCreateAppApplicationsPost,
useUpdateAppMetaApplicationsApplicationIdPut
} from '@api/linguflow'
import { ApplicationInfo } from '@api/linguflow.schemas'
import { useEffect, useState } from 'react'
import { useQueryClient } from 'react-query'
import { useNavigate } from 'react-router-dom'

export interface ModifyAppModelProps {
opened: boolean
onClose: () => void
app?: ApplicationInfo
}

export const ModifyAppModel: React.FC<ModifyAppModelProps> = ({ opened, onClose, app }) => {
const queryClient = useQueryClient()
const navigate = useNavigate()
const [name, setName] = useState(app?.name || '')
const [langfusePK, setLangfusePK] = useState(app?.langfuse_public_key || '')
const [langfuseSK, setLangfuseSK] = useState(app?.langfuse_secret_key || '')
const [template, setTemplate] = useState<string[]>([])
const { mutateAsync: createApp, isLoading: isCreating } = useCreateAppApplicationsPost({
mutation: {
onSuccess: async (data) => {
await queryClient.fetchQuery({ queryKey: getListAppApplicationsGetQueryKey() })
onClose()

const redirectTo = template.length ? `/app/${data.id}/ver?template=${template[0]}` : `/app/${data.id}`
navigate(redirectTo)
}
}
})
const { mutateAsync: updateApp, isLoading: isUpdating } = useUpdateAppMetaApplicationsApplicationIdPut({
mutation: {
onSuccess: async () => {
await queryClient.fetchQuery({ queryKey: getListAppApplicationsGetQueryKey() })
onClose()
}
}
})
const handleConfirm = async () => {
if (isLoading || !opened || !name) {
return
}

if (!app) {
await createApp({ data: { name, langfusePublicKey: langfusePK, langfuseSecretKey: langfuseSK } })
} else {
await updateApp({
applicationId: app.id,
data: { name, langfusePublicKey: langfusePK, langfuseSecretKey: langfuseSK }
})
}
}

const isLoading = isCreating || isUpdating

useEffect(() => {
if (!opened) {
return
}
setName(app?.name || '')
setLangfusePK(app?.langfuse_public_key || '')
setLangfuseSK(app?.langfuse_secret_key || '')
setTemplate([])
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [opened])

return (
<Modal
closeOnClickOutside={!isLoading}
closeOnEscape={!isLoading}
withCloseButton={!isLoading}
opened={opened}
onClose={onClose}
title={
<Text fw="bold">
{!app ? (
'New Application'
) : (
<>
Edit <Code fz="md">{app.name}</Code>
</>
)}
</Text>
}
centered
trapFocus={false}
>
<Stack>
<TextInput
required
autoFocus
label="Name"
placeholder="Please input the application name"
value={name}
disabled={isLoading}
onChange={(event) => {
setName(event.currentTarget.value)
}}
onKeyDown={getHotkeyHandler([['Enter', handleConfirm]])}
/>

<TextInput
label="Langfuse Public Key"
placeholder="Please input the langfuse public key"
value={langfusePK}
disabled={isLoading}
onChange={(event) => {
setLangfusePK(event.currentTarget.value)
}}
/>

<TextInput
label="Langfuse Secret Key"
placeholder="Please input the langfuse secret key"
value={langfuseSK}
disabled={isLoading}
onChange={(event) => {
setLangfuseSK(event.currentTarget.value)
}}
onKeyDown={getHotkeyHandler([['Enter', handleConfirm]])}
/>

{!app && (
<>
<Divider />

<Title order={6}>Templates</Title>

<Chip.Group
multiple
value={template}
onChange={(ts) =>
setTemplate((oldTs) => {
return ts.filter((t) => !oldTs.includes(t))
})
}
>
<Group>
<Chip radius="xs" variant="outline" value="chatbot">
Chatbot
</Chip>
</Group>
</Chip.Group>
</>
)}
</Stack>

<Group mt="xl" justify="end">
<Button variant="default" onClick={onClose} disabled={isLoading}>
Cancel
</Button>
<Button color="dark" loading={isLoading} disabled={!name} onClick={handleConfirm}>
Confirm
</Button>
</Group>
</Modal>
)
}
136 changes: 5 additions & 131 deletions ui/src/modules/app_list/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,23 @@ import {
Title
} from '@mantine/core'
import { IconDots, IconPlus, IconSearch } from '@tabler/icons-react'
import { getHotkeyHandler, useClipboard, useDisclosure } from '@mantine/hooks'
import { useClipboard, useDisclosure } from '@mantine/hooks'
import {
getListAppApplicationsGetQueryKey,
useCreateAppApplicationsPost,
useDeleteAppApplicationsApplicationIdDelete,
useListAppApplicationsGet,
useUpdateAppMetaApplicationsApplicationIdPut
useListAppApplicationsGet
} from '@api/linguflow'
import { ApplicationInfo } from '@api/linguflow.schemas'
import { useEffect, useMemo, useState } from 'react'
import { useMemo, useState } from 'react'
import dayjs from 'dayjs'
import { useQueryClient } from 'react-query'
import { Link, useNavigate } from 'react-router-dom'
import { Link } from 'react-router-dom'
import { Card, LoadingCard } from '../../components/Card'
import { Pagination } from '../../components/Pagination'

import { NoResult } from '../../components/NoResult'
import classes from './index.module.css'
import { ModifyAppModel } from './ModifyAppModel'

const PAGE_SIZE = 12

Expand Down Expand Up @@ -90,131 +89,6 @@ export const AppList: React.FC = () => {
)
}

interface ModifyAppModelProps {
opened: boolean
onClose: () => void
app?: ApplicationInfo
}

const ModifyAppModel: React.FC<ModifyAppModelProps> = ({ opened, onClose, app }) => {
const queryClient = useQueryClient()
const navigate = useNavigate()
const [name, setName] = useState(app?.name || '')
const [langfusePK, setLangfusePK] = useState(app?.langfuse_public_key || '')
const [langfuseSK, setLangfuseSK] = useState(app?.langfuse_secret_key || '')
const { mutateAsync: createApp, isLoading: isCreating } = useCreateAppApplicationsPost({
mutation: {
onSuccess: async (data) => {
await queryClient.fetchQuery({ queryKey: getListAppApplicationsGetQueryKey() })
onClose()
navigate(`/app/${data.id}`)
}
}
})
const { mutateAsync: updateApp, isLoading: isUpdating } = useUpdateAppMetaApplicationsApplicationIdPut({
mutation: {
onSuccess: async () => {
await queryClient.fetchQuery({ queryKey: getListAppApplicationsGetQueryKey() })
onClose()
}
}
})
const handleConfirm = async () => {
if (isLoading || !opened || !name) {
return
}

if (!app) {
await createApp({ data: { name, langfusePublicKey: langfusePK, langfuseSecretKey: langfuseSK } })
} else {
await updateApp({
applicationId: app.id,
data: { name, langfusePublicKey: langfusePK, langfuseSecretKey: langfuseSK }
})
}
}

const isLoading = isCreating || isUpdating

useEffect(() => {
if (!opened) {
return
}
setName(app?.name || '')
setLangfusePK(app?.langfuse_public_key || '')
setLangfuseSK(app?.langfuse_secret_key || '')
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [opened])

return (
<Modal
closeOnClickOutside={!isLoading}
closeOnEscape={!isLoading}
withCloseButton={!isLoading}
opened={opened}
onClose={onClose}
title={
<Text fw="bold">
{!app ? (
'New Application'
) : (
<>
Edit <Code fz="md">{app.name}</Code>
</>
)}
</Text>
}
centered
trapFocus={false}
>
<Stack>
<TextInput
required
autoFocus
label="Name"
placeholder="Please input the application name"
value={name}
disabled={isLoading}
onChange={(event) => {
setName(event.currentTarget.value)
}}
onKeyDown={getHotkeyHandler([['Enter', handleConfirm]])}
/>

<TextInput
label="Langfuse Public Key"
placeholder="Please input the langfuse public key"
value={langfusePK}
disabled={isLoading}
onChange={(event) => {
setLangfusePK(event.currentTarget.value)
}}
/>

<TextInput
label="Langfuse Secret Key"
placeholder="Please input the langfuse secret key"
value={langfuseSK}
disabled={isLoading}
onChange={(event) => {
setLangfuseSK(event.currentTarget.value)
}}
onKeyDown={getHotkeyHandler([['Enter', handleConfirm]])}
/>
</Stack>

<Group mt="xl" justify="end">
<Button variant="default" onClick={onClose} disabled={isLoading}>
Cancel
</Button>
<Button color="dark" loading={isLoading} disabled={!name} onClick={handleConfirm}>
Confirm
</Button>
</Group>
</Modal>
)
}

const NewAppButton: React.FC<{ onClick: () => void }> = ({ onClick }) => {
return (
<Button
Expand Down
1 change: 0 additions & 1 deletion ui/src/modules/shared/PublishModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export interface PublishModalProps {
}

export const PublishModal: React.FC<PublishModalProps> = ({ opened, close, ver, beforePublish, onSuccess }) => {
console.log(ver)
const qc = useQueryClient()
const { mutateAsync: activeVersion, isLoading } =
useActiveAppVersionApplicationsApplicationIdVersionsVersionIdActivePut({
Expand Down

0 comments on commit 9c07d10

Please sign in to comment.