Skip to content

Commit

Permalink
Merge pull request #264 from openchatai/staging
Browse files Browse the repository at this point in the history
Staging
  • Loading branch information
codebanesr authored Nov 17, 2023
2 parents fcc8a0f + 23644cf commit c87afa7
Show file tree
Hide file tree
Showing 58 changed files with 1,919 additions and 328 deletions.
1,108 changes: 1,108 additions & 0 deletions _swaggers/guild_quality.json

Large diffs are not rendered by default.

62 changes: 31 additions & 31 deletions backend/public/pilot.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions backend/routes/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@


Route::get('/copilots', [ChatbotController::class, 'index']);
Route::get('/copilot/{sessions}/c/{id}', [ChatbotController::class, 'sessions']);
Route::post('/copilot/swagger', [ChatbotController::class, 'handleSwaggerFile']);
Route::get('/copilot/{id}', [ChatbotSettingController::class, 'generalSettings']);
Route::delete('/copilot/{id}', [ChatbotSettingController::class, 'deleteBot']);
Expand Down
1 change: 1 addition & 0 deletions copilot-widget/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
token: "1RuzS7w5ceGaN6CiK0J7",
triggerSelector: "#triggerSelector",
apiUrl: "https://cloud.openchat.so/api",
defaultOpen: true,
headers: [
{
Authorization: "Bearer your_auth_token_goes_here",
Expand Down
2 changes: 1 addition & 1 deletion copilot-widget/lib/contexts/ConfigData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ReactNode, createContext, useContext } from "react";

export type ConfigDataContextType = Pick<
Options,
"token" | "initialMessage" | "headers" | "apiUrl" | "user"
"token" | "initialMessage" | "headers" | "apiUrl" | "user" | "defaultOpen"
>;

const ConfigDataContext = createContext<ConfigDataContextType | undefined>(
Expand Down
2 changes: 1 addition & 1 deletion copilot-widget/lib/contexts/Controller.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const ChatProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
"/chat/send",
{
...message,
headers: config?.headers || [],
headers: config?.headers,
user: config?.user,
}
);
Expand Down
4 changes: 3 additions & 1 deletion copilot-widget/lib/contexts/WidgetState.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ReactNode, createContext, useContext } from "react";
import useToggle from "../hooks/useToggle";
import { useConfigData } from "./ConfigData";

