feat(web): auto fresh every 5 seconds for workflow display
This commit is contained in:
		
							parent
							
								
									825c8a63fb
								
							
						
					
					
						commit
						3c4bce630e
					
				@ -1,4 +1,5 @@
 | 
				
			|||||||
import { LoadingWrapper } from "@/components/LoadingWrapper";
 | 
					import { LoadingWrapper } from "@/components/LoadingWrapper";
 | 
				
			||||||
 | 
					import { RouteRefresher } from "@/components/RouteRefresher";
 | 
				
			||||||
import { RunsTable } from "@/components/RunsTable";
 | 
					import { RunsTable } from "@/components/RunsTable";
 | 
				
			||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
 | 
					import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -13,8 +14,11 @@ export default async function Page({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <Card className="w-full h-fit min-w-0">
 | 
					    <Card className="w-full h-fit min-w-0">
 | 
				
			||||||
      <CardHeader>
 | 
					      <CardHeader className="relative">
 | 
				
			||||||
        <CardTitle>Run</CardTitle>
 | 
					        <CardTitle>Run</CardTitle>
 | 
				
			||||||
 | 
					        <div className="absolute right-6 top-6">
 | 
				
			||||||
 | 
					          <RouteRefresher interval={5000} />
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
      </CardHeader>
 | 
					      </CardHeader>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <CardContent>
 | 
					      <CardContent>
 | 
				
			||||||
 | 
				
			|||||||
@ -54,7 +54,7 @@ export function LiveStatus({
 | 
				
			|||||||
          ? `${data.json.event} - ${data.json.data.node}`
 | 
					          ? `${data.json.event} - ${data.json.data.node}`
 | 
				
			||||||
          : "-"}
 | 
					          : "-"}
 | 
				
			||||||
      </TableCell>
 | 
					      </TableCell>
 | 
				
			||||||
      <TableCell className="text-right">
 | 
					      <TableCell className="truncate text-right">
 | 
				
			||||||
        <StatusBadge status={status} />
 | 
					        <StatusBadge status={status} />
 | 
				
			||||||
      </TableCell>
 | 
					      </TableCell>
 | 
				
			||||||
    </>
 | 
					    </>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,6 +12,22 @@ export function PaginationControl(props: {
 | 
				
			|||||||
  totalPage: number;
 | 
					  totalPage: number;
 | 
				
			||||||
  currentPage: number;
 | 
					  currentPage: number;
 | 
				
			||||||
}) {
 | 
					}) {
 | 
				
			||||||
 | 
					  let startPage = Math.max(props.currentPage - 2, 1);
 | 
				
			||||||
 | 
					  let endPage = Math.min(startPage + 3, props.totalPage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (props.currentPage <= 2) {
 | 
				
			||||||
 | 
					    endPage = Math.min(4, props.totalPage);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (props.currentPage > props.totalPage - 2) {
 | 
				
			||||||
 | 
					    startPage = Math.max(props.totalPage - 3, 1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const pageNumbers = Array.from(
 | 
				
			||||||
 | 
					    { length: endPage - startPage + 1 },
 | 
				
			||||||
 | 
					    (_, i) => startPage + i
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <Pagination>
 | 
					    <Pagination>
 | 
				
			||||||
      <PaginationContent>
 | 
					      <PaginationContent>
 | 
				
			||||||
@ -22,9 +38,15 @@ export function PaginationControl(props: {
 | 
				
			|||||||
              : `?page=${props.currentPage}`
 | 
					              : `?page=${props.currentPage}`
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
        <PaginationLink href="#" isActive>
 | 
					        {pageNumbers.map((page) => (
 | 
				
			||||||
          {props.currentPage}
 | 
					          <PaginationLink
 | 
				
			||||||
        </PaginationLink>
 | 
					            key={page}
 | 
				
			||||||
 | 
					            href={`?page=${page}`}
 | 
				
			||||||
 | 
					            isActive={props.currentPage === page}
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {page}
 | 
				
			||||||
 | 
					          </PaginationLink>
 | 
				
			||||||
 | 
					        ))}
 | 
				
			||||||
        <PaginationItem>
 | 
					        <PaginationItem>
 | 
				
			||||||
          <PaginationEllipsis />
 | 
					          <PaginationEllipsis />
 | 
				
			||||||
        </PaginationItem>
 | 
					        </PaginationItem>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										41
									
								
								web/src/components/RouteRefresher.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								web/src/components/RouteRefresher.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					"use client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { LoadingIcon } from "@/components/LoadingIcon";
 | 
				
			||||||
 | 
					import { useRouter } from "next/navigation";
 | 
				
			||||||
 | 
					import { useEffect, useTransition } from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function RouteRefresher(props: { interval: number }) {
 | 
				
			||||||
 | 
					  const [isPending, startTransition] = useTransition();
 | 
				
			||||||
 | 
					  const router = useRouter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    let timeout: NodeJS.Timeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const refresh = () => {
 | 
				
			||||||
 | 
					      console.log("refreshing");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      startTransition(() => {
 | 
				
			||||||
 | 
					        router.refresh();
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      timeout = setTimeout(refresh, props.interval);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const handleVisibilityChange = () => {
 | 
				
			||||||
 | 
					      if (document.hidden) {
 | 
				
			||||||
 | 
					        clearTimeout(timeout);
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        refresh();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    window.addEventListener("visibilitychange", handleVisibilityChange);
 | 
				
			||||||
 | 
					    refresh();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return () => {
 | 
				
			||||||
 | 
					      clearTimeout(timeout);
 | 
				
			||||||
 | 
					      window.removeEventListener("visibilitychange", handleVisibilityChange);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  }, [props.interval, router]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return <div>{isPending && <LoadingIcon />}</div>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -24,8 +24,12 @@ export async function RunDisplay({
 | 
				
			|||||||
      <DialogTrigger asChild className="appearance-none hover:cursor-pointer">
 | 
					      <DialogTrigger asChild className="appearance-none hover:cursor-pointer">
 | 
				
			||||||
        <TableRow>
 | 
					        <TableRow>
 | 
				
			||||||
          <TableCell>{run.number}</TableCell>
 | 
					          <TableCell>{run.number}</TableCell>
 | 
				
			||||||
          <TableCell className="font-medium">{run.machine?.name}</TableCell>
 | 
					          <TableCell className="font-medium truncate">
 | 
				
			||||||
          <TableCell>{getRelativeTime(run.created_at)}</TableCell>
 | 
					            {run.machine?.name}
 | 
				
			||||||
 | 
					          </TableCell>
 | 
				
			||||||
 | 
					          <TableCell className="truncate">
 | 
				
			||||||
 | 
					            {getRelativeTime(run.created_at)}
 | 
				
			||||||
 | 
					          </TableCell>
 | 
				
			||||||
          <TableCell>{run.version?.version}</TableCell>
 | 
					          <TableCell>{run.version?.version}</TableCell>
 | 
				
			||||||
          <LiveStatus run={run} />
 | 
					          <LiveStatus run={run} />
 | 
				
			||||||
        </TableRow>
 | 
					        </TableRow>
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,7 @@ import {
 | 
				
			|||||||
} from "@/components/ui/table";
 | 
					} from "@/components/ui/table";
 | 
				
			||||||
import { parseAsInteger } from "next-usequerystate";
 | 
					import { parseAsInteger } from "next-usequerystate";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const itemPerPage = 4;
 | 
					const itemPerPage = 6;
 | 
				
			||||||
const pageParser = parseAsInteger.withDefault(1);
 | 
					const pageParser = parseAsInteger.withDefault(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function RunsTable(props: {
 | 
					export async function RunsTable(props: {
 | 
				
			||||||
@ -33,7 +33,7 @@ export async function RunsTable(props: {
 | 
				
			|||||||
  });
 | 
					  });
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
      <div className="overflow-auto h-[400px] w-full">
 | 
					      <div className="overflow-auto h-fit w-full">
 | 
				
			||||||
        <Table className="">
 | 
					        <Table className="">
 | 
				
			||||||
          {/* <TableCaption>A list of your recent runs.</TableCaption> */}
 | 
					          {/* <TableCaption>A list of your recent runs.</TableCaption> */}
 | 
				
			||||||
          <TableHeader className="bg-background top-0 sticky">
 | 
					          <TableHeader className="bg-background top-0 sticky">
 | 
				
			||||||
@ -42,7 +42,7 @@ export async function RunsTable(props: {
 | 
				
			|||||||
              <TableHead className="">Machine</TableHead>
 | 
					              <TableHead className="">Machine</TableHead>
 | 
				
			||||||
              <TableHead className="">Time</TableHead>
 | 
					              <TableHead className="">Time</TableHead>
 | 
				
			||||||
              <TableHead className="w-[100px]">Version</TableHead>
 | 
					              <TableHead className="w-[100px]">Version</TableHead>
 | 
				
			||||||
              <TableHead className="">Live Status</TableHead>
 | 
					              <TableHead className="truncate">Live Status</TableHead>
 | 
				
			||||||
              <TableHead className=" text-right">Status</TableHead>
 | 
					              <TableHead className=" text-right">Status</TableHead>
 | 
				
			||||||
            </TableRow>
 | 
					            </TableRow>
 | 
				
			||||||
          </TableHeader>
 | 
					          </TableHeader>
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user