From 483b4497da9a326de6f8f14239dffaa733addad0 Mon Sep 17 00:00:00 2001 From: Nikhil Kothari Date: Wed, 16 Oct 2024 20:15:53 +0530 Subject: [PATCH 1/2] feat: dynamic message actions --- .flake8 | 1 + .github/helper/flake8.conf | 1 + frontend/src/App.tsx | 19 +- .../feature/CommandMenu/CommandMenu.tsx | 2 - .../feature/CommandMenu/SettingsList.tsx | 11 +- .../MessageActions/MessageActionSubMenu.tsx | 65 +++ .../MessageActions/MessageActions.tsx | 3 + .../MessageActionController.tsx | 30 ++ .../message-actions/MessageActionForm.tsx | 196 +++++++ .../message-actions/MessageActionModal.tsx | 318 ++++++++++++ .../MessageActionVariableBuilder.tsx | 487 ++++++++++++++++++ .../feature/settings/ai/bots/BotForm.tsx | 2 - .../functions/DoctypeVariableDialogForm.tsx | 4 +- .../feature/userSettings/SettingsSidebar.tsx | 1 + frontend/src/pages/MainPage.tsx | 2 + .../MessageActions/CreateMessageAction.tsx | 57 ++ .../MessageActions/MessageActionList.tsx | 71 +++ .../MessageActions/ViewMessageAction.tsx | 81 +++ .../RavenIntegrations/RavenMessageAction.ts | 32 ++ .../RavenMessageActionFields.ts | 29 ++ raven/api/message_actions.py | 69 +++ .../doctype/raven_message_action/__init__.py | 0 .../raven_message_action.js | 8 + .../raven_message_action.json | 124 +++++ .../raven_message_action.py | 62 +++ .../test_raven_message_action.py | 29 ++ .../raven_message_action_fields/__init__.py | 0 .../raven_message_action_fields.json | 93 ++++ .../raven_message_action_fields.py | 32 ++ 29 files changed, 1809 insertions(+), 20 deletions(-) create mode 100644 frontend/src/components/feature/chat/ChatMessage/MessageActions/MessageActionSubMenu.tsx create mode 100644 frontend/src/components/feature/message-actions/MessageActionController.tsx create mode 100644 frontend/src/components/feature/message-actions/MessageActionForm.tsx create mode 100644 frontend/src/components/feature/message-actions/MessageActionModal.tsx create mode 100644 frontend/src/components/feature/message-actions/MessageActionVariableBuilder.tsx create mode 100644 frontend/src/pages/settings/MessageActions/CreateMessageAction.tsx create mode 100644 frontend/src/pages/settings/MessageActions/MessageActionList.tsx create mode 100644 frontend/src/pages/settings/MessageActions/ViewMessageAction.tsx create mode 100644 frontend/src/types/RavenIntegrations/RavenMessageAction.ts create mode 100644 frontend/src/types/RavenIntegrations/RavenMessageActionFields.ts create mode 100644 raven/api/message_actions.py create mode 100644 raven/raven_integrations/doctype/raven_message_action/__init__.py create mode 100644 raven/raven_integrations/doctype/raven_message_action/raven_message_action.js create mode 100644 raven/raven_integrations/doctype/raven_message_action/raven_message_action.json create mode 100644 raven/raven_integrations/doctype/raven_message_action/raven_message_action.py create mode 100644 raven/raven_integrations/doctype/raven_message_action/test_raven_message_action.py create mode 100644 raven/raven_integrations/doctype/raven_message_action_fields/__init__.py create mode 100644 raven/raven_integrations/doctype/raven_message_action_fields/raven_message_action_fields.json create mode 100644 raven/raven_integrations/doctype/raven_message_action_fields/raven_message_action_fields.py diff --git a/.flake8 b/.flake8 index 4b852abd7..06fe235c0 100644 --- a/.flake8 +++ b/.flake8 @@ -25,6 +25,7 @@ ignore = W503, W504, F403, + F811, B007, B950, W191, diff --git a/.github/helper/flake8.conf b/.github/helper/flake8.conf index 8a97e17c9..e6f31158d 100644 --- a/.github/helper/flake8.conf +++ b/.github/helper/flake8.conf @@ -57,6 +57,7 @@ ignore = F401, F403, F405, + F811, W191, W291, W292, diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 696d9596f..627715b63 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -18,7 +18,8 @@ const NO_CACHE_KEYS = [ "frappe.desk.search.search_link", "frappe.model.workflow.get_transitions", "frappe.desk.reportview.get_count", - "frappe.core.doctype.server_script.server_script.enabled" + "frappe.core.doctype.server_script.server_script.enabled", + "raven.api.message_actions.get_action_defaults" ] @@ -80,21 +81,17 @@ const router = createBrowserRouter( import('./pages/settings/ServerScripts/SchedulerEvents/CreateSchedulerEvent')} /> import('./pages/settings/ServerScripts/SchedulerEvents/ViewSchedulerEvent')} /> + + + import('./pages/settings/MessageActions/MessageActionList')} /> + import('./pages/settings/MessageActions/CreateMessageAction')} /> + import('./pages/settings/MessageActions/ViewMessageAction')} /> + import('@/pages/ChatSpace')}> import('./components/feature/threads/ThreadDrawer/ThreadDrawer')} /> - {/* import('./pages/settings/Settings')}> - - import('./pages/settings/Webhooks/WebhookList')} /> - import('./pages/settings/Webhooks/CreateWebhook')} /> - import('./pages/settings/Webhooks/ViewWebhook')} /> - import('./pages/settings/ServerScripts/SchedulerEvents/SchedulerEvents')} /> - import('./pages/settings/ServerScripts/SchedulerEvents/CreateSchedulerEvent')} /> - import('./pages/settings/ServerScripts/SchedulerEvents/ViewSchedulerEvent')} /> - - */} import('./pages/NotFound')} /> diff --git a/frontend/src/components/feature/CommandMenu/CommandMenu.tsx b/frontend/src/components/feature/CommandMenu/CommandMenu.tsx index cb505be87..939198045 100644 --- a/frontend/src/components/feature/CommandMenu/CommandMenu.tsx +++ b/frontend/src/components/feature/CommandMenu/CommandMenu.tsx @@ -6,8 +6,6 @@ import './commandMenu.styles.css' import ChannelList from './ChannelList' import UserList from './UserList' import clsx from 'clsx' -import { BiCog, BiFile, BiMoon, BiSearch, BiSmile } from 'react-icons/bi' -import ArchivedChannelList from './ArchivedChannelList' import { atom, useAtom } from 'jotai' import { useIsDesktop } from '@/hooks/useMediaQuery' import { Drawer, DrawerContent } from '@/components/layout/Drawer' diff --git a/frontend/src/components/feature/CommandMenu/SettingsList.tsx b/frontend/src/components/feature/CommandMenu/SettingsList.tsx index adc0cb403..b39d3341e 100644 --- a/frontend/src/components/feature/CommandMenu/SettingsList.tsx +++ b/frontend/src/components/feature/CommandMenu/SettingsList.tsx @@ -1,6 +1,6 @@ import { Command } from 'cmdk' import { useSetAtom } from 'jotai' -import { BiBot, BiFile, BiGroup, BiMessageSquareDots, BiUserCircle } from 'react-icons/bi' +import { BiBoltCircle, BiBot, BiFile, BiGroup, BiMessageSquareDots, BiTime, BiUserCircle } from 'react-icons/bi' import { useNavigate } from 'react-router-dom' import { commandMenuOpenAtom } from './CommandMenu' import { PiOpenAiLogo } from 'react-icons/pi' @@ -47,12 +47,17 @@ const SettingsList = (props: Props) => { HR + + + Message Actions + + - + Scheduled Messages - + Webhooks diff --git a/frontend/src/components/feature/chat/ChatMessage/MessageActions/MessageActionSubMenu.tsx b/frontend/src/components/feature/chat/ChatMessage/MessageActions/MessageActionSubMenu.tsx new file mode 100644 index 000000000..25e3cef96 --- /dev/null +++ b/frontend/src/components/feature/chat/ChatMessage/MessageActions/MessageActionSubMenu.tsx @@ -0,0 +1,65 @@ +import { ContextMenu, Flex, Text } from '@radix-ui/themes' +import { BiBoltCircle } from 'react-icons/bi' +import { useFrappeGetDocList } from 'frappe-react-sdk' +import { RavenMessageAction } from '@/types/RavenIntegrations/RavenMessageAction' +import { useSetAtom } from 'jotai' +import { messageActionAtom } from '@/components/feature/message-actions/MessageActionController' + +type Props = { + messageID: string, +} + +const MessageActionSubMenu = (props: Props) => { + return + + + + Actions + + + + + {/* + + + Create Action + + */} + + +} + +export default MessageActionSubMenu + + +const MessageActionSubMenuContent = (props: Props) => { + + const { data } = useFrappeGetDocList("Raven Message Action", { + fields: ['name', 'action_name'], + filters: [ + ['enabled', '=', 1] + ], + orderBy: { + field: 'action', + order: 'asc' + } + }, undefined, { + revalidateOnFocus: false, + }) + + const setMessageAction = useSetAtom(messageActionAtom) + + return <> + {data && data.length > 0 ? data?.map((action) => { + return setMessageAction({ actionID: action.name, messageID: props.messageID })}> + + {action.action_name} + + + }) + + : + No Actions Available + } + +} \ No newline at end of file diff --git a/frontend/src/components/feature/chat/ChatMessage/MessageActions/MessageActions.tsx b/frontend/src/components/feature/chat/ChatMessage/MessageActions/MessageActions.tsx index 7a224638a..db1419c18 100644 --- a/frontend/src/components/feature/chat/ChatMessage/MessageActions/MessageActions.tsx +++ b/frontend/src/components/feature/chat/ChatMessage/MessageActions/MessageActions.tsx @@ -12,6 +12,7 @@ import { AiOutlineEdit } from 'react-icons/ai' import { LuForward, LuReply } from 'react-icons/lu' import { MdOutlineEmojiEmotions } from "react-icons/md"; import { CreateThreadContextItem } from './QuickActions/CreateThreadButton' +import MessageActionSubMenu from './MessageActionSubMenu' export interface MessageContextMenuProps { message?: Message | null, @@ -103,6 +104,8 @@ export const MessageContextMenu = ({ message, onDelete, onEdit, onReply, onForwa } + + {isOwner && {message.message_type === 'Text' && diff --git a/frontend/src/components/feature/message-actions/MessageActionController.tsx b/frontend/src/components/feature/message-actions/MessageActionController.tsx new file mode 100644 index 000000000..c79be5249 --- /dev/null +++ b/frontend/src/components/feature/message-actions/MessageActionController.tsx @@ -0,0 +1,30 @@ +import { atom, useAtom } from 'jotai' +import MessageActionModal from './MessageActionModal' + +type MessageActionAtomType = { + actionID: string, + messageID: string +} +export const messageActionAtom = atom({ + actionID: '', + messageID: '' +}) + +const MessageActionController = () => { + + const [messageAction, setMessageAction] = useAtom(messageActionAtom) + + const closeMessageAction = () => { + setMessageAction({ actionID: '', messageID: '' }) + } + + return ( + + ) +} + +export default MessageActionController \ No newline at end of file diff --git a/frontend/src/components/feature/message-actions/MessageActionForm.tsx b/frontend/src/components/feature/message-actions/MessageActionForm.tsx new file mode 100644 index 000000000..4771a9eb8 --- /dev/null +++ b/frontend/src/components/feature/message-actions/MessageActionForm.tsx @@ -0,0 +1,196 @@ +import { ErrorText, HelperText, Label } from '@/components/common/Form' +import LinkFormField from '@/components/common/LinkField/LinkFormField' +import { HStack, Stack } from '@/components/layout/Stack' +import { RavenMessageAction } from '@/types/RavenIntegrations/RavenMessageAction' +import { Box, Checkbox, Grid, Select, Text, TextArea, TextField } from '@radix-ui/themes' +import { Tabs } from '@radix-ui/themes' +import { ChangeEvent } from 'react' +import { Controller, useFormContext } from 'react-hook-form' +import { BiBoltCircle } from 'react-icons/bi' +import { LuVariable } from 'react-icons/lu' +import MessageActionVariableBuilder from './MessageActionVariableBuilder' + +const ICON_PROPS = { + size: 18, + className: 'mr-1.5' +} + + +const MessageActionForm = () => { + return ( + + + General + Fields + + + + + + + + + + + ) +} + +export default MessageActionForm + + +const GeneralTab = () => { + const { register, control, formState: { errors }, setValue, watch } = useFormContext() + + const action = watch('action') + + const onActionChange = (event: ChangeEvent) => { + + if (event.target.value !== 'Custom Function') { + setValue('custom_function_path', '') + } + + if (event.target.value !== "Create Document") { + setValue('document_type', '') + } + } + return + + + + + + { + setValue('title', e.target.value.trim()) + } + })} + placeholder="Create support ticket" + aria-invalid={errors.action_name ? 'true' : 'false'} + /> + + {errors.action_name && {errors.action_name?.message}} + + + + + ( + field.onChange(value)}> + + + Create Document + Custom Function + + + )} + /> + + {errors.action && {errors.action?.message}} + + {action === "Create Document" && + + + The document you want this action to create. + + {errors.document_type && {errors.document_type?.message}} + } + + {action === 'Custom Function' && + + +