new changes
This commit is contained in:
		
							parent
							
								
									4efc9e05e0
								
							
						
					
					
						commit
						92cb203503
					
				| @ -12,6 +12,7 @@ | |||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@headlessui/react": "^1.7.13", |     "@headlessui/react": "^1.7.13", | ||||||
|     "@heroicons/react": "^2.0.17", |     "@heroicons/react": "^2.0.17", | ||||||
|  |     "@mantine/form": "^6.0.7", | ||||||
|     "@prisma/client": "^4.11.0", |     "@prisma/client": "^4.11.0", | ||||||
|     "@supabase/auth-helpers-nextjs": "^0.6.0", |     "@supabase/auth-helpers-nextjs": "^0.6.0", | ||||||
|     "@supabase/auth-helpers-react": "^0.3.1", |     "@supabase/auth-helpers-react": "^0.3.1", | ||||||
| @ -24,6 +25,7 @@ | |||||||
|     "@trpc/next": "^10.18.0", |     "@trpc/next": "^10.18.0", | ||||||
|     "@trpc/react-query": "^10.18.0", |     "@trpc/react-query": "^10.18.0", | ||||||
|     "@trpc/server": "^10.18.0", |     "@trpc/server": "^10.18.0", | ||||||
|  |     "axios": "^1.3.5", | ||||||
|     "langchain": "^0.0.55", |     "langchain": "^0.0.55", | ||||||
|     "next": "^13.2.4", |     "next": "^13.2.4", | ||||||
|     "react": "18.2.0", |     "react": "18.2.0", | ||||||
|  | |||||||
							
								
								
									
										36
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										36
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							| @ -7,6 +7,9 @@ dependencies: | |||||||
|   '@heroicons/react': |   '@heroicons/react': | ||||||
|     specifier: ^2.0.17 |     specifier: ^2.0.17 | ||||||
|     version: 2.0.17(react@18.2.0) |     version: 2.0.17(react@18.2.0) | ||||||
|  |   '@mantine/form': | ||||||
|  |     specifier: ^6.0.7 | ||||||
|  |     version: 6.0.7(react@18.2.0) | ||||||
|   '@prisma/client': |   '@prisma/client': | ||||||
|     specifier: ^4.11.0 |     specifier: ^4.11.0 | ||||||
|     version: 4.11.0(prisma@4.11.0) |     version: 4.11.0(prisma@4.11.0) | ||||||
| @ -43,6 +46,9 @@ dependencies: | |||||||
|   '@trpc/server': |   '@trpc/server': | ||||||
|     specifier: ^10.18.0 |     specifier: ^10.18.0 | ||||||
|     version: 10.18.0 |     version: 10.18.0 | ||||||
|  |   axios: | ||||||
|  |     specifier: ^1.3.5 | ||||||
|  |     version: 1.3.5 | ||||||
|   langchain: |   langchain: | ||||||
|     specifier: ^0.0.55 |     specifier: ^0.0.55 | ||||||
|     version: 0.0.55(@supabase/supabase-js@2.15.0) |     version: 0.0.55(@supabase/supabase-js@2.15.0) | ||||||
| @ -244,6 +250,16 @@ packages: | |||||||
|       '@jridgewell/resolve-uri': 3.1.0 |       '@jridgewell/resolve-uri': 3.1.0 | ||||||
|       '@jridgewell/sourcemap-codec': 1.4.14 |       '@jridgewell/sourcemap-codec': 1.4.14 | ||||||
| 
 | 
 | ||||||
