NotificationChannelForm.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import { css } from '@emotion/css';
  2. import React, { FC, useEffect } from 'react';
  3. import { GrafanaTheme, SelectableValue } from '@grafana/data';
  4. import { Button, FormAPI, HorizontalGroup, stylesFactory, useTheme, Spinner } from '@grafana/ui';
  5. import config from 'app/core/config';
  6. import { NotificationChannelType, NotificationChannelDTO, NotificationChannelSecureFields } from '../../../types';
  7. import { BasicSettings } from './BasicSettings';
  8. import { ChannelSettings } from './ChannelSettings';
  9. import { NotificationSettings } from './NotificationSettings';
  10. interface Props
  11. extends Pick<FormAPI<NotificationChannelDTO>, 'control' | 'errors' | 'register' | 'watch' | 'getValues'> {
  12. selectableChannels: Array<SelectableValue<string>>;
  13. selectedChannel?: NotificationChannelType;
  14. imageRendererAvailable: boolean;
  15. secureFields: NotificationChannelSecureFields;
  16. resetSecureField: (key: string) => void;
  17. onTestChannel: (data: NotificationChannelDTO) => void;
  18. }
  19. export interface NotificationSettingsProps
  20. extends Pick<FormAPI<NotificationChannelDTO>, 'control' | 'errors' | 'register'> {
  21. currentFormValues: NotificationChannelDTO;
  22. }
  23. export const NotificationChannelForm: FC<Props> = ({
  24. control,
  25. errors,
  26. selectedChannel,
  27. selectableChannels,
  28. register,
  29. watch,
  30. getValues,
  31. imageRendererAvailable,
  32. onTestChannel,
  33. resetSecureField,
  34. secureFields,
  35. }) => {
  36. const styles = getStyles(useTheme());
  37. useEffect(() => {
  38. /*
  39. Find fields that have dependencies on other fields and removes duplicates.
  40. Needs to be prefixed with settings.
  41. */
  42. const fieldsToWatch =
  43. new Set(
  44. selectedChannel?.options
  45. .filter((o) => o.showWhen.field)
  46. .map((option) => {
  47. return `settings.${option.showWhen.field}`;
  48. })
  49. ) || [];
  50. watch(['type', 'sendReminder', 'uploadImage', ...fieldsToWatch]);
  51. }, [selectedChannel?.options, watch]);
  52. const currentFormValues = getValues();
  53. if (!selectedChannel) {
  54. return <Spinner />;
  55. }
  56. return (
  57. <div className={styles.formContainer}>
  58. <div className={styles.formItem}>
  59. <BasicSettings
  60. selectedChannel={selectedChannel}
  61. channels={selectableChannels}
  62. secureFields={secureFields}
  63. resetSecureField={resetSecureField}
  64. currentFormValues={currentFormValues}
  65. register={register}
  66. errors={errors}
  67. control={control}
  68. />
  69. </div>
  70. {/* If there are no non-required fields, don't render this section*/}
  71. {selectedChannel.options.filter((o) => !o.required).length > 0 && (
  72. <div className={styles.formItem}>
  73. <ChannelSettings
  74. selectedChannel={selectedChannel}
  75. secureFields={secureFields}
  76. resetSecureField={resetSecureField}
  77. currentFormValues={currentFormValues}
  78. register={register}
  79. errors={errors}
  80. control={control}
  81. />
  82. </div>
  83. )}
  84. <div className={styles.formItem}>
  85. <NotificationSettings
  86. imageRendererAvailable={imageRendererAvailable}
  87. currentFormValues={currentFormValues}
  88. register={register}
  89. errors={errors}
  90. control={control}
  91. />
  92. </div>
  93. <div className={styles.formButtons}>
  94. <HorizontalGroup>
  95. <Button type="submit">Save</Button>
  96. <Button type="button" variant="secondary" onClick={() => onTestChannel(getValues())}>
  97. Test
  98. </Button>
  99. <a href={`${config.appSubUrl}/alerting/notifications`}>
  100. <Button type="button" variant="secondary">
  101. Back
  102. </Button>
  103. </a>
  104. </HorizontalGroup>
  105. </div>
  106. </div>
  107. );
  108. };
  109. const getStyles = stylesFactory((theme: GrafanaTheme) => {
  110. return {
  111. formContainer: css``,
  112. formItem: css`
  113. flex-grow: 1;
  114. padding-top: ${theme.spacing.md};
  115. `,
  116. formButtons: css`
  117. padding-top: ${theme.spacing.xl};
  118. `,
  119. };
  120. });