Reuse Policies' Automations button on Dashboard, Software, and Reports (#46846)
Resolves #45147 (AutomationsButton introduced as part of that issue) <img width="950" height="250" alt="Screenshot 2026-06-04 at 3 51 45 PM" src="https://github.com/user-attachments/assets/0fdb18d2-5b6a-4101-9821-957dd5ab7c5e" /> ## Testing - [x] QA'd all new/changed functionality manually <img width="1425" height="210" alt="Screenshot 2026-06-04 at 3 49 49 PM" src="https://github.com/user-attachments/assets/ad4624ea-fb32-48fa-885a-27597f687c18" /> <img width="1784" height="690" alt="Screenshot 2026-06-04 at 3 49 53 PM" src="https://github.com/user-attachments/assets/36bd371a-5cc6-4c5b-a842-344ee0183d22" /> <img width="1717" height="399" alt="Screenshot 2026-06-04 at 3 50 05 PM" src="https://github.com/user-attachments/assets/bac8dac8-3238-4d53-9534-1ca11165757e" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Introduces a standardized "Automations" button (settings icon + label) and replaces prior controls across Dashboard, Software, Policies, and Queries pages. * Info cards and page actions now support an "automations" action type to consistently open automation management from relevant UIs. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
import React from "react";
|
||||
import classnames from "classnames";
|
||||
|
||||
import Button, { IButtonProps } from "components/buttons/Button";
|
||||
import Icon from "components/Icon";
|
||||
|
||||
const baseClass = "automations-button";
|
||||
|
||||
export type IAutomationsButtonProps = Pick<
|
||||
IButtonProps,
|
||||
"onClick" | "disabled" | "className" | "size"
|
||||
>;
|
||||
|
||||
const AutomationsButton = ({
|
||||
onClick,
|
||||
disabled,
|
||||
className,
|
||||
size,
|
||||
}: IAutomationsButtonProps): JSX.Element => {
|
||||
const classNames = classnames(baseClass, className);
|
||||
|
||||
return (
|
||||
<Button
|
||||
className={classNames}
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
variant="inverse"
|
||||
size={size}
|
||||
>
|
||||
<Icon name="settings" /> Automations
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export default AutomationsButton;
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "./AutomationsButton";
|
||||
@@ -1 +1,2 @@
|
||||
export { default } from "./Button";
|
||||
export type { IButtonProps, ButtonVariant } from "./Button";
|
||||
|
||||
@@ -665,8 +665,7 @@ const DashboardPage = ({ router, location }: IDashboardProps): JSX.Element => {
|
||||
showTitle: showActivityFeedTitle,
|
||||
action: canEditActivityFeedAutomations
|
||||
? {
|
||||
type: "button",
|
||||
text: "Manage automations",
|
||||
type: "automations",
|
||||
onClick: () => setShowActivityFeedAutomationsModal(true),
|
||||
}
|
||||
: undefined,
|
||||
|
||||
@@ -3,6 +3,7 @@ import { browserHistory } from "react-router";
|
||||
|
||||
import Card from "components/Card";
|
||||
import Button from "components/buttons/Button";
|
||||
import AutomationsButton from "components/buttons/AutomationsButton";
|
||||
import Icon from "components/Icon";
|
||||
import classnames from "classnames";
|
||||
|
||||
@@ -22,6 +23,10 @@ interface IInfoCardProps {
|
||||
type: "button";
|
||||
text: string;
|
||||
onClick?: () => void;
|
||||
}
|
||||
| {
|
||||
type: "automations";
|
||||
onClick?: () => void;
|
||||
};
|
||||
total_host_count?: number;
|
||||
showTitle?: boolean;
|
||||
@@ -59,6 +64,16 @@ const useInfoCard = ({
|
||||
|
||||
const renderAction = () => {
|
||||
if (action) {
|
||||
if (action.type === "automations") {
|
||||
return (
|
||||
<AutomationsButton
|
||||
className={`${baseClass}__action-button`}
|
||||
size="small"
|
||||
onClick={action.onClick}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (action.type === "button") {
|
||||
return (
|
||||
<Button
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
import { getNextLocationPath } from "utilities/helpers";
|
||||
|
||||
import Button from "components/buttons/Button";
|
||||
import AutomationsButton from "components/buttons/AutomationsButton";
|
||||
import MainContent from "components/MainContent";
|
||||
import TeamsHeader from "components/TeamsHeader";
|
||||
import TooltipWrapper from "components/TooltipWrapper";
|
||||
@@ -398,16 +399,13 @@ const SoftwarePage = ({ children, router, location }: ISoftwarePageProps) => {
|
||||
position="top"
|
||||
showArrow
|
||||
>
|
||||
<Button
|
||||
<AutomationsButton
|
||||
// TODO(Product) - Why not enable managing global automations when on any team like this
|
||||
// for everyone?
|
||||
disabled={!isAllTeamsSelected && !isPrimoMode}
|
||||
onClick={toggleManageAutomationsModal}
|
||||
className={`${baseClass}__manage-automations`}
|
||||
variant="inverse"
|
||||
>
|
||||
Manage automations
|
||||
</Button>
|
||||
/>
|
||||
</TooltipWrapper>
|
||||
)}
|
||||
{canAddSoftware && (
|
||||
|
||||
@@ -48,7 +48,7 @@ import teamsAPI, { ILoadTeamResponse } from "services/entities/teams";
|
||||
import { ITableQueryData } from "components/TableContainer/TableContainer";
|
||||
import TableCount from "components/TableContainer/TableCount";
|
||||
import Button from "components/buttons/Button";
|
||||
import Icon from "components/Icon";
|
||||
import AutomationsButton from "components/buttons/AutomationsButton";
|
||||
|
||||
import { SingleValue } from "react-select-5";
|
||||
import DropdownWrapper from "components/forms/fields/DropdownWrapper";
|
||||
@@ -880,16 +880,10 @@ const ManagePolicyPage = ({
|
||||
let automationsButton = null;
|
||||
if (canEditAutomationsSettings) {
|
||||
automationsButton = (
|
||||
<Button
|
||||
className={`${baseClass}__automations-button`}
|
||||
<AutomationsButton
|
||||
onClick={toggleAutomationsModal}
|
||||
disabled={!hasPoliciesToAutomate}
|
||||
variant="inverse"
|
||||
>
|
||||
<>
|
||||
<Icon name="settings" /> Automations
|
||||
</>
|
||||
</Button>
|
||||
/>
|
||||
);
|
||||
if (!hasPoliciesToAutomate) {
|
||||
const tipContent =
|
||||
|
||||
@@ -23,12 +23,6 @@
|
||||
min-width: 277px;
|
||||
}
|
||||
|
||||
&__automations-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $pad-small;
|
||||
}
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -34,6 +34,7 @@ import PATHS from "router/paths";
|
||||
|
||||
import PageDescription from "components/PageDescription";
|
||||
import Button from "components/buttons/Button";
|
||||
import AutomationsButton from "components/buttons/AutomationsButton";
|
||||
import TableDataError from "components/DataError";
|
||||
import MainContent from "components/MainContent";
|
||||
import TeamsDropdown from "components/TeamsDropdown";
|
||||
@@ -425,13 +426,10 @@ const ManageQueriesPage = ({
|
||||
<div className={`${baseClass}__action-button-container`}>
|
||||
{canManageAutomations &&
|
||||
(isManageAutomationsEnabled ? (
|
||||
<Button
|
||||
<AutomationsButton
|
||||
onClick={onManageAutomationsClick}
|
||||
className={`${baseClass}__manage-automations button`}
|
||||
variant="inverse"
|
||||
>
|
||||
Manage automations
|
||||
</Button>
|
||||
/>
|
||||
) : (
|
||||
<TooltipWrapper
|
||||
tipContent={
|
||||
@@ -455,13 +453,10 @@ const ManageQueriesPage = ({
|
||||
position="top"
|
||||
showArrow
|
||||
>
|
||||
<Button
|
||||
<AutomationsButton
|
||||
disabled
|
||||
className={`${baseClass}__manage-automations button`}
|
||||
variant="inverse"
|
||||
>
|
||||
Manage automations
|
||||
</Button>
|
||||
/>
|
||||
</TooltipWrapper>
|
||||
))}
|
||||
{canCustomQuery && (
|
||||
|
||||
Reference in New Issue
Block a user