|  |   /@mantine/form@6.0.7(react@18.2.0): | ||||||
|  |     resolution: {integrity: sha512-5fApVmV9gqqh0h04KkeLzZ79LCBMt91Nydj/h1uzFNluiIxcLCpN/VrOvqiG9DbvIi6h6yeBP/7rbZheHjuXgg==} | ||||||
|  |     peerDependencies: | ||||||
|  |       react: '>=16.8.0' | ||||||
|  |     dependencies: | ||||||
|  |       fast-deep-equal: 3.1.3 | ||||||
|  |       klona: 2.0.6 | ||||||
|  |       react: 18.2.0 | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|   /@next/env@13.2.4: |   /@next/env@13.2.4: | ||||||
|     resolution: {integrity: sha512-+Mq3TtpkeeKFZanPturjcXt+KHfKYnLlX6jMLyCrmpq6OOs4i1GqBOAauSkii9QeKCMTYzGppar21JU57b/GEA==} |     resolution: {integrity: sha512-+Mq3TtpkeeKFZanPturjcXt+KHfKYnLlX6jMLyCrmpq6OOs4i1GqBOAauSkii9QeKCMTYzGppar21JU57b/GEA==} | ||||||
|     dev: false |     dev: false | ||||||
| @ -969,6 +985,16 @@ packages: | |||||||
|       - debug |       - debug | ||||||
|     dev: false |     dev: false | ||||||
| 
 | 
 | ||||||
|  |   /axios@1.3.5: | ||||||
|  |     resolution: {integrity: sha512-glL/PvG/E+xCWwV8S6nCHcrfg1exGx7vxyUIivIA1iL7BIh6bePylCfVHwp6k13ao7SATxB6imau2kqY+I67kw==} | ||||||
|  |     dependencies: | ||||||
|  |       follow-redirects: 1.15.2 | ||||||
|  |       form-data: 4.0.0 | ||||||
|  |       proxy-from-env: 1.1.0 | ||||||
|  |     transitivePeerDependencies: | ||||||
|  |       - debug | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|   /axobject-query@3.1.1: |   /axobject-query@3.1.1: | ||||||
|     resolution: {integrity: sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==} |     resolution: {integrity: sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==} | ||||||
|     dependencies: |     dependencies: | ||||||
| @ -1672,7 +1698,6 @@ packages: | |||||||
| 
 | 
 | ||||||
|   /fast-deep-equal@3.1.3: |   /fast-deep-equal@3.1.3: | ||||||
|     resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} |     resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} | ||||||
|     dev: true |  | ||||||
| 
 | 
 | ||||||
|   /fast-glob@3.2.12: |   /fast-glob@3.2.12: | ||||||
|     resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} |     resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} | ||||||
| @ -2220,6 +2245,11 @@ packages: | |||||||
|       object.assign: 4.1.4 |       object.assign: 4.1.4 | ||||||
|     dev: true |     dev: true | ||||||
| 
 | 
 | ||||||
|  |   /klona@2.0.6: | ||||||
|  |     resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} | ||||||
|  |     engines: {node: '>= 8'} | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|   /langchain@0.0.55(@supabase/supabase-js@2.15.0): |   /langchain@0.0.55(@supabase/supabase-js@2.15.0): | ||||||
|     resolution: {integrity: sha512-ScL53LvBm2X0rIO1fdMLEoCFYESLVTmY0d71qX7qDrB1y8Y8nCtCA1ZiUNYl4WDQeEvKcvB39qWmAJ2XcB8tqQ==} |     resolution: {integrity: sha512-ScL53LvBm2X0rIO1fdMLEoCFYESLVTmY0d71qX7qDrB1y8Y8nCtCA1ZiUNYl4WDQeEvKcvB39qWmAJ2XcB8tqQ==} | ||||||
|     engines: {node: '>=18'} |     engines: {node: '>=18'} | ||||||
| @ -2891,6 +2921,10 @@ packages: | |||||||
|       object-assign: 4.1.1 |       object-assign: 4.1.1 | ||||||
|       react-is: 16.13.1 |       react-is: 16.13.1 | ||||||
| 
 | 
 | ||||||
|  |   /proxy-from-env@1.1.0: | ||||||
|  |     resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|   /punycode@2.3.0: |   /punycode@2.3.0: | ||||||
|     resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} |     resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} | ||||||
|     engines: {node: '>=6'} |     engines: {node: '>=6'} | ||||||
|  | |||||||
| @ -22,4 +22,19 @@ class SupaService: | |||||||
|                 "url": url, |                 "url": url, | ||||||
|                 "user_id": user_id |                 "user_id": user_id | ||||||
|             }).execute() |             }).execute() | ||||||
|         return result |         return result | ||||||
|  |      | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     def find_website(self, id: str, user_id: str): | ||||||
|  |         result = self.supabase.table("Website").select("*").eq("id", id).eq("user_id", user_id).execute() | ||||||
|  |         return result | ||||||
|  |      | ||||||
|  | 
 | ||||||
