feat(web): add custom file download button for runs output
This commit is contained in:
		
							parent
							
								
									8f67a136c3
								
							
						
					
					
						commit
						ee68507755
					
				@ -6,12 +6,13 @@ import { z } from "zod";
 | 
			
		||||
const Request = z.object({
 | 
			
		||||
  file_name: z.string(),
 | 
			
		||||
  run_id: z.string(),
 | 
			
		||||
  type: z.enum(["image/png", "image/jpeg"]),
 | 
			
		||||
  type: z.string(),
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export const dynamic = "force-dynamic";
 | 
			
		||||
 | 
			
		||||
export async function GET(request: Request) {
 | 
			
		||||
  console.log("yo hello");
 | 
			
		||||
  const [data, error] = await parseDataSafe(Request, request);
 | 
			
		||||
  if (!data || error) return error;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,7 @@ export async function POST(request: Request) {
 | 
			
		||||
 | 
			
		||||
  const { run_id, status, output_data } = data;
 | 
			
		||||
 | 
			
		||||
  console.log(run_id, status, output_data);
 | 
			
		||||
  // console.log(run_id, status, output_data);
 | 
			
		||||
 | 
			
		||||
  if (output_data) {
 | 
			
		||||
    const workflow_run_output = await db.insert(workflowRunOutputs).values({
 | 
			
		||||
@ -25,7 +25,7 @@ export async function POST(request: Request) {
 | 
			
		||||
      data: output_data,
 | 
			
		||||
    });
 | 
			
		||||
  } else if (status) {
 | 
			
		||||
    console.log("status", status);
 | 
			
		||||
    // console.log("status", status);
 | 
			
		||||
    const workflow_run = await db
 | 
			
		||||
      .update(workflowRunsTable)
 | 
			
		||||
      .set({
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,8 @@
 | 
			
		||||
import { replaceCDNUrl } from "@/server/resource";
 | 
			
		||||
import { NextResponse, type NextRequest } from "next/server";
 | 
			
		||||
import { getFileDownloadUrl } from "../../../server/getFileDownloadUrl";
 | 
			
		||||
 | 
			
		||||
export async function GET(request: NextRequest) {
 | 
			
		||||
  const file = new URL(request.url).searchParams.get("file");
 | 
			
		||||
  // console.log(`${process.env.SPACES_ENDPOINT}/comfyui-deploy/${file}`);
 | 
			
		||||
  return NextResponse.redirect(
 | 
			
		||||
    replaceCDNUrl(
 | 
			
		||||
      `${process.env.SPACES_ENDPOINT}/${process.env.SPACES_BUCKET}/${file}`
 | 
			
		||||
    )
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
  if (!file) return NextResponse.redirect("/");
 | 
			
		||||
  return NextResponse.redirect(getFileDownloadUrl(file));
 | 
			
		||||
}
 | 
			
		||||
@ -3,5 +3,5 @@ import { LoaderIcon } from "lucide-react";
 | 
			
		||||
import * as React from "react";
 | 
			
		||||
 | 
			
		||||
export function LoadingIcon() {
 | 
			
		||||
  return <LoaderIcon size={14} className="ml-2 animate-spin" />;
 | 
			
		||||
  return <LoaderIcon size={14} className="animate-spin" />;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										31
									
								
								web/src/components/OutputRender.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								web/src/components/OutputRender.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
'use client'
 | 
			
		||||
 | 
			
		||||
import { Download } from "lucide-react";
 | 
			
		||||
import { Button } from "@/components/ui/button";
 | 
			
		||||
import { getFileDownloadUrl } from "@/server/getFileDownloadUrl";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export function OutputRender(props: { run_id: string; filename: string; }) {
 | 
			
		||||
  if (props.filename.endsWith(".png")) {
 | 
			
		||||
    return (
 | 
			
		||||
      <img
 | 
			
		||||
        className="max-w-[200px]"
 | 
			
		||||
        alt={props.filename}
 | 
			
		||||
        src={`/api/view?file=${encodeURIComponent(
 | 
			
		||||
          `outputs/runs/${props.run_id}/${props.filename}`
 | 
			
		||||
        )}`} />
 | 
			
		||||
    );
 | 
			
		||||
  } else {
 | 
			
		||||
    return <Button className="gap-2" onClick={async () => {
 | 
			
		||||
      const url = await getFileDownloadUrl(`outputs/runs/${props.run_id}/${props.filename}`);
 | 
			
		||||
 | 
			
		||||
      const a = document.createElement('a');
 | 
			
		||||
      a.href = url;
 | 
			
		||||
      a.download = props.filename;
 | 
			
		||||
      a.target = '_blank'; // Add this line
 | 
			
		||||
      document.body.appendChild(a);
 | 
			
		||||
      a.click();
 | 
			
		||||
      document.body.removeChild(a);
 | 
			
		||||
    }}>Download <Download size={14} /></Button>;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,3 +1,4 @@
 | 
			
		||||
 | 
			
		||||
import { RunInputs } from "@/components/RunInputs";
 | 
			
		||||
import { LiveStatus } from "./LiveStatus";
 | 
			
		||||
import { RunOutputs } from "@/components/RunOutputs";
 | 
			
		||||
@ -51,17 +52,3 @@ export async function RunDisplay({
 | 
			
		||||
    </Dialog>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function OutputRender(props: { run_id: string; filename: string }) {
 | 
			
		||||
  if (props.filename.endsWith(".png")) {
 | 
			
		||||
    return (
 | 
			
		||||
      <img
 | 
			
		||||
        className="max-w-[200px]"
 | 
			
		||||
        alt={props.filename}
 | 
			
		||||
        src={`/api/view?file=${encodeURIComponent(
 | 
			
		||||
          `outputs/runs/${props.run_id}/${props.filename}`
 | 
			
		||||
        )}`}
 | 
			
		||||
      />
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
import { OutputRender } from "./RunDisplay";
 | 
			
		||||
import { OutputRender } from "./OutputRender";
 | 
			
		||||
import { CodeBlock } from "@/components/CodeBlock";
 | 
			
		||||
import {
 | 
			
		||||
  Table,
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
import { OutputRender } from "./RunDisplay";
 | 
			
		||||
import { OutputRender } from "./OutputRender";
 | 
			
		||||
import { CodeBlock } from "@/components/CodeBlock";
 | 
			
		||||
import {
 | 
			
		||||
  Table,
 | 
			
		||||
 | 
			
		||||
@ -128,7 +128,7 @@ export function RunWorkflowButton({
 | 
			
		||||
        }
 | 
			
		||||
      }}
 | 
			
		||||
    >
 | 
			
		||||
      Run <Play size={14} /> {isLoading && <LoadingIcon />}
 | 
			
		||||
      Run  {isLoading ?  <LoadingIcon /> : <Play size={14} />}
 | 
			
		||||
    </Button>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
@ -155,7 +155,7 @@ export function CreateDeploymentButton({
 | 
			
		||||
    <DropdownMenu>
 | 
			
		||||
      <DropdownMenuTrigger asChild>
 | 
			
		||||
        <Button className="gap-2" disabled={isLoading} variant="outline">
 | 
			
		||||
          Deploy <MoreVertical size={14} /> {isLoading && <LoadingIcon />}
 | 
			
		||||
          Deploy  {isLoading ? <LoadingIcon /> : <MoreVertical size={14} /> }
 | 
			
		||||
        </Button>
 | 
			
		||||
      </DropdownMenuTrigger>
 | 
			
		||||
      <DropdownMenuContent className="w-56">
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								web/src/server/getFileDownloadUrl.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								web/src/server/getFileDownloadUrl.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
'use server'
 | 
			
		||||
 | 
			
		||||
import { replaceCDNUrl } from "@/server/resource";
 | 
			
		||||
 | 
			
		||||
export async function getFileDownloadUrl(file: string) {
 | 
			
		||||
  return replaceCDNUrl(
 | 
			
		||||
    `${process.env.SPACES_ENDPOINT}/${process.env.SPACES_BUCKET}/${file}`
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user