diff --git a/src/components/layout/AppFooter.jsx b/src/components/layout/AppFooter.jsx index 2a736bc8439a..6437061d9133 100644 --- a/src/components/layout/AppFooter.jsx +++ b/src/components/layout/AppFooter.jsx @@ -30,7 +30,11 @@ const AppFooter = () => { - + diff --git a/src/views/cipp/app-settings/CIPPSettings.jsx b/src/views/cipp/app-settings/CIPPSettings.jsx index ff43ad2a5a94..c1e6b9463fd7 100644 --- a/src/views/cipp/app-settings/CIPPSettings.jsx +++ b/src/views/cipp/app-settings/CIPPSettings.jsx @@ -11,6 +11,7 @@ import { SettingsLicenses } from 'src/views/cipp/app-settings/SettingsLicenses.j import { SettingsExtensions } from 'src/views/cipp/app-settings/SettingsExtensions.jsx' import { SettingsMaintenance } from 'src/views/cipp/app-settings/SettingsMaintenance.jsx' import { SettingsExtensionMappings } from 'src/views/cipp/app-settings/SettingsExtensionMappings.jsx' +import { SettingsPartner } from 'src/views/cipp/app-settings/SettingsPartner.jsx' /** * This function returns the settings page content for CIPP. @@ -35,15 +36,18 @@ export default function CIPPSettings() { Notifications setActive(5)} href="#"> - Licenses + Partner Webhooks setActive(6)} href="#"> - Maintenance + Licenses setActive(7)} href="#"> - Extensions + Maintenance setActive(8)} href="#"> + Extensions + + setActive(9)} href="#"> Extension Mappings @@ -68,22 +72,26 @@ export default function CIPPSettings() { - - - + + - + - + + + + + + diff --git a/src/views/cipp/app-settings/SettingsPartner.jsx b/src/views/cipp/app-settings/SettingsPartner.jsx new file mode 100644 index 000000000000..91f45d98c11e --- /dev/null +++ b/src/views/cipp/app-settings/SettingsPartner.jsx @@ -0,0 +1,267 @@ +import { + useGenericGetRequestQuery, + useLazyGenericGetRequestQuery, + useLazyGenericPostRequestQuery, +} from 'src/store/api/app.js' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { + CBadge, + CButton, + CCallout, + CCard, + CCardBody, + CCardHeader, + CCardTitle, + CCol, + CForm, + CLink, + CRow, + CSpinner, +} from '@coreui/react' +import { Form } from 'react-final-form' +import { RFFSelectSearch } from 'src/components/forms/index.js' +import React, { useEffect } from 'react' +import { CippCallout } from 'src/components/layout/index.js' +import { CippCodeBlock } from 'src/components/utilities' +import { CellDate } from 'src/components/tables' + +/** + * Sets the notification settings. + * @returns {JSX.Element} The notification settings component. + */ +export function SettingsPartner() { + const webhookConfig = useGenericGetRequestQuery({ + path: '/api/ExecPartnerWebhook', + params: { Action: 'ListSubscription' }, + }) + const webhookEvents = useGenericGetRequestQuery({ + path: '/api/ExecPartnerWebhook', + params: { Action: 'ListEventTypes' }, + }) + const [submitWebhook, webhookCreateResult] = useLazyGenericPostRequestQuery() + const [sendTest, sendTestResult] = useLazyGenericGetRequestQuery() + const [checkTest, checkTestResult] = useLazyGenericGetRequestQuery() + + const onSubmit = (values) => { + const shippedValues = { + EventType: values?.EventType?.map((event) => event.value), + } + submitWebhook({ + path: '/api/ExecPartnerWebhook?Action=CreateSubscription', + values: shippedValues, + }).then((res) => { + webhookConfig.refetch() + }) + } + + useEffect(() => { + if ( + sendTestResult.isSuccess && + sendTestResult?.data?.Results?.correlationId && + !checkTestResult?.data?.Results?.results + ) { + setTimeout( + checkTest({ + path: '/api/ExecPartnerWebhook', + params: { + Action: 'ValidateTest', + CorrelationId: sendTestResult?.data?.Results?.correlationId, + }, + }), + 1000, + ) + } + }, [sendTestResult, checkTest, checkTestResult]) + + return ( + + + + <> + webhookConfig.refetch()} + className="mb-2" + disabled={webhookConfig.isFetching} + > + {webhookConfig.isFetching ? ( + <> + Loading... + + ) : ( + <> + + Refresh + + )} + + + {!webhookConfig.isFetching && webhookConfig.error && ( + Error loading data + )} + {webhookConfig.isSuccess && ( + <> +

Webhook Configuration

+ + + Subscribe to Microsoft Partner center webhooks to enable automatic tenant + onboarding and alerting. Updating the settings will replace any existing webhook + subscription with one pointing to CIPP. Refer to the{' '} + + Microsoft Partner Center documentation + {' '} + for more information on the webhook types. + + + + +

Webhook URL

+ +
+ +

Last Updated

+ +
+ +

Subscribed Events

+
({ + label: event, + value: event, + })), + }} + render={({ handleSubmit }) => ( + <> + + ({ + name: event, + value: event, + }))} + multi={true} + refreshFunction={() => webhookEvents.refetch()} + helpText="Select the events you want to receive notifications for." + /> + + {webhookCreateResult.isFetching ? ( + <> + + Saving... + + ) : ( + 'Save' + )} + + + + )} + /> + {webhookCreateResult.isSuccess && ( + + {webhookCreateResult?.data?.Results} + + )} + + +

Webhook Test

+ + + + sendTest({ + path: '/api/ExecPartnerWebhook', + params: { Action: 'SendTest' }, + }) + } + > + {sendTestResult.isFetching ? ( + <> + + Running Test... + + ) : ( + 'Start Test' + )} + + {checkTestResult.isFetching && !checkTestResult?.data?.Results?.result && ( + <> + Waiting for results + + )} + + + + {checkTestResult.isSuccess && ( + <> + +

Status

+ {checkTestResult?.data?.Results.status} +
+ {Array.isArray(checkTestResult?.data?.Results?.results) && ( + <> + +

Status Code

+ + {checkTestResult?.data?.Results?.results[0].responseCode} +
+ {checkTestResult?.data?.Results?.results[0].responseMessage !== '' && ( + +

Response Message

+ {checkTestResult.data.Results.results[0].responseMessage} +
+ )} + +

Date/Time

+ +
+ + )} + + )} +
+ + )} + + + + ) +}