Merge branch 'arc53:main' into issues/1262

This commit is contained in:
Mousumi Pal
2024-10-08 23:00:29 +05:30
committed by GitHub
32 changed files with 500 additions and 177 deletions

View File

@@ -37,7 +37,7 @@ export default function Hero({
<Fragment key={key}>
<button
onClick={() => handleQuestion({ question: demo.query })}
className="w-full rounded-full border-2 border-silver px-6 py-4 text-left hover:border-gray-4000 dark:hover:border-gray-3000 xl:min-w-[24vw]"
className="w-full rounded-full border border-silver px-6 py-4 text-left hover:border-gray-4000 dark:hover:border-gray-3000 xl:min-w-[24vw]"
>
<p className="mb-1 font-semibold text-black dark:text-silver">
{demo.header}

View File

@@ -119,6 +119,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
.delete(id, {})
.then(() => {
fetchConversations();
resetConversation();
})
.catch((error) => console.error(error));
};
@@ -155,6 +156,15 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
});
};
const resetConversation = () => {
dispatch(setConversation([]));
dispatch(
updateConversationId({
query: { conversationId: null },
}),
);
};
async function updateConversationName(updatedConversation: {
name: string;
id: string;
@@ -199,24 +209,28 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
<img
src={Expand}
alt="menu toggle"
className={`${
!navOpen ? 'rotate-180' : 'rotate-0'
} m-auto transition-all duration-200`}
className={`${!navOpen ? 'rotate-180' : 'rotate-0'
} m-auto transition-all duration-200`}
/>
</button>
)}
<div
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-[1px] border-b-0 bg-white transition-all dark:border-r-purple-taupe dark:bg-chinese-black dark:text-white`}
className={`${!navOpen && '-ml-96 md:-ml-[18rem]'
} duration-20 fixed top-0 z-20 flex h-full w-72 flex-col border-r-[1px] border-b-0 bg-white transition-all dark:border-r-purple-taupe dark:bg-chinese-black dark:text-white`}
>
<div
className={'visible mt-2 flex h-[6vh] 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 className="my-auto mx-4 flex cursor-pointer gap-1.5" onClick={() => {
if (isMobile) {
setNavOpen(!navOpen);
}
}}>
<a href="/" className="flex gap-1.5">
<img className="mb-2 h-10" src={DocsGPT3} alt="" />
<p className="my-auto text-2xl font-semibold">DocsGPT</p>
</a>
</div>
<button
className="float-right mr-5"
@@ -227,25 +241,21 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
<img
src={Expand}
alt="menu toggle"
className={`${
!navOpen ? 'rotate-180' : 'rotate-0'
} m-auto transition-all duration-200`}
className={`${!navOpen ? 'rotate-180' : 'rotate-0'
} m-auto transition-all duration-200`}
/>
</button>
</div>
<NavLink
to={'/'}
onClick={() => {
dispatch(setConversation([]));
dispatch(
updateConversationId({
query: { conversationId: null },
}),
);
if (isMobile) {
setNavOpen(!navOpen);
}
resetConversation();
}}
className={({ isActive }) =>
`${
isActive ? 'bg-gray-3000 dark:bg-transparent' : ''
`${isActive ? 'bg-gray-3000 dark:bg-transparent' : ''
} group sticky 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 dark:border-purple-taupe dark:text-white dark:hover:bg-transparent`
}
>
@@ -270,6 +280,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
key={conversation.id}
conversation={conversation}
selectConversation={(id) => handleConversationClick(id)}
onCoversationClick={() => {if (isMobile) { setNavOpen(false) }}}
onDeleteConversation={(id) => handleDeleteConversation(id)}
onSave={(conversation) =>
updateConversationName(conversation)
@@ -293,21 +304,36 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
isDocsListOpen={isDocsListOpen}
setIsDocsListOpen={setIsDocsListOpen}
handleDeleteClick={handleDeleteClick}
handlePostDocumentSelect={(option?: string) => {
if (isMobile) {
setNavOpen(!navOpen)
}
}}
/>
<img
className="mt-2 h-9 w-9 hover:cursor-pointer"
src={UploadIcon}
onClick={() => setUploadModalState('ACTIVE')}
></img>
onClick={() => {
setUploadModalState('ACTIVE')
if (isMobile) {
setNavOpen(!navOpen);
}
}
}></img>
</div>
<p className="ml-5 mt-3 text-sm font-semibold">{t('sourceDocs')}</p>
</div>
<div className="flex flex-col gap-2 border-b-[1px] py-2 dark:border-b-purple-taupe">
<NavLink
onClick={() => {
if (isMobile) {
setNavOpen(!navOpen);
}
resetConversation();
}}
to="/settings"
className={({ isActive }) =>
`my-auto mx-4 flex h-9 cursor-pointer gap-4 rounded-3xl hover:bg-gray-100 dark:hover:bg-[#28292E] ${
isActive ? 'bg-gray-3000 dark:bg-transparent' : ''
`my-auto mx-4 flex h-9 cursor-pointer gap-4 rounded-3xl hover:bg-gray-100 dark:hover:bg-[#28292E] ${isActive ? 'bg-gray-3000 dark:bg-transparent' : ''
}`
}
>
@@ -323,10 +349,15 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
</div>
<div className="flex justify-between gap-2 border-b-[1.5px] py-2 dark:border-b-purple-taupe">
<NavLink
onClick={() => {
if (isMobile) {
setNavOpen(!navOpen);
}
resetConversation();
}}
to="/about"
className={({ isActive }) =>
`my-auto mx-4 flex h-9 cursor-pointer gap-4 rounded-3xl hover:bg-gray-100 dark:hover:bg-[#28292E] ${
isActive ? 'bg-gray-3000 dark:bg-[#28292E]' : ''
`my-auto mx-4 flex h-9 cursor-pointer gap-4 rounded-3xl hover:bg-gray-100 dark:hover:bg-[#28292E] ${isActive ? 'bg-gray-3000 dark:bg-[#28292E]' : ''
}`
}
>

View File

@@ -0,0 +1,96 @@
import React, { useCallback, useRef, useState } from 'react';
import ArrowLeft from '../assets/arrow-left.svg';
import ArrowRight from '../assets/arrow-right.svg';
import { useTranslation } from 'react-i18next';
type HiddenGradientType = 'left' | 'right' | undefined;
const useTabs = () => {
const { t } = useTranslation();
const tabs = [
t('settings.general.label'),
t('settings.documents.label'),
t('settings.apiKeys.label'),
t('settings.analytics.label'),
t('settings.logs.label'),
];
return tabs;
};
interface SettingsBarProps {
setActiveTab: React.Dispatch<React.SetStateAction<string>>;
activeTab: string;
}
const SettingsBar = ({ setActiveTab, activeTab }: SettingsBarProps) => {
const [hiddenGradient, setHiddenGradient] =
useState<HiddenGradientType>('left');
const containerRef = useRef<null | HTMLDivElement>(null);
const tabs = useTabs();
const scrollTabs = useCallback(
(direction: number) => {
if (containerRef.current) {
const container = containerRef.current;
container.scrollLeft += direction * 100; // Adjust the scroll amount as needed
if (container.scrollLeft === 0) {
setHiddenGradient('left');
} else if (
container.scrollLeft + container.offsetWidth ===
container.scrollWidth
) {
setHiddenGradient('right');
} else {
setHiddenGradient(undefined);
}
}
},
[containerRef.current],
);
return (
<div className="relative mt-6 flex flex-row items-center space-x-1 md:space-x-0 overflow-auto">
<div
className={`${hiddenGradient === 'left' ? 'hidden' : ''} md:hidden absolute inset-y-0 left-6 w-14 bg-gradient-to-r from-white dark:from-raisin-black pointer-events-none`}
></div>
<div
className={`${hiddenGradient === 'right' ? 'hidden' : ''} md:hidden absolute inset-y-0 right-6 w-14 bg-gradient-to-l from-white dark:from-raisin-black pointer-events-none`}
></div>
<div className="md:hidden z-10">
<button
onClick={() => scrollTabs(-1)}
className="flex h-6 w-6 items-center rounded-full justify-center transition-all hover:bg-gray-100"
>
<img src={ArrowLeft} alt="left-arrow" className="h-3" />
</button>
</div>
<div
ref={containerRef}
className="flex flex-nowrap overflow-x-auto no-scrollbar md:space-x-4 scroll-smooth snap-x"
>
{tabs.map((tab, index) => (
<button
key={index}
onClick={() => setActiveTab(tab)}
className={`snap-start h-9 rounded-3xl px-4 font-bold ${
activeTab === tab
? 'bg-purple-3000 text-purple-30 dark:bg-dark-charcoal'
: 'text-gray-6000'
}`}
>
{tab}
</button>
))}
</div>
<div className="md:hidden z-10">
<button
onClick={() => scrollTabs(1)}
className="flex h-6 w-6 rounded-full items-center justify-center hover:bg-gray-100"
>
<img src={ArrowRight} alt="right-arrow" className="h-3" />
</button>
</div>
</div>
);
};
export default SettingsBar;

View File

@@ -11,6 +11,7 @@ type Props = {
isDocsListOpen: boolean;
setIsDocsListOpen: React.Dispatch<React.SetStateAction<boolean>>;
handleDeleteClick: any;
handlePostDocumentSelect: any;
};
function SourceDropdown({
@@ -20,6 +21,7 @@ function SourceDropdown({
setIsDocsListOpen,
isDocsListOpen,
handleDeleteClick,
handlePostDocumentSelect, // Callback function fired after a document is selected
}: Props) {
const dispatch = useDispatch();
const { t } = useTranslation();
@@ -85,6 +87,7 @@ function SourceDropdown({
onClick={() => {
dispatch(setSelectedDocs(option));
setIsDocsListOpen(false);
handlePostDocumentSelect(option);
}}
>
<span
@@ -118,7 +121,9 @@ function SourceDropdown({
className="flex cursor-pointer items-center justify-between hover:bg-gray-100 dark:text-bright-gray dark:hover:bg-purple-taupe"
onClick={handleEmptyDocumentSelect}
>
<span className="ml-4 flex-1 overflow-hidden overflow-ellipsis whitespace-nowrap py-3">
<span className="ml-4 flex-1 overflow-hidden overflow-ellipsis whitespace-nowrap py-3" onClick = {() => {
handlePostDocumentSelect(null);
}}>
{t('none')}
</span>
</div>

View File

@@ -54,10 +54,6 @@ export default function Conversation() {
}
}, []);
useEffect(() => {
fetchStream.current && fetchStream.current.abort();
}, [conversationId]);
useEffect(() => {
if (queries.length) {
queries[queries.length - 1].error && setLastQueryReturnedErr(true);

View File

@@ -59,7 +59,12 @@ const ConversationBubble = forwardRef<
className={`flex flex-row-reverse self-end flex-wrap ${className}`}
>
<Avatar className="mt-2 text-2xl" avatar="🧑‍💻"></Avatar>
<div className="ml-10 mr-2 flex items-center rounded-[28px] bg-purple-30 py-[14px] px-[19px] text-white max-w-full whitespace-pre-wrap leading-normal break-normal">
<div
style={{
wordBreak: 'break-word',
}}
className="ml-10 mr-2 flex items-center rounded-[28px] bg-purple-30 py-[14px] px-[19px] text-white max-w-full whitespace-pre-wrap leading-normal"
>
{message}
</div>
</div>

View File

@@ -22,6 +22,7 @@ interface ConversationProps {
interface ConversationTileProps {
conversation: ConversationProps;
selectConversation: (arg1: string) => void;
onCoversationClick: () => void; //Callback to handle click on conversation tile regardless of selected or not
onDeleteConversation: (arg1: string) => void;
onSave: ({ name, id }: ConversationProps) => void;
}
@@ -29,6 +30,7 @@ interface ConversationTileProps {
export default function ConversationTile({
conversation,
selectConversation,
onCoversationClick,
onDeleteConversation,
onSave,
}: ConversationTileProps) {
@@ -90,6 +92,7 @@ export default function ConversationTile({
setIsHovered(false);
}}
onClick={() => {
onCoversationClick();
conversationId !== conversation.id &&
selectConversation(conversation.id);
}}
@@ -158,7 +161,12 @@ export default function ConversationTile({
</button>
)}
{isOpen && (
<div className="flex-start absolute z-30 flex w-32 translate-x-1 translate-y-5 flex-col rounded-xl bg-stone-100 text-sm text-black shadow-xl dark:bg-chinese-black dark:text-chinese-silver md:w-36">
<div
className="flex-start absolute z-30 flex w-32 translate-x-1 translate-y-5 flex-col rounded-xl bg-stone-100 text-sm text-black shadow-xl dark:bg-chinese-black dark:text-chinese-silver md:w-36"
style={{
top: `${(tileRef.current?.getBoundingClientRect().top ?? 0) + window.scrollY + 8}px`,
}}
>
<button
onClick={(event: SyntheticEvent) => {
event.stopPropagation();

View File

@@ -151,6 +151,7 @@ export const conversationSlice = createSlice({
state,
action: PayloadAction<{ index: number; query: Partial<Query> }>,
) {
if (state.status === 'idle') return;
const { index, query } = action.payload;
if (query.response != undefined) {
state.queries[index].response =
@@ -167,6 +168,7 @@ export const conversationSlice = createSlice({
action: PayloadAction<{ query: Partial<Query> }>,
) {
state.conversationId = action.payload.query.conversationId ?? null;
state.status = 'idle';
},
updateStreamingSource(
state,

View File

@@ -47,6 +47,28 @@ body.dark {
}
}
@layer components {
.table-default {
@apply block w-max table-auto content-center justify-center rounded-xl border border-silver dark:border-silver/40 text-center dark:text-bright-gray;
}
.table-default th {
@apply border-r border-silver dark:border-silver/40 p-4 w-[244px];
}
.table-default th:last-child {
@apply w-[auto] border-r-0;
}
.table-default td {
@apply border-r border-t border-silver dark:border-silver/40 px-4 py-2;
}
.table-default td:last-child {
@apply border-r-0;
}
}
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
/* Document

View File

@@ -79,12 +79,13 @@
"remote": "Remote",
"name": "Name",
"choose": "Choose Files",
"info": "Please upload .pdf, .txt, .rst, .csv, .docx, .md, .zip limited to 25mb",
"info": "Please upload .pdf, .txt, .rst, .csv, .xlsx, .docx, .md, .zip limited to 25mb",
"uploadedFiles": "Uploaded Files",
"cancel": "Cancel",
"train": "Train",
"link": "Link",
"urlLink": "URL Link",
"repoUrl": "Repository URL",
"reddit": {
"id": "Client ID",
"secret": "Client Secret",

View File

@@ -85,6 +85,7 @@
"train": "Entrenar",
"link": "Enlace",
"urlLink": "Enlace URL",
"repoUrl": "URL del Repositorio",
"reddit": {
"id": "ID de Cliente",
"secret": "Secreto de Cliente",

View File

@@ -85,6 +85,7 @@
"train": "トレーニング",
"link": "リンク",
"urlLink": "URLリンク",
"repoUrl": "リポジトリURL",
"reddit": {
"id": "クライアントID",
"secret": "クライアントシークレット",

View File

@@ -85,6 +85,7 @@
"train": "训练",
"link": "链接",
"urlLink": "URL 链接",
"repoUrl": "存储库 URL",
"reddit": {
"id": "客户端 ID",
"secret": "客户端密钥",

View File

@@ -100,35 +100,29 @@ export default function APIKeys() {
)}
<div className="mt-[27px] w-full">
<div className="w-full overflow-x-auto">
<table className="block w-max table-auto content-center justify-center rounded-xl border text-center dark:border-chinese-silver dark:text-bright-gray">
<table className="table-default">
<thead>
<tr>
<th className="w-[244px] border-r p-4">
{t('settings.apiKeys.name')}
</th>
<th className="w-[244px] border-r px-4 py-2">
{t('settings.apiKeys.sourceDoc')}
</th>
<th className="w-[244px] border-r px-4 py-2">
{t('settings.apiKeys.key')}
</th>
<th className="px-4 py-2"></th>
<th>{t('settings.apiKeys.name')}</th>
<th>{t('settings.apiKeys.sourceDoc')}</th>
<th>{t('settings.apiKeys.key')}</th>
<th></th>
</tr>
</thead>
<tbody>
{!apiKeys?.length && (
<tr>
<td colSpan={4} className="border-t p-4">
<td colSpan={4} className="!p-4">
{t('settings.apiKeys.noData')}
</td>
</tr>
)}
{apiKeys?.map((element, index) => (
<tr key={index}>
<td className="border-r border-t p-4">{element.name}</td>
<td className="border-r border-t p-4">{element.source}</td>
<td className="border-r border-t p-4">{element.key}</td>
<td className="border-t p-4">
<td>{element.name}</td>
<td>{element.source}</td>
<td>{element.key}</td>
<td>
<img
src={Trash}
alt="Delete"

View File

@@ -55,28 +55,20 @@ const Documents: React.FC<DocumentsProps> = ({
<div className="mt-8">
<div className="flex flex-col relative">
<div className="z-10 w-full overflow-x-auto">
<table className="block w-max table-auto content-center justify-center rounded-xl border text-center dark:border-chinese-silver dark:text-bright-gray">
<table className="table-default">
<thead>
<tr>
<th className="border-r p-4 md:w-[244px]">
{t('settings.documents.name')}
</th>
<th className="w-[244px] border-r px-4 py-2">
{t('settings.documents.date')}
</th>
<th className="w-[244px] border-r px-4 py-2">
{t('settings.documents.tokenUsage')}
</th>
<th className="w-[244px] border-r px-4 py-2">
{t('settings.documents.type')}
</th>
<th className="px-4 py-2"></th>
<th>{t('settings.documents.name')}</th>
<th>{t('settings.documents.date')}</th>
<th>{t('settings.documents.tokenUsage')}</th>
<th>{t('settings.documents.type')}</th>
<th></th>
</tr>
</thead>
<tbody>
{!documents?.length && (
<tr>
<td colSpan={5} className="border-t p-4">
<td colSpan={5} className="!p-4">
{t('settings.documents.noData')}
</td>
</tr>
@@ -84,19 +76,15 @@ const Documents: React.FC<DocumentsProps> = ({
{documents &&
documents.map((document, index) => (
<tr key={index}>
<td className="border-r border-t px-4 py-2">
{document.name}
</td>
<td className="border-r border-t px-4 py-2">
{document.date}
</td>
<td className="border-r border-t px-4 py-2">
<td>{document.name}</td>
<td>{document.date}</td>
<td>
{document.tokens ? formatTokens(+document.tokens) : ''}
</td>
<td className="border-r border-t px-4 py-2">
<td>
{document.type === 'remote' ? 'Pre-loaded' : 'Private'}
</td>
<td className="border-t px-4 py-2">
<td>
<div className="flex flex-row items-center">
{document.type !== 'remote' && (
<img

View File

@@ -3,8 +3,7 @@ import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
import userService from '../api/services/userService';
import ArrowLeft from '../assets/arrow-left.svg';
import ArrowRight from '../assets/arrow-right.svg';
import SettingsBar from '../components/SettingsBar';
import i18n from '../locale/i18n';
import { Doc } from '../models/misc';
import {
@@ -21,13 +20,6 @@ import Widgets from './Widgets';
export default function Settings() {
const dispatch = useDispatch();
const { t } = useTranslation();
const tabs = [
t('settings.general.label'),
t('settings.documents.label'),
t('settings.apiKeys.label'),
t('settings.analytics.label'),
t('settings.logs.label'),
];
const [activeTab, setActiveTab] = React.useState(t('settings.general.label'));
const [widgetScreenshot, setWidgetScreenshot] = React.useState<File | null>(
null,
@@ -61,39 +53,7 @@ export default function Settings() {
<p className="text-2xl font-bold text-eerie-black dark:text-bright-gray">
{t('settings.label')}
</p>
<div className="mt-6 flex flex-row items-center space-x-4 overflow-auto md:space-x-8 ">
<div className="md:hidden">
<button
onClick={() => scrollTabs(-1)}
className="flex h-8 w-8 items-center justify-center rounded-full border-2 border-purple-30 transition-all hover:bg-gray-100"
>
<img src={ArrowLeft} alt="left-arrow" className="h-6 w-6" />
</button>
</div>
<div className="flex flex-nowrap space-x-4 overflow-x-auto no-scrollbar md:space-x-8">
{tabs.map((tab, index) => (
<button
key={index}
onClick={() => setActiveTab(tab)}
className={`h-9 rounded-3xl px-4 font-bold ${
activeTab === tab
? 'bg-purple-3000 text-purple-30 dark:bg-dark-charcoal'
: 'text-gray-6000'
}`}
>
{tab}
</button>
))}
</div>
<div className="md:hidden">
<button
onClick={() => scrollTabs(1)}
className="flex h-8 w-8 items-center justify-center rounded-full border-2 border-purple-30 hover:bg-gray-100"
>
<img src={ArrowRight} alt="right-arrow" className="h-6 w-6" />
</button>
</div>
</div>
<SettingsBar activeTab={activeTab} setActiveTab={setActiveTab} />
{renderActiveTab()}
{/* {activeTab === 'Widgets' && (
@@ -105,13 +65,6 @@ export default function Settings() {
</div>
);
function scrollTabs(direction: number) {
const container = document.querySelector('.flex-nowrap');
if (container) {
container.scrollLeft += direction * 100; // Adjust the scroll amount as needed
}
}
function renderActiveTab() {
switch (activeTab) {
case t('settings.general.label'):

View File

@@ -24,6 +24,7 @@ function Upload({
const [docName, setDocName] = useState('');
const [urlName, setUrlName] = useState('');
const [url, setUrl] = useState('');
const [repoUrl, setRepoUrl] = useState(''); // P3f93
const [redditData, setRedditData] = useState({
client_id: '',
client_secret: '',
@@ -48,6 +49,7 @@ function Upload({
// { label: 'Sitemap', value: 'sitemap' },
{ label: 'Link', value: 'url' },
{ label: 'Reddit', value: 'reddit' },
{ label: 'GitHub', value: 'github' }, // P3f93
];
const [urlType, setUrlType] = useState<{ label: string; value: string }>({
@@ -238,6 +240,9 @@ function Upload({
formData.set('name', 'other');
formData.set('data', JSON.stringify(redditData));
}
if (urlType.value === 'github') {
formData.append('repo_url', repoUrl); // Pdeac
}
const apiHost = import.meta.env.VITE_API_HOST;
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', (event) => {
@@ -270,6 +275,7 @@ function Upload({
'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
['.docx'],
'text/csv': ['.csv'],
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': ['.xlsx'],
},
});
@@ -376,7 +382,7 @@ function Upload({
size="w-full"
rounded="3xl"
/>
{urlType.label !== 'Reddit' ? (
{urlType.label !== 'Reddit' && urlType.label !== 'GitHub' ? (
<>
<Input
placeholder={`Enter ${t('modals.uploadDoc.name')}`}
@@ -403,6 +409,33 @@ function Upload({
</span>
</div>
</>
) : urlType.label === 'GitHub' ? ( // P3f93
<>
<Input
placeholder={`Enter ${t('modals.uploadDoc.name')}`}
type="text"
value={urlName}
onChange={(e) => setUrlName(e.target.value)}
borderVariant="thin"
></Input>
<div className="relative bottom-12 left-2 mt-[-20px]">
<span className="bg-white px-2 text-xs text-gray-4000 dark:bg-outer-space dark:text-silver">
{t('modals.uploadDoc.name')}
</span>
</div>
<Input
placeholder={t('modals.uploadDoc.repoUrl')}
type="text"
value={repoUrl}
onChange={(e) => setRepoUrl(e.target.value)}
borderVariant="thin"
></Input>
<div className="relative bottom-12 left-2 mt-[-20px]">
<span className="bg-white px-2 text-xs text-gray-4000 dark:bg-outer-space dark:text-silver">
{t('modals.uploadDoc.repoUrl')}
</span>
</div>
</>
) : (
<div className="flex flex-col gap-1 mt-2">
<div>