Commit 794dcaff authored by Hines, Jesse's avatar Hines, Jesse
Browse files

Change jobs tab to only contain current jobs in replay

parent 54410535
Loading
Loading
Loading
Loading
+1 −5
Original line number Diff line number Diff line
@@ -37,14 +37,12 @@ export function JobList({
  totalJobs,
  fetchNextPage,
  hasNextPage,
  isFetchingNextPage,
  onSort,
}: {
  jobs: Job[];
  totalJobs: number;
  fetchNextPage: (options?: FetchNextPageOptions | undefined) => void;
  hasNextPage: boolean;
  isFetchingNextPage: boolean;
  onSort: (header: string, sorted: boolean, direction: "asc" | "desc") => void;
}) {
  const navigate = useNavigate({ from: JobsRoute.fullPath });
@@ -73,8 +71,7 @@ export function JobList({

    if (
      lastItem.index >= rows.length - 1 &&
      hasNextPage &&
      !isFetchingNextPage
      hasNextPage
    ) {
      fetchNextPage();
    }
@@ -82,7 +79,6 @@ export function JobList({
    hasNextPage,
    fetchNextPage,
    rows.length,
    isFetchingNextPage,
    rowVirtualizer.getVirtualItems(),
  ]);

+19 −35
Original line number Diff line number Diff line
import { createFileRoute } from "@tanstack/react-router";
import { ListResponse } from "../util/queryOptions";
import { useInfiniteQuery } from "@tanstack/react-query";
import { simulationConfigurationQueryOptions } from "../util/queryOptions";
import { useQuery } from "@tanstack/react-query";
import { LoadingSpinner } from "../components/shared/loadingSpinner";
import { JobList } from "../components/jobs/JobList";
import { headers as JobColumns } from "../components/jobs/list/JobListColumns";
import { ArrowDownTrayIcon } from "@heroicons/react/24/outline";
import { operatorCombinator, sortCombinator } from "../util/filterCombinator";
import { Job } from "../models/Job.model";
import axios from "axios";
import { toDate } from "date-fns";
import { useState } from "react";
import { Tooltip } from "react-tooltip";
import { JobListFilterModal } from "../components/jobs/list/JobListFilterModal";
import { useJobReplay } from "../util/hooks/useReplay";

export const Route = createFileRoute("/simulations/$simulationId/jobs")({
  component: SimulationJobs,
});

const jobLimit = 15;

function SimulationJobs() {
  const { simulationId } = Route.useParams();
  const search = Route.useSearch();
  const currentTimestamp = search.currentTimestamp ? toDate(search.currentTimestamp) : undefined;

  const [columns, setColumns] = useState(structuredClone(JobColumns));
  const { data, isLoading, fetchNextPage, hasNextPage, isFetchingNextPage } =
    useInfiniteQuery({
      queryKey: ["simulation", "jobs", simulationId, columns],
      queryFn: async ({ pageParam }) => {
        const sortParams = sortCombinator(columns);
        const filterParams = operatorCombinator(columns);
        const fields = `&fields=job_id,name,node_count,state_current,time_limit,time_start,time_end,time_submission`;
        const params =
          fields +
          (sortParams ? "&" : "") +
          sortParams +
          (filterParams ? "&" : "") +
          filterParams;
        const res = await axios.get<ListResponse<Job>>(
          `/frontier/simulation/${simulationId}/scheduler/jobs?limit=${jobLimit}&offset=${pageParam * jobLimit}${params}`,
        );

        return res.data;
      },
      initialPageParam: 0,
      getNextPageParam: (lastPage, allPages) =>
        allPages.length <= lastPage.total_results / jobLimit
          ? allPages.length
          : undefined,
      refetchOnWindowFocus: false,
    });
  const { data: sim } = useQuery(simulationConfigurationQueryOptions(simulationId));

  const { data: jobs, totalResults, fetchNextPage, hasNextPage } = useJobReplay({
    sim: sim,
    timestamp: currentTimestamp,
    stepInterval: search.playbackInterval,
    summarize: !currentTimestamp,
    sort: sortCombinator(columns),
    filters: operatorCombinator(columns),
  })

  const onSort = (
    header: string,
@@ -66,11 +52,10 @@ function SimulationJobs() {
    setColumns(updatedColumns);
  };

  if (isLoading) {
  if (!jobs) {
    return <LoadingSpinner />;
  }

  const jobs = data?.pages.map((page) => page.results).flat() ?? [];
  return (
    <div className="flex flex-1 flex-col overflow-hidden">
      <div className="flex items-center justify-end gap-4 px-4 py-4">
@@ -87,10 +72,9 @@ function SimulationJobs() {
      </div>
      <JobList
        jobs={jobs}
        totalJobs={data?.pages[0].total_results ?? 0}
        totalJobs={totalResults}
        fetchNextPage={fetchNextPage}
        hasNextPage={hasNextPage}
        isFetchingNextPage={isFetchingNextPage}
        onSort={onSort}
      />
    </div>
+3 −19
Original line number Diff line number Diff line
import { ColumnHeader } from "../models/dataGrid/columnHeader.model";

export function sortCombinator(columns: ColumnHeader[]) {
  return columns.reduce((prev, curr) => {
    if (curr.sort.sorted) {
      return (
        prev +
        `${prev ? "&" : ""}sort=${curr.sort.direction}:${curr.propertyName}`
      );
    }
    return prev + "";
  }, "");
  return columns
    .flatMap(col => col.sort.sorted ? [`${col.sort.direction}:${col.propertyName}`] : [])
}

export function operatorCombinator(columns: ColumnHeader[]) {
  return columns
    .filter((column) => column.activeFilters.length > 0)
    .reduce((prev, curr) => {
      const columnFilters = curr.activeFilters.reduce(
        (previousFilters, currentFilter) =>
          previousFilters +
          `${previousFilters ? "&" : ""}${curr.propertyName}=${currentFilter.operator}:${currentFilter.value}`,
        ""
      );
      return prev + `${prev ? "&" : ""}${columnFilters}`;
    }, "");
    .flatMap(col => col.activeFilters.map(f => `${col.propertyName}=${f.operator}:${f.value}`))
}