Frontend: Unit tests /components directory, convert to svg icons (#8716)
This commit is contained in:
@@ -184,10 +184,13 @@ describe("Policies flow (empty)", () => {
|
||||
i: number,
|
||||
expected: boolean[]
|
||||
) => {
|
||||
const check = expected[i] ? "compatible" : "incompatible";
|
||||
const check = expected[i]
|
||||
? "compatible-platform"
|
||||
: "incompatible-platform";
|
||||
const compatibility = expected[i] ? "compatible" : "incompatible";
|
||||
assert(
|
||||
el.children("img").attr("alt") === check,
|
||||
`expected policy to be ${platforms[i]} ${check}`
|
||||
el.children("div").attr("class").includes(check),
|
||||
`expected policy to be ${platforms[i]} ${compatibility}`
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -327,7 +327,7 @@ const PlatformWrapper = ({
|
||||
</p>
|
||||
</div>
|
||||
<RevealButton
|
||||
baseClass={baseClass}
|
||||
className={baseClass}
|
||||
isShowing={showPlainOsquery}
|
||||
hideText={"Plain osquery"}
|
||||
showText={"Plain osquery"}
|
||||
|
||||
@@ -7,7 +7,7 @@ describe("BackLink - component", () => {
|
||||
render(<BackLink text="Back to software" />);
|
||||
|
||||
const text = screen.getByText("Back to software");
|
||||
const icon = screen.getByTestId("Icon");
|
||||
const icon = screen.getByTestId("icon");
|
||||
|
||||
expect(text).toBeInTheDocument();
|
||||
expect(icon).toBeInTheDocument();
|
||||
|
||||
@@ -32,7 +32,7 @@ describe("CustomLink - component", () => {
|
||||
/>
|
||||
);
|
||||
|
||||
const icon = screen.getByTestId("Icon");
|
||||
const icon = screen.getByTestId("icon");
|
||||
|
||||
expect(icon).toBeInTheDocument();
|
||||
expect(icon.closest("a")).toHaveAttribute("target", "_blank");
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
import React from "react";
|
||||
import { screen } from "@testing-library/react";
|
||||
import { renderWithSetup } from "test/testingUtils";
|
||||
|
||||
import EnrollSecretRow from "./EnrollSecretRow";
|
||||
|
||||
const TEAM_SECRET = {
|
||||
secret: "super-secret-secret",
|
||||
created_at: "",
|
||||
team_id: 2,
|
||||
};
|
||||
describe("Enroll secret row", () => {
|
||||
it("Hides secret by default and shows secret on click of eye icon", async () => {
|
||||
const { user, container } = renderWithSetup(
|
||||
<EnrollSecretRow secret={TEAM_SECRET} />
|
||||
);
|
||||
|
||||
// Secret hidden by default
|
||||
const secretHidden = container.querySelector("input");
|
||||
expect(secretHidden?.type === "password").toBeTruthy();
|
||||
|
||||
// Click eye icon
|
||||
const eyeIcon = screen.getByTestId("eye-icon");
|
||||
await user.click(eyeIcon);
|
||||
|
||||
// Secret shown
|
||||
const secretShown = container.querySelector("input");
|
||||
expect(secretShown?.type === "text").toBeTruthy();
|
||||
});
|
||||
});
|
||||
+5
-1
@@ -93,7 +93,11 @@ const EnrollSecretRow = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`${baseClass}__secret`} key={uniqueId()}>
|
||||
<div
|
||||
className={`${baseClass}__secret`}
|
||||
key={uniqueId()}
|
||||
data-testid="osquery-secret"
|
||||
>
|
||||
<InputField
|
||||
disabled
|
||||
inputWrapperClass={`${baseClass}__secret-input`}
|
||||
|
||||
@@ -35,7 +35,7 @@ const Icon = ({ name, color, direction, className, size }: IIconProps) => {
|
||||
const IconComponent = ICON_MAP[name];
|
||||
|
||||
return (
|
||||
<div className={classNames} data-testid="Icon">
|
||||
<div className={classNames} data-testid="icon">
|
||||
<IconComponent {...props} />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import React from "react";
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { renderWithSetup } from "test/testingUtils";
|
||||
|
||||
import LastUpdatedText from "./LastUpdatedText";
|
||||
|
||||
describe("Last updated text", () => {
|
||||
it("renders updated text", () => {
|
||||
const currentDate = new Date();
|
||||
currentDate.setDate(currentDate.getDate() - 2);
|
||||
const twoDaysAgo = currentDate.toISOString();
|
||||
|
||||
render(
|
||||
<LastUpdatedText whatToRetrieve="software" lastUpdatedAt={twoDaysAgo} />
|
||||
);
|
||||
|
||||
const text = screen.getByText("Updated 2 days ago");
|
||||
|
||||
expect(text).toBeInTheDocument();
|
||||
});
|
||||
it("renders never if missing timestamp", () => {
|
||||
render(<LastUpdatedText whatToRetrieve="software" />);
|
||||
|
||||
const text = screen.getByText("Updated never");
|
||||
|
||||
expect(text).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders tooltip on hover", async () => {
|
||||
const { user } = renderWithSetup(
|
||||
<LastUpdatedText whatToRetrieve="software" />
|
||||
);
|
||||
|
||||
await user.hover(screen.getByText("Updated never"));
|
||||
|
||||
expect(screen.getByText(/to retrieve software/i)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -7,7 +7,7 @@ import TooltipWrapper from "components/TooltipWrapper";
|
||||
const baseClass = "component__last-updated-text";
|
||||
|
||||
interface ILastUpdatedTextProps {
|
||||
lastUpdatedAt: string;
|
||||
lastUpdatedAt?: string;
|
||||
whatToRetrieve: string;
|
||||
}
|
||||
const LastUpdatedText = ({
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import React from "react";
|
||||
import { render, screen } from "@testing-library/react";
|
||||
|
||||
import PlatformCompatibility from "./PlatformCompatibility";
|
||||
|
||||
describe("Platform compatibility", () => {
|
||||
it("renders compatible platforms", () => {
|
||||
render(
|
||||
<PlatformCompatibility
|
||||
compatiblePlatforms={["macOS", "Windows"]}
|
||||
error={null}
|
||||
/>
|
||||
);
|
||||
const macCompatibility = screen.getByText("macOS").firstElementChild;
|
||||
const windowsCompatibility = screen.getByText("Windows").firstElementChild;
|
||||
const linuxCompatibility = screen.getByText("Linux").firstElementChild;
|
||||
|
||||
expect(macCompatibility).toHaveAttribute(
|
||||
"class",
|
||||
"icon compatible-platform"
|
||||
);
|
||||
expect(windowsCompatibility).toHaveAttribute(
|
||||
"class",
|
||||
"icon compatible-platform"
|
||||
);
|
||||
expect(linuxCompatibility).toHaveAttribute(
|
||||
"class",
|
||||
"icon incompatible-platform"
|
||||
);
|
||||
});
|
||||
it("renders empty state", () => {
|
||||
render(<PlatformCompatibility compatiblePlatforms={[]} error={null} />);
|
||||
|
||||
const text = screen.getByText(/No platforms/i);
|
||||
|
||||
expect(text).toBeInTheDocument();
|
||||
});
|
||||
it("renders error state", () => {
|
||||
render(
|
||||
<PlatformCompatibility
|
||||
compatiblePlatforms={["macOS"]}
|
||||
error={{ name: "Error", message: "The resource was not found." }}
|
||||
/>
|
||||
);
|
||||
|
||||
const text = screen.getByText(/possible syntax error/i);
|
||||
|
||||
expect(text).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -4,8 +4,7 @@ import { IOsqueryPlatform } from "interfaces/platform";
|
||||
import { PLATFORM_DISPLAY_NAMES } from "utilities/constants";
|
||||
|
||||
import TooltipWrapper from "components/TooltipWrapper";
|
||||
import CompatibleIcon from "../../../assets/images/icon-compatible-green-16x16@2x.png";
|
||||
import IncompatibleIcon from "../../../assets/images/icon-incompatible-red-16x16@2x.png";
|
||||
import Icon from "components/Icon";
|
||||
|
||||
interface IPlatformCompatibilityProps {
|
||||
compatiblePlatforms: IOsqueryPlatform[] | null;
|
||||
@@ -51,7 +50,10 @@ const PlatformCompatibility = ({
|
||||
return (
|
||||
<span className={baseClass}>
|
||||
<b>
|
||||
<TooltipWrapper tipContent="Estimated compatiblity based on <br /> the tables used in the query.">
|
||||
<TooltipWrapper
|
||||
tipContent="Estimated compatiblity based on <br /> the tables used in the query."
|
||||
isDelayed
|
||||
>
|
||||
Compatible with:
|
||||
</TooltipWrapper>
|
||||
</b>
|
||||
@@ -79,9 +81,12 @@ const PlatformCompatibility = ({
|
||||
key={`platform-compatibility__${platform}`}
|
||||
className="platform"
|
||||
>
|
||||
<img
|
||||
alt={isCompatible ? "compatible" : "incompatible"}
|
||||
src={isCompatible ? CompatibleIcon : IncompatibleIcon}
|
||||
<Icon
|
||||
name={isCompatible ? "check" : "ex"}
|
||||
className={
|
||||
isCompatible ? "compatible-platform" : "incompatible-platform"
|
||||
}
|
||||
color={isCompatible ? "status-success" : "status-error"}
|
||||
/>
|
||||
{platform}
|
||||
</span>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
padding-top: $pad-medium;
|
||||
|
||||
b,
|
||||
img,
|
||||
svg,
|
||||
span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -17,12 +17,10 @@
|
||||
|
||||
.platform {
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
img {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
padding-left: 12px;
|
||||
padding-right: $pad-xsmall;
|
||||
.icon {
|
||||
padding-left: 12px;
|
||||
padding-right: $pad-xsmall;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import React from "react";
|
||||
import { screen } from "@testing-library/react";
|
||||
import { renderWithSetup } from "test/testingUtils";
|
||||
|
||||
import DropdownCell from "./DropdownCell";
|
||||
|
||||
const DROPDOWN_OPTIONS = [
|
||||
{ disabled: false, label: "Edit", value: "edit-query" },
|
||||
{ disabled: false, label: "Show query", value: "show-query" },
|
||||
{ disabled: true, label: "Delete", value: "delete-query" },
|
||||
];
|
||||
const PLACEHOLDER = "Actions";
|
||||
const ON_CHANGE = (value: string) => {
|
||||
console.log(value);
|
||||
};
|
||||
|
||||
describe("Dropdown cell", () => {
|
||||
it("renders dropdown placeholder and options", async () => {
|
||||
const { user } = renderWithSetup(
|
||||
<DropdownCell
|
||||
options={DROPDOWN_OPTIONS}
|
||||
placeholder={PLACEHOLDER}
|
||||
onChange={ON_CHANGE}
|
||||
/>
|
||||
);
|
||||
|
||||
await user.click(screen.getByText("Actions"));
|
||||
|
||||
expect(screen.getByText(/edit/i)).toBeInTheDocument();
|
||||
expect(screen.getByText(/show query/i)).toBeInTheDocument();
|
||||
expect(screen.getByText(/delete/i)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
import React from "react";
|
||||
import { screen } from "@testing-library/react";
|
||||
import { createCustomRenderer } from "test/test-utils";
|
||||
|
||||
import IssueCell from "./IssueCell";
|
||||
|
||||
describe("Issue cell", () => {
|
||||
it("renders icon, total issues, and failing policies tooltip", async () => {
|
||||
const render = createCustomRenderer({});
|
||||
|
||||
const { user } = render(
|
||||
<IssueCell
|
||||
issues={{
|
||||
total_issues_count: 4,
|
||||
failing_policies_count: 2,
|
||||
}}
|
||||
rowId={1}
|
||||
/>
|
||||
);
|
||||
|
||||
const icon = screen.queryByTestId("icon");
|
||||
|
||||
await user.hover(screen.getByText("4"));
|
||||
|
||||
expect(screen.getByText(/failing policies/i)).toBeInTheDocument();
|
||||
expect(icon).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -2,6 +2,8 @@ import React from "react";
|
||||
import ReactTooltip from "react-tooltip";
|
||||
import { isEmpty } from "lodash";
|
||||
|
||||
import Icon from "components/Icon";
|
||||
|
||||
import IssueIcon from "../../../../../assets/images/icon-issue-fleet-black-50-16x16@2x.png";
|
||||
|
||||
interface IIssueCellProps<T> {
|
||||
@@ -25,7 +27,7 @@ const IssueCell = ({ issues, rowId }: IIssueCellProps<any>): JSX.Element => {
|
||||
data-for={`host-issue__${rowId.toString()}`}
|
||||
data-tip-disable={false}
|
||||
>
|
||||
<img alt="host issue" src={IssueIcon} />
|
||||
<Icon name="issue" />
|
||||
</span>
|
||||
<ReactTooltip
|
||||
place="top"
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import React from "react";
|
||||
import { screen } from "@testing-library/react";
|
||||
import { renderWithSetup } from "test/testingUtils";
|
||||
import PATHS from "router/paths";
|
||||
|
||||
import LinkCell from "./LinkCell";
|
||||
|
||||
const VALUE = "40 hosts";
|
||||
describe("Link cell", () => {
|
||||
it("renders text and path", async () => {
|
||||
const { user } = renderWithSetup(
|
||||
<LinkCell value={VALUE} path={PATHS.MANAGE_HOSTS} />
|
||||
);
|
||||
|
||||
await user.click(screen.getByText("40 hosts"));
|
||||
|
||||
expect(window.location.pathname).toContain("/hosts");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
import React from "react";
|
||||
import { screen } from "@testing-library/react";
|
||||
import { renderWithSetup } from "test/testingUtils";
|
||||
|
||||
import PillCell from "./PillCell";
|
||||
|
||||
const PERFORMANCE_IMPACT = { indicator: "Minimal", id: 3 };
|
||||
|
||||
describe("Pill cell", () => {
|
||||
it("renders pill text and tooltip on hover", async () => {
|
||||
const { user } = renderWithSetup(
|
||||
<PillCell value={PERFORMANCE_IMPACT} hostDetails />
|
||||
);
|
||||
|
||||
await user.hover(screen.getByText("Minimal"));
|
||||
|
||||
expect(screen.getByText(/little to no impact/i)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -1,11 +1,11 @@
|
||||
import React from "react";
|
||||
import classnames from "classnames";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { uniqueId } from "lodash";
|
||||
|
||||
import ReactTooltip from "react-tooltip";
|
||||
|
||||
interface IPillCellProps {
|
||||
value: [string, number];
|
||||
value: { indicator: string; id: number };
|
||||
customIdPrefix?: string;
|
||||
hostDetails?: boolean;
|
||||
}
|
||||
@@ -19,16 +19,15 @@ const PillCell = ({
|
||||
customIdPrefix,
|
||||
hostDetails,
|
||||
}: IPillCellProps): JSX.Element => {
|
||||
const [pillText, id] = value;
|
||||
|
||||
const { indicator, id } = value;
|
||||
const pillClassName = classnames(
|
||||
"data-table__pill",
|
||||
`data-table__pill--${generateClassTag(pillText)}`,
|
||||
`data-table__pill--${generateClassTag(indicator || "")}`,
|
||||
"tooltip"
|
||||
);
|
||||
|
||||
const disable = () => {
|
||||
switch (pillText) {
|
||||
switch (indicator) {
|
||||
case "Minimal":
|
||||
return false;
|
||||
case "Considerable":
|
||||
@@ -43,7 +42,7 @@ const PillCell = ({
|
||||
};
|
||||
|
||||
const tooltipText = () => {
|
||||
switch (pillText) {
|
||||
switch (indicator) {
|
||||
case "Minimal":
|
||||
return (
|
||||
<>
|
||||
@@ -85,25 +84,30 @@ const PillCell = ({
|
||||
return null;
|
||||
}
|
||||
};
|
||||
const tooltipId = uniqueId();
|
||||
|
||||
return (
|
||||
<>
|
||||
<span
|
||||
data-tip
|
||||
data-for={`${customIdPrefix || "pill"}__${id?.toString() || uuidv4()}`}
|
||||
data-for={`${customIdPrefix || "pill"}__${id?.toString() || tooltipId}`}
|
||||
data-tip-disable={disable()}
|
||||
>
|
||||
<span className={pillClassName}>{pillText}</span>
|
||||
<span className={pillClassName}>{indicator}</span>
|
||||
</span>
|
||||
<ReactTooltip
|
||||
place="bottom"
|
||||
// offset={getTooltipOffset(pillText)}
|
||||
effect="solid"
|
||||
backgroundColor="#3e4771"
|
||||
id={`${customIdPrefix || "pill"}__${id?.toString() || uuidv4()}`}
|
||||
id={`${customIdPrefix || "pill"}__${id?.toString() || tooltipId}`}
|
||||
data-html
|
||||
>
|
||||
<span className={`tooltip ${generateClassTag(pillText)}__tooltip-text`}>
|
||||
<span
|
||||
className={`tooltip ${generateClassTag(
|
||||
indicator || ""
|
||||
)}__tooltip-text`}
|
||||
>
|
||||
{tooltipText()}
|
||||
</span>
|
||||
</ReactTooltip>
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import React from "react";
|
||||
import { getByTestId, render, screen, within } from "@testing-library/react";
|
||||
|
||||
import PlatformCell from "./PlatformCell";
|
||||
|
||||
const PLATFORMS = ["windows", "darwin", "linux"];
|
||||
|
||||
describe("Platform cell", () => {
|
||||
it("renders platform icons in correct order", () => {
|
||||
render(<PlatformCell value={PLATFORMS} />);
|
||||
|
||||
const icons = screen.queryAllByTestId("icon");
|
||||
const appleIcon = screen.queryByTestId("apple-icon");
|
||||
const linuxIcon = screen.queryByTestId("linux-icon");
|
||||
const windowsIcon = screen.queryByTestId("windows-icon");
|
||||
|
||||
expect(icons).toHaveLength(3);
|
||||
expect(icons[0].firstChild).toBe(appleIcon);
|
||||
expect(icons[1].firstChild).toBe(linuxIcon);
|
||||
expect(icons[2].firstChild).toBe(windowsIcon);
|
||||
});
|
||||
it("renders empty state", () => {
|
||||
render(<PlatformCell value={[]} />);
|
||||
|
||||
const icons = screen.queryAllByTestId("icon");
|
||||
const emptyText = screen.queryByText("---");
|
||||
|
||||
expect(icons).toHaveLength(0);
|
||||
expect(emptyText).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -36,6 +36,7 @@ const PlatformCell = ({
|
||||
className={`${baseClass}__icon`}
|
||||
name={ICONS[platform]}
|
||||
size="small"
|
||||
key={ICONS[platform]}
|
||||
/>
|
||||
) : null;
|
||||
})
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useRef, useLayoutEffect } from "react";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { uniqueId } from "lodash";
|
||||
|
||||
import ReactTooltip from "react-tooltip";
|
||||
|
||||
@@ -26,7 +26,7 @@ const TruncatedTextCell = ({
|
||||
}
|
||||
}, []);
|
||||
|
||||
const id = uuidv4();
|
||||
const tooltipId = uniqueId();
|
||||
const tooltipDisabled = offsetWidth === scrollWidth;
|
||||
|
||||
return (
|
||||
@@ -34,7 +34,7 @@ const TruncatedTextCell = ({
|
||||
<div
|
||||
className={"data-table__truncated-text"}
|
||||
data-tip
|
||||
data-for={id}
|
||||
data-for={tooltipId}
|
||||
data-tip-disable={tooltipDisabled}
|
||||
>
|
||||
<span
|
||||
@@ -49,7 +49,7 @@ const TruncatedTextCell = ({
|
||||
place="bottom"
|
||||
effect="solid"
|
||||
backgroundColor="#3e4771"
|
||||
id={id}
|
||||
id={tooltipId}
|
||||
data-html
|
||||
className={"truncated-tooltip"} // responsive widths
|
||||
>
|
||||
|
||||
@@ -7,7 +7,7 @@ describe("ViewAllHostsLink - component", () => {
|
||||
render(<ViewAllHostsLink />);
|
||||
|
||||
const text = screen.getByText("View all hosts");
|
||||
const icon = screen.getByTestId("Icon");
|
||||
const icon = screen.getByTestId("icon");
|
||||
|
||||
expect(text).toBeInTheDocument();
|
||||
expect(icon).toBeInTheDocument();
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
import React from "react";
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { renderWithSetup } from "test/testingUtils";
|
||||
|
||||
import RevealButton from "./RevealButton";
|
||||
|
||||
const SHOW_TEXT = "Show advanced options";
|
||||
const HIDE_TEXT = "Hide advanced options";
|
||||
const TOOLTIP_HTML = "Customize logging type and platforms";
|
||||
|
||||
describe("Reveal button", () => {
|
||||
it("renders show text", async () => {
|
||||
render(
|
||||
<RevealButton
|
||||
isShowing={false}
|
||||
hideText={HIDE_TEXT}
|
||||
showText={SHOW_TEXT}
|
||||
/>
|
||||
);
|
||||
|
||||
const showText = screen.getByText(SHOW_TEXT);
|
||||
expect(showText).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders hide text", async () => {
|
||||
render(
|
||||
<RevealButton isShowing hideText={HIDE_TEXT} showText={SHOW_TEXT} />
|
||||
);
|
||||
|
||||
const hideText = screen.getByText(HIDE_TEXT);
|
||||
expect(hideText).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("hides caret by default", async () => {
|
||||
render(
|
||||
<RevealButton
|
||||
isShowing={false}
|
||||
hideText={HIDE_TEXT}
|
||||
showText={SHOW_TEXT}
|
||||
/>
|
||||
);
|
||||
|
||||
const icon = screen.queryByTestId("icon");
|
||||
|
||||
expect(icon).toBeNull();
|
||||
});
|
||||
|
||||
it("renders caret on left", async () => {
|
||||
render(
|
||||
<RevealButton
|
||||
isShowing={false}
|
||||
hideText={HIDE_TEXT}
|
||||
showText={SHOW_TEXT}
|
||||
caretPosition={"before"}
|
||||
/>
|
||||
);
|
||||
|
||||
const icon = screen.queryByTestId("icon");
|
||||
expect(icon?.nextSibling).toHaveTextContent(SHOW_TEXT);
|
||||
});
|
||||
|
||||
it("renders caret on right", async () => {
|
||||
render(
|
||||
<RevealButton
|
||||
isShowing={false}
|
||||
hideText={HIDE_TEXT}
|
||||
showText={SHOW_TEXT}
|
||||
caretPosition={"after"}
|
||||
/>
|
||||
);
|
||||
|
||||
const icon = screen.queryByTestId("icon");
|
||||
|
||||
expect(icon?.previousSibling).toHaveTextContent(SHOW_TEXT);
|
||||
});
|
||||
|
||||
it("renders tooltip on hover if provided", async () => {
|
||||
const { user } = renderWithSetup(
|
||||
<RevealButton
|
||||
isShowing={false}
|
||||
hideText={HIDE_TEXT}
|
||||
showText={SHOW_TEXT}
|
||||
caretPosition={"before"}
|
||||
tooltipHtml={TOOLTIP_HTML}
|
||||
/>
|
||||
);
|
||||
|
||||
await user.hover(screen.getByText(SHOW_TEXT));
|
||||
|
||||
expect(screen.getByText(TOOLTIP_HTML)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -1,10 +1,12 @@
|
||||
import React from "react";
|
||||
import classnames from "classnames";
|
||||
import Button from "components/buttons/Button";
|
||||
import TooltipWrapper from "components/TooltipWrapper";
|
||||
import Icon from "components/Icon";
|
||||
|
||||
export interface IRevealButtonProps {
|
||||
isShowing: boolean;
|
||||
baseClass: string;
|
||||
className?: string;
|
||||
hideText: string;
|
||||
showText: string;
|
||||
caretPosition?: "before" | "after";
|
||||
@@ -16,8 +18,11 @@ export interface IRevealButtonProps {
|
||||
| ((evt: React.MouseEvent<HTMLButtonElement>) => void);
|
||||
}
|
||||
|
||||
const baseClass = "reveal-button";
|
||||
|
||||
const RevealButton = ({
|
||||
isShowing,
|
||||
className,
|
||||
hideText,
|
||||
showText,
|
||||
caretPosition,
|
||||
@@ -26,31 +31,47 @@ const RevealButton = ({
|
||||
tooltipHtml,
|
||||
onClick,
|
||||
}: IRevealButtonProps): JSX.Element => {
|
||||
const classNameGenerator = () => {
|
||||
if (caretPosition === "before") {
|
||||
return isShowing ? "reveal upcaretbefore" : "reveal rightcaretbefore";
|
||||
}
|
||||
if (caretPosition === "after") {
|
||||
return isShowing ? "reveal upcaretafter" : "reveal downcaretafter";
|
||||
}
|
||||
return "reveal";
|
||||
};
|
||||
const classNames = classnames(baseClass, className);
|
||||
|
||||
const buttonText = isShowing ? hideText : showText;
|
||||
const buttonContent = () => {
|
||||
const text = isShowing ? hideText : showText;
|
||||
|
||||
const buttonText = tooltipHtml ? (
|
||||
<TooltipWrapper tipContent={tooltipHtml}>{text}</TooltipWrapper>
|
||||
) : (
|
||||
text
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{caretPosition === "before" && (
|
||||
<Icon
|
||||
name="chevron"
|
||||
direction={isShowing ? "right" : "down"}
|
||||
color="core-fleet-blue"
|
||||
/>
|
||||
)}
|
||||
{buttonText}
|
||||
{caretPosition === "after" && (
|
||||
<Icon
|
||||
name="chevron"
|
||||
direction={isShowing ? "up" : "down"}
|
||||
color="core-fleet-blue"
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Button
|
||||
variant="unstyled"
|
||||
className={`reveal-button ${classNameGenerator()}`}
|
||||
variant="text-icon"
|
||||
className={classNames}
|
||||
onClick={onClick}
|
||||
autofocus={autofocus}
|
||||
disabled={disabled}
|
||||
>
|
||||
{tooltipHtml ? (
|
||||
<TooltipWrapper tipContent={tooltipHtml}>{buttonText}</TooltipWrapper>
|
||||
) : (
|
||||
buttonText
|
||||
)}
|
||||
{buttonContent()}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,54 +1,6 @@
|
||||
.reveal {
|
||||
margin: $pad-medium 0 $pad-large;
|
||||
color: $core-vibrant-blue;
|
||||
font-weight: $bold;
|
||||
font-size: $x-small;
|
||||
}
|
||||
|
||||
.rightcaretbefore {
|
||||
&::before {
|
||||
content: url("../assets/images/icon-chevron-blue-16x16@2x.png");
|
||||
transform: scale(0.5) rotate(-90deg);
|
||||
width: 16px;
|
||||
padding: 0px;
|
||||
padding-right: 10px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.upcaretbefore {
|
||||
&::before {
|
||||
content: url("../assets/images/icon-chevron-blue-16x16@2x.png");
|
||||
transform: scale(0.5) rotate(180deg);
|
||||
width: 16px;
|
||||
padding: 0px;
|
||||
padding-right: 2px;
|
||||
margin-right: $pad-small;
|
||||
margin-top: 5px;
|
||||
position: relative;
|
||||
top: -4px;
|
||||
left: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.downcaretafter {
|
||||
&::after {
|
||||
content: url("../assets/images/icon-chevron-blue-16x16@2x.png");
|
||||
transform: scale(0.5);
|
||||
width: 16px;
|
||||
padding: 0px;
|
||||
padding-left: 2px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.upcaretafter {
|
||||
&::after {
|
||||
content: url("../assets/images/icon-chevron-blue-16x16@2x.png");
|
||||
transform: scale(0.5) rotate(180deg);
|
||||
width: 16px;
|
||||
padding: 0px;
|
||||
margin-bottom: 2px;
|
||||
margin-left: 11px;
|
||||
}
|
||||
.reveal-button .children-wrapper {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: $pad-small $pad-xxsmall; // larger clickable area
|
||||
gap: $pad-xsmall;
|
||||
}
|
||||
|
||||
+3
-4
@@ -1,9 +1,8 @@
|
||||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { difference, isEqual } from "lodash";
|
||||
import { difference, isEqual, uniqueId } from "lodash";
|
||||
import Select from "react-select";
|
||||
import "react-select/dist/react-select.css";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
import debounce from "utilities/debounce";
|
||||
import targetInterface from "interfaces/target";
|
||||
@@ -43,7 +42,7 @@ class SelectTargetsInput extends Component {
|
||||
// must have unique key to select correctly
|
||||
const uuidTargets = targets.map((target) => ({
|
||||
...target,
|
||||
uuid: uuidv4(),
|
||||
uuid: uniqueId(),
|
||||
}));
|
||||
|
||||
this.setState({ uuidTargets });
|
||||
@@ -53,7 +52,7 @@ class SelectTargetsInput extends Component {
|
||||
// must have unique key to deselect correctly
|
||||
const uuidSelectedTargets = selectedTargets.map((target) => ({
|
||||
...target,
|
||||
uuid: uuidv4(),
|
||||
uuid: uniqueId(),
|
||||
}));
|
||||
|
||||
this.setState({ uuidSelectedTargets });
|
||||
|
||||
@@ -23,6 +23,7 @@ const Apple = ({
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 16 16"
|
||||
data-testid="apple-icon"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import React from "react";
|
||||
import { COLORS, Colors } from "styles/var/colors";
|
||||
|
||||
interface ICheckProps {
|
||||
color?: string;
|
||||
color?: Colors;
|
||||
}
|
||||
|
||||
const Check = ({ color = "#6a67fe" }: ICheckProps) => {
|
||||
const Check = ({ color = "core-fleet-blue" }: ICheckProps) => {
|
||||
return (
|
||||
<svg
|
||||
width="16"
|
||||
@@ -18,7 +19,7 @@ const Check = ({ color = "#6a67fe" }: ICheckProps) => {
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M2.917 8.684c-.02 0-.042 0-.083.02a1.035 1.035 0 0 1-.23-.083c.063-.041.167-.021.313.063Zm10.56-5.603c-.543-.292-1.147.27-1.5.604-.812.791-1.5 1.708-2.27 2.54-.855.917-1.646 1.834-2.52 2.73-.5.5-1.042 1.04-1.375 1.666-.75-.73-1.396-1.52-2.228-2.166C2.98 7.996 1.98 7.663 2 8.767c.042 1.437 1.313 2.978 2.25 3.957.395.417.916.854 1.52.874.73.042 1.479-.833 1.916-1.312.77-.832 1.396-1.77 2.104-2.623.916-1.125 1.854-2.23 2.748-3.374.563-.709 2.333-2.458.938-3.208Z"
|
||||
fill={color}
|
||||
fill={COLORS[color]}
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
|
||||
@@ -8,6 +8,7 @@ const Eye = () => {
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 16 16"
|
||||
data-testid="eye-icon"
|
||||
>
|
||||
<g clipPath="url(#a)" fill="#6a67fe">
|
||||
<path d="M7.996 14C3.654 14 .246 8.6.102 8.37A.708.708 0 0 1 0 8c0-.133.036-.262.102-.37C.246 7.4 3.654 2 7.996 2c4.342 0 7.758 5.4 7.902 5.63A.708.708 0 0 1 16 8a.708.708 0 0 1-.102.37C15.754 8.6 12.346 14 7.996 14ZM2.198 8c.85 1.17 2.594 4 5.798 4 3.203 0 4.948-2.83 5.797-4-.85-1.17-2.602-4-5.797-4S3.022 6.83 2.198 8Z" />
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import React from "react";
|
||||
|
||||
import { COLORS, Colors } from "styles/var/colors";
|
||||
|
||||
interface IErrorProps {
|
||||
color?: Colors;
|
||||
}
|
||||
|
||||
const Issue = ({ color = "ui-fleet-black-50" }: IErrorProps) => {
|
||||
return (
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 16 16"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M8 14A6 6 0 1 0 8 2a6 6 0 0 0 0 12Zm0 2A8 8 0 1 0 8 0a8 8 0 0 0 0 16ZM8 4a1 1 0 0 1 1 1v3a1 1 0 1 1-2 0V5a1 1 0 0 1 1-1Zm0 8a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z"
|
||||
fill={COLORS[color]}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default Issue;
|
||||
@@ -23,6 +23,7 @@ const Linux = ({
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 16 16"
|
||||
data-testid="linux-icon"
|
||||
>
|
||||
<path
|
||||
d="M15.992 10.96c-.717-2.833-2.224-4.3-3.069-4.927l-.136-.18c.136-.413.211-.853.211-1.306C12.998 2.033 10.76 0 7.992 0 5.226 0 2.98 2.04 2.98 4.547c0 .453.075.893.211 1.306-.06.074-.113.147-.166.22C2.172 6.72.717 8.187.008 10.96c-.03.12.023.253.129.333.113.08.263.094.392.047.392-.16.912-.4 1.394-.733A5.99 5.99 0 0 0 4.23 14.4h-.904c-.498 0-.905.36-.905.8 0 .44.407.8.905.8h9.288c.498 0 .905-.36.905-.8 0-.44-.407-.8-.905-.8h-.875a5.987 5.987 0 0 0 2.307-3.813c.49.34 1.018.586 1.418.746a.412.412 0 0 0 .392-.046.302.302 0 0 0 .136-.327Zm-8.007 2.86c-2.36 0-4.275-1.88-4.275-4.193 0-1.187.505-2.687 1.312-3.86-.422-.327-.686-.807-.686-1.334 0-.986.905-1.78 2.013-1.78.67 0 1.259.287 1.628.734.37-.447.958-.734 1.629-.734 1.116 0 2.013.8 2.013 1.78 0 .534-.264 1.007-.686 1.334.806 1.173 1.312 2.666 1.312 3.86.015 2.32-1.9 4.193-4.26 4.193Z"
|
||||
|
||||
@@ -23,6 +23,7 @@ const Windows = ({
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 16 16"
|
||||
data-testid="windows-icon"
|
||||
>
|
||||
<path
|
||||
d="m1.092 13.142 5.192 1.038V8.32H1.092v4.822ZM1.092 7.665h5.192V1.836L1.092 2.874v4.79ZM7.11 7.665h8.382V0L7.11 1.677v5.988ZM7.11 14.34 15.491 16V8.32H7.11v6.02Z"
|
||||
|
||||
@@ -3,8 +3,8 @@ import CalendarCheck from "./CalendarCheck";
|
||||
import Check from "./Check";
|
||||
import Chevron from "./Chevron";
|
||||
import Ex from "./Ex";
|
||||
|
||||
import ExternalLink from "./ExternalLink";
|
||||
import Issue from "./Issue";
|
||||
import Plus from "./Plus";
|
||||
|
||||
import LowDiskSpaceHosts from "./LowDiskSpaceHosts";
|
||||
@@ -40,6 +40,7 @@ export const ICON_MAP = {
|
||||
"external-link": ExternalLink,
|
||||
"low-disk-space-hosts": LowDiskSpaceHosts,
|
||||
"missing-hosts": MissingHosts,
|
||||
issue: Issue,
|
||||
plus: Plus,
|
||||
clipboard: Clipboard,
|
||||
eye: Eye,
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ interface ICellProps extends IRowProps {
|
||||
|
||||
interface IPillCellProps extends IRowProps {
|
||||
cell: {
|
||||
value: [string, number];
|
||||
value: { indicator: string; id: number };
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useQuery, UseQueryResult } from "react-query";
|
||||
import { filter } from "lodash";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { filter, uniqueId } from "lodash";
|
||||
|
||||
import { IHost } from "interfaces/host";
|
||||
import { ILabel } from "interfaces/label";
|
||||
@@ -53,20 +52,23 @@ const getTargets = async (
|
||||
const all = filter(
|
||||
labels,
|
||||
({ display_text: text }) => text === "All Hosts"
|
||||
).map((label) => ({ ...label, uuid: uuidv4() }));
|
||||
).map((label) => ({ ...label, uuid: uniqueId() }));
|
||||
|
||||
const platforms = filter(
|
||||
labels,
|
||||
({ display_text: text }) =>
|
||||
text === "macOS" || text === "MS Windows" || text === "All Linux"
|
||||
).map((label) => ({ ...label, uuid: uuidv4() }));
|
||||
).map((label) => ({ ...label, uuid: uniqueId() }));
|
||||
|
||||
const other = filter(
|
||||
labels,
|
||||
({ label_type: type }) => type === "regular"
|
||||
).map((label) => ({ ...label, uuid: uuidv4() }));
|
||||
).map((label) => ({ ...label, uuid: uniqueId() }));
|
||||
|
||||
const teams = targets.teams.map((team) => ({ ...team, uuid: uuidv4() }));
|
||||
const teams = targets.teams.map((team) => ({
|
||||
...team,
|
||||
uuid: uniqueId(),
|
||||
}));
|
||||
|
||||
const labelCount =
|
||||
all.length + platforms.length + other.length + teams.length;
|
||||
|
||||
@@ -60,12 +60,11 @@ describe("SummaryTile - component", () => {
|
||||
|
||||
const title = screen.getByText("Windows hosts");
|
||||
const count = screen.getByText("200");
|
||||
// TOOD: Fix icon assertion
|
||||
// const icon = screen.getByRole("svg");
|
||||
const icon = screen.queryByTestId("icon");
|
||||
|
||||
expect(title).toBeInTheDocument();
|
||||
expect(count).toBeInTheDocument();
|
||||
// expect(icon).toBeInTheDocument();
|
||||
expect(icon).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("does not render icon if not provided", () => {
|
||||
@@ -80,7 +79,7 @@ describe("SummaryTile - component", () => {
|
||||
/>
|
||||
);
|
||||
|
||||
const icon = screen.queryByRole("img");
|
||||
const icon = screen.queryByRole("svg");
|
||||
|
||||
expect(icon).toBeNull();
|
||||
});
|
||||
|
||||
@@ -187,11 +187,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.host-issue {
|
||||
img {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
vertical-align: sub;
|
||||
}
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ interface ICellProps extends IRowProps {
|
||||
|
||||
interface IPillCellProps extends IRowProps {
|
||||
cell: {
|
||||
value: [string, number];
|
||||
value: { indicator: string; id: number };
|
||||
};
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ interface IDataColumn {
|
||||
interface IPackTable extends Partial<IQueryStats> {
|
||||
frequency: string;
|
||||
last_run: string;
|
||||
performance: (string | number)[];
|
||||
performance: { indicator: string; id: number };
|
||||
}
|
||||
|
||||
// NOTE: cellProps come from react-table
|
||||
@@ -123,10 +123,10 @@ const enhancePackData = (query_stats: IQueryStats[]): IPackTable[] => {
|
||||
last_executed: query.last_executed,
|
||||
frequency: secondsToHms(query.interval),
|
||||
last_run: humanQueryLastRun(query.last_executed),
|
||||
performance: [
|
||||
performanceIndicator(scheduledQueryPerformance),
|
||||
query.scheduled_query_id || uniqueId(),
|
||||
],
|
||||
performance: {
|
||||
indicator: performanceIndicator(scheduledQueryPerformance),
|
||||
id: query.scheduled_query_id || parseInt(uniqueId(), 10),
|
||||
},
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import React from "react";
|
||||
import { uniqueId } from "lodash";
|
||||
|
||||
import { IQueryStats } from "interfaces/query_stats";
|
||||
import { performanceIndicator, secondsToDhms } from "utilities/helpers";
|
||||
@@ -29,7 +28,10 @@ interface ICellProps extends IRowProps {
|
||||
|
||||
interface IPillCellProps extends IRowProps {
|
||||
cell: {
|
||||
value: [string, number];
|
||||
value: {
|
||||
indicator: string;
|
||||
id: number;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -46,7 +48,7 @@ interface IDataColumn {
|
||||
|
||||
interface IScheduleTable extends Partial<IQueryStats> {
|
||||
frequency: string;
|
||||
performance: (string | number)[];
|
||||
performance: { indicator: string; id: number };
|
||||
}
|
||||
|
||||
// NOTE: cellProps come from react-table
|
||||
@@ -102,10 +104,10 @@ const enhanceScheduleData = (query_stats: IQueryStats[]): IScheduleTable[] => {
|
||||
return {
|
||||
query_name: query.query_name,
|
||||
frequency: secondsToDhms(query.interval),
|
||||
performance: [
|
||||
performanceIndicator(scheduledQueryPerformance),
|
||||
query.scheduled_query_id || uniqueId(),
|
||||
],
|
||||
performance: {
|
||||
indicator: performanceIndicator(scheduledQueryPerformance),
|
||||
id: query.scheduled_query_id,
|
||||
},
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
@@ -461,7 +461,7 @@ const ManagePolicyPage = ({
|
||||
{showInheritedPoliciesButton && globalPolicies && (
|
||||
<RevealButton
|
||||
isShowing={showInheritedPolicies}
|
||||
baseClass={baseClass}
|
||||
className={baseClass}
|
||||
hideText={inheritedPoliciesButtonText(
|
||||
showInheritedPolicies,
|
||||
globalPolicies.length
|
||||
|
||||
@@ -422,7 +422,7 @@ const PolicyForm = ({
|
||||
</div>
|
||||
<RevealButton
|
||||
isShowing={showQueryEditor}
|
||||
baseClass={baseClass}
|
||||
className={baseClass}
|
||||
hideText="Hide SQL"
|
||||
showText="Show SQL"
|
||||
onClick={() => setShowQueryEditor(!showQueryEditor)}
|
||||
|
||||
+6
-1
@@ -156,7 +156,12 @@ const generateTableHeaders = (currentUser: IUser): IDataColumn[] => {
|
||||
disableSortBy: true,
|
||||
accessor: "performance",
|
||||
Cell: (cellProps: ICellProps) => (
|
||||
<PillCell value={[cellProps.cell.value, cellProps.row.original.id]} />
|
||||
<PillCell
|
||||
value={{
|
||||
indicator: cellProps.cell.value,
|
||||
id: cellProps.row.original.id,
|
||||
}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
|
||||
@@ -404,7 +404,7 @@ const QueryForm = ({
|
||||
</div>
|
||||
<RevealButton
|
||||
isShowing={showQueryEditor}
|
||||
baseClass={baseClass}
|
||||
className={baseClass}
|
||||
hideText="Hide SQL"
|
||||
showText="Show SQL"
|
||||
onClick={() => setShowQueryEditor(!showQueryEditor)}
|
||||
|
||||
@@ -536,7 +536,7 @@ const ManageSchedulePage = ({
|
||||
inheritedScheduledQueriesList.length > 0 ? (
|
||||
<RevealButton
|
||||
isShowing={showInheritedQueries}
|
||||
baseClass={baseClass}
|
||||
className={baseClass}
|
||||
hideText={`Hide ${inheritedScheduledQueriesList.length} inherited ${inheritedQueryOrQueries}`}
|
||||
showText={`Show ${inheritedScheduledQueriesList.length} inherited ${inheritedQueryOrQueries}`}
|
||||
caretPosition={"before"}
|
||||
|
||||
+1
-1
@@ -275,7 +275,7 @@ const ScheduleEditorModal = ({
|
||||
<div>
|
||||
<RevealButton
|
||||
isShowing={showAdvancedOptions}
|
||||
baseClass={baseClass}
|
||||
className={baseClass}
|
||||
hideText={"Hide advanced options"}
|
||||
showText={"Show advanced options"}
|
||||
caretPosition={"after"}
|
||||
|
||||
+9
-5
@@ -54,7 +54,7 @@ interface INumberCellProps extends IRowProps {
|
||||
|
||||
interface IPillCellProps extends IRowProps {
|
||||
cell: {
|
||||
value: [string, number];
|
||||
value: { indicator: string; id: number };
|
||||
};
|
||||
}
|
||||
|
||||
@@ -236,6 +236,10 @@ const enhanceAllScheduledQueryData = (
|
||||
system_time_p50: scheduledQuery.stats?.system_time_p50,
|
||||
total_executions: scheduledQuery.stats?.total_executions,
|
||||
};
|
||||
console.log(
|
||||
"performanceIndicator(scheduledQueryPerformance)",
|
||||
performanceIndicator(scheduledQueryPerformance)
|
||||
);
|
||||
return {
|
||||
name: scheduledQuery.name,
|
||||
query_name: scheduledQuery.query_name,
|
||||
@@ -250,10 +254,10 @@ const enhanceAllScheduledQueryData = (
|
||||
version: scheduledQuery.version,
|
||||
shard: scheduledQuery.shard,
|
||||
type: teamId ? "team_scheduled_query" : "global_scheduled_query",
|
||||
performance: [
|
||||
performanceIndicator(scheduledQueryPerformance),
|
||||
scheduledQuery.id,
|
||||
],
|
||||
performance: {
|
||||
indicator: performanceIndicator(scheduledQueryPerformance),
|
||||
id: scheduledQuery.id,
|
||||
},
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user