Skip to content

Commit

Permalink
Merge pull request #1156 from The-Commit-Company/raven-orgs
Browse files Browse the repository at this point in the history
feat: workspaces
  • Loading branch information
nikkothari22 authored Dec 14, 2024
2 parents 0cc5122 + 6a7ffda commit 4255001
Show file tree
Hide file tree
Showing 206 changed files with 6,202 additions and 1,419 deletions.
3 changes: 3 additions & 0 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@ dist-ssr
*.njsproj
*.sln
*.sw?

# Million Lint
.million
20 changes: 12 additions & 8 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"copy-html-entry": "cp ../raven/public/raven/index.html ../raven/www/raven.html"
},
"dependencies": {
"@radix-ui/themes": "^3.1.3",
"@radix-ui/themes": "3.1.4",
"@tiptap/extension-code-block-lowlight": "2.5.9",
"@tiptap/extension-highlight": "2.5.9",
"@tiptap/extension-image": "2.5.9",
Expand All @@ -33,35 +33,36 @@
"cal-sans": "^1.0.1",
"chrono-node": "^2.7.7",
"clsx": "^2.1.0",
"cmdk": "^1.0.0",
"cmdk": "^1.0.4",
"cva": "npm:class-variance-authority",
"dayjs": "^1.11.11",
"downshift": "^8.3.1",
"emoji-picker-element": "^1.22.3",
"emoji-picker-element": "^1.25.0",
"firebase": "^10.9.0",
"frappe-react-sdk": "^1.8.0",
"frappe-react-sdk": "^1.9.0",
"highlight.js": "^11.9.0",
"html-react-parser": "^5.1.8",
"jotai": "^2.9.3",
"jotai": "^2.10.3",
"js-cookie": "^3.0.5",
"lowlight": "^3.1.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-dropzone": "^14.2.3",
"react-error-boundary": "^4.0.13",
"react-hook-form": "^7.52.2",
"react-icons": "^5.3.0",
"react-icons": "^5.4.0",
"react-idle-timer": "^5.7.2",
"react-intersection-observer": "^9.10.3",
"react-router-dom": "^6.26.1",
"react-virtuoso": "^4.12.3",
"react-zoom-pan-pinch": "^3.4.4",
"sonner": "^1.5.0",
"sonner": "^1.7.0",
"tailwindcss": "^3.4.10",
"tailwindcss-animate": "^1.0.7",
"tippy.js": "^6.3.7",
"turndown": "^7.2.0",
"use-double-tap": "^1.3.6",
"vaul": "^0.9.1",
"vaul": "^1.1.1",
"vite": "^4.5.5",
"vite-plugin-pwa": "^0.20.0",
"vite-plugin-svgr": "^4.2.0"
Expand All @@ -72,5 +73,8 @@
"@types/react-dom": "^18.2.19",
"@types/turndown": "^5.0.4",
"typescript": "^5.3.3"
},
"resolutions": {
"@radix-ui/react-dialog": "1.1.1"
}
}
128 changes: 71 additions & 57 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { FrappeProvider } from 'frappe-react-sdk'
import { Route, RouterProvider, createBrowserRouter, createRoutesFromElements } from 'react-router-dom'
import { Navigate, Route, RouterProvider, createBrowserRouter, createRoutesFromElements } from 'react-router-dom'
import { MainPage } from './pages/MainPage'
import { ProtectedRoute } from './utils/auth/ProtectedRoute'
import { UserProvider } from './utils/auth/UserProvider'
import { ChannelRedirect } from './utils/channel/ChannelRedirect'
import "cal-sans";
import { ThemeProvider } from './ThemeProvider'
import { Toaster } from 'sonner'
import { useStickyState } from './hooks/useStickyState'
import MobileTabsPage from './pages/MobileTabsPage'
import Cookies from 'js-cookie'
import ErrorPage from './pages/ErrorPage'
import WorkspaceSwitcher from './pages/WorkspaceSwitcher'
import WorkspaceSwitcherGrid from './components/layout/WorkspaceSwitcherGrid'

