Samples work in ui now
This commit is contained in:
23
ui/src/components/JobOverview.tsx
Normal file
23
ui/src/components/JobOverview.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { Job } from '@prisma/client';
|
||||
|
||||
interface JobOverviewProps {
|
||||
job: Job;
|
||||
}
|
||||
|
||||
export default function JobOverview({ job }: JobOverviewProps) {
|
||||
return (
|
||||
<>
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<div className="">
|
||||
<h2 className="text-lg font-semibold">Job Details</h2>
|
||||
<p className="text-gray-400">ID: {job.id}</p>
|
||||
<p className="text-gray-400">Name: {job.name}</p>
|
||||
<p className="text-gray-400">GPUs: {job.gpu_ids}</p>
|
||||
<p className="text-gray-400">Status: {job.status}</p>
|
||||
<p className="text-gray-400">Info: {job.info}</p>
|
||||
<p className="text-gray-400">Step: {job.step}</p>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
67
ui/src/components/SampleImageCard.tsx
Normal file
67
ui/src/components/SampleImageCard.tsx
Normal file
@@ -0,0 +1,67 @@
|
||||
import React, { useRef, useEffect, useState, ReactNode } from 'react';
|
||||
|
||||
interface SampleImageCardProps {
|
||||
imageUrl: string;
|
||||
alt: string;
|
||||
children?: ReactNode;
|
||||
className?: string;
|
||||
onDelete?: () => void;
|
||||
}
|
||||
|
||||
const SampleImageCard: React.FC<SampleImageCardProps> = ({ imageUrl, alt, children, className = '' }) => {
|
||||
const cardRef = useRef<HTMLDivElement>(null);
|
||||
const [isVisible, setIsVisible] = useState<boolean>(false);
|
||||
const [loaded, setLoaded] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
// Create intersection observer to check visibility
|
||||
const observer = new IntersectionObserver(
|
||||
entries => {
|
||||
if (entries[0].isIntersecting) {
|
||||
setIsVisible(true);
|
||||
observer.disconnect();
|
||||
}
|
||||
},
|
||||
{ threshold: 0.1 },
|
||||
);
|
||||
|
||||
if (cardRef.current) {
|
||||
observer.observe(cardRef.current);
|
||||
}
|
||||
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleLoad = (): void => {
|
||||
setLoaded(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`flex flex-col ${className}`}>
|
||||
{/* Square image container */}
|
||||
<div
|
||||
ref={cardRef}
|
||||
className="relative w-full"
|
||||
style={{ paddingBottom: '100%' }} // Make it square
|
||||
>
|
||||
<div className="absolute inset-0 rounded-t-lg shadow-md">
|
||||
{isVisible && (
|
||||
<img
|
||||
src={`/api/img/${encodeURIComponent(imageUrl)}`}
|
||||
alt={alt}
|
||||
onLoad={handleLoad}
|
||||
className={`w-full h-full object-contain transition-opacity duration-300 ${
|
||||
loaded ? 'opacity-100' : 'opacity-0'
|
||||
}`}
|
||||
/>
|
||||
)}
|
||||
{children && <div className="absolute inset-0 flex items-center justify-center">{children}</div>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SampleImageCard;
|
||||
89
ui/src/components/SampleImages.tsx
Normal file
89
ui/src/components/SampleImages.tsx
Normal file
@@ -0,0 +1,89 @@
|
||||
import { useMemo } from 'react';
|
||||
import useSampleImages from '@/hooks/useSampleImages';
|
||||
import SampleImageCard from './SampleImageCard';
|
||||
import { Job } from '@prisma/client';
|
||||
import { JobConfig } from '@/types';
|
||||
|
||||
interface SampleImagesProps {
|
||||
job: Job;
|
||||
}
|
||||
|
||||
export default function SampleImages({ job }: SampleImagesProps) {
|
||||
const { sampleImages, status, refreshSampleImages } = useSampleImages(job.id, 5000);
|
||||
const numSamples = useMemo(() => {
|
||||
if (job?.job_config) {
|
||||
const jobConfig = JSON.parse(job.job_config) as JobConfig;
|
||||
const sampleConfig = jobConfig.config.process[0].sample;
|
||||
return sampleConfig.prompts.length;
|
||||
}
|
||||
return 10;
|
||||
}, [job]);
|
||||
|
||||
// Use direct Tailwind class without string interpolation
|
||||
// This way Tailwind can properly generate the class
|
||||
// I hate this, but it's the only way to make it work
|
||||
const gridColsClass = useMemo(() => {
|
||||
const cols = Math.min(numSamples, 20);
|
||||
|
||||
switch (cols) {
|
||||
case 1:
|
||||
return 'grid-cols-1';
|
||||
case 2:
|
||||
return 'grid-cols-2';
|
||||
case 3:
|
||||
return 'grid-cols-3';
|
||||
case 4:
|
||||
return 'grid-cols-4';
|
||||
case 5:
|
||||
return 'grid-cols-5';
|
||||
case 6:
|
||||
return 'grid-cols-6';
|
||||
case 7:
|
||||
return 'grid-cols-7';
|
||||
case 8:
|
||||
return 'grid-cols-8';
|
||||
case 9:
|
||||
return 'grid-cols-9';
|
||||
case 10:
|
||||
return 'grid-cols-10';
|
||||
case 11:
|
||||
return 'grid-cols-11';
|
||||
case 12:
|
||||
return 'grid-cols-12';
|
||||
case 13:
|
||||
return 'grid-cols-13';
|
||||
case 14:
|
||||
return 'grid-cols-14';
|
||||
case 15:
|
||||
return 'grid-cols-15';
|
||||
case 16:
|
||||
return 'grid-cols-16';
|
||||
case 17:
|
||||
return 'grid-cols-17';
|
||||
case 18:
|
||||
return 'grid-cols-18';
|
||||
case 19:
|
||||
return 'grid-cols-19';
|
||||
case 20:
|
||||
return 'grid-cols-20';
|
||||
default:
|
||||
return 'grid-cols-1';
|
||||
}
|
||||
}, [numSamples]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='pb-4'>
|
||||
{status === 'loading' && sampleImages.length === 0 && <p>Loading...</p>}
|
||||
{status === 'error' && <p>Error fetching sample images</p>}
|
||||
{sampleImages && (
|
||||
<div className={`grid ${gridColsClass} gap-1`}>
|
||||
{sampleImages.map((sample: string) => (
|
||||
<SampleImageCard key={sample} imageUrl={sample} alt="Sample Image" />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -20,7 +20,7 @@ export const TopBar: React.FC<Props> = ({ children, className }) => {
|
||||
|
||||
export const MainContent: React.FC<Props> = ({ children, className }) => {
|
||||
return (
|
||||
<div className={classNames('pt-16 px-4 absolute top-0 left-0 w-full h-full overflow-auto', className)}>
|
||||
<div className={classNames('pt-14 px-4 absolute top-0 left-0 w-full h-full overflow-auto', className)}>
|
||||
{children ? children : null}
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user