All files / react-app/src/components/Opensearch/main/Table index.tsx

100% Statements 20/20
100% Branches 21/21
100% Functions 7/7
100% Lines 15/15

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106                            105x 293x 291x 2543x 291x   291x 4x   3x 3x               3x 3x                       2543x 1994x               4x                                                                   27862x                                  
import { type FC, useState } from "react";
import { opensearch } from "shared-types";
 
import * as UI from "@/components";
import { LoadingSpinner, useOsUrl } from "@/components";
import { BLANK_VALUE } from "@/consts";
import { cn } from "@/utils";
 
import { useOsContext } from "../Provider";
import { OsTableColumn } from "./types";
 
export const OsTable: FC<{
  columns: OsTableColumn[];
  onToggle: (field: string) => void;
}> = (props) => {
  const context = useOsContext();
  const url = useOsUrl();
  const onlyID = props.columns.filter((c) => c.hidden === false).length <= 2;
  const [sortAnnouncement, setSortAnnouncement] = useState("");
 
  const handleSort = (TH: OsTableColumn) => {
    if (!TH.field) return;
 
    const newOrder = url.state.sort.order === "desc" ? "asc" : "desc";
    url.onSet((s) => ({
      ...s,
      sort: {
        field: TH.field as opensearch.main.Field,
        order: newOrder,
      },
    }));
 
    const direction = newOrder === "desc" ? "descending" : "ascending";
    setSortAnnouncement(`Sorted by ${TH.label}, ${direction}`);
  };
 
  return (
    <>
      <div className="sr-only" aria-live="polite" aria-atomic="true">
        {sortAnnouncement}
      </div>
      <UI.Table className="overflow-scroll w-full" data-testid="os-table">
        <UI.TableHeader className="sticky top-0 bg-white">
          <UI.TableRow>
            {props.columns.map((TH) => {
              if (TH.hidden) return null;
              return (
                <UI.TableHead
                  {...(!!TH.props && TH.props)}
                  key={`TH-${TH.field}`}
                  isActive={url.state.sort?.field === TH.field}
                  className={cn({ "w-full": onlyID && TH.field === "id.keyword" })}
                  desc={url.state.sort?.order === "desc"}
                  {...(TH.isSystem && { className: "pointer-events-none" })}
                  onClick={() => handleSort(TH)}
                >
                  {TH.label}
                </UI.TableHead>
              );
            })}
          </UI.TableRow>
        </UI.TableHeader>
        <UI.TableBody>
          {/* TODO: Add a skeleton loader after discussing with HCD.
        See https://qmacbis.atlassian.net/browse/OY2-25623 */}
          {!context.data && (
            <UI.TableRow>
              <UI.TableCell>
                <LoadingSpinner />
              </UI.TableCell>
            </UI.TableRow>
          )}
          {context.data && !context.data.hits.length && (
            <UI.TableRow className="h-10">
              <UI.TableCell className="flex pb-14">
                <p className="font-medium whitespace-nowrap h-[20px]"> </p>
                <div className="absolute right-[50%] translate-x-[50%] translate-y-[50%] font-medium text-lg text-gray-500">
                  No Results Found
                  <p className="absolute right-[50%] translate-x-[50%] translate-y-[50%] text-sm whitespace-nowrap h-[20px]">
                    Adjust your search and filter to find what you are looking for.
                  </p>
                </div>
              </UI.TableCell>
            </UI.TableRow>
          )}
          {context.data?.hits.map((DAT) => (
            <UI.TableRow className="max-h-1" key={DAT._source.id}>
              {props.columns.map((COL) => {
                if (COL.hidden) return null;
                return (
                  <UI.TableCell
                    key={`${COL.field}-${DAT._source.id}`}
                    className="font-medium whitespace-nowrap"
                  >
                    {COL.cell(DAT._source) ?? BLANK_VALUE}
                  </UI.TableCell>
                );
              })}
            </UI.TableRow>
          ))}
        </UI.TableBody>
      </UI.Table>
    </>
  );
};