|  |     def get_user(self, jwt: str): | ||||||
|  |         try: | ||||||
|  |             result = self.supabase.auth.get_user(jwt) | ||||||
|  |             return result | ||||||
|  |         except: | ||||||
|  |             return None | ||||||
|  |          | ||||||
| @ -1,4 +1,4 @@ | |||||||
| from models import ChatBody | from models import ChatBody, ChatAppBody | ||||||
| from bs4 import BeautifulSoup | from bs4 import BeautifulSoup | ||||||
| 
 | 
 | ||||||
| from langchain.docstore.document import Document as LDocument | from langchain.docstore.document import Document as LDocument | ||||||
| @ -14,21 +14,43 @@ from langchain.prompts.chat import ( | |||||||
| ) | ) | ||||||
| from langchain.vectorstores import Chroma | from langchain.vectorstores import Chroma | ||||||
| 
 | 
 | ||||||
|  | from db.supa import SupaService | ||||||
| 
 | 
 | ||||||
| async def chat_extension_handler(body: ChatBody): | 
 | ||||||
|  | supabase = SupaService() | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | async def chat_app_handler(body: ChatAppBody, jwt: str): | ||||||
|     try: |     try: | ||||||
|         soup = BeautifulSoup(body.html, 'lxml') |  | ||||||
| 
 | 
 | ||||||
|         iframe = soup.find('iframe', id='pageassist-iframe') | 
 | ||||||
|         if iframe: |         user = supabase.get_user(jwt) | ||||||
|             iframe.decompose() | 
 | ||||||
|         div = soup.find('div', id='pageassist-icon') |         if not user: | ||||||
|         if div: |             return { | ||||||
|             div.decompose() |                 "bot_response": "You are not logged in", | ||||||
|         div = soup.find('div', id='__plasmo-loading__') |                 "human_message": body.user_message, | ||||||
|         if div: |             } | ||||||
|             div.decompose() |          | ||||||
|         text = soup.get_text() | 
 | ||||||
|  |         user_id = user.user.id | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         website_response = supabase.find_website(body.id, user_id) | ||||||
|  | 
 | ||||||
|  |         website = website_response.data | ||||||
|  | 
 | ||||||
|  |         if len(website) == 0: | ||||||
|  |             return { | ||||||
|  |                 "bot_response": "Website not found", | ||||||
|  |                 "human_message": body.user_message, | ||||||
|  |             } | ||||||
|  |          | ||||||
|  |         website = website[0] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         text = website["html"] | ||||||
| 
 | 
 | ||||||
