diff --git a/grafana-plugin/src/components/AlertTemplates/AlertTemplatesForm.config.ts b/grafana-plugin/src/components/AlertTemplates/AlertTemplatesForm.config.ts index 8e4bf0ae..b8c5efb0 100644 --- a/grafana-plugin/src/components/AlertTemplates/AlertTemplatesForm.config.ts +++ b/grafana-plugin/src/components/AlertTemplates/AlertTemplatesForm.config.ts @@ -3,7 +3,7 @@ import { AppFeature } from 'state/features'; import { TemplateForEdit, commonTemplateForEdit } from './CommonAlertTemplatesForm.config'; export const getTemplatesForEdit = (features: Record) => { - if (features[AppFeature.MsTeams]) { + if (features?.[AppFeature.MsTeams]) { return { ...commonTemplateForEdit, ...additionalTemplateForEdit }; } return commonTemplateForEdit; diff --git a/grafana-plugin/src/containers/Alerts/Alerts.tsx b/grafana-plugin/src/containers/Alerts/Alerts.tsx index 26b8059e..3a5c44e0 100644 --- a/grafana-plugin/src/containers/Alerts/Alerts.tsx +++ b/grafana-plugin/src/containers/Alerts/Alerts.tsx @@ -142,7 +142,7 @@ export const Alerts = function () { ); function showBannerTeam(): boolean { - return currentOrganization?.banner.title != null && !getItem(currentOrganization?.banner.title); + return Boolean(currentOrganization?.banner?.title) && !getItem(currentOrganization?.banner?.title); } function showMismatchWarning(): boolean { diff --git a/grafana-plugin/src/containers/IntegrationContainers/IntegrationTemplatesList.config.ts b/grafana-plugin/src/containers/IntegrationContainers/IntegrationTemplatesList.config.ts index 0b5c6bdd..59b79a54 100644 --- a/grafana-plugin/src/containers/IntegrationContainers/IntegrationTemplatesList.config.ts +++ b/grafana-plugin/src/containers/IntegrationContainers/IntegrationTemplatesList.config.ts @@ -26,10 +26,9 @@ const additionalTemplatesToRender: TemplateBlock[] = [ }, ]; -export const getTemplatesToRender = (features: Record) => { - if (features[AppFeature.MsTeams]) { +export const getTemplatesToRender = (features?: Record) => { + if (features?.[AppFeature.MsTeams]) { return commonTemplatesToRender.concat(additionalTemplatesToRender); } - return commonTemplatesToRender; }; diff --git a/grafana-plugin/src/containers/RotationForm/ScheduleOverrideForm.tsx b/grafana-plugin/src/containers/RotationForm/ScheduleOverrideForm.tsx index 3a10da68..0fff941d 100644 --- a/grafana-plugin/src/containers/RotationForm/ScheduleOverrideForm.tsx +++ b/grafana-plugin/src/containers/RotationForm/ScheduleOverrideForm.tsx @@ -179,7 +179,9 @@ export const ScheduleOverrideForm: FC = (props) => { }; const onError = useCallback((error) => { - setErrors(error.response.data); + if (error.response) { + setErrors(error.response.data); + } }, []); const handleChange = useDebouncedCallback(updatePreview, 200); diff --git a/grafana-plugin/src/containers/UserSettings/parts/tabs/PhoneVerification/PhoneVerification.tsx b/grafana-plugin/src/containers/UserSettings/parts/tabs/PhoneVerification/PhoneVerification.tsx index c0aca09b..6001c4f1 100644 --- a/grafana-plugin/src/containers/UserSettings/parts/tabs/PhoneVerification/PhoneVerification.tsx +++ b/grafana-plugin/src/containers/UserSettings/parts/tabs/PhoneVerification/PhoneVerification.tsx @@ -5,6 +5,7 @@ import cn from 'classnames/bind'; import { observer } from 'mobx-react'; import { PluginLink } from 'components/PluginLink/PluginLink'; +import { RenderConditionally } from 'components/RenderConditionally/RenderConditionally'; import { Text } from 'components/Text/Text'; import { WithPermissionControlDisplay } from 'containers/WithPermissionControl/WithPermissionControlDisplay'; import { WithPermissionControlTooltip } from 'containers/WithPermissionControl/WithPermissionControlTooltip'; @@ -168,7 +169,9 @@ export const PhoneVerification = observer((props: PhoneVerificationProps) => { const isButtonDisabled = phone === user.verified_phone_number || (!isCodeSent && !isPhoneValid && !isPhoneCallInitiated) || - !isPhoneProviderConfigured; + !isPhoneProviderConfigured || + !window.grecaptcha; + const disabledButtonTooltipText = window.grecaptcha ? undefined : 'reCAPTCHA has not been loaded'; const isPhoneDisabled = !!user.verified_phone_number; const isCodeFieldDisabled = (!isCodeSent && !isPhoneCallInitiated) || !isUserActionAllowed(action); @@ -263,6 +266,7 @@ export const PhoneVerification = observer((props: PhoneVerificationProps) => { isCodeSent={isCodeSent} isPhoneCallInitiated={isPhoneCallInitiated} isButtonDisabled={isButtonDisabled} + disabledButtonTooltipText={disabledButtonTooltipText} providerConfiguration={providerConfiguration} onSubmitCallback={onSubmitCallback} onVerifyCallback={onVerifyCallback} @@ -306,6 +310,7 @@ interface PhoneVerificationButtonsGroupProps { isCodeSent: boolean; isPhoneCallInitiated: boolean; isButtonDisabled: boolean; + disabledButtonTooltipText?: string; providerConfiguration: { configured: boolean; test_call: boolean; @@ -328,6 +333,7 @@ const PhoneVerificationButtonsGroup = observer( isCodeSent, isPhoneCallInitiated, isButtonDisabled, + disabledButtonTooltipText, providerConfiguration, onSubmitCallback, onVerifyCallback, @@ -353,30 +359,37 @@ const PhoneVerificationButtonsGroup = observer( ) : ( - - {providerConfiguration.verification_sms && ( - - - + ( + + {providerConfiguration.verification_sms && ( + + + + )} + {providerConfiguration.verification_call && ( + + + + )} + )} - {providerConfiguration.verification_call && ( - - - - )} - + > )} )} diff --git a/grafana-plugin/src/models/alertgroup/alertgroup.ts b/grafana-plugin/src/models/alertgroup/alertgroup.ts index d050eec3..aefde6e6 100644 --- a/grafana-plugin/src/models/alertgroup/alertgroup.ts +++ b/grafana-plugin/src/models/alertgroup/alertgroup.ts @@ -315,7 +315,7 @@ export class AlertGroupStore { async fetchTableSettings(): Promise { const tableSettings = await makeRequest('/alertgroup_table_settings', {}); - const { hidden, visible, default: isDefaultOrder } = tableSettings; + const { hidden = [], visible = [], default: isDefaultOrder } = tableSettings; runInAction(() => { this.isDefaultColumnOrder = isDefaultOrder; diff --git a/grafana-plugin/src/pages/incidents/Incidents.tsx b/grafana-plugin/src/pages/incidents/Incidents.tsx index 2416392b..4c5d3547 100644 --- a/grafana-plugin/src/pages/incidents/Incidents.tsx +++ b/grafana-plugin/src/pages/incidents/Incidents.tsx @@ -695,7 +695,7 @@ class _IncidentsPage extends React.Component { - if (!item.labels.length) { + if (!item.labels?.length) { return null; } diff --git a/grafana-plugin/src/plugin/GrafanaPluginRootPage.tsx b/grafana-plugin/src/plugin/GrafanaPluginRootPage.tsx index ae108d81..28ee7556 100644 --- a/grafana-plugin/src/plugin/GrafanaPluginRootPage.tsx +++ b/grafana-plugin/src/plugin/GrafanaPluginRootPage.tsx @@ -48,11 +48,7 @@ export const GrafanaPluginRootPage = (props: AppRootProps) => { }); return ( - { - FaroHelper.faro.api.pushError(error, { context: { type: 'react' } }); - }} - > + {() => ( diff --git a/grafana-plugin/src/utils/faro.ts b/grafana-plugin/src/utils/faro.ts index 3d91a002..c9212e95 100644 --- a/grafana-plugin/src/utils/faro.ts +++ b/grafana-plugin/src/utils/faro.ts @@ -70,6 +70,10 @@ class BaseFaroHelper { return this.faro; } + pushReactError = (error: Error) => { + this.faro?.api.pushError(error, { context: { type: 'react' } }); + }; + pushNetworkRequestEvent = (config: { method: string; url: string; body: string }) => { this.faro?.api.pushEvent('Request sent', config); }; @@ -97,10 +101,10 @@ class BaseFaroHelper { }); }; - pushAxiosNetworkResponseEvent = ({ name, res }: { name: string; res: AxiosResponse }) => { + pushAxiosNetworkResponseEvent = ({ name, res }: { name: string; res?: AxiosResponse }) => { this.faro?.api.pushEvent(name, { - url: res.config?.url, - status: `${res.status}`, + url: res?.config?.url, + status: `${res?.status}`, statusText: `${res.statusText}`, method: res.config?.method.toUpperCase(), });