Merge branch 'main' into settings
@@ -1,5 +1,6 @@
|
||||
//TODO - Add hyperlinks to text
|
||||
//TODO - Styling
|
||||
import DocsGPT3 from './assets/cute_docsgpt3.svg';
|
||||
|
||||
export default function About() {
|
||||
return (
|
||||
@@ -7,7 +8,7 @@ export default function About() {
|
||||
<article className="place-items-left mx-auto my-auto flex w-full max-w-6xl flex-col gap-4 rounded-3xl bg-gray-100 p-6 text-jet lg:p-6 xl:p-10">
|
||||
<div className="flex items-center">
|
||||
<p className="mr-2 text-3xl">About DocsGPT</p>
|
||||
<p className="text-[21px]">🦖</p>
|
||||
<img className="h14 mb-2" src={DocsGPT3} alt="DocsGPT" />
|
||||
</div>
|
||||
<p className="mt-4">
|
||||
Find the information in your documentation through AI-powered
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
export default function Avatar({
|
||||
avatar,
|
||||
size,
|
||||
className,
|
||||
}: {
|
||||
avatar: string;
|
||||
size?: 'SMALL' | 'MEDIUM' | 'LARGE';
|
||||
className: string;
|
||||
}) {
|
||||
const styles = {
|
||||
transform: 'scale(-1, 1)',
|
||||
};
|
||||
return (
|
||||
<div style={styles} className={className}>
|
||||
{avatar}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
import DocsGPT3 from './assets/cute_docsgpt3.svg';
|
||||
|
||||
export default function Hero({ className = '' }: { className?: string }) {
|
||||
return (
|
||||
<div className={`mt-14 mb-12 flex flex-col `}>
|
||||
<div className="mb-10 flex items-center justify-center ">
|
||||
<p className="mr-2 text-4xl font-semibold">DocsGPT</p>
|
||||
<p className="text-[27px]">🦖</p>
|
||||
<img className="mb-2 h-14" src={DocsGPT3} alt="DocsGPT" />
|
||||
</div>
|
||||
<p className="mb-3 text-center leading-6 text-black-1000">
|
||||
Welcome to DocsGPT, your technical documentation assistant!
|
||||
@@ -17,9 +19,9 @@ export default function Hero({ className = '' }: { className?: string }) {
|
||||
Start by entering your query in the input field below and we will do the
|
||||
rest!
|
||||
</p>
|
||||
<div className="sections mt-8 flex flex-wrap items-center justify-center sm:gap-1 md:gap-0 ">
|
||||
<div className="mr-4 mb-4 h-[224px] rounded-[25px] bg-gradient-to-l from-[#6EE7B7]/70 via-[#3B82F6] to-[#9333EA]/50 p-1">
|
||||
<div className="h-full rounded-[21px] bg-white p-6">
|
||||
<div className="sections mt-8 flex flex-col items-center justify-center gap-1 sm:gap-0 lg:flex-row">
|
||||
<div className="relative mb-4 h-60 rounded-[25px] bg-gradient-to-l from-[#6EE7B7]/70 via-[#3B82F6] to-[#9333EA]/50 p-1 sm:mr-0 lg:rounded-r-none">
|
||||
<div className="h-full rounded-[21px] bg-white p-6 lg:rounded-r-none">
|
||||
<img
|
||||
src="/message-text.svg"
|
||||
alt="lock"
|
||||
@@ -35,8 +37,8 @@ export default function Hero({ className = '' }: { className?: string }) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mr-4 mb-4 rounded-[25px] bg-gradient-to-l from-[#6EE7B7]/70 via-[#3B82F6] to-[#9333EA]/50 p-1">
|
||||
<div className="h-full rounded-[21px] bg-white p-6">
|
||||
<div className="relative mb-4 h-60 rounded-[25px] bg-gradient-to-r from-[#6EE7B7]/70 via-[#3B82F6] to-[#9333EA]/50 p-1 sm:mr-0 lg:rounded-none lg:px-0">
|
||||
<div className="h-full rounded-[21px] bg-white p-6 lg:rounded-none">
|
||||
<img src="/lock.svg" alt="lock" className="h-[24px] w-[24px]" />
|
||||
<h2 className="mt-2 mb-3 text-lg font-bold">Secure Data Storage</h2>
|
||||
<p className=" w-[250px] text-xs text-gray-500">
|
||||
@@ -47,8 +49,8 @@ export default function Hero({ className = '' }: { className?: string }) {
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-4 rounded-[25px] bg-gradient-to-l from-[#6EE7B7]/70 via-[#3B82F6] to-[#9333EA]/50 p-1">
|
||||
<div className="h-full rounded-[21px] bg-white p-6">
|
||||
<div className="relative mb-4 h-60 rounded-[25px] bg-gradient-to-l from-[#6EE7B7]/70 via-[#3B82F6] to-[#9333EA]/50 p-1 lg:rounded-l-none">
|
||||
<div className="h-full rounded-[21px] bg-white p-6 lg:rounded-l-none">
|
||||
<img
|
||||
src="/message-programming.svg"
|
||||
alt="lock"
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { NavLink, useNavigate } from 'react-router-dom';
|
||||
import Arrow1 from './assets/arrow.svg';
|
||||
import DocsGPT3 from './assets/cute_docsgpt3.svg';
|
||||
import Documentation from './assets/documentation.svg';
|
||||
import Discord from './assets/discord.svg';
|
||||
import Arrow2 from './assets/dropdown-arrow.svg';
|
||||
import Expand from './assets/expand.svg';
|
||||
import Exit from './assets/exit.svg';
|
||||
import Message from './assets/message.svg';
|
||||
import Github from './assets/github.svg';
|
||||
import Hamburger from './assets/hamburger.svg';
|
||||
import Key from './assets/key.svg';
|
||||
import Info from './assets/info.svg';
|
||||
import SettingGear from './assets/settingGear.svg';
|
||||
import Documentation from './assets/documentation.svg';
|
||||
import Discord from './assets/discord.svg';
|
||||
import Github from './assets/github.svg';
|
||||
import Key from './assets/key.svg';
|
||||
import Add from './assets/add.svg';
|
||||
import UploadIcon from './assets/upload.svg';
|
||||
import { ActiveState } from './models/misc';
|
||||
import APIKeyModal from './preferences/APIKeyModal';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import {
|
||||
selectApiKeyStatus,
|
||||
selectSelectedDocs,
|
||||
@@ -173,17 +177,17 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
|
||||
<>
|
||||
{!navOpen && (
|
||||
<button
|
||||
className="duration-25 absolute relative top-3 left-3 z-20 hidden transition-all md:block"
|
||||
className="duration-25 absolute sticky top-3 left-3 z-20 hidden transition-all md:block"
|
||||
onClick={() => {
|
||||
setNavOpen(!navOpen);
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src={Arrow1}
|
||||
src={Expand}
|
||||
alt="menu toggle"
|
||||
className={`${
|
||||
!navOpen ? 'rotate-180' : 'rotate-0'
|
||||
} m-auto w-3 transition-all duration-200`}
|
||||
} m-auto transition-all duration-200`}
|
||||
/>
|
||||
</button>
|
||||
)}
|
||||
@@ -191,21 +195,27 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
|
||||
ref={navRef}
|
||||
className={`${
|
||||
!navOpen && '-ml-96 md:-ml-[18rem]'
|
||||
} duration-20 fixed top-0 z-20 flex h-full w-72 flex-col border-r-2 bg-gray-50 transition-all`}
|
||||
} duration-20 fixed top-0 z-20 flex h-full w-72 flex-col border-r-2 bg-white transition-all`}
|
||||
>
|
||||
<div className={'visible h-16 w-full border-b-2 md:h-12'}>
|
||||
<div
|
||||
className={'visible mt-2 flex h-16 w-full justify-between md:h-12'}
|
||||
>
|
||||
<div className="my-auto mx-4 flex cursor-pointer gap-1.5">
|
||||
<img className="mb-2 h-10" src={DocsGPT3} alt="" />
|
||||
<p className="my-auto text-2xl font-semibold">DocsGPT</p>
|
||||
</div>
|
||||
<button
|
||||
className="float-right mr-5 mt-5 h-5 w-5 md:mt-3"
|
||||
className="float-right mr-5"
|
||||
onClick={() => {
|
||||
setNavOpen(!navOpen);
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src={Arrow1}
|
||||
src={Expand}
|
||||
alt="menu toggle"
|
||||
className={`${
|
||||
!navOpen ? 'rotate-180' : 'rotate-0'
|
||||
} m-auto w-3 transition-all duration-200`}
|
||||
} m-auto transition-all duration-200`}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
@@ -221,30 +231,38 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
|
||||
}}
|
||||
className={({ isActive }) =>
|
||||
`${
|
||||
isActive && conversationId === null ? 'bg-gray-3000' : ''
|
||||
} my-auto mx-4 mt-4 flex h-9 cursor-pointer gap-4 rounded-3xl hover:bg-gray-100`
|
||||
isActive ? 'bg-gray-3000' : ''
|
||||
} group my-auto mx-4 mt-4 flex cursor-pointer gap-2.5 rounded-3xl border border-silver p-3 hover:border-rainy-gray hover:bg-gray-3000`
|
||||
}
|
||||
>
|
||||
<img src={Message} className="ml-4 w-5"></img>
|
||||
<p className="my-auto text-sm text-eerie-black">New Chat</p>
|
||||
<img
|
||||
src={Add}
|
||||
alt="new"
|
||||
className="opacity-80 group-hover:opacity-100"
|
||||
/>
|
||||
<p className="my-auto text-sm text-dove-gray group-hover:text-neutral-600">
|
||||
New Chat
|
||||
</p>
|
||||
</NavLink>
|
||||
<div className="conversations-container max-h-[25rem] overflow-y-auto">
|
||||
{conversations?.map((conversation) => (
|
||||
<ConversationTile
|
||||
key={conversation.id}
|
||||
conversation={conversation}
|
||||
selectConversation={(id) => handleConversationClick(id)}
|
||||
onDeleteConversation={(id) => handleDeleteConversation(id)}
|
||||
onSave={(conversation) => updateConversationName(conversation)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
{conversations && (
|
||||
<div className="conversations-container max-h-[25rem] overflow-y-auto">
|
||||
<p className="ml-6 mt-3 text-sm font-semibold">Chats</p>
|
||||
{conversations?.map((conversation) => (
|
||||
<ConversationTile
|
||||
key={conversation.id}
|
||||
conversation={conversation}
|
||||
selectConversation={(id) => handleConversationClick(id)}
|
||||
onDeleteConversation={(id) => handleDeleteConversation(id)}
|
||||
onSave={(conversation) => updateConversationName(conversation)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex-grow border-b-2 border-gray-100"></div>
|
||||
<div className="flex flex-col-reverse border-b-2">
|
||||
<div className="relative my-4 flex gap-2 px-2">
|
||||
<div
|
||||
className="flex h-12 w-full cursor-pointer justify-between rounded-3xl border-2 bg-white"
|
||||
className="flex h-12 w-5/6 cursor-pointer justify-between rounded-3xl border-2 bg-white"
|
||||
onClick={() => setIsDocsListOpen(!isDocsListOpen)}
|
||||
>
|
||||
{selectedDocs && (
|
||||
@@ -306,7 +324,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<p className="ml-6 mt-3 font-bold text-jet">Source Docs</p>
|
||||
<p className="ml-6 mt-3 text-sm font-semibold">Source Docs</p>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2 border-b-2 py-2">
|
||||
<div
|
||||
@@ -316,7 +334,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
|
||||
}}
|
||||
>
|
||||
<img src={Key} alt="key" className="ml-2 w-6" />
|
||||
<p className="my-auto text-eerie-black">Reset Key</p>
|
||||
<p className="my-auto text-sm text-eerie-black">Reset Key</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -341,7 +359,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
|
||||
}
|
||||
>
|
||||
<img src={Info} alt="info" className="ml-2 w-5" />
|
||||
<p className="my-auto text-eerie-black">About</p>
|
||||
<p className="my-auto text-sm text-eerie-black">About</p>
|
||||
</NavLink>
|
||||
|
||||
<a
|
||||
@@ -351,7 +369,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
|
||||
className="my-auto mx-4 flex h-9 cursor-pointer gap-4 rounded-3xl hover:bg-gray-100"
|
||||
>
|
||||
<img src={Documentation} alt="documentation" className="ml-2 w-5" />
|
||||
<p className="my-auto text-eerie-black">Documentation</p>
|
||||
<p className="my-auto text-sm text-eerie-black">Documentation</p>
|
||||
</a>
|
||||
<a
|
||||
href="https://discord.gg/WHJdfbQDR4"
|
||||
@@ -360,7 +378,9 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
|
||||
className="my-auto mx-4 flex h-9 cursor-pointer gap-4 rounded-3xl hover:bg-gray-100"
|
||||
>
|
||||
<img src={Discord} alt="link" className="ml-2 w-5" />
|
||||
<p className="my-auto text-eerie-black">Visit our Discord</p>
|
||||
<p className="my-auto text-sm text-eerie-black">
|
||||
Visit our Discord
|
||||
</p>
|
||||
</a>
|
||||
|
||||
<a
|
||||
@@ -370,7 +390,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
|
||||
className="my-auto mx-4 flex h-9 cursor-pointer gap-4 rounded-3xl hover:bg-gray-100"
|
||||
>
|
||||
<img src={Github} alt="link" className="ml-2 w-5" />
|
||||
<p className="my-auto text-eerie-black">Visit our Github</p>
|
||||
<p className="my-auto text-sm text-eerie-black">Visit our Github</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
10
frontend/src/assets/add.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_2494_3464)">
|
||||
<path d="M7.43717 14.1667C7.43717 14.4485 7.54912 14.7187 7.74837 14.918C7.94763 15.1172 8.21788 15.2292 8.49967 15.2292C8.78147 15.2292 9.05172 15.1172 9.25098 14.918C9.45023 14.7187 9.56217 14.4485 9.56217 14.1667V9.56249H14.1663C14.4481 9.56249 14.7184 9.45055 14.9176 9.2513C15.1169 9.05204 15.2288 8.78179 15.2288 8.49999C15.2288 8.2182 15.1169 7.94795 14.9176 7.74869C14.7184 7.54944 14.4481 7.43749 14.1663 7.43749H9.56217V2.83333C9.56217 2.55154 9.45023 2.28128 9.25098 2.08203C9.05172 1.88277 8.78147 1.77083 8.49967 1.77083C8.21788 1.77083 7.94763 1.88277 7.74837 2.08203C7.54912 2.28128 7.43717 2.55154 7.43717 2.83333V7.43749H2.83301C2.55122 7.43749 2.28096 7.54944 2.08171 7.74869C1.88245 7.94795 1.77051 8.2182 1.77051 8.49999C1.77051 8.78179 1.88245 9.05204 2.08171 9.2513C2.28096 9.45055 2.55122 9.56249 2.83301 9.56249H7.43717V14.1667Z" fill="#5D5D5D" />
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_2494_3464">
|
||||
<rect width="17" height="17" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -1,3 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="11" viewBox="0 0 14 11" fill="none">
|
||||
<path d="M4.95919 10.1906C4.84318 10.1902 4.72847 10.166 4.62222 10.1194C4.51596 10.0729 4.42041 10.0049 4.34152 9.91985L0.229353 5.54538C0.0756344 5.38157 -0.00671208 5.1634 0.000428491 4.93886C0.00756906 4.71433 0.103612 4.50183 0.267428 4.34812C0.431245 4.1944 0.649417 4.11205 0.873948 4.11919C1.09848 4.12633 1.31098 4.22238 1.4647 4.38619L4.95073 8.10068L12.0666 0.316329C12.1389 0.226405 12.2287 0.152193 12.3306 0.0982513C12.4326 0.0443098 12.5445 0.0117775 12.6594 0.00265255C12.7744 -0.00647237 12.89 0.00800286 12.9992 0.045189C13.1084 0.082375 13.2088 0.141487 13.2943 0.218894C13.3798 0.296301 13.4485 0.390369 13.4964 0.49532C13.5442 0.600272 13.57 0.713891 13.5723 0.829198C13.5746 0.944506 13.5534 1.05907 13.5098 1.16585C13.4662 1.27263 13.4012 1.36937 13.3189 1.45014L5.58533 9.91139C5.50718 9.998 5.41197 10.0675 5.30567 10.1156C5.19938 10.1636 5.0843 10.1892 4.96766 10.1906H4.95919Z" fill="#747474"/>
|
||||
</svg>
|
||||
<svg width="16px" height="16px" viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg" fill="#11ee1c" stroke="#11ee1c" stroke-width="83.96799999999999"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"><path d="M866.133333 258.133333L362.666667 761.6l-204.8-204.8L98.133333 618.666667 362.666667 881.066667l563.2-563.2z" fill="#11ee1c"></path></g></svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 490 B |
9
frontend/src/assets/cute_docsgpt3.svg
Normal file
|
After Width: | Height: | Size: 256 KiB |
@@ -1,3 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="100" height="100" viewBox="0,0,256,256">
|
||||
<g transform="translate(-19.2,-19.2) scale(1.15,1.15)"><g fill="#605b5b" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><g transform="scale(10.66667,10.66667)"><path d="M13.172,2h-7.172c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2v-11.172c0,-0.53 -0.211,-1.039 -0.586,-1.414l-4.828,-4.828c-0.375,-0.375 -0.884,-0.586 -1.414,-0.586zM15,18h-6c-0.552,0 -1,-0.448 -1,-1v0c0,-0.552 0.448,-1 1,-1h6c0.552,0 1,0.448 1,1v0c0,0.552 -0.448,1 -1,1zM15,14h-6c-0.552,0 -1,-0.448 -1,-1v0c0,-0.552 0.448,-1 1,-1h6c0.552,0 1,0.448 1,1v0c0,0.552 -0.448,1 -1,1zM13,9v-5.5l5.5,5.5z"></path></g></g></g>
|
||||
</svg>
|
||||
<g transform="translate(-19.2,-19.2) scale(1.15,1.15)"><g fill="black" fill-opacity="0.5" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><g transform="scale(10.66667,10.66667)"><path d="M13.172,2h-7.172c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2v-11.172c0,-0.53 -0.211,-1.039 -0.586,-1.414l-4.828,-4.828c-0.375,-0.375 -0.884,-0.586 -1.414,-0.586zM15,18h-6c-0.552,0 -1,-0.448 -1,-1v0c0,-0.552 0.448,-1 1,-1h6c0.552,0 1,0.448 1,1v0c0,0.552 -0.448,1 -1,1zM15,14h-6c-0.552,0 -1,-0.448 -1,-1v0c0,-0.552 0.448,-1 1,-1h6c0.552,0 1,0.448 1,1v0c0,0.552 -0.448,1 -1,1zM13,9v-5.5l5.5,5.5z"></path></g></g></g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 936 B After Width: | Height: | Size: 950 B |
4
frontend/src/assets/expand.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="27" height="26" viewBox="0 0 27 26" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.03371 5.27275L4.1915 20.9162C4.20021 21.7802 4.90766 22.4735 5.77162 22.4648L21.4151 22.307C22.2791 22.2983 22.9724 21.5909 22.9637 20.7269L22.8059 5.0834C22.7972 4.21944 22.0897 3.52612 21.2258 3.53483L5.58228 3.69262C4.71831 3.70134 4.02499 4.40878 4.03371 5.27275Z" stroke="#949494" stroke-width="2.08591" stroke-linejoin="round"/>
|
||||
<path d="M9.42289 22.428L9.23354 3.65585M17.6924 15.0436L15.5856 12.9788L17.6504 10.872M6.29419 22.4596L12.5516 22.3965M6.10484 3.68741L12.3622 3.62429" stroke="#949494" stroke-width="2.08591" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 692 B |
13
frontend/src/components/Avatar.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
export default function Avatar({
|
||||
avatar,
|
||||
size,
|
||||
className,
|
||||
}: {
|
||||
avatar: string | ReactNode;
|
||||
size?: 'SMALL' | 'MEDIUM' | 'LARGE';
|
||||
className: string;
|
||||
}) {
|
||||
return <div className={`${className} flex-shrink-0`}>{avatar}</div>;
|
||||
}
|
||||
@@ -192,7 +192,7 @@ export default function Conversation() {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<p className="w-[100vw] self-center bg-white p-5 text-center text-xs text-gray-2000 md:w-full">
|
||||
<p className="w-[100vw] self-center bg-white p-5 text-center text-xs text-gray-595959 md:w-full">
|
||||
This is a chatbot that uses the GPT-3, Faiss and LangChain to answer
|
||||
questions.
|
||||
</p>
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import { forwardRef, useState } from 'react';
|
||||
import Avatar from '../Avatar';
|
||||
import Avatar from '../components/Avatar';
|
||||
import { FEEDBACK, MESSAGE_TYPE } from './conversationModels';
|
||||
import classes from './ConversationBubble.module.css';
|
||||
import Alert from './../assets/alert.svg';
|
||||
import { ReactComponent as Like } from './../assets/like.svg';
|
||||
import { ReactComponent as Dislike } from './../assets/dislike.svg';
|
||||
import { ReactComponent as Copy } from './../assets/copy.svg';
|
||||
import { ReactComponent as Checkmark } from './../assets/checkmark.svg';
|
||||
import { ReactComponent as CheckMark } from './../assets/checkmark.svg';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||
import { vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
||||
import DocsGPT3 from '../assets/cute_docsgpt3.svg';
|
||||
|
||||
const DisableSourceFE = import.meta.env.VITE_DISABLE_SOURCE_FE || false;
|
||||
|
||||
@@ -37,8 +38,13 @@ const ConversationBubble = forwardRef<
|
||||
// Reset copied to false after a few seconds
|
||||
setTimeout(() => {
|
||||
setCopied(false);
|
||||
}, 2000);
|
||||
}, 3000);
|
||||
};
|
||||
const [isCopyHovered, setIsCopyHovered] = useState(false);
|
||||
const [isLikeHovered, setIsLikeHovered] = useState(false);
|
||||
const [isDislikeHovered, setIsDislikeHovered] = useState(false);
|
||||
const [isLikeClicked, setIsLikeClicked] = useState(false);
|
||||
const [isDislikeClicked, setIsDislikeClicked] = useState(false);
|
||||
|
||||
let bubble;
|
||||
|
||||
@@ -55,13 +61,26 @@ const ConversationBubble = forwardRef<
|
||||
);
|
||||
} else {
|
||||
bubble = (
|
||||
<div ref={ref} className={`flex self-start ${className} group flex-col`}>
|
||||
<div
|
||||
ref={ref}
|
||||
className={`flex self-start ${className} group flex-col pr-20`}
|
||||
>
|
||||
<div className="flex self-start">
|
||||
<Avatar className="mt-2 text-2xl" avatar="🦖"></Avatar>
|
||||
<Avatar
|
||||
className="mt-2 h-12 w-12 text-2xl"
|
||||
avatar={
|
||||
<img
|
||||
src={DocsGPT3}
|
||||
alt="DocsGPT"
|
||||
className="h-full w-full object-cover"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
<div
|
||||
className={`ml-2 mr-5 flex rounded-3xl bg-gray-1000 p-3.5 ${
|
||||
type === 'ERROR'
|
||||
? 'flex-row rounded-full border border-transparent bg-[#FFE7E7] p-2 py-5 text-sm font-normal text-red-3000 dark:border-red-2000 dark:text-white'
|
||||
? 'flex-row items-center rounded-full border border-transparent bg-[#FFE7E7] p-2 py-5 text-sm font-normal text-red-3000 dark:border-red-2000 dark:text-white'
|
||||
: 'flex-col rounded-3xl'
|
||||
}`}
|
||||
>
|
||||
@@ -146,52 +165,113 @@ const ConversationBubble = forwardRef<
|
||||
)}
|
||||
</div>
|
||||
<div
|
||||
className={`relative mr-2 flex items-center justify-center md:invisible ${
|
||||
className={`relative mr-5 flex items-center justify-center md:invisible ${
|
||||
type !== 'ERROR' ? 'group-hover:md:visible' : ''
|
||||
}`}
|
||||
>
|
||||
{copied ? (
|
||||
<Checkmark className="absolute left-2 top-4" />
|
||||
) : (
|
||||
<Copy
|
||||
className={`absolute left-2 top-4 cursor-pointer fill-gray-4000 hover:stroke-gray-4000`}
|
||||
onClick={() => {
|
||||
handleCopyClick(message);
|
||||
<div className="absolute left-2 top-4">
|
||||
<div
|
||||
className="flex items-center justify-center rounded-full p-2"
|
||||
style={{
|
||||
backgroundColor: isCopyHovered ? '#EEEEEE' : '#ffffff',
|
||||
}}
|
||||
></Copy>
|
||||
)}
|
||||
>
|
||||
{copied ? (
|
||||
<CheckMark
|
||||
className="cursor-pointer stroke-green-2000"
|
||||
onMouseEnter={() => setIsCopyHovered(true)}
|
||||
onMouseLeave={() => setIsCopyHovered(false)}
|
||||
/>
|
||||
) : (
|
||||
<Copy
|
||||
className={`cursor-pointer fill-none`}
|
||||
onClick={() => {
|
||||
handleCopyClick(message);
|
||||
}}
|
||||
onMouseEnter={() => setIsCopyHovered(true)}
|
||||
onMouseLeave={() => setIsCopyHovered(false)}
|
||||
></Copy>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={`relative mr-2 flex items-center justify-center md:invisible ${
|
||||
className={`relative mr-5 flex items-center justify-center ${
|
||||
!isLikeClicked ? 'md:invisible' : ''
|
||||
} ${
|
||||
feedback === 'LIKE' || type !== 'ERROR'
|
||||
? 'group-hover:md:visible'
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
<Like
|
||||
className={`absolute left-6 top-4 cursor-pointer ${
|
||||
feedback === 'LIKE'
|
||||
? 'fill-purple-30 stroke-purple-30'
|
||||
: 'fill-none stroke-gray-4000 hover:fill-gray-4000'
|
||||
}`}
|
||||
onClick={() => handleFeedback?.('LIKE')}
|
||||
></Like>
|
||||
<div className="absolute left-6 top-4">
|
||||
<div
|
||||
className="flex items-center justify-center rounded-full p-2"
|
||||
style={{
|
||||
backgroundColor: isLikeHovered
|
||||
? isLikeClicked
|
||||
? 'rgba(125, 84, 209, 0.3)'
|
||||
: '#EEEEEE'
|
||||
: isLikeClicked
|
||||
? 'rgba(125, 84, 209, 0.3)'
|
||||
: '#ffffff',
|
||||
}}
|
||||
>
|
||||
<Like
|
||||
className={`cursor-pointer ${
|
||||
isLikeClicked || feedback === 'LIKE'
|
||||
? 'fill-white-3000 stroke-purple-30'
|
||||
: 'fill-none stroke-gray-4000'
|
||||
}`}
|
||||
onClick={() => {
|
||||
handleFeedback?.('LIKE');
|
||||
setIsLikeClicked(true);
|
||||
setIsDislikeClicked(false);
|
||||
}}
|
||||
onMouseEnter={() => setIsLikeHovered(true)}
|
||||
onMouseLeave={() => setIsLikeHovered(false)}
|
||||
></Like>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={`relative mr-10 flex items-center justify-center md:invisible ${
|
||||
className={`mr-13 relative flex items-center justify-center ${
|
||||
!isDislikeClicked ? 'md:invisible' : ''
|
||||
} ${
|
||||
feedback === 'DISLIKE' || type !== 'ERROR'
|
||||
? 'group-hover:md:visible'
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
<Dislike
|
||||
className={`absolute left-10 top-4 cursor-pointer ${
|
||||
feedback === 'DISLIKE'
|
||||
? 'fill-red-2000 stroke-red-2000'
|
||||
: 'fill-none stroke-gray-4000 hover:fill-gray-4000'
|
||||
}`}
|
||||
onClick={() => handleFeedback?.('DISLIKE')}
|
||||
></Dislike>
|
||||
<div className="absolute left-10 top-4">
|
||||
<div
|
||||
className="flex items-center justify-center rounded-full p-2"
|
||||
style={{
|
||||
backgroundColor: isDislikeHovered
|
||||
? isDislikeClicked
|
||||
? 'rgba(248, 113, 113, 0.3)'
|
||||
: '#EEEEEE'
|
||||
: isDislikeClicked
|
||||
? 'rgba(248, 113, 113, 0.3)'
|
||||
: '#ffffff',
|
||||
}}
|
||||
>
|
||||
<Dislike
|
||||
className={`cursor-pointer ${
|
||||
isDislikeClicked || feedback === 'DISLIKE'
|
||||
? 'fill-white-3000 stroke-red-2000'
|
||||
: 'fill-none stroke-gray-4000'
|
||||
}`}
|
||||
onClick={() => {
|
||||
handleFeedback?.('DISLIKE');
|
||||
setIsDislikeClicked(true);
|
||||
setIsLikeClicked(false);
|
||||
}}
|
||||
onMouseEnter={() => setIsDislikeHovered(true)}
|
||||
onMouseLeave={() => setIsDislikeHovered(false)}
|
||||
></Dislike>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -3,11 +3,10 @@ import { useSelector } from 'react-redux';
|
||||
import Edit from '../assets/edit.svg';
|
||||
import Exit from '../assets/exit.svg';
|
||||
import Message from '../assets/message.svg';
|
||||
import CheckMark from '../assets/checkmark.svg';
|
||||
import CheckMark2 from '../assets/checkMark2.svg';
|
||||
import Trash from '../assets/trash.svg';
|
||||
|
||||
import { selectConversationId } from '../preferences/preferenceSlice';
|
||||
import { useOutsideAlerter } from '../hooks';
|
||||
|
||||
interface ConversationProps {
|
||||
name: string;
|
||||
@@ -31,15 +30,15 @@ export default function ConversationTile({
|
||||
|
||||
const [isEdit, setIsEdit] = useState(false);
|
||||
const [conversationName, setConversationsName] = useState('');
|
||||
useOutsideAlerter(
|
||||
tileRef,
|
||||
() =>
|
||||
handleSaveConversation({
|
||||
id: conversationId || conversation.id,
|
||||
name: conversationName,
|
||||
}),
|
||||
[conversationName],
|
||||
);
|
||||
// useOutsideAlerter(
|
||||
// tileRef,
|
||||
// () =>
|
||||
// handleSaveConversation({
|
||||
// id: conversationId || conversation.id,
|
||||
// name: conversationName,
|
||||
// }),
|
||||
// [conversationName],
|
||||
// );
|
||||
|
||||
useEffect(() => {
|
||||
setConversationsName(conversation.name);
|
||||
@@ -95,7 +94,7 @@ export default function ConversationTile({
|
||||
{conversationId === conversation.id && (
|
||||
<div className="flex">
|
||||
<img
|
||||
src={isEdit ? CheckMark : Edit}
|
||||
src={isEdit ? CheckMark2 : Edit}
|
||||
alt="Edit"
|
||||
className="mr-2 h-4 w-4 cursor-pointer hover:opacity-50"
|
||||
id={`img-${conversation.id}`}
|
||||
|
||||
@@ -29,6 +29,12 @@ module.exports = {
|
||||
'purple-3000': 'rgb(230,222,247)',
|
||||
'blue-4000': 'rgba(0, 125, 255, 0.36)',
|
||||
'blue-5000': 'rgba(0, 125, 255)',
|
||||
'green-2000': '#0FFF50',
|
||||
'light-gray': '#edeef0',
|
||||
'white-3000': '#ffffff',
|
||||
'dove-gray': '#6c6c6c',
|
||||
silver: '#c4c4c4',
|
||||
'rainy-gray': '#a4a4a4',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||