diff --git a/changes/warn-on-save-script b/changes/warn-on-save-script new file mode 100644 index 0000000000..fdd4e12898 --- /dev/null +++ b/changes/warn-on-save-script @@ -0,0 +1 @@ +- Warn users of consequences when updating script contents diff --git a/frontend/components/Modal/Modal.tsx b/frontend/components/Modal/Modal.tsx index 9fc43231cb..9aefe5fda4 100644 --- a/frontend/components/Modal/Modal.tsx +++ b/frontend/components/Modal/Modal.tsx @@ -6,6 +6,7 @@ import Icon from "components/Icon/Icon"; const baseClass = "modal"; type ModalWidth = "medium" | "large" | "xlarge" | "auto"; +// 650px 800px 850px auto export interface IModalProps { title: string | JSX.Element; diff --git a/frontend/pages/ManageControlsPage/Scripts/components/EditScriptModal/EditScriptModal.tsx b/frontend/pages/ManageControlsPage/Scripts/components/EditScriptModal/EditScriptModal.tsx index 4f8329a1b7..c91d3a145e 100644 --- a/frontend/pages/ManageControlsPage/Scripts/components/EditScriptModal/EditScriptModal.tsx +++ b/frontend/pages/ManageControlsPage/Scripts/components/EditScriptModal/EditScriptModal.tsx @@ -1,6 +1,8 @@ import React, { useContext, useState } from "react"; import { useQuery } from "react-query"; +import classnames from "classnames"; + import { NotificationContext } from "context/notification"; import { AppContext } from "context/app"; import { getPathWithQueryParams } from "utilities/url"; @@ -21,6 +23,52 @@ import { getErrorMessage } from "../ScriptUploader/helpers"; const baseClass = "edit-script-modal"; +interface IWarningModal { + onExit: () => void; + onSave: () => void; + scriptName: string; + isSubmitting: boolean; +} +const WarningModal = ({ + onExit, + onSave, + scriptName, + isSubmitting, +}: IWarningModal) => { + return ( + + <> +

+ The changes you are making will cancel any pending script runs for{" "} + {scriptName}.
+
+ If this script is currently running on a host, it will complete, but + results won't appear in Fleet.
+
+ You cannot undo this action. +

+
+ + +
+ +
+ ); +}; + interface IEditScriptModal { onExit: () => void; scriptId: number; @@ -47,7 +95,10 @@ const EditScriptModal = ({ const [isSubmitting, setIsSubmitting] = useState(false); const [formError, setFormError] = useState(null); + const [showConfirmChanges, setShowConfirmChanges] = useState(false); + const { + data: curScriptContent, error: isSelectedScriptContentError, isLoading: isLoadingSelectedScriptContent, } = useQuery( @@ -55,8 +106,8 @@ const EditScriptModal = ({ () => scriptAPI.downloadScript(scriptId), { ...DEFAULT_USE_QUERY_OPTIONS, - onSuccess: (scriptContent) => { - setScriptFormData(scriptContent); + onSuccess: (curScriptContent_) => { + setScriptFormData(curScriptContent_); }, } ); @@ -79,6 +130,12 @@ const EditScriptModal = ({ if (err || isSubmitting) { return; } + // if contents have changed and not already showing the warning modal + if (curScriptContent !== scriptFormData && !showConfirmChanges) { + setShowConfirmChanges(true); + return; + } + // show warning modal and abort this call try { setIsSubmitting(true); await scriptAPI.updateScript(scriptId, scriptFormData, scriptName); @@ -88,6 +145,7 @@ const EditScriptModal = ({ renderFlash("error", getErrorMessage(e)); } finally { setIsSubmitting(false); + setShowConfirmChanges(false); } }; @@ -161,15 +219,28 @@ const EditScriptModal = ({ ); }; + const classes = classnames(baseClass, { + [`${baseClass}__hide-main`]: !!showConfirmChanges, + }); return ( - - {renderContent()} - + <> + + {renderContent()} + + {!!showConfirmChanges && ( + setShowConfirmChanges(false)} + onSave={onSave} + scriptName={scriptName} + isSubmitting={isSubmitting} + /> + )} + ); }; diff --git a/frontend/pages/ManageControlsPage/Scripts/components/EditScriptModal/_styles.scss b/frontend/pages/ManageControlsPage/Scripts/components/EditScriptModal/_styles.scss new file mode 100644 index 0000000000..932b535ab2 --- /dev/null +++ b/frontend/pages/ManageControlsPage/Scripts/components/EditScriptModal/_styles.scss @@ -0,0 +1,10 @@ +.edit-script-modal { + &__hide-main { + visibility: hidden; + } +} +// since this modal shows only while anotheris also showing, suppress background for one of them to +// prevent "double-darkening" +.modal__background:has(.edit-script-modal.edit-script-modal__hide-main) { + visibility: hidden; +}