Alerting: Add oncall contact point type and narrow create hook function (#107711)
This commit is contained in:
@@ -51,7 +51,26 @@ type SlackIntegration = OverrideProperties<
|
||||
}
|
||||
>;
|
||||
|
||||
export type Integration = EmailIntegration | SlackIntegration | GenericIntegration;
|
||||
// Based on https://github.com/grafana/alerting/blob/main/receivers/oncall/config.go#L14-L27
|
||||
type OnCallIntegration = OverrideProperties<
|
||||
GenericIntegration,
|
||||
{
|
||||
type: 'OnCall';
|
||||
settings: {
|
||||
url: string;
|
||||
httpMethod?: 'POST' | 'PUT';
|
||||
maxAlerts?: number;
|
||||
authorization_scheme?: string;
|
||||
authorization_credentials?: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
title?: string;
|
||||
message?: string;
|
||||
};
|
||||
}
|
||||
>;
|
||||
|
||||
export type Integration = EmailIntegration | SlackIntegration | OnCallIntegration | GenericIntegration;
|
||||
|
||||
// Enhanced version of ContactPoint with typed integrations
|
||||
// ⚠️ MergeDeep does not check if the property you are overriding exists in the base type and there is no "DeepOverrideProperties" helper
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@ import { chain } from 'lodash';
|
||||
import { Combobox, ComboboxOption } from '@grafana/ui';
|
||||
|
||||
import type { ContactPoint } from '../../../api/v0alpha1/types';
|
||||
import { useListContactPointsv0alpha1 } from '../../hooks/useContactPoints';
|
||||
import { useListContactPoints } from '../../hooks/v0alpha1/useContactPoints';
|
||||
import { getContactPointDescription } from '../../utils';
|
||||
|
||||
import { CustomComboBoxProps } from './ComboBox.types';
|
||||
@@ -17,7 +17,7 @@ export type ContactPointSelectorProps = CustomComboBoxProps<ContactPoint>;
|
||||
* @TODO make ComboBox accept a ReactNode so we can use icons and such
|
||||
*/
|
||||
function ContactPointSelector(props: ContactPointSelectorProps) {
|
||||
const { currentData: contactPoints, isLoading } = useListContactPointsv0alpha1();
|
||||
const { currentData: contactPoints, isLoading } = useListContactPoints();
|
||||
|
||||
// Create a mapping of options with their corresponding contact points
|
||||
const contactPointOptions = chain(contactPoints?.items)
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
import { type TypedUseQueryHookResult, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
|
||||
|
||||
import { type ListReceiverApiArg, alertingAPI } from '../../api/v0alpha1/api.gen';
|
||||
import type { EnhancedListReceiverApiResponse } from '../../api/v0alpha1/types';
|
||||
|
||||
// this is a workaround for the fact that the generated types are not narrow enough
|
||||
type EnhancedHookResult = TypedUseQueryHookResult<
|
||||
EnhancedListReceiverApiResponse,
|
||||
ListReceiverApiArg,
|
||||
ReturnType<typeof fetchBaseQuery>
|
||||
>;
|
||||
|
||||
/**
|
||||
* useListContactPoints is a hook that fetches a list of contact points
|
||||
*
|
||||
* This function wraps the alertingAPI.useListReceiverQuery with proper typing
|
||||
* to ensure that the returned ContactPoints are correctly typed in the data.items array.
|
||||
*
|
||||
* It automatically uses the configured namespace for the query.
|
||||
*/
|
||||
function useListContactPointsv0alpha1() {
|
||||
return alertingAPI.useListReceiverQuery<EnhancedHookResult>({});
|
||||
}
|
||||
|
||||
export { useListContactPointsv0alpha1 };
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
import {
|
||||
type TypedUseMutationResult,
|
||||
type TypedUseQueryHookResult,
|
||||
fetchBaseQuery,
|
||||
} from '@reduxjs/toolkit/query/react';
|
||||
import { OverrideProperties } from 'type-fest';
|
||||
|
||||
import { CreateReceiverApiArg, type ListReceiverApiArg, alertingAPI } from '../../../api/v0alpha1/api.gen';
|
||||
import type { ContactPoint, EnhancedListReceiverApiResponse } from '../../../api/v0alpha1/types';
|
||||
|
||||
// this is a workaround for the fact that the generated types are not narrow enough
|
||||
type ListContactPointsHookResult = TypedUseQueryHookResult<
|
||||
EnhancedListReceiverApiResponse,
|
||||
ListReceiverApiArg,
|
||||
ReturnType<typeof fetchBaseQuery>
|
||||
>;
|
||||
|
||||
/**
|
||||
* useListContactPoints is a hook that fetches a list of contact points
|
||||
*
|
||||
* This function wraps the alertingAPI.useListReceiverQuery with proper typing
|
||||
* to ensure that the returned ContactPoints are correctly typed in the data.items array.
|
||||
*
|
||||
* It automatically uses the configured namespace for the query.
|
||||
*/
|
||||
export function useListContactPoints() {
|
||||
return alertingAPI.useListReceiverQuery<ListContactPointsHookResult>({});
|
||||
}
|
||||
|
||||
// type narrowing mutations requires us to define a few helper types
|
||||
type CreateContactPointArgs = OverrideProperties<
|
||||
CreateReceiverApiArg,
|
||||
{ receiver: Omit<ContactPoint, 'status' | 'metadata'> }
|
||||
>;
|
||||
|
||||
type CreateContactPointMutation = TypedUseMutationResult<
|
||||
ContactPoint,
|
||||
CreateContactPointArgs,
|
||||
ReturnType<typeof fetchBaseQuery>
|
||||
>;
|
||||
|
||||
type UseCreateContactPointOptions = Parameters<
|
||||
typeof alertingAPI.endpoints.createReceiver.useMutation<CreateContactPointMutation>
|
||||
>[0];
|
||||
|
||||
/**
|
||||
* useCreateContactPoint is a hook that creates a new contact point with one or more integrations
|
||||
*
|
||||
* This function wraps the alertingAPI.useCreateReceiverMutation with proper typing
|
||||
* to ensure that the payload supports type narrowing.
|
||||
*/
|
||||
export function useCreateContactPoint(options?: UseCreateContactPointOptions) {
|
||||
const [updateFn, result] = alertingAPI.endpoints.createReceiver.useMutation<CreateContactPointMutation>(options);
|
||||
|
||||
const typedUpdateFn = (args: CreateContactPointArgs) => {
|
||||
// @ts-expect-error this one is just impossible for me to figure out
|
||||
const response = updateFn(args);
|
||||
return response;
|
||||
};
|
||||
|
||||
return [typedUpdateFn, result] as const;
|
||||
}
|
||||
@@ -4,14 +4,8 @@
|
||||
|
||||
// Contact Points
|
||||
export * from './grafana/api/v0alpha1/types';
|
||||
export { useListContactPointsv0alpha1 } from './grafana/contactPoints/hooks/useContactPoints';
|
||||
export { useListContactPoints } from './grafana/contactPoints/hooks/v0alpha1/useContactPoints';
|
||||
export { ContactPointSelector } from './grafana/contactPoints/components/ContactPointSelector/ContactPointSelector';
|
||||
|
||||
// Low-level API hooks
|
||||
export { alertingAPI as alertingAPIv0alpha1 } from './grafana/api/v0alpha1/api.gen';
|
||||
|
||||
// model factories / mocks
|
||||
export * as mocksV0alpha1 from './grafana/api/v0alpha1/mocks/fakes/Receivers';
|
||||
|
||||
// MSW handlers
|
||||
export * as handlersV0alpha1 from './grafana/api/v0alpha1/mocks/handlers';
|
||||
export { alertingAPI } from './grafana/api/v0alpha1/api.gen';
|
||||
|
||||
@@ -2,13 +2,13 @@ import { configureStore } from '@reduxjs/toolkit';
|
||||
import { useEffect } from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
|
||||
import { alertingAPIv0alpha1 } from '../src/unstable';
|
||||
import { alertingAPI } from '../src/unstable';
|
||||
|
||||
// create an empty store
|
||||
export const store = configureStore({
|
||||
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(alertingAPIv0alpha1.middleware),
|
||||
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(alertingAPI.middleware),
|
||||
reducer: {
|
||||
[alertingAPIv0alpha1.reducerPath]: alertingAPIv0alpha1.reducer,
|
||||
[alertingAPI.reducerPath]: alertingAPI.reducer,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -35,7 +35,7 @@ export const getDefaultWrapper = () => {
|
||||
function useResetQueryCacheAfterUnmount() {
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
store.dispatch(alertingAPIv0alpha1.util.resetApiState());
|
||||
store.dispatch(alertingAPI.util.resetApiState());
|
||||
};
|
||||
}, []);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user