fleet/frontend/pages/admin/OrgSettingsPage/cards/HostStatusWebhook/HostStatusWebhook.tsx
Jacob Shandling 8a5569cd1b
9349 new controls page (#9431)
# Addresses #9349

# Implements
https://www.loom.com/share/bbf8d6f97fe74e65a0c9a394f1bda3f1
- New Controls page, only visible to Global|Team Admins|Maintainers
- Header for free users is 'Controls', for premium is a teams filter
dropdown that defaults to 'No teams,' which filters via updating the URL
query param "team_id"
    - Includes tabs macUpdates (default) and macSettings
- Cleaned up how site nav items are conditionally included/excluded
based on authorization – see
`frontend/components/top_nav/SiteTopNav/navItems.ts`
- Updated masthead styles: Removed icons from site nav links; updated
colors and spacing; Updated default user avatar TBD in separate PR
(waiting on guidance)

# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/` 
- [x] Updated testing suite inventory
- [x] Manual QA for all new/changed functionality

Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
2023-01-26 11:33:54 -08:00

235 lines
7.4 KiB
TypeScript

import React, { useState, useEffect } from "react";
import { syntaxHighlight } from "utilities/helpers";
import Button from "components/buttons/Button";
import Checkbox from "components/forms/fields/Checkbox";
// @ts-ignore
import Dropdown from "components/forms/fields/Dropdown";
// @ts-ignore
import InputField from "components/forms/fields/InputField";
import Modal from "components/Modal";
import {
IAppConfigFormProps,
IFormField,
IAppConfigFormErrors,
percentageOfHosts,
numberOfDays,
hostStatusPreview,
} from "../constants";
const baseClass = "app-config-form";
const HostStatusWebhook = ({
appConfig,
handleSubmit,
isUpdatingSettings,
}: IAppConfigFormProps): JSX.Element => {
const [
showHostStatusWebhookPreviewModal,
setShowHostStatusWebhookPreviewModal,
] = useState(false);
const [formData, setFormData] = useState<any>({
enableHostStatusWebhook:
appConfig.webhook_settings.host_status_webhook
.enable_host_status_webhook || false,
hostStatusWebhookDestinationURL:
appConfig.webhook_settings.host_status_webhook.destination_url || "",
hostStatusWebhookHostPercentage:
appConfig.webhook_settings.host_status_webhook.host_percentage ||
undefined,
hostStatusWebhookDaysCount:
appConfig.webhook_settings.host_status_webhook.days_count || undefined,
});
const {
enableHostStatusWebhook,
hostStatusWebhookDestinationURL,
hostStatusWebhookHostPercentage,
hostStatusWebhookDaysCount,
} = formData;
const [formErrors, setFormErrors] = useState<IAppConfigFormErrors>({});
const handleInputChange = ({ name, value }: IFormField) => {
setFormData({ ...formData, [name]: value });
setFormErrors({});
};
const validateForm = () => {
const errors: IAppConfigFormErrors = {};
if (enableHostStatusWebhook) {
if (!hostStatusWebhookDestinationURL) {
errors.destination_url = "Destination URL must be present";
}
if (!hostStatusWebhookDaysCount) {
errors.days_count = "Number of days must be present";
}
if (!hostStatusWebhookDaysCount) {
errors.host_percentage = "Percentage of hosts must be present";
}
}
setFormErrors(errors);
};
useEffect(() => {
validateForm();
}, [enableHostStatusWebhook]);
const toggleHostStatusWebhookPreviewModal = () => {
setShowHostStatusWebhookPreviewModal(!showHostStatusWebhookPreviewModal);
return false;
};
const onFormSubmit = (evt: React.MouseEvent<HTMLFormElement>) => {
evt.preventDefault();
// Formatting of API not UI
const formDataToSubmit = {
webhook_settings: {
host_status_webhook: {
enable_host_status_webhook: enableHostStatusWebhook,
destination_url: hostStatusWebhookDestinationURL,
host_percentage: hostStatusWebhookHostPercentage,
days_count: hostStatusWebhookDaysCount,
},
},
};
handleSubmit(formDataToSubmit);
};
const renderHostStatusWebhookPreviewModal = () => {
if (!showHostStatusWebhookPreviewModal) {
return null;
}
return (
<Modal
title="Host status webhook"
onExit={toggleHostStatusWebhookPreviewModal}
className={`${baseClass}__host-status-webhook-preview-modal`}
>
<>
<p>
An example request sent to your configured <b>Destination URL</b>.
</p>
<div className={`${baseClass}__host-status-webhook-preview`}>
<pre
dangerouslySetInnerHTML={{
__html: syntaxHighlight(hostStatusPreview),
}}
/>
</div>
<div className="modal-cta-wrap">
<Button type="button" onClick={toggleHostStatusWebhookPreviewModal}>
Done
</Button>
</div>
</>
</Modal>
);
};
return (
<>
<form className={baseClass} onSubmit={onFormSubmit} autoComplete="off">
<div className={`${baseClass}__section`}>
<h2>Host status webhook</h2>
<div className={`${baseClass}__host-status-webhook`}>
<p className={`${baseClass}__section-description`}>
Send an alert if a portion of your hosts go offline.
</p>
<Checkbox
onChange={handleInputChange}
name="enableHostStatusWebhook"
value={enableHostStatusWebhook}
parseTarget
>
Enable host status webhook
</Checkbox>
<p className={`${baseClass}__section-description`}>
A request will be sent to your configured <b>Destination URL</b>{" "}
if the configured <b>Percentage of hosts</b> have not checked into
Fleet for the configured <b>Number of days</b>.
</p>
</div>
<div className={`${baseClass}__inputs ${baseClass}__inputs--webhook`}>
<Button
type="button"
variant="inverse"
onClick={toggleHostStatusWebhookPreviewModal}
>
Preview request
</Button>
</div>
<div className={`${baseClass}__inputs`}>
<InputField
placeholder="https://server.com/example"
label="Destination URL"
onChange={handleInputChange}
name="hostStatusWebhookDestinationURL"
value={hostStatusWebhookDestinationURL}
parseTarget
onBlur={validateForm}
error={formErrors.destination_url}
tooltip={
"\
<p>Provide a URL to deliver <br/>the webhook request to.</p>\
"
}
/>
</div>
<div className={`${baseClass}__inputs ${baseClass}__host-percentage`}>
<Dropdown
label="Percentage of hosts"
options={percentageOfHosts}
onChange={handleInputChange}
name="hostStatusWebhookHostPercentage"
value={hostStatusWebhookHostPercentage}
parseTarget
onBlur={validateForm}
tooltip={
"\
<p>Select the minimum percentage of hosts that<br/>must fail to check into Fleet in order to trigger<br/>the webhook request.</p>\
"
}
/>
</div>
<div className={`${baseClass}__inputs ${baseClass}__days-count`}>
<Dropdown
label="Number of days"
options={numberOfDays}
onChange={handleInputChange}
name="hostStatusWebhookDaysCount"
value={hostStatusWebhookDaysCount}
parseTarget
onBlur={validateForm}
tooltip={
"\
<p>Select the minimum number of days that the<br/>configured <b>Percentage of hosts</b> must fail to<br/>check into Fleet in order to trigger the<br/>webhook request.</p>\
"
}
/>
</div>
</div>
<Button
type="submit"
variant="brand"
disabled={Object.keys(formErrors).length > 0}
className="save-loading"
isLoading={isUpdatingSettings}
>
Save
</Button>
</form>
{showHostStatusWebhookPreviewModal &&
renderHostStatusWebhookPreviewModal()}
</>
);
};
export default HostStatusWebhook;