Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ const platformSubNav: IPlatformSubNav[] = [
interface IPlatformWrapperProps {
enrollSecret: string;
onCancel: () => void;
certificate: any;
certificate: string | undefined;
isFetchingCertificate: boolean;
fetchCertificateError: any;
fetchCertificateError: Error | null;
config: IConfig | null;
}

Expand Down Expand Up @@ -419,7 +419,7 @@ const PlatformWrapper = ({
<br />
{fetchCertificateError ? (
<span className={`${baseClass}__error`}>
{fetchCertificateError}
{fetchCertificateError?.message}
</span>
) : (
<Button variant="inverse" onClick={onDownloadFlagfile}>
Expand Down
1 change: 1 addition & 0 deletions frontend/components/ClickableUrls/ClickableUrls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const ClickableUrls = ({ text, className }: IClickableUrls): JSX.Element => {
return (
<div
className={clickableUrlClasses}
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: sanitizedTextWithLinks }}
/>
);
Expand Down
1 change: 1 addition & 0 deletions frontend/components/Editor/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ interface IEditorProps {
isFormField?: boolean;
maxLines?: number;
className?: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
onChange?: (value: string, event?: any) => void;
onBlur?: () => void;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import ReactTooltip, { Place } from "react-tooltip";

interface IHumanTimeDiffWithDateTip {
timeString: string;
// eslint-disable-next-line react/no-unused-prop-types
cutoffBeforeFleetLaunch?: boolean;
tooltipPosition?: Place;
}
Expand Down
7 changes: 0 additions & 7 deletions frontend/components/PaginatedList/PaginatedList.tests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,6 @@ describe("PaginatedList", () => {
},
];

const fetchTinyPage = (pageNumber: number) => {
if (pageNumber <= 2) {
return [items[pageNumber]];
}
throw new Error("Invalid page number");
};

const fetchSmallPage = (pageNumber: number) => {
if (pageNumber === 0) {
return [items[0], items[1]];
Expand Down
3 changes: 2 additions & 1 deletion frontend/components/PaginatedList/PaginatedList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ interface IPaginatedListProps<TItem> {
helpText?: React.ReactNode;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function PaginatedListInner<TItem extends Record<string, any>>(
{
data,
Expand Down Expand Up @@ -104,7 +105,7 @@ function PaginatedListInner<TItem extends Record<string, any>>(
const [dirtyItems, setDirtyItems] = useState<Record<string | number, TItem>>(
{}
);
const [error, setError] = useState<Error | null>(null);
const [error] = useState<Error | null>(null);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wut

const idKey = _idKey ?? "id";
const labelKey = _labelKey ?? "name";
const pageSize = _pageSize ?? 20;
Expand Down
8 changes: 4 additions & 4 deletions frontend/components/SQLEditor/SQLEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,12 @@ const SQLEditor = ({
[`${baseClass}__wrapper--readonly-copy`]: !!isReadonlyCopy,
});

const onClickCopy = () => {
const onClickCopy = useCallback(() => {
stringToClipboard(value || "").then(() => {
setCopied(true);
setTimeout(() => setCopied(false), 2000);
});
};
}, [value]);

const fixHotkeys = (editor: Ace.Editor) => {
editor.commands.removeCommand("gotoline");
Expand Down Expand Up @@ -261,7 +261,7 @@ const SQLEditor = ({
onLoad && onLoad(editor);
};

const onBlurHandler = (event: any, editor?: Ace.Editor): void => {
const onBlurHandler = (_event: unknown, editor?: Ace.Editor): void => {
onBlur && onBlur(editor);
};

Expand Down Expand Up @@ -313,7 +313,7 @@ const SQLEditor = ({
</div>
</div>
);
}, [error, label, labelActionComponent, enableCopy, copied]);
}, [error, label, labelActionComponent, enableCopy, copied, onClickCopy]);

const renderHelpText = () => {
if (helpText) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from "react";

import { syntaxHighlight } from "utilities/helpers";

interface ISyntaxHighlightedCodeProps {
json: unknown;
className?: string;
}

/**
* Renders a JSON object as syntax-highlighted HTML inside a <pre> tag.
*
* This component wraps the `syntaxHighlight` utility which generates safe HTML
* from trusted JSON data (all HTML entities are escaped before span tags are
* added for styling). The dangerouslySetInnerHTML usage is intentional and safe
* because the content is never derived from user input — it is always
* serialized from a controlled JavaScript object.
*/
const SyntaxHighlightedCode = ({
json,
className,
}: ISyntaxHighlightedCodeProps): JSX.Element => {
return (
<pre
className={className}
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: syntaxHighlight(json) }}
/>
);
};

export default SyntaxHighlightedCode;
1 change: 1 addition & 0 deletions frontend/components/SyntaxHighlightedCode/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./SyntaxHighlightedCode";
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ describe("DataTable - component", () => {
},
];

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const data: any = [];

render(
Expand Down
68 changes: 54 additions & 14 deletions frontend/components/TableContainer/DataTable/DataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import React, {
} from "react";
import classnames from "classnames";
import {
Cell,
Column,
HeaderGroup,
Row,
Expand Down Expand Up @@ -37,18 +38,19 @@ const baseClass = "data-table-block";

interface IDataTableProps {
columns: Column[];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data: any;
filters?: Record<string, string | number | boolean>;
isLoading: boolean;
manualSortBy?: boolean;
sortHeader: any;
sortDirection: any;
onSort: any; // TODO: an event type
sortHeader: string;
sortDirection: string;
onSort: (id: string | undefined, desc?: boolean) => void;
disableMultiRowSelect: boolean;
keyboardSelectableRows?: boolean;
showMarkAllPages: boolean;
isAllPagesSelected: boolean; // TODO: make dependent on showMarkAllPages
toggleAllPagesSelected?: any; // TODO: an event type and make it dependent on showMarkAllPages
toggleAllPagesSelected?: (value: boolean) => void;
resultsTitle?: string;
defaultPageSize: number;
defaultPageIndex?: number;
Expand All @@ -72,6 +74,7 @@ interface IDataTableProps {
/** Set to `true` to not display the footer section of the table */
hideFooter?: boolean;
onSelectSingleRow?: (value: Row) => void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
onClickRow?: (value: any) => void;
onResultsCountChange?: (value: number) => void;
/** Optional help text to render on bottom-left of the table. Hidden when table is loading and no
Expand All @@ -84,6 +87,7 @@ interface IDataTableProps {
/** Optional override for react-table's row ID derivation.
* Note: avoid index-only row IDs in server-side paginated or selectable tables,
* as IDs would collide across pages. */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getRowId?: (row: any, index: number) => string;
}

Expand Down Expand Up @@ -188,6 +192,7 @@ const DataTable = ({
// Use a stable row ID when available (row.id), otherwise fall back to the index-based ID (default of react-table)
getRowId:
getRowIdProp ??
// eslint-disable-next-line @typescript-eslint/no-explicit-any
((row: any, index: number) =>
row && row.id != null ? String(row.id) : String(index)),
initialState: {
Expand Down Expand Up @@ -291,11 +296,22 @@ const DataTable = ({
!!allFilters.length && setAllFilters(allFilters);
setExportRows && setExportRows(rows);
}
}, [tableFilters]);
// NOTE: `rows` is intentionally excluded from deps to avoid an infinite
// re-render loop. `setExportRows` calls setState in the parent, which
// regenerates column configs, which produces a new `rows` reference,
// which would re-trigger this effect → OOM. `tableFilters` is the
// correct trigger for this side-effect.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [tableFilters, setAllFilters, setExportRows, setGlobalFilter]);

useEffect(() => {
setExportRows && setExportRows(rows);
}, [tableState.filters, rows.length]);
// NOTE: `rows` is intentionally excluded – only `rows.length` is used so
// we detect actual data-count changes without reacting to every
// referential change (which would cause an infinite loop via
// setExportRows → parent re-render → new columns → new rows → …).
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [tableState.filters, rows.length, setExportRows]);

// Listen for changes to filters if clientSideFilter is enabled

Expand Down Expand Up @@ -323,7 +339,14 @@ const DataTable = ({
toggleAllRowsSelected(false); // Resets row selection on query change (client-side)
}
isInitialRender.current = false;
}, [searchQuery, searchQueryColumn]);
}, [
searchQuery,
searchQueryColumn,
isClientSideFilter,
persistSelectedRows,
setDebouncedClientFilter,
toggleAllRowsSelected,
]);

useEffect(() => {
if (isClientSideFilter && selectedDropdownFilter) {
Expand All @@ -332,7 +355,12 @@ const DataTable = ({
? setDebouncedClientFilter("platforms", "")
: setDebouncedClientFilter("platforms", selectedDropdownFilter);
}
}, [selectedDropdownFilter]);
}, [
selectedDropdownFilter,
isClientSideFilter,
setDebouncedClientFilter,
toggleAllRowsSelected,
]);

// track previous sort state
const prevSort = useRef<{ id?: string; desc?: boolean }>({
Expand Down Expand Up @@ -372,7 +400,14 @@ const DataTable = ({
prevSort.current = column
? { id: newId, desc: newDesc }
: { id: undefined, desc: undefined };
}, [sortBy, sortHeader, onSort, sortDirection, isClientSidePagination]);
}, [
sortBy,
sortHeader,
onSort,
sortDirection,
isClientSidePagination,
gotoPage,
]);

/** For onClientSidePaginationChange only:
* Prevents bug where URL page + table page mismatch
Expand Down Expand Up @@ -404,7 +439,7 @@ const DataTable = ({

useEffect(() => {
setPageSize(defaultPageSize);
}, [setPageSize]);
}, [setPageSize, defaultPageSize]);

useDeepEffect(() => {
if (
Expand All @@ -416,7 +451,7 @@ const DataTable = ({
}, [tableState.selectedRowIds, toggleAllPagesSelected]);

const onToggleAllPagesClick = useCallback(() => {
toggleAllPagesSelected();
toggleAllPagesSelected?.(true);
}, [toggleAllPagesSelected]);

const onClearSelectionClick = useCallback(() => {
Expand All @@ -426,7 +461,7 @@ const DataTable = ({
}, [onClearSelection, toggleAllPagesSelected, toggleAllRowsSelected]);

const onSelectRowClick = useCallback(
(row: any) => {
(row: Row) => {
if (disableMultiRowSelect) {
row.toggleRowSelected();
onSelectSingleRow && onSelectSingleRow(row);
Expand Down Expand Up @@ -483,6 +518,7 @@ const DataTable = ({
};

const renderPrimarySelectAction = (): JSX.Element | null => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const targetIds = selectedFlatRows.map((row: any) => row.original.id);
const buttonText =
typeof primarySelectAction?.buttonText === "function"
Expand All @@ -504,6 +540,7 @@ const DataTable = ({

const renderSecondarySelectActions = (): JSX.Element[] | null => {
if (secondarySelectActions) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const targetIds = selectedFlatRows.map((row: any) => row.original.id);
const buttons = secondarySelectActions.map((actionProps) => {
actionProps = { ...actionProps, targetIds };
Expand Down Expand Up @@ -666,10 +703,13 @@ const DataTable = ({
// Can tab onto an entire row if a child element does not have the same onClick functionality as clicking the whole row
tabIndex={keyboardSelectableRows ? 0 : -1}
>
{row.cells.map((cell: any, index: number) => {
{/* eslint-disable-next-line @typescript-eslint/no-unused-vars */}
{row.cells.map((cell: Cell, _index: number) => {
// Only allow row click behavior on first cell
// if the first cell is not a checkbox
const cellProps = cell.getCellProps();
// Destructure key from cellProps to avoid "key specified more than once" warning
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { key: _cellKey, ...cellProps } = cell.getCellProps();
const multiRowSelectEnabled = !disableMultiRowSelect;

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { DEFAULT_EMPTY_CELL_VALUE } from "utilities/constants";
const baseClass = "text-cell";
interface ITextCellProps {
value?: React.ReactNode | { timeString: string };
// eslint-disable-next-line @typescript-eslint/no-explicit-any
formatter?: (val: any) => React.ReactNode; // string, number, or null
grey?: boolean;
italic?: boolean;
Expand Down
Loading
Loading