Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Raven Webhooks and Simple Scheduled Messages #817

Merged
merged 19 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions raven-app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@ const router = createBrowserRouter(
<Route path="saved-messages" lazy={() => import('./components/feature/saved-messages/SavedMessages')} />
<Route path=":channelID" lazy={() => import('@/pages/ChatSpace')} />
</Route>
{/* <Route path='settings' lazy={() => import('./pages/settings/Settings')}>
<Route path='settings' lazy={() => import('./pages/settings/Settings')}>
<Route path='integrations'>
<Route path='webhooks' lazy={() => import('./pages/settings/Webhooks/WebhookList')} />
<Route path='webhooks/create' lazy={() => import('./pages/settings/Webhooks/CreateWebhook')} />
<Route path='webhooks/:ID' lazy={() => import('./pages/settings/Webhooks/ViewWebhook')} />
<Route path='scheduled-messages' element={<TemporalEvents />} />
<Route path='scheduled-messages/create' element={<CreateSchedulerEvent />} />
<Route path='scheduled-messages/:ID' element={<ViewSchedulerEvent />} />
<Route path='scheduled-messages' lazy={() => import('./pages/settings/ServerScripts/SchedulerEvents/SchedulerEvents')} />
<Route path='scheduled-messages/create' lazy={() => import('./pages/settings/ServerScripts/SchedulerEvents/CreateSchedulerEvent')} />
<Route path='scheduled-messages/:ID' lazy={() => import('./pages/settings/ServerScripts/SchedulerEvents/ViewSchedulerEvent')} />
</Route>
</Route> */}
</Route>
</Route>
</Route>
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,14 @@
import { Flex, Text } from "@radix-ui/themes"
import { BiChevronLeft } from "react-icons/bi"
import { Button } from "@radix-ui/themes"
import { FiArrowLeft } from "react-icons/fi"
import { useNavigate } from "react-router-dom"

export const BackToList = () => {
export const BackToList = ({ path, label }: { path: string, label: string }) => {

const navigate = useNavigate()

return (
<header>
<Flex
align='center'
gap={'1'}
className="cursor-pointer"
onClick={() => navigate('/settings/integrations/webhooks')}
>
<BiChevronLeft size={'24px'} color="gray" />
<Text as='span' size='2' color='gray' weight={'medium'}>Back to the list</Text>
</Flex>
</header>
<Button type="button" variant="ghost" color="gray" onClick={() => navigate(path)}>
<FiArrowLeft /> {label}
</Button>
)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ErrorBanner } from "@/components/layout/AlertBanner"
import { AlertDialog, Badge, Button, DropdownMenu, Flex, IconButton, Separator, Text } from "@radix-ui/themes"
import { AlertDialog, Badge, Box, Button, DropdownMenu, Flex, IconButton, Section, Text } from "@radix-ui/themes"
import { FrappeDoc, useFrappeUpdateDoc } from "frappe-react-sdk"
import { FieldValues, FormProvider, useForm } from "react-hook-form"
import { KeyedMutator } from 'swr'
Expand Down Expand Up @@ -56,24 +56,24 @@ export const ViewWebhookPage = ({ data, mutate }: { data: FrappeDoc<RavenWebhook
}

return (
<Flex direction='column' gap='4' py='4' width={'100%'} height={'100%'} style={{
alignItems: 'center',
justifyContent: 'start',
minHeight: '100vh'
}}>
<Flex direction='column' gap='4' pt={'4'} width='100%' style={{
maxWidth: '700px'
}} >
<BackToList />
<Flex direction='column' gap='4' width='100%' px={'2'}>
<Flex direction={'row'} gap={'2'} justify={'between'} align={'center'}>
<Flex direction={'row'} gap={'2'} align={'center'}>
<Text size='6' weight='bold'>{data?.name}</Text>
<Badge color={data.enabled ? 'green' : 'red'}>{data.enabled ? 'Enabled' : 'Disabled'}</Badge>
</Flex>
<Box className="lg:mx-[10rem] md:mx-[5rem] mt-9 h-full">
<BackToList label="Webhooks" path="/settings/integrations/webhooks" />
<Flex direction='column' width='100%' mt={'6'}>
<Flex direction={'row'} gap={'3'} justify={'between'} align={'center'}>
<Flex direction={'row'} gap={'2'} align={'center'}>
<Text size='6' weight='bold'>{data?.name}</Text>
<Badge color={data.enabled ? 'green' : 'red'}>{data.enabled ? 'Enabled' : 'Disabled'}</Badge>
</Flex>
<Flex gap={'3'}>
<Button onClick={methods.handleSubmit(onSubmit)} disabled={loading || !isDirty} variant='solid' style={{
alignSelf: 'flex-end',
marginBottom: '1rem'
}}>
Save
</Button>
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<IconButton aria-label='Options' color='gray' variant='ghost' style={{
<IconButton aria-label='Options' variant="soft" color="gray" style={{
// @ts-ignore
'--icon-button-ghost-padding': '0',
height: 'var(--base-button-height)',
Expand All @@ -84,24 +84,20 @@ export const ViewWebhookPage = ({ data, mutate }: { data: FrappeDoc<RavenWebhook
</DropdownMenu.Trigger>
<DropdownMenu.Content variant='soft'>
<DropdownMenu.Item color='gray' onClick={() => setOpen(true)} className="cursor-pointer">
{data.enabled ? 'Disable' : 'Enable'} Webhook
{data.enabled ? 'Disable' : 'Enable'}
</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Root>
</Flex>
<Separator size='4' className={`bg-gray-4 dark:bg-gray-6`} />
</Flex>
<Section size={'2'}>
<ErrorBanner error={error} />
<FormProvider {...methods}>
<form onSubmit={methods.handleSubmit(onSubmit)}>
<WebhookForm isEdit={true} />
</form>
</FormProvider>
<Button onClick={methods.handleSubmit(onSubmit)} disabled={loading || !isDirty} variant='solid' style={{
alignSelf: 'flex-end'
}}>
Save Webhook
</Button>
</Flex>
</Section>
</Flex>
<AlertDialog.Root open={open} onOpenChange={setOpen}>
<AlertDialog.Content className={DIALOG_CONTENT_CLASS}>
Expand All @@ -119,14 +115,14 @@ export const ViewWebhookPage = ({ data, mutate }: { data: FrappeDoc<RavenWebhook
</Button>
</AlertDialog.Cancel>
<AlertDialog.Action>
<Button variant="solid" color="green" onClick={onUpdateEnabled} disabled={loading}>
<Button variant="solid" color={data.enabled ? "red" : "green"} onClick={onUpdateEnabled} disabled={loading}>
{loading && <Loader />}
{loading ? "Updating" : data.enabled ? "Disable" : "Enable"}
</Button>
</AlertDialog.Action>
</Flex>
</AlertDialog.Content>
</AlertDialog.Root>
</Flex >
</Box >
)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useContext } from 'react';
import React, { useContext, useMemo } from 'react';
import { Controller, useFormContext } from 'react-hook-form';
import { Box, Checkbox, Flex, TextFieldInput, Select, TextArea, Heading, Text, Code, } from '@radix-ui/themes';
import { ErrorText, HelperText, Label } from '@/components/common/Form';
Expand Down Expand Up @@ -26,6 +26,15 @@ export const WebhookForm = ({ isEdit = false }: { isEdit?: boolean }) => {

const { channels } = useContext(ChannelListContext) as ChannelListContextType

const webhookTrigger = watch('webhook_trigger')

const triggerOn = useMemo(() => {
if (webhookTrigger) {
return TriggerEvents?.find((event) => event.label === webhookTrigger)?.trigger_on
}
return []
}, [webhookTrigger])

return (
<Flex direction='column' gap='4' >
{isEdit === false ? <Box>
Expand Down Expand Up @@ -71,7 +80,6 @@ export const WebhookForm = ({ isEdit = false }: { isEdit?: boolean }) => {
</Flex>
)}
/>

{errors?.enable_security && <ErrorText>{errors.enable_security.message}</ErrorText>}
</Box>
{security ? <Box>
Expand Down Expand Up @@ -141,11 +149,10 @@ export const WebhookForm = ({ isEdit = false }: { isEdit?: boolean }) => {
</Flex>
)}
/>

{errors?.enable_security && <ErrorText>{errors.enable_security.message}</ErrorText>}
</Box>
{needCondition && <Box>
<Flex direction={'column'} gap='1'>
{needCondition ?
<Flex direction={'column'}>
<Label htmlFor='condition'>Trigger On</Label>
<Controller
control={control}
Expand All @@ -167,35 +174,39 @@ export const WebhookForm = ({ isEdit = false }: { isEdit?: boolean }) => {
<Select.Content>
<Select.Group>
<Select.Label>Trigger On</Select.Label>
<Select.Item value='Channel'>Channel</Select.Item>
<Select.Item value='User'>User</Select.Item>
<Select.Item value='Channel Type' >Channel Type</Select.Item>
{triggerOn?.map((event, index) => (
<Select.Item key={index} value={event}>{event}</Select.Item>
))}
<Select.Item value='Custom'>Custom</Select.Item>
</Select.Group>
</Select.Content>
</Select.Root>
)}
/>
<HelperText>Field on which the condition will be applied</HelperText>
</Flex>
</Box>}
<HelperText style={{
paddingTop: '0.25rem'
}}>Field on which the condition will be applied</HelperText>
</Flex> : null}
{conditionOn === 'Custom' ? <Box>
<Flex direction={'row'} gap={'4'} align={'center'}>
<Flex direction={'column'} gap='1' style={{
<Flex direction={'row'} gap={'4'} align={'end'}>
<Flex direction={'column'} style={{
width: '60%'
}} >
<Label htmlFor='condition'>Condition</Label>
<TextArea {...register('condition')} rows={4} />
<HelperText>The webhook will be triggered if this expression is true</HelperText>
<HelperText style={{
paddingTop: '0.25rem'
}}>The webhook will be triggered if this expression is true</HelperText>
</Flex>
<Code color='gray' size='2' className='p-2'>
<Text weight='bold' size='2' className='block pb-1'>Try something like:</Text>
<Code color='gray' size='2' className='mb-5 p-1.5'>
<Text weight='bold' size='2' className='block'>Try something like:</Text>
doc.channel_id == 'general'<br />
doc.is_direct_message == 1
doc.is_direct_message == 1 <br />
doc.owner == 'Administrator'
</Code>
</Flex>
</Box> : conditionOn === 'Channel' ? <Box>
<Flex direction={'column'} gap='1'>
<Flex direction={'column'}>
<Label htmlFor='channel_id'>Channel</Label>
<Controller
control={control}
Expand All @@ -218,10 +229,11 @@ export const WebhookForm = ({ isEdit = false }: { isEdit?: boolean }) => {
</Select.Root>
)}
/>
<HelperText>Webhook will trigger only if the message is sent on this channel.</HelperText>
<HelperText style={{
paddingTop: '0.25rem'
}}>Webhook will trigger only if the message is sent on this channel.</HelperText>
</Flex>
</Box> : conditionOn === 'User' ? <Box>
<Flex direction={'column'} gap='1' >
</Box> : conditionOn === 'User' ? <Flex direction={'column'}>
<Label htmlFor='user_id'>User</Label>
<Controller
control={control}
Expand All @@ -244,10 +256,10 @@ export const WebhookForm = ({ isEdit = false }: { isEdit?: boolean }) => {
</Select.Root>
)}
/>
<HelperText>Condition for webhook - user</HelperText>
</Flex>
</Box> : conditionOn === 'Channel Type' ? <Box>
<Flex direction={'column'} gap='1'>
<HelperText style={{
paddingTop: '0.25rem'
}}>Condition for webhook - user</HelperText>
</Flex> : conditionOn === 'Channel Type' ? <Flex direction={'column'}>
<Label htmlFor='channel_type'>Channel Type</Label>
<Controller
control={control}
Expand All @@ -268,11 +280,12 @@ export const WebhookForm = ({ isEdit = false }: { isEdit?: boolean }) => {
</Select.Root>
)}
/>
<HelperText>The webhook will trigger if the channel type is equal to the value selected here.</HelperText>
</Flex>
</Box> : null
<HelperText style={{
paddingTop: '0.25rem'
}}>The webhook will trigger if the channel type is equal to the value selected here.</HelperText>
</Flex> : null
}
<Flex direction={'column'} gap={'4'} py={'2'} >
<Flex direction={'column'} gap={'4'} >
<WebhookData />
<WebhookHeaders />
</Flex>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { ErrorBanner } from "@/components/layout/AlertBanner"
import { RavenWebhook } from "@/types/RavenIntegrations/RavenWebhook"
import { DateMonthYear } from "@/utils/dateConversions"
import { DIALOG_CONTENT_CLASS } from "@/utils/layout/dialog"
import { Flex, Badge, IconButton, AlertDialog, Text, Button } from "@radix-ui/themes"
import { useFrappeDeleteDoc } from "frappe-react-sdk"
import { Flex, Badge, IconButton, AlertDialog, Text } from "@radix-ui/themes"
import { useState } from "react"
import { BiEdit, BiTrash } from "react-icons/bi"
import { useNavigate } from "react-router-dom"
import { AlertContent } from "../../settings/common/DeleteAlert"
import { toast } from "sonner"

export const WebhookItem = ({ webhook, mutate }: { webhook: RavenWebhook, mutate: () => void }) => {
Expand All @@ -25,7 +25,7 @@ export const WebhookItem = ({ webhook, mutate }: { webhook: RavenWebhook, mutate
<Flex direction='column' gap='1'>
<Flex direction={'row'} gap={'2'}>
<Text size={'2'} weight={'bold'}>{webhook.name}</Text>
<Badge variant='outline' color={webhook.enabled ? 'green' : 'red'}>{webhook.enabled ? 'Enabled' : 'Disabled'}</Badge>
<Badge color={webhook.enabled ? 'green' : 'red'}>{webhook.enabled ? 'Enabled' : 'Disabled'}</Badge>
</Flex>
<Text size='1' style={{
fontStyle: 'italic',
Expand Down Expand Up @@ -65,15 +65,13 @@ export const WebhookItem = ({ webhook, mutate }: { webhook: RavenWebhook, mutate
</IconButton>
</AlertDialog.Trigger>
<AlertDialog.Content className={DIALOG_CONTENT_CLASS}>
<DeleteWebhookAlertContent webhhookID={webhook.name} onClose={onClose} mutate={mutate} />
<AlertContent doctype="Raven Webhook" docname={webhook.name} onClose={onClose} onUpdate={mutate} />
</AlertDialog.Content>
</AlertDialog.Root>
</Flex>

</Flex>
</Flex>
)
}

const DeleteWebhookAlertContent = ({ webhhookID, onClose, mutate }: { webhhookID: string, onClose: () => void, mutate: () => void }) => {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ export const WebhookData = () => {
<Flex direction='column' gap='2' width='100%'>
<Flex direction='row' align='end' justify={'between'}>
<Flex direction={'column'} gap='1'>
<Heading size='4'>Payload</Heading>
<HelperText>Select the fields you want to send in the webhook request.</HelperText>
<Heading size='4'>Webhook Data</Heading>
<HelperText>Select the fields you want in webhook response.</HelperText>
</Flex>
<Flex direction={'row'} gap={'4'} align={'center'}>
<Dialog.Root open={previewOpen} onOpenChange={setPreviewOpen}>
Expand Down Expand Up @@ -171,11 +171,13 @@ export const FieldInfoModal = ({ fieldIndex, triggerEvent, onClose }: { fieldInd
<Flex direction={'column'} gap={'4'} width={'100%'}>
<Dialog.Title>
<Flex direction='column' gap='1' width='100%'>
<Flex direction='row' align='end' gap={'2'} >
<Flex direction='row' align='center' gap={'2'} >
<Heading size='6'>
{fieldData?.label}
</Heading>
<Badge variant='outline' radius="large" color='gray'>{fieldData?.fieldtype}</Badge>
<Badge variant='outline' radius="large" color='gray' style={{
marginTop: '1rem',
}}>{fieldData?.fieldtype}</Badge>
</Flex>
<HelperText>{fieldData?.description}</HelperText>
</Flex>
Expand Down
Loading
Loading