import React, { useCallback, useContext, useState } from "react"; import { useQuery } from "react-query"; import classnames from "classnames"; import { NotificationContext } from "context/notification"; import { IScript } from "interfaces/script"; import { DEFAULT_USE_QUERY_OPTIONS } from "utilities/constants"; import Modal from "components/Modal"; import scriptsAPI, { IListScriptsQueryKey, IScriptsResponse, } from "services/entities/scripts"; import ScriptDetailsModal from "pages/hosts/components/ScriptDetailsModal"; import Spinner from "components/Spinner"; import EmptyTable from "components/EmptyTable"; import Button from "components/buttons/Button"; import RunScriptBatchPaginatedList from "../RunScriptBatchPaginatedList"; import { IPaginatedListScript } from "../RunScriptBatchPaginatedList/RunScriptBatchPaginatedList"; const baseClass = "run-script-batch-modal"; interface IRunScriptBatchModal { selectedHostIds: number[]; onCancel: () => void; teamId: number; } const RunScriptBatchModal = ({ selectedHostIds, onCancel, teamId, }: IRunScriptBatchModal) => { const { renderFlash } = useContext(NotificationContext); const [isUpdating, setIsUpdating] = useState(false); const [scriptForDetails, setScriptForDetails] = useState< IPaginatedListScript | undefined >(undefined); // just used to get total number of scripts, could be optimized by implementing a dedicated scriptsCount endpoint const { data: scripts } = useQuery< IScriptsResponse, Error, IScript[], IListScriptsQueryKey[] >( [ { scope: "scripts", team_id: teamId, }, ], ({ queryKey }) => { return scriptsAPI.getScripts(queryKey[0]); }, { ...DEFAULT_USE_QUERY_OPTIONS, keepPreviousData: true, select: (data) => data.scripts || [], } ); const onRunScriptBatch = useCallback( async (script: IScript) => { setIsUpdating(true); try { await scriptsAPI.runScriptBatch({ host_ids: selectedHostIds, script_id: script.id, }); renderFlash( "success", `Script is running on ${selectedHostIds.length} hosts, or will run as each host comes online. See host details for individual results.` ); } catch (error) { renderFlash("error", "Could not run script."); // can determine more specific error case with additional call to upcoming summary endpoint } finally { setIsUpdating(false); } }, [renderFlash, selectedHostIds] ); const renderModalContent = () => { if (scripts === undefined) { return ; } if (!scripts.length) { return ( You can add saved scripts{" "} here. } /> ); } const targetCount = selectedHostIds.length; return ( <>

Will run on{" "} {targetCount} host{targetCount > 1 ? "s" : ""} . You can see individual script results on the host details page.

); }; const classes = classnames(baseClass, { [`${baseClass}__hide-main`]: !!scriptForDetails, }); return ( <> <> {renderModalContent()}
{!!scriptForDetails && ( setScriptForDetails(undefined)} selectedScriptDetails={scriptForDetails} suppressSecondaryActions customPrimaryButtons={
} /> )} ); }; export default RunScriptBatchModal;