|         result = [LDocument(page_content=text, metadata={"source": "test"})] |         result = [LDocument(page_content=text, metadata={"source": "test"})] | ||||||
|         token_splitter =  CharacterTextSplitter(chunk_size=1000, chunk_overlap=0) |         token_splitter =  CharacterTextSplitter(chunk_size=1000, chunk_overlap=0) | ||||||
| @ -43,7 +65,76 @@ async def chat_extension_handler(body: ChatBody): | |||||||
|         messages = [ |         messages = [ | ||||||
|             SystemMessagePromptTemplate.from_template("""You are PageAssist bot. Use the following pieces of context from this webpage to answer the question from the user. |             SystemMessagePromptTemplate.from_template("""You are PageAssist bot. Use the following pieces of context from this webpage to answer the question from the user. | ||||||
| If you don't know the answer, just say you don't know. DO NOT try to make up an answer. | If you don't know the answer, just say you don't know. DO NOT try to make up an answer. | ||||||
| If user want recommendation, helping based on the context then help the user. | If user want recommendation, help from the context, or any other information, please provide it. | ||||||
|  | If the question is not related to the context, politely respond that you are tuned to only answer questions that are related to the context. Helpful answer in markdown: | ||||||
|  | ----------------- | ||||||
|  | {context} | ||||||
|  |             """), | ||||||
|  |             HumanMessagePromptTemplate.from_template("{question}") | ||||||
|  |         ] | ||||||
|  | 
 | ||||||
|  |         prompt = ChatPromptTemplate.from_messages(messages) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         chat =  ConversationalRetrievalChain.from_llm(OpenAI(temperature=0, model_name="gpt-3.5-turbo"), vectorstore.as_retriever(search_kwargs={"k": 1}), return_source_documents=True, qa_prompt=prompt,) | ||||||
|  | 
 | ||||||
|  |         history = [(d["human_message"], d["bot_response"]) for d in body.history] | ||||||
|  | 
 | ||||||
|  |         response = chat({ | ||||||
|  |             "question": body.user_message, | ||||||
|  |             "chat_history": history | ||||||
|  |         }) | ||||||
|  |          | ||||||
|  | 
 | ||||||
|  |         answer = response["answer"] | ||||||
|  |         answer = answer[answer.find(":")+1:].strip() | ||||||
|  | 
 | ||||||
|  |          | ||||||
|  |         return { | ||||||
|  |             "bot_response": answer, | ||||||
|  |             "human_message": body.user_message, | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     except Exception as e: | ||||||
|  |         print(e) | ||||||
|  |         return { | ||||||
|  |             "bot_response": "Something went wrong please try again later", | ||||||
|  |             "human_message": body.user_message, | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | async def chat_extension_handler(body: ChatBody): | ||||||
|  |     try: | ||||||
|  |         soup = BeautifulSoup(body.html, 'lxml') | ||||||
|  | 
 | ||||||
|  |         iframe = soup.find('iframe', id='pageassist-iframe') | ||||||
|  |         if iframe: | ||||||
|  |             iframe.decompose() | ||||||
|  |         div = soup.find('div', id='pageassist-icon') | ||||||
|  |         if div: | ||||||
|  |             div.decompose() | ||||||
|  |         div = soup.find('div', id='__plasmo-loading__') | ||||||
|  |         if div: | ||||||
|  |             div.decompose() | ||||||
|  |         text = soup.get_text() | ||||||
|  | 
 | ||||||
|  |         result = [LDocument(page_content=text, metadata={"source": "test"})] | ||||||
|  |         token_splitter =  CharacterTextSplitter(chunk_size=1000, chunk_overlap=0) | ||||||
|  |         doc = token_splitter.split_documents(result) | ||||||
|  | 
 | ||||||
|  |         print(f'Number of documents: {len(doc)}') | ||||||
|  |          | ||||||
|  | 
 | ||||||
|  |         vectorstore = Chroma.from_documents(doc, OpenAIEmbeddings()) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         messages = [ | ||||||
|  |             SystemMessagePromptTemplate.from_template("""You are PageAssist bot. Use the following pieces of context from this webpage to answer the question from the user. | ||||||
|  | If you don't know the answer, just say you don't know. DO NOT try to make up an answer. | ||||||
|  | If user want recommendation, help from the context, or any other information, please provide it. | ||||||
| If the question is not related to the context, politely respond that you are tuned to only answer questions that are related to the context. Helpful answer in markdown: | If the question is not related to the context, politely respond that you are tuned to only answer questions that are related to the context. Helpful answer in markdown: | ||||||
| ----------------- | ----------------- | ||||||
| {context} | {context} | ||||||
|  | |||||||
| @ -1,2 +1,2 @@ | |||||||
| from .chat import ChatBody | from .chat import ChatBody, ChatAppBody | ||||||
| from .user import UserValidation, SaveChatToApp | from .user import UserValidation, SaveChatToApp | ||||||
| @ -5,3 +5,9 @@ class ChatBody(BaseModel): | |||||||
|     html: str |     html: str | ||||||
|     history: list |     history: list | ||||||
|     # url: str |     # url: str | ||||||
|  | 
 | ||||||
|  | class ChatAppBody(BaseModel): | ||||||
|  |     id: str | ||||||
|  |     user_message: str | ||||||
|  |     url: str | ||||||
|  |     history: list | ||||||
| @ -1,9 +1,14 @@ | |||||||
| from fastapi import APIRouter | from fastapi import APIRouter, Header | ||||||
| from models import ChatBody | from models import ChatBody, ChatAppBody | ||||||
| from handlers.chat import chat_extension_handler | from handlers.chat import chat_extension_handler, chat_app_handler | ||||||
| 
 | 
 | ||||||
| router = APIRouter(prefix="/api/v1") | router = APIRouter(prefix="/api/v1") | ||||||
| 
 | 
 | ||||||
| @router.post("/chat/chrome", tags=["chat"]) | @router.post("/chat/chrome", tags=["chat"]) | ||||||
| async def chat_extension(body: ChatBody): | async def chat_extension(body: ChatBody): | ||||||
|     return await chat_extension_handler(body) |     return await chat_extension_handler(body) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @router.post("/chat/app", tags=["chat"]) | ||||||
|  | async def chat_app(body: ChatAppBody, x_auth_token: str = Header()): | ||||||
|  |     return await chat_app_handler(body, x_auth_token) | ||||||
| @ -1,8 +1,15 @@ | |||||||
| import { TrashIcon } from "@heroicons/react/24/outline"; | import { TrashIcon } from "@heroicons/react/24/outline"; | ||||||
|  | import { useSupabaseClient } from "@supabase/auth-helpers-react"; | ||||||
| import Link from "next/link"; | import Link from "next/link"; | ||||||
|  | import { useRouter } from "next/router"; | ||||||
| import React from "react"; | import React from "react"; | ||||||
|  | import { api } from "~/utils/api"; | ||||||
| import { iconUrl } from "~/utils/icon"; | import { iconUrl } from "~/utils/icon"; | ||||||
| 
 | 
 | ||||||
|  | import { useForm } from "@mantine/form"; | ||||||
|  | import axios from "axios"; | ||||||
|  | import { useMutation } from "@tanstack/react-query"; | ||||||
|  | 
 | ||||||
| type Message = { | type Message = { | ||||||
|   isBot: boolean; |   isBot: boolean; | ||||||
|   message: string; |   message: string; | ||||||
| @ -22,6 +29,51 @@ type Props = { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export const CahtBox = (props: Props) => { | export const CahtBox = (props: Props) => { | ||||||
|  |   const supabase = useSupabaseClient(); | ||||||
|  | 
 | ||||||
|  |   const form = useForm({ | ||||||
|  |     initialValues: { | ||||||
|  |       message: "", | ||||||
|  |       isBot: false, | ||||||
|  |     }, | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   const sendToBot = async (message: string) => { | ||||||
|  |     const { data } = await supabase.auth.getSession(); | ||||||
|  | 
 | ||||||
|  |     const response = await axios.post( | ||||||
|  |       `${process.env.NEXT_PUBLIC_PAGEASSIST_URL}/api/v1/chat/app`, | ||||||
|  |       { | ||||||
|  |         user_message: message, | ||||||
|  |         history: history, | ||||||
|  |         url: props.url, | ||||||
|  |         id: props.id, | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         headers: { | ||||||
|  |           "X-Auth-Token": data.session?.access_token, | ||||||
|  |         }, | ||||||
|  |       } | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     return response.data; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   const { mutateAsync: sendToBotAsync, isLoading: isSending } = useMutation( | ||||||
|  |     sendToBot, | ||||||
|  |     { | ||||||
|  |       onSuccess: (data) => { | ||||||
|  |         setMessages([...messages, { isBot: true, message: data.bot_response }]); | ||||||
|  |         setHistory([...history, data]); | ||||||
|  |       }, | ||||||
|  |       onError: (error) => { | ||||||
|  |         setMessages([ | ||||||
|  |           ...messages, | ||||||
|  |           { isBot: true, message: "Something went wrong" }, | ||||||
|  |         ]); | ||||||
|  |       }, | ||||||
|  |     } | ||||||
|  |   ); | ||||||
|   const [messages, setMessages] = React.useState<Message[]>([ |   const [messages, setMessages] = React.useState<Message[]>([ | ||||||
|     { |     { | ||||||
|       isBot: true, |       isBot: true, | ||||||
| @ -29,6 +81,12 @@ export const CahtBox = (props: Props) => { | |||||||
|     }, |     }, | ||||||
|   ]); |   ]); | ||||||
| 
 | 
 | ||||||
|  |   // const fetchSession = async () => {
 | ||||||
|  | 
 | ||||||
|  |   // const {data}= await supabase.auth.getSession();
 | ||||||
|  |   // data.session?.access_token
 | ||||||
|  |   // }
 | ||||||
|  | 
 | ||||||
|   const [history, setHistory] = React.useState<History[]>([]); |   const [history, setHistory] = React.useState<History[]>([]); | ||||||
|   const divRef = React.useRef(null); |   const divRef = React.useRef(null); | ||||||
| 
 | 
 | ||||||
| @ -37,6 +95,15 @@ export const CahtBox = (props: Props) => { | |||||||
|     divRef.current.scrollIntoView({ behavior: "smooth" }); |     divRef.current.scrollIntoView({ behavior: "smooth" }); | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|  |   const router = useRouter(); | ||||||
|  | 
 | ||||||
|  |   const { mutateAsync: deleteChatByIdAsync, isLoading: isDeleting } = | ||||||
|  |     api.chat.deleteChatById.useMutation({ | ||||||
|  |       onSuccess: () => { | ||||||
|  |         router.push("/dashboard"); | ||||||
|  |       }, | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|   return ( |   return ( | ||||||
|     <div className="flex flex-col border bg-white"> |     <div className="flex flex-col border bg-white"> | ||||||
|       {/* header */} |       {/* header */} | ||||||
| @ -67,10 +134,40 @@ export const CahtBox = (props: Props) => { | |||||||
| 
 | 
 | ||||||
|         <div className="flex"> |         <div className="flex"> | ||||||
|           <button |           <button | ||||||
|  |             onClick={async () => { | ||||||
|  |               const isOk = confirm( | ||||||
|  |                 "Are you sure you want to delete this chat?" | ||||||
|  |               ); | ||||||
|  | 
 | ||||||
|  |               if (isOk) { | ||||||
|  |                 await deleteChatByIdAsync({ | ||||||
|  |                   id: props.id, | ||||||
|  |                 }); | ||||||
|  |               } | ||||||
|  |             }} | ||||||
|  |             disabled={isDeleting} | ||||||
|             type="button" |             type="button" | ||||||
|             className="inline-flex items-center rounded-full border border-transparent bg-red-600 p-1.5 text-white shadow-sm hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2" |             className="inline-flex items-center rounded-full border border-transparent bg-red-600 p-1.5 text-white shadow-sm hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2" | ||||||
|           > |           > | ||||||
|             <TrashIcon className="h-5 w-5" aria-hidden="true" /> |             {isDeleting ? ( | ||||||
|  |               <svg | ||||||
|  |                 xmlns="http://www.w3.org/2000/svg" | ||||||
|  |                 fill="none" | ||||||
|  |                 className="h-5 w-5 animate-spin fill-white text-white dark:text-gray-600" | ||||||
|  |                 viewBox="0 0 100 101" | ||||||
|  |               > | ||||||
|  |                 <path | ||||||
|  |                   fill="currentColor" | ||||||
|  |                   d="M100 50.59c0 27.615-22.386 50.001-50 50.001s-50-22.386-50-50 22.386-50 50-50 50 22.386 50 50zm-90.919 0c0 22.6 18.32 40.92 40.919 40.92 22.599 0 40.919-18.32 40.919-40.92 0-22.598-18.32-40.918-40.919-40.918-22.599 0-40.919 18.32-40.919 40.919z" | ||||||
|  |                 ></path> | ||||||
|  |                 <path | ||||||
|  |                   fill="currentFill" | ||||||
|  |                   d="M93.968 39.04c2.425-.636 3.894-3.128 3.04-5.486A50 50 0 0041.735 1.279c-2.474.414-3.922 2.919-3.285 5.344.637 2.426 3.12 3.849 5.6 3.484a40.916 40.916 0 0144.131 25.769c.902 2.34 3.361 3.802 5.787 3.165z" | ||||||
|  |                 ></path> | ||||||
|  |               </svg> | ||||||
|  |             ) : ( | ||||||
|  |               <TrashIcon className="h-5 w-5" aria-hidden="true" /> | ||||||
|  |             )} | ||||||
|           </button> |           </button> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
| @ -107,22 +204,31 @@ export const CahtBox = (props: Props) => { | |||||||
|               </div> |               </div> | ||||||
|             ); |             ); | ||||||
|           })} |           })} | ||||||
|  |           {isSending && ( | ||||||
|  |             <div className="mt-2 flex w-full max-w-xs space-x-3"> | ||||||
|  |               <div> | ||||||
|  |                 <div className="rounded-r-lg rounded-bl-lg bg-gray-300 p-3"> | ||||||
|  |                   <p className="text-sm">Hold on, I'm looking...</p> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           )} | ||||||
|           <div ref={divRef} /> |           <div ref={divRef} /> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|       <div className="items-center bg-gray-300 px-4  py-4"> |       <div className="items-center bg-gray-300 px-4  py-4"> | ||||||
|         <form |         <form | ||||||
|         //   onSubmit={form.onSubmit(async (values) => {
 |           onSubmit={form.onSubmit(async (values) => { | ||||||
|         //     setMessages([...messages, values])
 |             setMessages([...messages, values]); | ||||||
|         //     form.reset()
 |             form.reset(); | ||||||
|         //     await sendToBotAsync(values.message)
 |             await sendToBotAsync(values.message); | ||||||
|         //   })}
 |           })} | ||||||
|         > |         > | ||||||
|           <div className="flex-grow space-y-6"> |           <div className="flex-grow space-y-6"> | ||||||
|             <div className="flex"> |             <div className="flex"> | ||||||
|               <span className="mr-3"> |               <span className="mr-3"> | ||||||
|                 <button |                 <button | ||||||
|                   //   disabled={isSending || isSaving}
 |                   disabled={isSending} | ||||||
|                   onClick={() => { |                   onClick={() => { | ||||||
|                     setHistory([]); |                     setHistory([]); | ||||||
|                     setMessages([ |                     setMessages([ | ||||||
| @ -153,12 +259,12 @@ export const CahtBox = (props: Props) => { | |||||||
|               </span> |               </span> | ||||||
|               <div className="flex-grow"> |               <div className="flex-grow"> | ||||||
|                 <input |                 <input | ||||||
|                   //   disabled={isSending || isSaving}
 |                   disabled={isSending} | ||||||
|                   className="flex h-10 w-full items-center rounded px-3 text-sm" |                   className="flex h-10 w-full items-center rounded px-3 text-sm" | ||||||
|                   type="text" |                   type="text" | ||||||
|                   required |                   required | ||||||
|                   placeholder="Type your message…" |                   placeholder="Type your message…" | ||||||
|                   //   {...form.getInputProps("message")}
 |                   {...form.getInputProps("message")} | ||||||
|                 /> |                 /> | ||||||
|               </div> |               </div> | ||||||
|             </div> |             </div> | ||||||
|  | |||||||
| @ -48,7 +48,6 @@ export const chatRouter = createTRPCRouter({ | |||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     const site = await prisma.website.findFirst({ |     const site = await prisma.website.findFirst({ | ||||||
|       where: { |       where: { | ||||||
|         id: input.id, |         id: input.id, | ||||||
| @ -74,4 +73,39 @@ export const chatRouter = createTRPCRouter({ | |||||||
| 
 | 
 | ||||||
|     return site; |     return site; | ||||||
|   }), |   }), | ||||||
|  | 
 | ||||||
|  |   deleteChatById: publicProcedure.input(z.object({ | ||||||
|  |     id: z.string(), | ||||||
|  |   })).mutation(async ({ ctx, input }) => { | ||||||
|  |     const user = ctx.user; | ||||||
|  |     const prisma = ctx.prisma; | ||||||
|  |     if (!user) { | ||||||
|  |       throw new TRPCError({ | ||||||
|  |         "code": "UNAUTHORIZED", | ||||||
|  |         "message": "You are not authorized to access this resource", | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const site = await prisma.website.findFirst({ | ||||||
|  |       where: { | ||||||
|  |         id: input.id, | ||||||
|  |         user_id: user.id, | ||||||
|  |       }, | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     if (!site) { | ||||||
|  |       throw new TRPCError({ | ||||||
|  |         "code": "NOT_FOUND", | ||||||
|  |         "message": "Chat not found", | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     await prisma.website.delete({ | ||||||
|  |       where: { | ||||||
|  |         id: input.id, | ||||||
|  |       }, | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     return site; | ||||||
|  |   }), | ||||||
| }); | }); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user