diff --git a/web/src/api/buster_socket/chats.zip b/web/src/api/buster_socket/chats.zip deleted file mode 100644 index 0fe4c2576..000000000 Binary files a/web/src/api/buster_socket/chats.zip and /dev/null differ diff --git a/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetCollectionInterfaces.ts b/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetCollectionInterfaces.ts index a93ca8671..18433c940 100644 --- a/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetCollectionInterfaces.ts +++ b/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetCollectionInterfaces.ts @@ -1,3 +1,6 @@ +import type { FileType } from '../config'; + export type BusterCollectionAsset = { id: string; + type: FileType.COLLECTION; }; diff --git a/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetDashboardInterfaces.ts b/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetDashboardInterfaces.ts index dffe97d77..72a0a70ae 100644 --- a/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetDashboardInterfaces.ts +++ b/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetDashboardInterfaces.ts @@ -1,8 +1,10 @@ import type { BusterDashboardMetric } from '../../../buster_rest/dashboards'; import type { DashboardConfig } from '../../dashboards'; +import type { FileType } from '../config'; export type BusterDashboardAsset = { id: string; + type: FileType.DASHBOARD; metrics: BusterDashboardMetric[]; config: DashboardConfig; created_at: string; diff --git a/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetDatasetInterfaces.ts b/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetDatasetInterfaces.ts index 69770f004..bc4b6db34 100644 --- a/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetDatasetInterfaces.ts +++ b/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetDatasetInterfaces.ts @@ -1,3 +1,6 @@ +import type { FileType } from '../config'; + export type BusterDatasetAsset = { id: string; + type: FileType.DATASET; }; diff --git a/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetMetricInterfaces.ts b/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetMetricInterfaces.ts index cfef48090..39a19c115 100644 --- a/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetMetricInterfaces.ts +++ b/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetMetricInterfaces.ts @@ -1,7 +1,9 @@ import type { BusterChartConfigProps } from '@/components/charts'; +import type { FileType } from '../config'; export type BusterMetricAsset = { id: string; + type: FileType.METRIC; title: string; description: string | null; time_frame: string; diff --git a/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetTermInterfaces.ts b/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetTermInterfaces.ts index da72e03c1..dbed4581d 100644 --- a/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetTermInterfaces.ts +++ b/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetTermInterfaces.ts @@ -1,3 +1,6 @@ +import type { FileType } from '../config'; + export type BusterTermAsset = { id: string; + type: FileType.TERM; }; diff --git a/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetValueInterfaces.ts b/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetValueInterfaces.ts index 7c8d6c990..ed6c95251 100644 --- a/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetValueInterfaces.ts +++ b/web/src/api/buster_socket/chats/chatAssetInterfaces/chatAssetValueInterfaces.ts @@ -1,3 +1,6 @@ +import type { FileType } from '../config'; + export type BusterValueAsset = { id: string; + type: FileType.VALUE; }; diff --git a/web/src/api/buster_socket/chats/chatInterfaces.ts b/web/src/api/buster_socket/chats/chatInterfaces.ts index 631f70fef..1f88e2494 100644 --- a/web/src/api/buster_socket/chats/chatInterfaces.ts +++ b/web/src/api/buster_socket/chats/chatInterfaces.ts @@ -1,6 +1,6 @@ import type { BusterChatMessage } from './chatMessageInterfaces'; -export interface BusterChat { +export interface IBusterChat { id: string; title: string; is_favorited: boolean; diff --git a/web/src/api/buster_socket/chats/chatRequests.ts b/web/src/api/buster_socket/chats/chatRequests.ts index 9a4b4f2ec..743359d59 100644 --- a/web/src/api/buster_socket/chats/chatRequests.ts +++ b/web/src/api/buster_socket/chats/chatRequests.ts @@ -19,7 +19,7 @@ export type ChatUnsubscribeFromChat = BusterSocketRequestBase<'/chats/unsubscrib export type ChatGetChatAsset = BusterSocketRequestBase< '/chats/get/asset', - { id: string; type: FileType; version_id?: string } + { chat_id?: string; asset_id: string; type: FileType; version_id?: string } >; export type ChatListEmitPayload = BusterSocketRequestBase< diff --git a/web/src/api/buster_socket/chats/chatResponses.ts b/web/src/api/buster_socket/chats/chatResponses.ts index 78f32435a..18f26d867 100644 --- a/web/src/api/buster_socket/chats/chatResponses.ts +++ b/web/src/api/buster_socket/chats/chatResponses.ts @@ -1,6 +1,6 @@ import type { RustApiError } from '../../buster_rest/errors'; import type { BusterChatAsset } from './chatAssetInterfaces'; -import type { BusterChat, BusterChatListItem } from './chatInterfaces'; +import type { IBusterChat, BusterChatListItem } from './chatInterfaces'; export enum ChatsResponses { '/chats/list:getChatsList' = '/chats/list:getChatsList', @@ -25,7 +25,7 @@ export type Chat_unsubscribed = { export type Chat_getChat = { route: '/chats/get:getChat'; - callback: (d: BusterChat) => void; + callback: (d: IBusterChat) => void; onError?: (d: unknown | RustApiError) => void; }; @@ -39,13 +39,13 @@ export type Chat_getChatAsset = { export type ChatPost_initializeChat = { route: '/chats/post:initializeChat'; - callback: (d: BusterChat) => void; + callback: (d: IBusterChat) => void; onError?: (d: unknown | RustApiError) => void; }; export type ChatPost_generatingTitle = { route: '/chats/post:generatingTitle'; - callback: (d: BusterChat) => void; + callback: (d: IBusterChat) => void; onError?: (d: unknown | RustApiError) => void; }; diff --git a/web/src/api/buster_socket/chats/index.ts b/web/src/api/buster_socket/chats/index.ts index 7fc9774a7..9f80a9c57 100644 --- a/web/src/api/buster_socket/chats/index.ts +++ b/web/src/api/buster_socket/chats/index.ts @@ -1,3 +1,5 @@ export * from './chatAssetInterfaces'; +export * from './chatInterfaces'; export * from './chatRequests'; export * from './chatResponses'; +export * from './config'; diff --git a/web/src/api/buster_socket/index.ts b/web/src/api/buster_socket/index.ts index bd0ebcfb8..fdba6122e 100644 --- a/web/src/api/buster_socket/index.ts +++ b/web/src/api/buster_socket/index.ts @@ -18,6 +18,7 @@ import { OrganizationResponsesTypes, OrganizationsEmits } from './organizations'; +import { ChatEmits, ChatResponseTypes, ChatsResponses } from './chats'; export type BusterSocketRequest = | ThreadEmits @@ -31,7 +32,8 @@ export type BusterSocketRequest = | TermsEmits | PermissionsEmits | BusterSearchEmits - | OrganizationsEmits; + | OrganizationsEmits + | ChatEmits; export type BusterSocketResponse = | ThreadResponseTypes @@ -45,7 +47,8 @@ export type BusterSocketResponse = | TermsResponseTypes | PermissionsResponseTypes | SearchResponseTypes - | OrganizationResponsesTypes; + | OrganizationResponsesTypes + | ChatResponseTypes; export type BusterSocketResponseRoute = | keyof typeof ThreadResponses @@ -59,4 +62,5 @@ export type BusterSocketResponseRoute = | keyof typeof TermsResponses | keyof typeof PermissionsResponses | keyof typeof SearchResponses - | keyof typeof OrganizationResponses; + | keyof typeof OrganizationResponses + | keyof typeof ChatsResponses; diff --git a/web/src/context/AppProviders.tsx b/web/src/context/AppProviders.tsx index 2a10a144b..e7d149bfa 100644 --- a/web/src/context/AppProviders.tsx +++ b/web/src/context/AppProviders.tsx @@ -24,6 +24,7 @@ import { BusterAssetsProvider } from './Assets/BusterAssetsProvider'; import { BusterUserResponse } from '@/api/buster_rest/users'; import { BusterPosthogProvider } from './Posthog/usePosthog'; import { BusterNotificationsProvider } from './BusterNotifications'; +import { BusterChatProvider } from './Chats'; import { RoutePrefetcher } from './RoutePrefetcher'; import { BusterMessageDataProvider } from './MessageData'; @@ -66,16 +67,19 @@ export const AppProviders: React.FC< + {/* TODO: remove when we are ready to use chats */} - - - {children} - - - + + + + {children} + + + + diff --git a/web/src/context/Chats/ChatProvider.tsx b/web/src/context/Chats/ChatProvider.tsx new file mode 100644 index 000000000..8696d2c66 --- /dev/null +++ b/web/src/context/Chats/ChatProvider.tsx @@ -0,0 +1,151 @@ +import React, { useCallback, useRef, useState, useTransition } from 'react'; +import { + createContext, + ContextSelector, + useContextSelector +} from '@fluentui/react-context-selector'; +import { useBusterWebSocket } from '../BusterWebSocket'; +import type { BusterChatAsset, IBusterChat } from '@/api/buster_socket/chats'; +import { useMemoizedFn, useMount, useUnmount } from 'ahooks'; +import type { FileType } from '@/api/buster_socket/chats'; + +export const useBusterChat = () => { + const busterSocket = useBusterWebSocket(); + const [isPending, startTransition] = useTransition(); + const chatsRef = useRef>({}); + const [seletedAssetId, setSeletedAssetId] = useState>({}); + + // GETTERS + + const getSelectedAssetId = useCallback( + (chatId: string) => { + return seletedAssetId[chatId] || null; + }, + [seletedAssetId] + ); + + // SETTERS + + const onSetSelectedAssetId = useMemoizedFn((chatId: string, assetId: string | null) => { + setSeletedAssetId((prev) => ({ ...prev, [chatId]: assetId })); + }); + + // LISTENERS + + const _onGetChat = useMemoizedFn((chat: IBusterChat) => { + chatsRef.current[chat.id] = chat; + startTransition(() => { + //just used to trigger UI update + }); + return chat; + }); + + const _onGetChatAsset = useMemoizedFn((asset: BusterChatAsset) => { + const { id, type } = asset; + console.log('TODO: handle this. Put the asset in their respective chat'); + return asset; + }); + + // EMITTERS + + const unsubscribeFromChat = useMemoizedFn(({ chatId }: { chatId: string }) => { + return busterSocket.emit({ + route: '/chats/unsubscribe', + payload: { + id: chatId + } + }); + }); + + const subscribeToChat = useMemoizedFn(({ chatId }: { chatId: string }) => { + return busterSocket.emitAndOnce({ + emitEvent: { + route: '/chats/get', + payload: { + id: chatId + } + }, + responseEvent: { + route: '/chats/get:getChat', + callback: _onGetChat + } + }); + }); + + const getChatAsset = useMemoizedFn( + ({ + chatId: chat_id, + assetId: asset_id, + type, + versionId: version_id + }: { + chatId?: string; + assetId: string; + type: FileType; + versionId?: string; + }) => { + return busterSocket.emitAndOnce({ + emitEvent: { + route: '/chats/get/asset', + payload: { + type, + chat_id, + asset_id, + version_id + } + }, + responseEvent: { + route: '/chats/get:getChatAsset', + callback: _onGetChatAsset + } + }); + } + ); + + return { + getSelectedAssetId, + chats: chatsRef.current, + unsubscribeFromChat, + subscribeToChat, + getChatAsset, + onSetSelectedAssetId + }; +}; + +const BusterChat = createContext>( + {} as ReturnType +); + +export const BusterChatProvider: React.FC<{ + children: React.ReactNode; +}> = ({ children }) => { + const value = useBusterChat(); + + return {children}; +}; + +export const useBusterChatContextSelector = ( + selector: ContextSelector, T> +) => useContextSelector(BusterChat, selector); + +export const useBusterChatIndividual = ({ chatId }: { chatId: string }) => { + const chat = useBusterChatContextSelector((x) => x.chats[chatId]); + const subscribeToChat = useBusterChatContextSelector((x) => x.subscribeToChat); + const unsubscribeFromChat = useBusterChatContextSelector((x) => x.unsubscribeFromChat); + const selectedAssetId = useBusterChatContextSelector((x) => x.getSelectedAssetId(chatId)); + const onSetSelectedAssetId = useBusterChatContextSelector((x) => x.onSetSelectedAssetId); + + useMount(() => { + subscribeToChat({ chatId }); + }); + + useUnmount(() => { + unsubscribeFromChat({ chatId }); + }); + + return { + chat, + selectedAssetId, + onSetSelectedAssetId + }; +}; diff --git a/web/src/context/Chats/index.ts b/web/src/context/Chats/index.ts new file mode 100644 index 000000000..702a16db0 --- /dev/null +++ b/web/src/context/Chats/index.ts @@ -0,0 +1 @@ +export * from './ChatProvider'; diff --git a/web/src/context/Dashboards/DashboardProvider.tsx b/web/src/context/Dashboards/DashboardProvider.tsx index e37415b18..1280294fe 100644 --- a/web/src/context/Dashboards/DashboardProvider.tsx +++ b/web/src/context/Dashboards/DashboardProvider.tsx @@ -1,35 +1,12 @@ -import { - BusterDashboard, - BusterDashboardListItem, - BusterDashboardResponse, - BusterMetricDataResponse, - BusterVerificationStatus, - IBusterDashboardMetric -} from '@/api/buster_rest'; -import { useParams, useRouter } from 'next/navigation'; -import React, { - PropsWithChildren, - useContext, - useEffect, - useLayoutEffect, - useRef, - useState -} from 'react'; -import { useBusterWebSocket } from '../BusterWebSocket'; +import { useParams } from 'next/navigation'; +import React, { PropsWithChildren, useEffect, useLayoutEffect, useState } from 'react'; import { useAppLayoutContextSelector } from '../BusterAppLayout'; -import { BusterRoutes, createBusterRoute } from '@/routes'; -import { DashboardUpdate, DashboardsListEmitPayload } from '@/api/buster_socket/dashboards'; -import isEqual from 'lodash/isEqual'; -import { useMemoizedFn, useMount, useUnmount } from 'ahooks'; -import { useBusterAssetsContextSelector } from '@/context/Assets/BusterAssetsProvider'; -import { upgradeDashboardMetric } from './dashboardContextHelper'; -import { useBusterNotifications } from '../BusterNotifications'; +import { useUnmount } from 'ahooks'; import { useContextSelector, createContext, ContextSelector } from '@fluentui/react-context-selector'; -import { useBusterMessageDataContextSelector } from '../MessageData'; import { useDashboardLists } from './useDashboardLists'; import { useDashboardIndividual } from './useDashboardIndividual'; import { useDashboardMetrics } from './useDashboardMetrics'; diff --git a/web/src/context/Threads/BusterThreadsProvider.tsx b/web/src/context/Threads/BusterThreadsProvider.tsx index cab5f9cf0..165990f20 100644 --- a/web/src/context/Threads/BusterThreadsProvider.tsx +++ b/web/src/context/Threads/BusterThreadsProvider.tsx @@ -7,7 +7,7 @@ import { import { BusterNewThreadsProvider } from './BusterNewThreadsProvider'; import { BusterThreadsListProvider } from './BusterThreadsListProvider'; import { defaultIBusterThread } from './config'; -import { useDebounceFn, useMemoizedFn, useMount, useWhyDidYouUpdate } from 'ahooks'; +import { useDebounceFn, useMemoizedFn, useMount, useUnmount } from 'ahooks'; import type { IBusterThread, IBusterThreadMessage } from './interfaces'; import type { BusterThread, BusterThreadUser, BusterVerificationStatus } from '@/api/buster_rest'; import { useBusterWebSocket } from '../BusterWebSocket';