mirror of
https://github.com/fleetdm/fleet
synced 2026-04-28 00:47:22 +00:00
## Addresses #12636 ### See issue for list work done   ### Notes for review: - Because other work is based on this branch, TODOs / fixes are noted here until the team comes to a strategy for merging all of the work: - Add missing space in the Performance impact column "Undetermined" tooltip text - I'm having trouble confirming that the inherited queries table is working right with the mock hard-coded data, though I did see it working correctly previously. There's an issue with the page reverting to "All teams" when trying to show the inherited table, though it does show the table before re-rendering. - This work is organized clearly by commit, so that might be a manageable way to go through this code. - Since the updated API for this work is not yet complete, this work can be manually tested by either: - Using mock API infrastructure, or - in `ManageQueriesPage.tsx`, comment out the two `useQuery` calls and add appropriate mock data. You can then modify any fields of interest to test their related UI functionality. For example, lines 119 -242 might read: ``` // const { // data: curTeamEnhancedQueries, // error: curTeamQueriesError, // isFetching: isFetchingCurTeamQueries, // refetch: refetchCurTeamQueries, // } = useQuery<IListQueriesResponse, Error, IEnhancedQuery[]>( // [{ scope: "queries", teamId: teamIdForApi }], // () => queriesAPI.loadAll(teamIdForApi), // { // refetchOnWindowFocus: false, // enabled: isRouteOk, // select: (data) => data.queries.map(enhanceQuery), // } // ); // // If a team is selected, fetch inherited global queries as well // const { // data: globalEnhancedQueries, // error: globalQueriesError, // isFetching: isFetchingGlobalQueries, // refetch: refetchGlobalQueries, // } = useQuery<IListQueriesResponse, Error, IEnhancedQuery[]>( // [{ scope: "queries", teamId: -1 }], // () => queriesAPI.loadAll(), // { // refetchOnWindowFocus: false, // enabled: isRouteOk && isAnyTeamSelected, // select: (data) => data.queries.map(enhanceQuery), // } // ); const [ curTeamEnhancedQueries, curTeamQueriesError, isFetchingCurTeamQueries, refetchCurTeamQueries, ] = useMemo(() => { return [ [ { created_at: "2023-06-08T15:31:35Z", updated_at: "2023-06-08T15:31:35Z", id: 2, name: "test", description: "", query: "SELECT * FROM osquery_info;", team_id: 43, platform: "darwin", min_osquery_version: "", automations_enabled: true, logging: "snapshot", saved: true, // interval: 300, interval: 0, observer_can_run: false, author_id: 1, author_name: "Jacob", author_email: "jacob@fleetdm.com", packs: [], stats: { // system_time_p50: 1, // system_time_p95: null, // user_time_p50: 1, // user_time_p95: null, // total_executions: 1, }, performance: "Undetermined", platforms: ["darwin"], }, ] as IEnhancedQuery[], undefined, false, () => { console.log("got the new queries"); }, ]; }, []); const [ globalEnhancedQueries, globalQueriesError, isFetchingGlobalQueries, refetchGlobalQueries, ] = useMemo(() => { return [ [ { created_at: "2023-06-08T15:31:35Z", updated_at: "2023-06-08T15:31:35Z", id: 200, name: "test", description: "", query: "SELECT * FROM osquery_info;", team_id: null, platform: "darwin", min_osquery_version: "", automations_enabled: true, logging: "snapshot", saved: true, // interval: 300, interval: 0, observer_can_run: false, author_id: 1, author_name: "Jacob", author_email: "jacob@fleetdm.com", packs: [], stats: { // system_time_p50: 1, // system_time_p95: null, // user_time_p50: 1, // user_time_p95: null, // total_executions: 1, }, performance: "Undetermined", platforms: ["darwin"], }, ] as IEnhancedQuery[], undefined, false, () => { console.log("got the new inherited queries"); }, ]; }, []); ``` - [x] Changes file added for user-visible changes in `changes/` - [x] Manual QA for all new/changed functionality --------- Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
59 lines
1.4 KiB
TypeScript
59 lines
1.4 KiB
TypeScript
import { uniqueId } from "lodash";
|
|
import React from "react";
|
|
import ReactTooltip from "react-tooltip";
|
|
import { DEFAULT_EMPTY_CELL_VALUE } from "utilities/constants";
|
|
|
|
interface ITextCellProps {
|
|
value?: string | number | boolean | { timeString: string };
|
|
formatter?: (val: any) => JSX.Element | string; // string, number, or null
|
|
greyed?: boolean;
|
|
classes?: string;
|
|
emptyCellTooltipText?: JSX.Element | string;
|
|
}
|
|
|
|
const TextCell = ({
|
|
value,
|
|
formatter = (val) => val, // identity function if no formatter is provided
|
|
greyed,
|
|
classes = "w250",
|
|
emptyCellTooltipText,
|
|
}: ITextCellProps): JSX.Element => {
|
|
let val = value;
|
|
|
|
if (typeof value === "boolean") {
|
|
val = value.toString();
|
|
}
|
|
if (!val) {
|
|
greyed = true;
|
|
}
|
|
|
|
const renderEmptyCell = () => {
|
|
if (emptyCellTooltipText) {
|
|
const tooltipId = uniqueId();
|
|
return (
|
|
<>
|
|
<span data-tip data-for={tooltipId}>
|
|
{DEFAULT_EMPTY_CELL_VALUE}
|
|
</span>
|
|
<ReactTooltip
|
|
place="top"
|
|
effect="solid"
|
|
backgroundColor="#3e4771"
|
|
id={tooltipId}
|
|
>
|
|
{emptyCellTooltipText}
|
|
</ReactTooltip>
|
|
</>
|
|
);
|
|
}
|
|
return DEFAULT_EMPTY_CELL_VALUE;
|
|
};
|
|
|
|
return (
|
|
<span className={`text-cell ${classes} ${greyed && "grey-cell"}`}>
|
|
{formatter(val) || renderEmptyCell()}
|
|
</span>
|
|
);
|
|
};
|
|
|
|
export default TextCell;
|