From 851ca2e12a8ef0138ace43546b24ea21e01ec3a4 Mon Sep 17 00:00:00 2001 From: Dominik Broj Date: Mon, 15 Jul 2024 09:15:44 +0200 Subject: [PATCH] Fix Slack channel and user group values not populating on first visit of schedule notification settings (#4671) # What this PR does Make sure GSelect gets rerendered with updated items., more context [here](https://raintank-corp.slack.com/archives/C04JCU51NF8/p1720559481963519) ## Which issue(s) this PR closes https://github.com/grafana/oncall/issues/4670 ## Checklist - [ ] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes. --- .../components/Policy/EscalationPolicy.tsx | 44 ++++++++++++++----- .../parts/connectors/MSTeamsConnector.tsx | 14 ++++-- .../parts/connectors/SlackConnector.tsx | 9 ++-- .../parts/connectors/TelegramConnector.tsx | 14 ++++-- .../AttachIncidentForm/AttachIncidentForm.tsx | 8 +++- .../EscalationChainForm.tsx | 15 +++++-- .../GrafanaTeamSelect/GrafanaTeamSelect.tsx | 9 +++- .../IntegrationForm/IntegrationForm.tsx | 10 ++++- .../MaintenanceForm/MaintenanceForm.tsx | 8 +++- .../OutgoingWebhookFormFields.tsx | 9 +++- .../containers/ScheduleForm/ScheduleForm.tsx | 24 +++++++--- .../tabs/GoogleCalendar/GoogleCalendar.tsx | 9 +++- .../tabs/SlackSettings/SlackSettings.tsx | 4 +- 13 files changed, 131 insertions(+), 46 deletions(-) diff --git a/grafana-plugin/src/components/Policy/EscalationPolicy.tsx b/grafana-plugin/src/components/Policy/EscalationPolicy.tsx index c91700e9..592f19d9 100644 --- a/grafana-plugin/src/components/Policy/EscalationPolicy.tsx +++ b/grafana-plugin/src/components/Policy/EscalationPolicy.tsx @@ -168,7 +168,11 @@ class _EscalationPolicy extends React.Component { data, isDisabled, theme, - store: { userStore }, + store: { + userStore, + // dereferencing items is needed to rerender GSelect + userStore: { items: userItems }, + }, } = this.props; const { notify_to_users_queue } = data; const styles = getEscalationPolicyStyles(theme); @@ -187,7 +191,7 @@ class _EscalationPolicy extends React.Component { onChange={this.getOnChangeHandler('notify_to_users_queue')} getOptionLabel={({ value }: SelectableValue) => } width={'auto'} - items={userStore.items} + items={userItems} fetchItemsFn={userStore.fetchItems} fetchItemFn={async (id) => await userStore.fetchItemById({ userPk: id, skipIfAlreadyPending: true })} getSearchResult={() => UserHelper.getSearchResult(userStore)} @@ -352,7 +356,12 @@ class _EscalationPolicy extends React.Component { data, theme, isDisabled, - store: { grafanaTeamStore, scheduleStore }, + store: { + scheduleStore, + // dereferencing items is needed to rerender GSelect + grafanaTeamStore: { items: grafanaTeamItems }, + scheduleStore: { items: scheduleItems }, + }, } = this.props; const { notify_schedule } = data; const styles = getEscalationPolicyStyles(theme); @@ -362,7 +371,7 @@ class _EscalationPolicy extends React.Component { allowClear disabled={isDisabled} - items={scheduleStore.items} + items={scheduleItems} fetchItemsFn={scheduleStore.updateItems} fetchItemFn={scheduleStore.updateItem} getSearchResult={scheduleStore.getSearchResult} @@ -373,7 +382,7 @@ class _EscalationPolicy extends React.Component { value={notify_schedule} onChange={this.getOnChangeHandler('notify_schedule')} getOptionLabel={(item: SelectableValue) => { - const team = grafanaTeamStore.items[scheduleStore.items[item.value].team]; + const team = grafanaTeamItems[scheduleStore.items[item.value].team]; return ( <> {item.label} @@ -391,7 +400,11 @@ class _EscalationPolicy extends React.Component { data, theme, isDisabled, - store: { userGroupStore }, + store: { + userGroupStore, + // dereferencing items is needed to rerender GSelect + userGroupStore: { items: userGroupItems }, + }, } = this.props; const { notify_to_group } = data; @@ -402,7 +415,7 @@ class _EscalationPolicy extends React.Component { allowClear disabled={isDisabled} - items={userGroupStore.items} + items={userGroupItems} fetchItemsFn={userGroupStore.updateItems} fetchItemFn={userGroupStore.fetchItemById} getSearchResult={userGroupStore.getSearchResult} @@ -423,7 +436,12 @@ class _EscalationPolicy extends React.Component { data, theme, isDisabled, - store: { grafanaTeamStore, outgoingWebhookStore }, + store: { + grafanaTeamStore, + outgoingWebhookStore, + // dereferencing items is needed to rerender GSelect + outgoingWebhookStore: { items: outgoingWebhookItems }, + }, } = this.props; const { custom_webhook } = data; @@ -433,7 +451,7 @@ class _EscalationPolicy extends React.Component { disabled={isDisabled} - items={outgoingWebhookStore.items} + items={outgoingWebhookItems} fetchItemsFn={outgoingWebhookStore.updateItems} fetchItemFn={outgoingWebhookStore.updateItem} getSearchResult={outgoingWebhookStore.getSearchResult} @@ -466,7 +484,11 @@ class _EscalationPolicy extends React.Component { const { data, isDisabled, - store: { grafanaTeamStore }, + store: { + grafanaTeamStore, + // dereferencing items is needed to rerender GSelect + grafanaTeamStore: { items: grafanaTeamItems }, + }, } = this.props; const { notify_to_team_members } = data; @@ -474,7 +496,7 @@ class _EscalationPolicy extends React.Component { disabled={isDisabled} - items={grafanaTeamStore.items} + items={grafanaTeamItems} fetchItemsFn={grafanaTeamStore.updateItems} fetchItemFn={grafanaTeamStore.fetchItemById} getSearchResult={grafanaTeamStore.getSearchResult} diff --git a/grafana-plugin/src/containers/AlertRules/parts/connectors/MSTeamsConnector.tsx b/grafana-plugin/src/containers/AlertRules/parts/connectors/MSTeamsConnector.tsx index 58ba0805..138c3d1f 100644 --- a/grafana-plugin/src/containers/AlertRules/parts/connectors/MSTeamsConnector.tsx +++ b/grafana-plugin/src/containers/AlertRules/parts/connectors/MSTeamsConnector.tsx @@ -2,6 +2,7 @@ import React, { useCallback } from 'react'; import { HorizontalGroup, InlineSwitch } from '@grafana/ui'; import cn from 'classnames/bind'; +import { observer } from 'mobx-react'; import { GSelect } from 'containers/GSelect/GSelect'; import { WithPermissionControlTooltip } from 'containers/WithPermissionControl/WithPermissionControlTooltip'; @@ -18,11 +19,16 @@ interface MSTeamsConnectorProps { channelFilterId: ChannelFilter['id']; } -export const MSTeamsConnector = (props: MSTeamsConnectorProps) => { +export const MSTeamsConnector = observer((props: MSTeamsConnectorProps) => { const { channelFilterId } = props; const store = useStore(); - const { alertReceiveChannelStore, msteamsChannelStore } = store; + const { + alertReceiveChannelStore, + msteamsChannelStore, + // dereferencing items is needed to rerender GSelect + msteamsChannelStore: { items: msteamsChannelItems }, + } = store; const channelFilter = store.alertReceiveChannelStore.channelFilters[channelFilterId]; @@ -57,7 +63,7 @@ export const MSTeamsConnector = (props: MSTeamsConnectorProps) => { allowClear className={cx('select', 'control')} - items={msteamsChannelStore.items} + items={msteamsChannelItems} fetchItemsFn={msteamsChannelStore.updateItems} fetchItemFn={msteamsChannelStore.updateById} getSearchResult={msteamsChannelStore.getSearchResult} @@ -71,4 +77,4 @@ export const MSTeamsConnector = (props: MSTeamsConnectorProps) => { ); -}; +}); diff --git a/grafana-plugin/src/containers/AlertRules/parts/connectors/SlackConnector.tsx b/grafana-plugin/src/containers/AlertRules/parts/connectors/SlackConnector.tsx index 3c2713dd..ba7abdeb 100644 --- a/grafana-plugin/src/containers/AlertRules/parts/connectors/SlackConnector.tsx +++ b/grafana-plugin/src/containers/AlertRules/parts/connectors/SlackConnector.tsx @@ -2,6 +2,7 @@ import React, { useCallback } from 'react'; import { HorizontalGroup, InlineSwitch } from '@grafana/ui'; import cn from 'classnames/bind'; +import { observer } from 'mobx-react'; import { GSelect } from 'containers/GSelect/GSelect'; import { WithPermissionControlTooltip } from 'containers/WithPermissionControl/WithPermissionControlTooltip'; @@ -19,7 +20,7 @@ interface SlackConnectorProps { channelFilterId: ChannelFilter['id']; } -export const SlackConnector = (props: SlackConnectorProps) => { +export const SlackConnector = observer((props: SlackConnectorProps) => { const { channelFilterId } = props; const store = useStore(); @@ -27,6 +28,8 @@ export const SlackConnector = (props: SlackConnectorProps) => { organizationStore: { currentOrganization }, alertReceiveChannelStore, slackChannelStore, + // dereferencing items is needed to rerender GSelect + slackChannelStore: { items: slackChannelItems }, } = store; const channelFilter = store.alertReceiveChannelStore.channelFilters[channelFilterId]; @@ -57,7 +60,7 @@ export const SlackConnector = (props: SlackConnectorProps) => { allowClear className={cx('select', 'control')} - items={slackChannelStore.items} + items={slackChannelItems} fetchItemsFn={slackChannelStore.updateItems} fetchItemFn={slackChannelStore.updateItem} getSearchResult={getSearchResult} @@ -94,4 +97,4 @@ export const SlackConnector = (props: SlackConnectorProps) => { return results; } -}; +}); diff --git a/grafana-plugin/src/containers/AlertRules/parts/connectors/TelegramConnector.tsx b/grafana-plugin/src/containers/AlertRules/parts/connectors/TelegramConnector.tsx index 73d15e8f..1d5db0db 100644 --- a/grafana-plugin/src/containers/AlertRules/parts/connectors/TelegramConnector.tsx +++ b/grafana-plugin/src/containers/AlertRules/parts/connectors/TelegramConnector.tsx @@ -2,6 +2,7 @@ import React, { useCallback } from 'react'; import { HorizontalGroup, InlineSwitch } from '@grafana/ui'; import cn from 'classnames/bind'; +import { observer } from 'mobx-react'; import { GSelect } from 'containers/GSelect/GSelect'; import { WithPermissionControlTooltip } from 'containers/WithPermissionControl/WithPermissionControlTooltip'; @@ -18,9 +19,14 @@ interface TelegramConnectorProps { channelFilterId: ChannelFilter['id']; } -export const TelegramConnector = ({ channelFilterId }: TelegramConnectorProps) => { +export const TelegramConnector = observer(({ channelFilterId }: TelegramConnectorProps) => { const store = useStore(); - const { alertReceiveChannelStore, telegramChannelStore } = store; + const { + alertReceiveChannelStore, + telegramChannelStore, + // dereferencing items is needed to rerender GSelect + telegramChannelStore: { items: telegramChannelItems }, + } = store; const channelFilter = store.alertReceiveChannelStore.channelFilters[channelFilterId]; @@ -49,7 +55,7 @@ export const TelegramConnector = ({ channelFilterId }: TelegramConnectorProps) = allowClear className={cx('select', 'control')} - items={telegramChannelStore.items} + items={telegramChannelItems} fetchItemsFn={telegramChannelStore.updateItems} fetchItemFn={telegramChannelStore.updateById} getSearchResult={telegramChannelStore.getSearchResult} @@ -63,4 +69,4 @@ export const TelegramConnector = ({ channelFilterId }: TelegramConnectorProps) = ); -}; +}); diff --git a/grafana-plugin/src/containers/AttachIncidentForm/AttachIncidentForm.tsx b/grafana-plugin/src/containers/AttachIncidentForm/AttachIncidentForm.tsx index a894a8bf..508a299a 100644 --- a/grafana-plugin/src/containers/AttachIncidentForm/AttachIncidentForm.tsx +++ b/grafana-plugin/src/containers/AttachIncidentForm/AttachIncidentForm.tsx @@ -42,7 +42,11 @@ const GroupedAlertNumber = observer(({ value }: GroupedAlertNumberProps) => { export const AttachIncidentForm = observer(({ id, onUpdate, onHide }: AttachIncidentFormProps) => { const store = useStore(); - const { alertGroupStore } = store; + const { + alertGroupStore, + // dereferencing alerts is needed to rerender GSelect + alertGroupStore: { alerts: alertGroupAlerts }, + } = store; const [selected, setSelected] = useState(undefined); @@ -75,7 +79,7 @@ export const AttachIncidentForm = observer(({ id, onUpdate, onHide }: AttachInci > - items={Object.fromEntries(alertGroupStore.alerts)} + items={Object.fromEntries(alertGroupAlerts)} fetchItemsFn={async (query: string) => { await alertGroupStore.fetchAlertGroups(false, query); }} diff --git a/grafana-plugin/src/containers/EscalationChainForm/EscalationChainForm.tsx b/grafana-plugin/src/containers/EscalationChainForm/EscalationChainForm.tsx index dc248f81..ec694f7b 100644 --- a/grafana-plugin/src/containers/EscalationChainForm/EscalationChainForm.tsx +++ b/grafana-plugin/src/containers/EscalationChainForm/EscalationChainForm.tsx @@ -2,6 +2,7 @@ import React, { ChangeEvent, FC, useCallback, useState } from 'react'; import { Button, Field, HorizontalGroup, Input, Modal } from '@grafana/ui'; import cn from 'classnames/bind'; +import { observer } from 'mobx-react'; import { GSelect } from 'containers/GSelect/GSelect'; import { EscalationChain } from 'models/escalation_chain/escalation_chain.types'; @@ -26,11 +27,17 @@ interface EscalationChainFormProps { const cx = cn.bind(styles); -export const EscalationChainForm: FC = (props) => { +export const EscalationChainForm: FC = observer((props) => { const { escalationChainId, onHide, onSubmit: onSubmitProp, mode } = props; const store = useStore(); - const { escalationChainStore, userStore, grafanaTeamStore } = store; + const { + escalationChainStore, + userStore, + grafanaTeamStore, + // dereferencing items is needed to rerender GSelect + grafanaTeamStore: { items: grafanaTeamItems }, + } = store; const user = userStore.currentUser; @@ -93,7 +100,7 @@ export const EscalationChainForm: FC = (props) => {
- items={grafanaTeamStore.items} + items={grafanaTeamItems} fetchItemsFn={grafanaTeamStore.updateItems} fetchItemFn={grafanaTeamStore.fetchItemById} getSearchResult={grafanaTeamStore.getSearchResult} @@ -125,4 +132,4 @@ export const EscalationChainForm: FC = (props) => {
); -}; +}); diff --git a/grafana-plugin/src/containers/GrafanaTeamSelect/GrafanaTeamSelect.tsx b/grafana-plugin/src/containers/GrafanaTeamSelect/GrafanaTeamSelect.tsx index b1d48095..bc8dbc38 100644 --- a/grafana-plugin/src/containers/GrafanaTeamSelect/GrafanaTeamSelect.tsx +++ b/grafana-plugin/src/containers/GrafanaTeamSelect/GrafanaTeamSelect.tsx @@ -25,7 +25,12 @@ export const GrafanaTeamSelect = observer( ({ onSelect, onHide, withoutModal, defaultValue }: GrafanaTeamSelectProps) => { const store = useStore(); - const { userStore, grafanaTeamStore } = store; + const { + userStore, + grafanaTeamStore, + // dereferencing items is needed to rerender GSelect + grafanaTeamStore: { items: grafanaTeamItems }, + } = store; const user = userStore.currentUser; const [selectedTeam, setSelectedTeam] = useState(defaultValue); @@ -53,7 +58,7 @@ export const GrafanaTeamSelect = observer( const select = ( - items={grafanaTeamStore.items} + items={grafanaTeamItems} fetchItemsFn={grafanaTeamStore.updateItems} fetchItemFn={grafanaTeamStore.fetchItemById} getSearchResult={grafanaTeamStore.getSearchResult} diff --git a/grafana-plugin/src/containers/IntegrationForm/IntegrationForm.tsx b/grafana-plugin/src/containers/IntegrationForm/IntegrationForm.tsx index 80964db2..39c58f6e 100644 --- a/grafana-plugin/src/containers/IntegrationForm/IntegrationForm.tsx +++ b/grafana-plugin/src/containers/IntegrationForm/IntegrationForm.tsx @@ -97,7 +97,13 @@ export const IntegrationForm = observer( const history = useHistory(); const styles = useStyles2(getIntegrationFormStyles); const isNew = id === 'new'; - const { userStore, grafanaTeamStore, alertReceiveChannelStore } = store; + const { + userStore, + grafanaTeamStore, + // dereferencing items is needed to rerender GSelect + grafanaTeamStore: { items: grafanaTeamItems }, + alertReceiveChannelStore, + } = store; const data: Partial = isNew ? { @@ -234,7 +240,7 @@ export const IntegrationForm = observer( placeholder="Assign to team" {...field} {...{ - items: grafanaTeamStore.items, + items: grafanaTeamItems, fetchItemsFn: grafanaTeamStore.updateItems, fetchItemFn: grafanaTeamStore.fetchItemById, getSearchResult: grafanaTeamStore.getSearchResult, diff --git a/grafana-plugin/src/containers/MaintenanceForm/MaintenanceForm.tsx b/grafana-plugin/src/containers/MaintenanceForm/MaintenanceForm.tsx index 54ec54ee..d8d30084 100644 --- a/grafana-plugin/src/containers/MaintenanceForm/MaintenanceForm.tsx +++ b/grafana-plugin/src/containers/MaintenanceForm/MaintenanceForm.tsx @@ -37,7 +37,11 @@ interface FormFields { export const MaintenanceForm = observer((props: MaintenanceFormProps) => { const { onUpdate, onHide, initialData = {} } = props; - const { alertReceiveChannelStore } = useStore(); + const { + alertReceiveChannelStore, + // dereferencing items is needed to rerender GSelect + alertReceiveChannelStore: { items: alertReceiveChannelItems }, + } = useStore(); const onSubmit = useCallback(async (data) => { try { @@ -87,7 +91,7 @@ export const MaintenanceForm = observer((props: MaintenanceFormProps) => { > disabled - items={alertReceiveChannelStore.items} + items={alertReceiveChannelItems} fetchItemsFn={alertReceiveChannelStore.fetchItems} fetchItemFn={alertReceiveChannelStore.fetchItemById} getSearchResult={() => AlertReceiveChannelHelper.getSearchResult(alertReceiveChannelStore)} diff --git a/grafana-plugin/src/containers/OutgoingWebhookForm/OutgoingWebhookFormFields.tsx b/grafana-plugin/src/containers/OutgoingWebhookForm/OutgoingWebhookFormFields.tsx index 041d6200..aa8111bd 100644 --- a/grafana-plugin/src/containers/OutgoingWebhookForm/OutgoingWebhookFormFields.tsx +++ b/grafana-plugin/src/containers/OutgoingWebhookForm/OutgoingWebhookFormFields.tsx @@ -48,7 +48,12 @@ const FORWARD_RADIO_OPTIONS = [ export const OutgoingWebhookFormFields: React.FC = observer( ({ preset, hasLabelsFeature, onTemplateEditClick }) => { - const { grafanaTeamStore, alertReceiveChannelStore } = useStore(); + const { + grafanaTeamStore, + // dereferencing items is needed to rerender GSelect + grafanaTeamStore: { items: grafanaTeamItems }, + alertReceiveChannelStore, + } = useStore(); const { items, fetchItems, fetchItemById } = alertReceiveChannelStore; const { control, @@ -98,7 +103,7 @@ export const OutgoingWebhookFormFields: React.FC > allowClear - items={grafanaTeamStore.items} + items={grafanaTeamItems} fetchItemsFn={grafanaTeamStore.updateItems} fetchItemFn={grafanaTeamStore.fetchItemById} getSearchResult={grafanaTeamStore.getSearchResult} diff --git a/grafana-plugin/src/containers/ScheduleForm/ScheduleForm.tsx b/grafana-plugin/src/containers/ScheduleForm/ScheduleForm.tsx index f3248a9e..0dae9b81 100644 --- a/grafana-plugin/src/containers/ScheduleForm/ScheduleForm.tsx +++ b/grafana-plugin/src/containers/ScheduleForm/ScheduleForm.tsx @@ -199,7 +199,11 @@ const FormFields = ({ scheduleType }: { scheduleType: Schedule['type'] }) => { }; const ScheduleCommonFields = () => { - const { grafanaTeamStore } = useStore(); + const { + grafanaTeamStore, + // dereferencing items is needed to rerender GSelect + grafanaTeamStore: { items: grafanaTeamItems }, + } = useStore(); const { control, formState } = useFormContext(); const { errors } = formState; @@ -222,7 +226,7 @@ const ScheduleCommonFields = () => { render={({ field }) => ( - items={grafanaTeamStore.items} + items={grafanaTeamItems} fetchItemsFn={grafanaTeamStore.updateItems} fetchItemFn={grafanaTeamStore.fetchItemById} getSearchResult={grafanaTeamStore.getSearchResult} @@ -239,12 +243,18 @@ const ScheduleCommonFields = () => { ); }; -const ScheduleNotificationSettingsFields = () => { +const ScheduleNotificationSettingsFields = observer(() => { const store = useStore(); const styles = useStyles2(getStyles); - const { slackChannelStore, userGroupStore } = store; + const { + slackChannelStore, + userGroupStore, + // dereferencing items is needed to rerender GSelect + slackChannelStore: { items: slackChannelItems }, + userGroupStore: { items: userGroupItems }, + } = store; const { control, @@ -265,7 +275,7 @@ const ScheduleNotificationSettingsFields = () => { > allowClear - items={slackChannelStore.items} + items={slackChannelItems} fetchItemsFn={slackChannelStore.updateItems} fetchItemFn={slackChannelStore.updateItem} getSearchResult={slackChannelStore.getSearchResult} @@ -291,7 +301,7 @@ const ScheduleNotificationSettingsFields = () => { > allowClear - items={userGroupStore.items} + items={userGroupItems} fetchItemsFn={userGroupStore.updateItems} fetchItemFn={userGroupStore.fetchItemById} getSearchResult={userGroupStore.getSearchResult} @@ -395,7 +405,7 @@ const ScheduleNotificationSettingsFields = () => { /> ); -}; +}); export const getStyles = () => ({ collapse: css` diff --git a/grafana-plugin/src/containers/UserSettings/parts/tabs/GoogleCalendar/GoogleCalendar.tsx b/grafana-plugin/src/containers/UserSettings/parts/tabs/GoogleCalendar/GoogleCalendar.tsx index 84c06db2..9a9dfd53 100644 --- a/grafana-plugin/src/containers/UserSettings/parts/tabs/GoogleCalendar/GoogleCalendar.tsx +++ b/grafana-plugin/src/containers/UserSettings/parts/tabs/GoogleCalendar/GoogleCalendar.tsx @@ -19,7 +19,12 @@ import { UserActions } from 'utils/authorization/authorization'; import { DOCS_ROOT } from 'utils/consts'; const GoogleCalendar: React.FC<{ id: ApiSchemas['User']['pk'] }> = observer(({ id }) => { - const { userStore, scheduleStore } = useStore(); + const { + userStore, + scheduleStore, + // dereferencing items is needed to rerender GSelect + scheduleStore: { items: scheduleItems }, + } = useStore(); const utils = useStyles2(getUtilStyles); @@ -92,7 +97,7 @@ const GoogleCalendar: React.FC<{ id: ApiSchemas['User']['pk'] }> = observer(({ i isMulti allowClear disabled={false} - items={scheduleStore.items} + items={scheduleItems} fetchItemsFn={scheduleStore.updateItems} fetchItemFn={scheduleStore.updateItem} getSearchResult={scheduleStore.getSearchResult} diff --git a/grafana-plugin/src/pages/settings/tabs/ChatOps/tabs/SlackSettings/SlackSettings.tsx b/grafana-plugin/src/pages/settings/tabs/ChatOps/tabs/SlackSettings/SlackSettings.tsx index 13915572..1933359f 100644 --- a/grafana-plugin/src/pages/settings/tabs/ChatOps/tabs/SlackSettings/SlackSettings.tsx +++ b/grafana-plugin/src/pages/settings/tabs/ChatOps/tabs/SlackSettings/SlackSettings.tsx @@ -112,6 +112,8 @@ class _SlackSettings extends Component { organizationStore: { currentOrganization }, slackStore, slackChannelStore, + // dereferencing items is needed to rerender GSelect + slackChannelStore: { items: slackChannelItems }, } = store; return ( @@ -126,7 +128,7 @@ class _SlackSettings extends Component { > - items={slackChannelStore.items} + items={slackChannelItems} fetchItemsFn={slackChannelStore.updateItems} fetchItemFn={slackChannelStore.updateItem} getSearchResult={slackChannelStore.getSearchResult}