diff --git a/apps/dashboard/components/AgentDeployTab.tsx b/apps/dashboard/components/AgentDeployTab.tsx
index 457ed9c2b..0f9e59680 100644
--- a/apps/dashboard/components/AgentDeployTab.tsx
+++ b/apps/dashboard/components/AgentDeployTab.tsx
@@ -123,8 +123,7 @@ function AgentDeployTab(props: Props) {
disableSubmitButton
cardProps={{
sx: {
- maxWidth: 'md',
- mx: 'auto',
+ maxWidth: '100%',
},
}}
>
diff --git a/apps/dashboard/components/ChatSection.tsx b/apps/dashboard/components/ChatSection.tsx
index a26b9f11d..2f39f063a 100644
--- a/apps/dashboard/components/ChatSection.tsx
+++ b/apps/dashboard/components/ChatSection.tsx
@@ -32,6 +32,7 @@ function ChatSection({
rootSx={{
pt: 1,
height: '100%',
+ minHeight: '100%',
width: '200px',
}}
currentConversationId={currentConversationId}
diff --git a/apps/dashboard/components/ConversationExport.tsx b/apps/dashboard/components/ConversationExport.tsx
index ea6215fe1..7332ad2c8 100644
--- a/apps/dashboard/components/ConversationExport.tsx
+++ b/apps/dashboard/components/ConversationExport.tsx
@@ -1,22 +1,62 @@
import DownloadForOfflineRoundedIcon from '@mui/icons-material/DownloadForOfflineRounded';
-import InfoRoundedIcon from '@mui/icons-material/InfoRounded';
-import { Alert, Button, Card, Stack } from '@mui/joy';
+import { Button } from '@mui/joy';
import axios from 'axios';
import { saveAs } from 'file-saver';
import { useState } from 'react';
import { toast } from 'react-hot-toast';
+import { z } from 'zod';
-interface Props {}
+import {
+ ConversationChannel,
+ ConversationPriority,
+ MessageEval,
+} from '@chaindesk/prisma';
-export function ConversationExport({}: Props) {
+interface Props {
+ channel?: ConversationChannel;
+ priority?: ConversationPriority;
+ agentId?: string;
+ assigneeId?: string;
+ messageEval?: MessageEval;
+}
+
+export function ConversationExport({
+ channel,
+ priority,
+ messageEval,
+ agentId,
+ assigneeId,
+}: Props) {
const [isLoading, setIsLoading] = useState(false);
const exportConversations = async () => {
try {
+ const { success: validChannel } = z
+ .nativeEnum(ConversationChannel)
+ .safeParse(channel);
+ const { success: validEval } = z
+ .nativeEnum(MessageEval)
+ .safeParse(messageEval);
+ const { success: validPriority } = z
+ .nativeEnum(MessageEval)
+ .safeParse(priority);
+
+ const { success: validAgentId } = z.string().min(3).safeParse(agentId);
+ const { success: validAssigneeId } = z
+ .string()
+ .min(3)
+ .safeParse(assigneeId);
+
setIsLoading(true);
const { data } = await toast.promise(
axios.post(
'/api/conversations/export',
- {},
+ {
+ ...(validChannel ? { channel } : {}),
+ ...(validPriority ? { priority } : {}),
+ ...(validAgentId ? { agentId } : {}),
+ ...(validAssigneeId ? { assigneeId } : {}),
+ ...(validEval ? { messageEval } : {}),
+ },
{
responseType: 'blob',
}
diff --git a/apps/dashboard/components/ConversationList.tsx b/apps/dashboard/components/ConversationList.tsx
index 861bae279..9cd98b807 100644
--- a/apps/dashboard/components/ConversationList.tsx
+++ b/apps/dashboard/components/ConversationList.tsx
@@ -1,8 +1,5 @@
-import AddCircleOutlineRoundedIcon from '@mui/icons-material/AddCircleOutlineRounded';
import AddRoundedIcon from '@mui/icons-material/AddRounded';
import Button from '@mui/joy/Button';
-import Chip from '@mui/joy/Chip';
-import Divider from '@mui/joy/Divider';
import List from '@mui/joy/List';
import ListDivider from '@mui/joy/ListDivider';
import ListItem from '@mui/joy/ListItem';
@@ -13,7 +10,7 @@ import Stack from '@mui/joy/Stack';
import { SxProps } from '@mui/joy/styles/types';
import Typography from '@mui/joy/Typography';
import { useRouter } from 'next/router';
-import React, { useEffect, useRef } from 'react';
+import React, { useEffect, useMemo, useRef } from 'react';
import InfiniteScroll from 'react-infinite-scroller';
import useSWR, { useSWRConfig } from 'swr';
import useSWRInfinite from 'swr/infinite';
@@ -65,8 +62,6 @@ const Item = (props: {
-
- {/* */}
);
};
@@ -80,6 +75,7 @@ function ConversationList({
}: Props) {
const scrollParentRef = useRef(null);
const router = useRouter();
+
const [state, setState] = useStateReducer({
hasMore: true,
hasLoadedOnce: false,
@@ -106,7 +102,7 @@ function ConversationList({
},
fetcher,
{
- refreshInterval: 5000,
+ refreshInterval: router?.query?.conversationId ? 5000 : 500,
onSuccess: (data) => {
const id = data?.[0]?.[0]?.id;
@@ -117,19 +113,25 @@ function ConversationList({
}
);
- const conversations = getConversationsQuery?.data?.flat?.() || [];
+ const conversations = useMemo(
+ () => getConversationsQuery?.data?.flat?.() || [],
+ [getConversationsQuery?.data]
+ );
+
+ const conversationsLength = useMemo(
+ () => conversations.length,
+ [conversations]
+ );
useEffect(() => {
+ const conversationId = (router.query.conversationId ||
+ conversations[0]?.id) as string;
if (router.query?.conversationId) {
- handleSelectConversation?.(router.query.conversationId as string);
+ handleSelectConversation?.(conversationId);
} else {
- handleSelectConversation?.(conversations[0]?.id);
+ handleSelectConversation?.(conversationId);
}
- }, [getConversationsQuery?.data]);
-
- if (!getConversationsQuery.isLoading && conversations.length === 0) {
- return null;
- }
+ }, [conversationsLength]);
return (
- {/* */}
+
-
- {/* */}
)) as any
}
>
+ {!router.query.conversationId && (
+
+ )}
+
{conversations?.map((each) => (
-
- Advanced Settings
-
-
-
-
-
+
{!props.hideText && defaultValues?.datastoreId && defaultValues?.id && (
diff --git a/apps/dashboard/components/DatastoreSettings.tsx b/apps/dashboard/components/DatastoreSettings.tsx
index 4c306d89a..f074d967c 100644
--- a/apps/dashboard/components/DatastoreSettings.tsx
+++ b/apps/dashboard/components/DatastoreSettings.tsx
@@ -371,7 +371,8 @@ function DatastoreSettings() {
({
maxWidth: '100%',
- width: theme.breakpoints.values.md,
+ width: '100%',
+ px: 4,
mx: 'auto',
})}
>
diff --git a/apps/dashboard/components/FormInstallTab.tsx b/apps/dashboard/components/FormInstallTab.tsx
index 02d05196d..fa8a79a2a 100644
--- a/apps/dashboard/components/FormInstallTab.tsx
+++ b/apps/dashboard/components/FormInstallTab.tsx
@@ -32,7 +32,7 @@ function FormInstallTab({ formId }: Props) {
`;
return (
-
+
Web Component
diff --git a/apps/dashboard/components/FormSettingsTab.tsx b/apps/dashboard/components/FormSettingsTab.tsx
index fddfad37a..1d87822c1 100644
--- a/apps/dashboard/components/FormSettingsTab.tsx
+++ b/apps/dashboard/components/FormSettingsTab.tsx
@@ -28,16 +28,13 @@ function FormSettingsTab({ formId }: Props) {
}
return (
-
+
diff --git a/apps/dashboard/components/Layout/ExpandedNavigation.tsx b/apps/dashboard/components/Layout/ExpandedNavigation.tsx
new file mode 100644
index 000000000..dfcf56365
--- /dev/null
+++ b/apps/dashboard/components/Layout/ExpandedNavigation.tsx
@@ -0,0 +1,433 @@
+import ArrowForwardRoundedIcon from '@mui/icons-material/ArrowForwardRounded';
+import ChatRoundedIcon from '@mui/icons-material/ChatRounded';
+import LinkedInIcon from '@mui/icons-material/LinkedIn';
+import TwitterIcon from '@mui/icons-material/Twitter';
+import {
+ Box,
+ Button,
+ Chip,
+ ColorPaletteProp,
+ Divider,
+ IconButton,
+ List,
+ ListItem,
+ ListItemButton,
+ ListItemContent,
+ ListItemDecorator,
+ Stack,
+ SvgIcon,
+ Typography,
+} from '@mui/joy';
+import Head from 'next/head';
+import Image from 'next/image';
+import Link from 'next/link';
+import { useSession } from 'next-auth/react';
+
+import { ProductType } from '@app/hooks/useProduct';
+
+import { appUrl } from '@chaindesk/lib/config';
+import { AppStatus, RouteNames } from '@chaindesk/lib/types';
+import DarkModeToggle from '@chaindesk/ui/DarkModeToggle';
+
+import AccountCard from '../AccountCard';
+import UserMenu from '../UserMenu';
+
+export type AppLink =
+ | {
+ label: string;
+ route: RouteNames;
+ icon: JSX.Element;
+ active: boolean;
+ isNew: boolean;
+ isExperimental?: undefined;
+ }
+ | {
+ label: string;
+ route: RouteNames;
+ icon: JSX.Element;
+ active: boolean;
+ isExperimental: boolean;
+ isNew: boolean;
+ };
+
+function NavigationLink(props: {
+ href: string;
+ target?: string;
+ active?: boolean;
+ icon?: React.ReactNode;
+ label?: string | React.ReactElement;
+ isExperimental?: boolean;
+ isNew?: boolean;
+}) {
+ return (
+
+
+
+
+ {props.icon}
+
+ {props.label}
+
+
+ {props.isNew && (
+
+ new
+
+ )}
+
+ {props.isExperimental && (
+
+ beta
+
+ )}
+
+
+
+
+ );
+}
+
+export default function ExpandedNavigation({
+ product,
+ appLinks,
+ settingLinks,
+ docLinks,
+ publicRuntimeConfig,
+ status,
+}: {
+ product: ProductType;
+ appLinks: AppLink[];
+ settingLinks: AppLink[];
+ docLinks: AppLink[];
+ status: AppStatus | undefined;
+ publicRuntimeConfig: Record & { version?: string };
+}) {
+ const { data: session } = useSession({
+ required: true,
+ });
+ return (
+ <>
+
+
+
+
+
+
+
+ Chaindesk
+
+
+
+
+
+
+
+ {!!session?.user?.id && (
+
+