const StateContext = createContext<ReturnType<typeof useToggle> | undefined>(
undefined
Expand All @@ -15,6 +16,7 @@ export function useWidgetStateContext(): ReturnType<typeof useToggle> {
}

export default function WidgetState({ children }: { children: ReactNode }) {
const data = useToggle(false)
const cdata = useConfigData()
const data = useToggle(cdata?.defaultOpen || false)
return <StateContext.Provider value={data}>{children}</StateContext.Provider>;
}
3 changes: 2 additions & 1 deletion copilot-widget/lib/types/options.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
export type Options = {
token: string;
headers?: Record<string, string>[];
headers?: Record<string, string>;
initialMessage: string;
triggerSelector: string;
apiUrl: string;
defaultOpen?: boolean;
user?: {
name?: string;
};
Expand Down
2 changes: 1 addition & 1 deletion copilot-widget/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@openchatai/copilot-widget",
"private": false,
"version": "1.1.2",
"version": "1.2.0",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
43 changes: 28 additions & 15 deletions dashboard/app/(copilot)/copilot/[copilot_id]/CopilotWidget.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,39 @@
import { Button } from '@/components/ui/button';
import {
CopilotWidget,
Root
} from '@openchatai/copilot-widget';
import { ErrorBoundary } from "react-error-boundary";
export default function Widget({
token
}: {
token: string
}) {
return <Root
options={{
apiUrl: "http://localhost:8888/backend/api",
token,
initialMessage: "Hey Pal!",
headers: {
"X-Copilot": "copilot"
},
}}
>
<div className="[&>div]:static [&>div]:!max-h-full [&>div]:!h-full h-full overflow-hidden border-border border rounded-lg">
<CopilotWidget
triggerSelector="#triggerSelector"
/>
return <ErrorBoundary FallbackComponent={({ resetErrorBoundary }) => {
return <div className="flex flex-col items-center justify-center h-full">
<div className="flex flex-col gap-3 items-center justify-center">
<h1 className="text-2xl font-semibold text-gray-700">Something went wrong</h1>
<Button onClick={() => resetErrorBoundary()} variant='destructive'>Try again</Button>
</div>
</div>
</Root>
}}>

<Root
options={{
apiUrl: "http://localhost:8888/backend/api",
defaultOpen: true,
token,
initialMessage: "Hey Pal!",
headers: {
"X-Copilot": "copilot"
},
}}
>
<div className="[&>div]:static [&>div]:!max-h-full [&>div]:!h-full h-full overflow-hidden [&>div]:!border-border [&>div]:!border rounded-lg">
<CopilotWidget
triggerSelector="#triggerSelector"
/>
</div>
</Root>
</ErrorBoundary>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
'use client';
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { useAtomValue } from "jotai";
import { activeSessionId } from "./atoms";
import useSWR from "swr";
import { ChatMessageType, getConversationBySessionId } from "@/data/conversations";
import Loader from "@/components/ui/Loader";
import { format } from 'timeago.js';
import { EmptyBlock } from "@/components/domain/EmptyBlock";

function UserMessage({ message, created_at }: ChatMessageType) {
return (
<div className="flex w-full flex-row items-center justify-end gap-2">
<div className="flex flex-col items-end">
<p className="w-fit max-w-sm rounded-lg bg-primary px-4 py-3 text-sm select-none text-white">
{message}
</p>
<span className="text-xs">
{format(created_at)}
</span>
</div>
</div>
);
}
function CopilotMessage({ message, created_at }: ChatMessageType) {
return (
<div className="flex w-full flex-row items-start justify-start gap-2 relative">
<Avatar size="large" className="sticky top-0">
<AvatarFallback>C</AvatarFallback>
</Avatar>
<div className="flex items-start flex-col gap-1.5">
<p className="w-fit max-w-sm rounded-lg bg-secondary px-4 py-3 text-sm text-accent-foreground select-none">
{message}
</p>
<span className="text-xs">{format(created_at)}</span>
</div>
</div>
);
}
function ChatDivider({ content }: { content: string }) {
return (
<div className="relative my-4 block h-px w-full bg-secondary">
<span className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 bg-white px-4 text-xs">
{content}
</span>
</div>
);
}

export function ChatScreen() {
const activeid = useAtomValue(activeSessionId);
const {
data: chat,
isLoading
} = useSWR(activeid, getConversationBySessionId)
return (
<div className="flex-1 space-y-3 overflow-auto p-4 font-medium">
{
isLoading && <Loader className="h-full flex-center" />
}
{
chat ? chat?.data.map((c, i) => {
if (c.from_user) {
return <UserMessage key={i} {...c} />
} else if (!c.from_user) {
return <CopilotMessage key={i} {...c} />
}
}) : <EmptyBlock>
<p className="text-center text-sm">
Select a conversation to start chatting
</p>
</EmptyBlock>
}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"use client";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { useAtomValue } from "jotai";
import { Bookmark, CheckCircle, Trash2 } from "lucide-react";
import { activeSessionId } from "./atoms";

export function ConversationAside() {
const activeid = useAtomValue(activeSessionId);

return (
activeid &&
<aside className="animate-in slide-in-from-right fade-in h-full w-full max-w-xs border-l border-border xl:inline">
<section className="border-y border-border">
<div className="px-4 py-8 text-center">
<div className="flex-center -space-x-2">
<Avatar size="large">
<AvatarFallback className="bg-accent-foreground text-white select-none">
U
</AvatarFallback>
</Avatar>
<Avatar size="large">
<AvatarFallback className="bg-accent select-none">CO</AvatarFallback>
</Avatar>
</div>
<h2 className="mt-2 text-sm font-semibold">
Conversation between your assistant and Unknown User
</h2>
</div>
</section>
<section className="border-y border-border bg-white">
<div className="p-4">
<span className="text-xs font-semibold uppercase text-secondary-foreground">
actions
</span>
<div className="mt-2 w-full space-y-2 text-accent-foreground/80 ">
<button className="flex w-full items-center justify-between px-1 py-2 text-sm">
<span className="text-xs font-semibold">Mark as Reviewed</span>
<CheckCircle className="h-4 w-4" />
</button>
<button className="flex w-full items-center justify-between px-1 py-2 text-sm">
<span className="text-xs font-semibold">Save for Later</span>
<Bookmark className="h-4 w-4" />
</button>
<button className="flex w-full items-center justify-between px-1 py-2 text-sm text-destructive">
<span className="text-xs font-semibold">Delete</span>
<Trash2 className="h-4 w-4" />
</button>
</div>
</div>
</section>
</aside>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from "react";
import { HeaderShell } from "@/components/domain/HeaderShell";

export function ConversationHeader() {
return (
<HeaderShell className="items-center justify-between">
<h1 className="max-w-md flex-1 text-start text-base font-semibold text-secondary-foreground">
Conversation
</h1>
</HeaderShell>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"use client";
import { useAtom } from "jotai";
import { activeSessionId } from "./atoms";
import { cn } from "@/lib/utils";
import useSWR from "swr";
import { useCopilot } from "../../../_context/CopilotProvider";
import { ConversationType, getSessionsByBotId } from "@/data/conversations";
import { format } from 'timeago.js';
function Conversation(props: ConversationType) {
const [activeid, setActiveId] = useAtom(activeSessionId);
const isActive = activeid === props.session_id;
return (
<li
onClick={() => setActiveId(props.session_id)}
role="button"
className={cn(
"w-full border border-l-[3px] p-4 transition-colors last-of-type:mb-2",
isActive
? "sticky bottom-0 left-0 top-0 !border-l-primary bg-accent"
: "border-x-transparent bg-white border-border",
)}
>
<div
className="h-full w-full text-start">
<p className="line-clamp-1 text-base">{props.first_message.message}</p>
<p className="text-[10px]">{format(props.first_message.created_at)}</p>
</div>
</li>
);
}

export function ListConversations() {
const {
id: copilotId,
} = useCopilot();
const {
data: conversations
} = useSWR(copilotId + "/conversations", async () => (await getSessionsByBotId(copilotId))?.data)
return (
<div className="w-full flex-1 overflow-hidden">
<ul className="h-full overflow-auto">
{conversations?.map((c, i) => (
<Conversation {...c} key={i} />
))}
</ul>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { atom } from "jotai";

export const activeSessionId = atom<string | null>(null);
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { HeaderShell } from "@/components/domain/HeaderShell";
import { Button } from "@/components/ui/button";
import { RefreshCcw } from "lucide-react";
import React from "react";
import { ListConversations } from "./_parts/ListConverations";

type Props = {
children: React.ReactNode;
Expand All @@ -13,15 +11,15 @@ type Props = {
export default function SettingsLayout({ children, params }: Props) {
const copilotBase = `/copilot/${params.copilot_id}/conversations`;
return (
<div className="flex h-full flex-col overflow-hidden">
<HeaderShell className="justify-between">
<h1 className="text-lg font-bold text-secondary-foreground">
Conversations
</h1>
<Button size="icon" variant="secondary" className="hidden">
<RefreshCcw className="h-6 w-6" />
</Button>
</HeaderShell>
<div className="flex h-full flex-row overflow-hidden">
<div className="flex h-full w-full max-w-xs shrink-0 flex-col items-start border-r bg-primary-foreground">
<div className="flex-center h-header shrink-0 justify-start border-b px-6">
<h1 className="text-lg font-bold text-secondary-foreground">
Conversations
</h1>
</div>
<ListConversations />
</div>
<div className="h-full flex-1 overflow-auto">{children}</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import React from "react";
import { ConversationAside } from "./_parts/ConversationAside";
import { ChatScreen } from "./_parts/ChatScreen";

import { ConversationHeader } from "./_parts/ConversationHeader";

export default function Conversations() {
return (
<div className="flex-center h-full w-full">
<div className="text-xl font-bold">
<h2>Nothing here Yet</h2>
<h2>Work in Progress</h2>
<div className="flex h-full w-full flex-col overflow-hidden [&_input]:font-semibold">
<div className="flex flex-1 items-start overflow-auto bg-accent/25">
<div className="flex h-full flex-1 flex-col overflow-hidden bg-white">
<ConversationHeader />
<ChatScreen />
</div>
<ConversationAside />
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ function AddUrlDataSource() {
title: "Data source(s) added successfully",
variant: "success"
});
_.delay(() => setDialog(null), 2000)
_.delay(() => setDialog(null), 1000)
} else {
toast({
title: "Error adding data source(s)",
Expand Down
Loading

0 comments on commit c87afa7

Please sign in to comment.