mirror of
https://github.com/arc53/DocsGPT.git
synced 2025-11-30 17:13:15 +00:00
conflict fixing
This commit is contained in:
80
frontend/src/components/Help.tsx
Normal file
80
frontend/src/components/Help.tsx
Normal file
@@ -0,0 +1,80 @@
|
||||
import { useState, useRef, useEffect } from 'react';
|
||||
import Info from '../assets/info.svg';
|
||||
import PageIcon from '../assets/documentation.svg';
|
||||
import EmailIcon from '../assets/envelope.svg';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
const Help = () => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const dropdownRef = useRef<HTMLDivElement | null>(null);
|
||||
const buttonRef = useRef<HTMLButtonElement | null>(null);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const toggleDropdown = () => {
|
||||
setIsOpen((prev) => !prev);
|
||||
};
|
||||
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (
|
||||
dropdownRef.current &&
|
||||
!dropdownRef.current.contains(event.target as Node) &&
|
||||
buttonRef.current &&
|
||||
!buttonRef.current.contains(event.target as Node)
|
||||
) {
|
||||
setIsOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="relative inline-block text-sm" ref={dropdownRef}>
|
||||
<button
|
||||
ref={buttonRef}
|
||||
onClick={toggleDropdown}
|
||||
className="my-auto mx-4 w-full flex items-center h-9 gap-4 rounded-3xl hover:bg-gray-100 dark:hover:bg-[#28292E]"
|
||||
>
|
||||
<img src={Info} alt="info" className="ml-1 w-5 filter dark:invert" />
|
||||
{t('help')}
|
||||
</button>
|
||||
{isOpen && (
|
||||
<div
|
||||
className={`absolute translate-x-4 -translate-y-28 z-10 w-48 shadow-lg bg-white dark:bg-[#444654] rounded-xl`}
|
||||
>
|
||||
<a
|
||||
href="https://docs.docsgpt.cloud/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-start gap-4 px-4 py-2 text-black dark:text-white hover:bg-bright-gray dark:hover:bg-[#545561] rounded-t-xl"
|
||||
>
|
||||
<img
|
||||
src={PageIcon}
|
||||
alt="Documentation"
|
||||
className="filter dark:invert"
|
||||
width={20}
|
||||
/>
|
||||
{t('documentation')}
|
||||
</a>
|
||||
<a
|
||||
href="mailto:contact@arc53.com"
|
||||
className="flex items-start gap-4 px-4 py-2 text-black dark:text-white hover:bg-bright-gray dark:hover:bg-[#545561] rounded-b-xl"
|
||||
>
|
||||
<img
|
||||
src={EmailIcon}
|
||||
alt="Email Us"
|
||||
className="filter dark:invert p-0.5"
|
||||
width={20}
|
||||
/>
|
||||
{t('emailUs')}
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Help;
|
||||
@@ -4,10 +4,11 @@ const RetryIcon = (props: SVGProps<SVGSVGElement>) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlSpace="preserve"
|
||||
width={16}
|
||||
height={16}
|
||||
width={props.width ? props.width : 16}
|
||||
height={props.height ? props.height : 16}
|
||||
fill={props.fill}
|
||||
stroke={props.stroke}
|
||||
stroke={props.stroke ? props.stroke : 'none'}
|
||||
strokeWidth={props.strokeWidth ? props.strokeWidth : 10}
|
||||
viewBox="0 0 383.748 383.748"
|
||||
{...props}
|
||||
>
|
||||
|
||||
@@ -71,9 +71,9 @@ const SettingsBar = ({ setActiveTab, activeTab }: SettingsBarProps) => {
|
||||
<button
|
||||
key={index}
|
||||
onClick={() => setActiveTab(tab)}
|
||||
className={`snap-start h-9 rounded-3xl px-4 font-bold ${
|
||||
className={`snap-start h-9 rounded-3xl px-4 font-bold hover:text-neutral-600 dark:hover:text-white/60 ${
|
||||
activeTab === tab
|
||||
? 'bg-purple-3000 text-purple-30 dark:bg-dark-charcoal'
|
||||
? 'bg-neutral-100 text-neutral-600 dark:bg-dark-charcoal dark:text-white/60'
|
||||
: 'text-gray-6000'
|
||||
}`}
|
||||
>
|
||||
|
||||
138
frontend/src/components/SkeletonLoader.tsx
Normal file
138
frontend/src/components/SkeletonLoader.tsx
Normal file
@@ -0,0 +1,138 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
interface SkeletonLoaderProps {
|
||||
count?: number;
|
||||
component?: 'default' | 'analysis' | 'chatbot' | 'logs';
|
||||
}
|
||||
|
||||
const SkeletonLoader: React.FC<SkeletonLoaderProps> = ({
|
||||
count = 1,
|
||||
component = 'default',
|
||||
}) => {
|
||||
const [skeletonCount, setSkeletonCount] = useState(count);
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
const windowWidth = window.innerWidth;
|
||||
|
||||
if (windowWidth > 1024) {
|
||||
setSkeletonCount(1);
|
||||
} else if (windowWidth > 768) {
|
||||
setSkeletonCount(count);
|
||||
} else {
|
||||
setSkeletonCount(Math.min(count, 2));
|
||||
}
|
||||
};
|
||||
|
||||
handleResize();
|
||||
window.addEventListener('resize', handleResize);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', handleResize);
|
||||
};
|
||||
}, [count]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col space-y-4">
|
||||
{component === 'default' ? (
|
||||
[...Array(skeletonCount)].map((_, idx) => (
|
||||
<div
|
||||
key={idx}
|
||||
className={`p-6 ${skeletonCount === 1 ? 'w-full' : 'w-60'} dark:bg-raisin-black rounded-3xl animate-pulse`}
|
||||
>
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<div className="h-4 bg-gray-600 rounded mb-2 w-3/4"></div>
|
||||
<div className="h-4 bg-gray-600 rounded mb-2 w-5/6"></div>
|
||||
<div className="h-4 bg-gray-600 rounded mb-2 w-1/2"></div>
|
||||
<div className="h-4 bg-gray-600 rounded mb-2 w-3/4"></div>
|
||||
<div className="h-4 bg-gray-600 rounded mb-2 w-full"></div>
|
||||
</div>
|
||||
<div className="border-t border-gray-600 my-4"></div>
|
||||
<div>
|
||||
<div className="h-4 bg-gray-600 rounded mb-2 w-2/3"></div>
|
||||
<div className="h-4 bg-gray-600 rounded mb-2 w-1/4"></div>
|
||||
<div className="h-4 bg-gray-600 rounded mb-2 w-full"></div>
|
||||
</div>
|
||||
<div className="border-t border-gray-600 my-4"></div>
|
||||
<div>
|
||||
<div className="h-4 bg-gray-600 rounded mb-2 w-5/6"></div>
|
||||
<div className="h-4 bg-gray-600 rounded mb-2 w-1/3"></div>
|
||||
<div className="h-4 bg-gray-600 rounded mb-2 w-2/3"></div>
|
||||
<div className="h-4 bg-gray-600 rounded mb-2 w-full"></div>
|
||||
</div>
|
||||
<div className="border-t border-gray-600 my-4"></div>
|
||||
<div className="h-4 bg-gray-600 rounded w-3/4 mb-2"></div>
|
||||
<div className="h-4 bg-gray-600 rounded w-5/6 mb-2"></div>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : component === 'analysis' ? (
|
||||
[...Array(skeletonCount)].map((_, idx) => (
|
||||
<div
|
||||
key={idx}
|
||||
className="p-6 w-full dark:bg-raisin-black rounded-3xl animate-pulse"
|
||||
>
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-2">
|
||||
<div className="h-4 bg-gray-600 rounded w-1/3 mb-4"></div>
|
||||
<div className="grid grid-cols-6 gap-2 items-end">
|
||||
<div className="h-32 bg-gray-600 rounded"></div>
|
||||
<div className="h-24 bg-gray-600 rounded"></div>
|
||||
<div className="h-40 bg-gray-600 rounded"></div>
|
||||
<div className="h-28 bg-gray-600 rounded"></div>
|
||||
<div className="h-36 bg-gray-600 rounded"></div>
|
||||
<div className="h-20 bg-gray-600 rounded"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<div className="h-4 bg-gray-600 rounded w-1/4 mb-4"></div>
|
||||
<div className="h-32 bg-gray-600 rounded"></div>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="h-4 bg-gray-600 rounded w-full"></div>
|
||||
<div className="h-4 bg-gray-600 rounded w-full"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : component === 'chatbot' ? (
|
||||
<div className="space-y-2 p-6 w-full dark:bg-raisin-black rounded-3xl animate-pulse">
|
||||
<div className="grid grid-cols-4 gap-2 p-2">
|
||||
<div className="h-4 bg-gray-600 rounded w-full"></div>
|
||||
<div className="h-4 bg-gray-600 rounded w-full"></div>
|
||||
<div className="h-4 bg-gray-600 rounded w-full"></div>
|
||||
<div className="h-4 bg-gray-600 rounded w-full"></div>
|
||||
</div>
|
||||
<div className="border-t border-gray-600 my-2"></div>
|
||||
|
||||
{[...Array(skeletonCount * 6)].map((_, idx) => (
|
||||
<div key={idx} className="grid grid-cols-4 gap-2 p-2 space-x-2">
|
||||
<div className="h-4 bg-gray-500 rounded w-full"></div>
|
||||
<div className="h-4 bg-gray-500 rounded w-full"></div>
|
||||
<div className="h-4 bg-gray-500 rounded w-full"></div>
|
||||
<div className="h-4 bg-gray-500 rounded w-full"></div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
[...Array(skeletonCount)].map((_, idx) => (
|
||||
<div
|
||||
key={idx}
|
||||
className="p-6 w-full dark:bg-raisin-black rounded-3xl animate-pulse"
|
||||
>
|
||||
<div className="space-y-4">
|
||||
<div className="h-4 bg-gray-600 rounded w-1/2"></div>
|
||||
<div className="h-4 bg-gray-600 rounded w-5/6"></div>
|
||||
<div className="h-4 bg-gray-600 rounded w-3/4"></div>
|
||||
<div className="h-4 bg-gray-600 rounded w-2/3"></div>
|
||||
<div className="h-4 bg-gray-600 rounded w-1/4"></div>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SkeletonLoader;
|
||||
Reference in New Issue
Block a user