feat(share): display muliple images (#28)
* fix(workflows): user can click multiple times on run even while loading * feat(share): display muliple images
This commit is contained in:
		
							parent
							
								
									17653508c5
								
							
						
					
					
						commit
						2cfad8bef6
					
				@ -80,7 +80,9 @@
 | 
			
		||||
  /* @apply rounded-lg p-2 overflow-x-scroll */
 | 
			
		||||
  @apply  p-2 max-w-full overflow-auto w-full
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
.vsc-controller{
 | 
			
		||||
  position: absolute;
 | 
			
		||||
}
 | 
			
		||||
@layer base {
 | 
			
		||||
  * {
 | 
			
		||||
    @apply border-border;
 | 
			
		||||
 | 
			
		||||
@ -60,6 +60,7 @@ import { callServerPromise } from "./callServerPromise";
 | 
			
		||||
import fetcher from "./fetcher";
 | 
			
		||||
import { ButtonAction } from "@/components/ButtonActionLoader";
 | 
			
		||||
import { editWorkflowOnMachine } from "@/server/editWorkflowOnMachine";
 | 
			
		||||
import { VisualizeImagesGrid } from "@/components/VisualizeImagesGrid";
 | 
			
		||||
 | 
			
		||||
export function VersionSelect({
 | 
			
		||||
  workflow,
 | 
			
		||||
@ -169,19 +170,21 @@ export function useSelectedMachine(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PublicRunStore = {
 | 
			
		||||
  image: string;
 | 
			
		||||
  image: {
 | 
			
		||||
    url: string;
 | 
			
		||||
  }[] | null;
 | 
			
		||||
  loading: boolean;
 | 
			
		||||
  runId: string;
 | 
			
		||||
  status: string;
 | 
			
		||||
 | 
			
		||||
  setImage: (image: string) => void;
 | 
			
		||||
  setImage: (image: { url: string; }[]) => void;
 | 
			
		||||
  setLoading: (loading: boolean) => void;
 | 
			
		||||
  setRunId: (runId: string) => void;
 | 
			
		||||
  setStatus: (status: string) => void;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const publicRunStore = create<PublicRunStore>((set) => ({
 | 
			
		||||
  image: "",
 | 
			
		||||
  image: null,
 | 
			
		||||
  loading: false,
 | 
			
		||||
  runId: "",
 | 
			
		||||
  status: "",
 | 
			
		||||
@ -205,7 +208,10 @@ export function PublicRunOutputs(props: {
 | 
			
		||||
        console.log(res?.status);
 | 
			
		||||
        if (res) setStatus(res.status);
 | 
			
		||||
        if (res && res.status === "success") {
 | 
			
		||||
          setImage(res.outputs[0]?.data.images[0].url);
 | 
			
		||||
          const imageURLs = res.outputs[0]?.data.images.map((item: { url: string; }) => {
 | 
			
		||||
            return { url: item.url };
 | 
			
		||||
          });
 | 
			
		||||
          setImage(imageURLs);
 | 
			
		||||
          setLoading(false);
 | 
			
		||||
          clearInterval(interval);
 | 
			
		||||
        }
 | 
			
		||||
@ -214,30 +220,25 @@ export function PublicRunOutputs(props: {
 | 
			
		||||
    return () => clearInterval(interval);
 | 
			
		||||
  }, [runId]);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="border border-gray-200 w-full square h-[400px] rounded-lg relative">
 | 
			
		||||
      {!loading && !image && props.preview && props.preview.length > 0 && (
 | 
			
		||||
        <>
 | 
			
		||||
          <img
 | 
			
		||||
            className="w-full h-full object-contain"
 | 
			
		||||
            src={props.preview[0]?.url}
 | 
			
		||||
            alt="Generated image"
 | 
			
		||||
          />
 | 
			
		||||
        </>
 | 
			
		||||
      )}
 | 
			
		||||
      {!loading && image && (
 | 
			
		||||
        <img
 | 
			
		||||
          className="w-full h-full object-contain"
 | 
			
		||||
          src={image}
 | 
			
		||||
          alt="Generated image"
 | 
			
		||||
        />
 | 
			
		||||
      )}
 | 
			
		||||
      {loading && (
 | 
			
		||||
  if (loading) {
 | 
			
		||||
    return (
 | 
			
		||||
      <div className="border border-gray-200 w-full h-[400px] square rounded-lg relative p-4 ">
 | 
			
		||||
        <div className="absolute top-0 left-0 w-full h-full flex items-center justify-center gap-2">
 | 
			
		||||
          {status} <LoadingIcon />
 | 
			
		||||
        </div>
 | 
			
		||||
        <Skeleton className="w-full h-full" />
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="border border-gray-200 w-full min-h-[400px] square rounded-lg relative p-4 ">
 | 
			
		||||
      {!image && props.preview && props.preview.length > 0 &&
 | 
			
		||||
        <VisualizeImagesGrid images={props.preview} />
 | 
			
		||||
      }
 | 
			
		||||
      {image && (
 | 
			
		||||
        <VisualizeImagesGrid images={image} />
 | 
			
		||||
      )}
 | 
			
		||||
      {loading && <Skeleton className="w-full h-full" />}
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										42
									
								
								web/src/components/VisualizeImagesGrid.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								web/src/components/VisualizeImagesGrid.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,42 @@
 | 
			
		||||
type imagesType = {
 | 
			
		||||
  url: string;
 | 
			
		||||
  width?: number;
 | 
			
		||||
  height?: number;
 | 
			
		||||
};
 | 
			
		||||
type VisualizeImagesGridProps = {
 | 
			
		||||
  images: imagesType[];
 | 
			
		||||
  layout?: 'justify-between' | 'justify-center' | 'justify-start' | 'justify-end';
 | 
			
		||||
};
 | 
			
		||||
export function VisualizeImagesGrid({ images, layout }: VisualizeImagesGridProps) {
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className={`flex gap-4 flex-wrap ${layout || 'justify-center'}`}>
 | 
			
		||||
      <>
 | 
			
		||||
        {images && images.length > 0 &&
 | 
			
		||||
          images.map(item => {
 | 
			
		||||
            if (!item) {
 | 
			
		||||
              return;
 | 
			
		||||
            }
 | 
			
		||||
            if (item?.url.endsWith(".mp4") || item?.url.endsWith(".webm")) {
 | 
			
		||||
              return (
 | 
			
		||||
                <video key={item?.url} controls autoPlay className="rounded-xl" style={{ maxHeight: item.height || 370, maxWidth: item.width || "auto" }}>
 | 
			
		||||
                  <source src={item?.url} type="video/mp4" />
 | 
			
		||||
                  <source src={item?.url} type="video/webm" />
 | 
			
		||||
                  Your browser does not support the video tag.
 | 
			
		||||
                </video>
 | 
			
		||||
              );
 | 
			
		||||
            }
 | 
			
		||||
            return <img
 | 
			
		||||
              key={item?.url}
 | 
			
		||||
              className="object-contain overflow-hidden rounded-xl"
 | 
			
		||||
              src={item?.url}
 | 
			
		||||
              alt="Generated image"
 | 
			
		||||
              style={{ maxHeight: item.height || 370, maxWidth: item.width || "auto" }}
 | 
			
		||||
            />;
 | 
			
		||||
          })
 | 
			
		||||
        }
 | 
			
		||||
      </>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user