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 297x 295x 2589x 295x 295x 4x 3x 3x 3x 3x 2589x 2028x 4x 28414x | 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>
</>
);
};
|