/** Following keys will not be cached in app cache */
const NO_CACHE_KEYS = [
Expand All @@ -19,9 +20,13 @@ const NO_CACHE_KEYS = [
"frappe.model.workflow.get_transitions",
"frappe.desk.reportview.get_count",
"frappe.core.doctype.server_script.server_script.enabled",
"raven.api.message_actions.get_action_defaults"
"raven.api.message_actions.get_action_defaults",
"raven.api.document_link.get_preview_data"
]

const lastWorkspace = localStorage.getItem('ravenLastWorkspace') ?? ''
const lastChannel = localStorage.getItem('ravenLastChannel') ?? ''


const router = createBrowserRouter(
createRoutesFromElements(
Expand All @@ -31,64 +36,73 @@ const router = createBrowserRouter(
<Route path='/signup' lazy={() => import('@/pages/auth/SignUp')} />
<Route path='/forgot-password' lazy={() => import('@/pages/auth/ForgotPassword')} />
<Route path="/" element={<ProtectedRoute />} errorElement={<ErrorPage />}>
<Route path="/" element={<ChannelRedirect />}>
<Route path="channel" element={<MainPage />} >
<Route path="/" element={<WorkspaceSwitcher />}>
<Route index element={lastWorkspace && lastChannel ? <Navigate to={`/${lastWorkspace}/${lastChannel}`} replace /> : lastWorkspace ? <Navigate to={`/${lastWorkspace}`} replace /> : <WorkspaceSwitcherGrid />} />
<Route path="workspace-explorer" element={<WorkspaceSwitcherGrid />} />
<Route path="settings" lazy={() => import('./pages/settings/Settings')}>
<Route index lazy={() => import('./components/feature/userSettings/UserProfile/UserProfile')} />
<Route path="profile" lazy={() => import('./components/feature/userSettings/UserProfile/UserProfile')} />
<Route path="users" lazy={() => import('./pages/settings/Users/UserList')} />
<Route path="appearance" lazy={() => import('./pages/settings/Appearance')} />
<Route path="hr" lazy={() => import('./pages/settings/Integrations/FrappeHR')} />

<Route path="workspaces" >
<Route index lazy={() => import('./pages/settings/Workspaces/WorkspaceList')} />
<Route path=":ID" lazy={() => import('./pages/settings/Workspaces/ViewWorkspace')} />
</Route>

<Route path="bots" >
<Route index lazy={() => import('./pages/settings/AI/BotList')} />
<Route path="create" lazy={() => import('./pages/settings/AI/CreateBot')} />
<Route path=":ID" lazy={() => import('./pages/settings/AI/ViewBot')} />
</Route>

<Route path="functions">
<Route index lazy={() => import('./pages/settings/AI/FunctionList')} />
<Route path="create" lazy={() => import('./pages/settings/AI/CreateFunction')} />
<Route path=":ID" lazy={() => import('./pages/settings/AI/ViewFunction')} />
</Route>


<Route path="instructions">
<Route index lazy={() => import('./pages/settings/AI/InstructionTemplateList')} />
<Route path="create" lazy={() => import('./pages/settings/AI/CreateInstructionTemplate')} />
<Route path=":ID" lazy={() => import('./pages/settings/AI/ViewInstructionTemplate')} />
</Route>

<Route path="commands">
<Route index lazy={() => import('./pages/settings/AI/SavedPromptsList')} />
<Route path="create" lazy={() => import('./pages/settings/AI/CreateSavedPrompt')} />
<Route path=":ID" lazy={() => import('./pages/settings/AI/ViewSavedPrompt')} />
</Route>

<Route path="openai-settings" lazy={() => import('./pages/settings/AI/OpenAISettings')} />

<Route path="webhooks">
<Route index lazy={() => import('./pages/settings/Webhooks/WebhookList')} />
<Route path="create" lazy={() => import('./pages/settings/Webhooks/CreateWebhook')} />
<Route path=":ID" lazy={() => import('./pages/settings/Webhooks/ViewWebhook')} />
</Route>

<Route path="scheduled-messages">
<Route index lazy={() => import('./pages/settings/ServerScripts/SchedulerEvents/SchedulerEvents')} />
<Route path="create" lazy={() => import('./pages/settings/ServerScripts/SchedulerEvents/CreateSchedulerEvent')} />
<Route path=":ID" lazy={() => import('./pages/settings/ServerScripts/SchedulerEvents/ViewSchedulerEvent')} />
</Route>

<Route path="message-actions">
<Route index lazy={() => import('./pages/settings/MessageActions/MessageActionList')} />
<Route path="create" lazy={() => import('./pages/settings/MessageActions/CreateMessageAction')} />
<Route path=":ID" lazy={() => import('./pages/settings/MessageActions/ViewMessageAction')} />
</Route>
</Route>
<Route path=":workspaceID" element={<MainPage />}>
<Route index element={<MobileTabsPage />} />
<Route path="threads" lazy={() => import('./components/feature/threads/Threads')}>
<Route path="thread/:threadID" lazy={() => import('./components/feature/threads/ThreadDrawer/ThreadDrawer')} />
</Route>
<Route path="saved-messages" lazy={() => import('./components/feature/saved-messages/SavedMessages')} />
<Route path="settings" lazy={() => import('./pages/settings/Settings')}>
<Route index lazy={() => import('./components/feature/userSettings/UserProfile/UserProfile')} />
<Route path="profile" lazy={() => import('./components/feature/userSettings/UserProfile/UserProfile')} />
<Route path="users" lazy={() => import('./pages/settings/Users/UserList')} />
<Route path="appearance" lazy={() => import('./pages/settings/Appearance')} />
<Route path="hr" lazy={() => import('./pages/settings/Integrations/FrappeHR')} />
<Route path="bots" >
<Route index lazy={() => import('./pages/settings/AI/BotList')} />
<Route path="create" lazy={() => import('./pages/settings/AI/CreateBot')} />
<Route path=":ID" lazy={() => import('./pages/settings/AI/ViewBot')} />
</Route>

<Route path="functions">
<Route index lazy={() => import('./pages/settings/AI/FunctionList')} />
<Route path="create" lazy={() => import('./pages/settings/AI/CreateFunction')} />
<Route path=":ID" lazy={() => import('./pages/settings/AI/ViewFunction')} />
</Route>


<Route path="instructions">
<Route index lazy={() => import('./pages/settings/AI/InstructionTemplateList')} />
<Route path="create" lazy={() => import('./pages/settings/AI/CreateInstructionTemplate')} />
<Route path=":ID" lazy={() => import('./pages/settings/AI/ViewInstructionTemplate')} />
</Route>

<Route path="commands">
<Route index lazy={() => import('./pages/settings/AI/SavedPromptsList')} />
<Route path="create" lazy={() => import('./pages/settings/AI/CreateSavedPrompt')} />
<Route path=":ID" lazy={() => import('./pages/settings/AI/ViewSavedPrompt')} />
</Route>

<Route path="openai-settings" lazy={() => import('./pages/settings/AI/OpenAISettings')} />

<Route path="webhooks">
<Route index lazy={() => import('./pages/settings/Webhooks/WebhookList')} />
<Route path="create" lazy={() => import('./pages/settings/Webhooks/CreateWebhook')} />
<Route path=":ID" lazy={() => import('./pages/settings/Webhooks/ViewWebhook')} />
</Route>

<Route path="scheduled-messages">
<Route index lazy={() => import('./pages/settings/ServerScripts/SchedulerEvents/SchedulerEvents')} />
<Route path="create" lazy={() => import('./pages/settings/ServerScripts/SchedulerEvents/CreateSchedulerEvent')} />
<Route path=":ID" lazy={() => import('./pages/settings/ServerScripts/SchedulerEvents/ViewSchedulerEvent')} />
</Route>

<Route path="message-actions">
<Route index lazy={() => import('./pages/settings/MessageActions/MessageActionList')} />
<Route path="create" lazy={() => import('./pages/settings/MessageActions/CreateMessageAction')} />
<Route path=":ID" lazy={() => import('./pages/settings/MessageActions/ViewMessageAction')} />
</Route>
</Route>

<Route path=":channelID" lazy={() => import('@/pages/ChatSpace')}>
<Route path="thread/:threadID" lazy={() => import('./components/feature/threads/ThreadDrawer/ThreadDrawer')} />
</Route>
Expand Down Expand Up @@ -123,7 +137,7 @@ function App() {
socketPort={import.meta.env.VITE_SOCKET_PORT ? import.meta.env.VITE_SOCKET_PORT : undefined}
//@ts-ignore
swrConfig={{
provider: localStorageProvider
errorRetryCount: 2,
}}
siteName={getSiteName()}
>
Expand Down
14 changes: 5 additions & 9 deletions frontend/src/components/common/Callouts/CustomCallout.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { Callout } from "@radix-ui/themes";
import {
CalloutIconProps,
CalloutRootProps,
CalloutTextProps,
} from "@radix-ui/themes/dist/cjs/components/callout";
import clsx from "clsx";
import { PropsWithChildren } from "react";

export type CalloutObject = {
Expand All @@ -12,10 +8,10 @@ export type CalloutObject = {
}

export type CustomCalloutProps = {
rootProps?: CalloutRootProps;
iconProps?: CalloutIconProps;
rootProps?: Callout.RootProps;
iconProps?: Callout.IconProps;
iconChildren?: React.ReactNode;
textProps?: CalloutTextProps;
textProps?: Callout.TextProps;
textChildren?: React.ReactNode;
};

Expand All @@ -27,7 +23,7 @@ export const CustomCallout = ({
iconChildren,
}: PropsWithChildren<CustomCalloutProps>) => {
return (
<Callout.Root {...rootProps}>
<Callout.Root {...rootProps} className={clsx("animate-fadein", rootProps?.className)}>
<Callout.Icon {...iconProps}>{iconChildren}</Callout.Icon>
<Callout.Text {...textProps}>{textChildren}</Callout.Text>
</Callout.Root>
Expand Down
15 changes: 10 additions & 5 deletions frontend/src/components/common/LinkField/LinkField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useCombobox } from "downshift";
import { Filter, SearchResult, useSearch } from "frappe-react-sdk";
import { useState } from "react";
import { Label } from "../Form";
import { Text, TextField } from "@radix-ui/themes";
import { Text, TextField, VisuallyHidden } from "@radix-ui/themes";
import { useIsDesktop } from "@/hooks/useMediaQuery";
import clsx from "clsx";

Expand All @@ -20,10 +20,11 @@ export interface LinkFieldProps {
dropdownClass?: string,
required?: boolean,
suggestedItems?: SearchResult[],
hideLabel?: boolean
}


const LinkField = ({ doctype, filters, label, placeholder, value, required, setValue, disabled, autofocus, dropdownClass, suggestedItems }: LinkFieldProps) => {
const LinkField = ({ doctype, filters, hideLabel = false, label, placeholder, value, required, setValue, disabled, autofocus, dropdownClass, suggestedItems }: LinkFieldProps) => {

const [searchText, setSearchText] = useState(value ?? '')

Expand Down Expand Up @@ -63,9 +64,13 @@ const LinkField = ({ doctype, filters, label, placeholder, value, required, setV

return <div className="w-full">
<div className="flex flex-col">
<Label className="w-fit" isRequired={required} {...getLabelProps()}>
{label}
</Label>
{hideLabel ? <VisuallyHidden>
<Label isRequired={required} {...getLabelProps()}></Label>
</VisuallyHidden> :
<Label className="w-fit" isRequired={required} {...getLabelProps()}>
{label}
</Label>
}
<TextField.Root
placeholder={placeholder ?? `Search ${doctype}`}
className='w-full'
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/common/LinkField/LinkFormField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const LinkFormField = ({ name, rules, ...linkFieldProps }: LinkFormFieldProps) =
render={({ field }) => (
<LinkField
value={field.value}
disabled={field.disabled}
setValue={field.onChange}
{...linkFieldProps}
/>
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/components/common/Loader.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
export const Loader = () => {
import clsx from "clsx"

export const Loader = ({ className }: { className?: string }) => {
return (
<svg className="animate-spin h-4 w-4 dark:text-white text-gray-900" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<svg className={clsx("animate-spin h-4 w-4 dark:text-white text-gray-900", className)} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
Expand Down
Loading

0 comments on commit 4255001

Please sign in to comment.