From 6e5cb4e8a7577f6318ea937491e2b796ba2a419e Mon Sep 17 00:00:00 2001 From: Joey Orlando Date: Mon, 24 Oct 2022 14:27:03 +0200 Subject: [PATCH] [UI] fix eslint/prettier warnings (#678) * UI spring cleaning - fix ~570 outstanding eslint warnings - make eslint force user to correct warnings - remove .css files that are not referenced - remove dummy.tsx as it is not consumed anywhere - remove a few functions that were "dead code" (ie. not consumed anywhere) - remove commented out blocks of code that had no explanatory comments surrounding them * add prettier to pre-commit configuration * change ignoreRestSiblings to true we have a few spots in the codebase where we destructure an object key and then use something like ...restProps setting this to true allows that * upgrade from eslint 7.21.0 to 8.25.0 - add @grafana/eslint-config to dev dependencies and pre-commit eslint deps - add @grafana/eslint-config peer dependencies to package.json * fix remaining outstanding prettier warnings * enable noUnusedLocals and noUnusedParameters and fix errors related to this * make pre-commit complain about eslint warnings * import from moment-timezone instead of moment * fix react/display-name eslint warning * add eslint-plugin-react-hooks to dev deps this is a peer dependency from @grafana/eslint-config * turn off react/prop-types * temporarily turn off react-hooks/exhaustive-deps add note that it will be turned back on and fixed in next PR * fix unused import errors after rebase to dev * fix more new prettier errors * turn react/no-unescaped-entities eslint rule off * address PR comment about useReducer * remove includeTemplateGroup from src/components/AlertTemplates/AlertTemplatesForm.helper.tsx * update arg typing for refreshPageError * update handleSyncException typing * fix strict equality in containers/IntegrationSettings/parts/Autoresolve.tsx * enhance typing in components/AlertTemplates/AlertTemplatesForm.tsx * revert small change per Maxim's comment --- .pre-commit-config.yaml | 18 +- grafana-plugin/.eslintrc.js | 39 ++- grafana-plugin/.stylelintrc | 10 +- grafana-plugin/package.json | 13 +- grafana-plugin/src/GrafanaPluginRootPage.tsx | 4 +- grafana-plugin/src/README.md | 2 + .../AlertTemplatesForm.helper.tsx | 4 - .../AlertTemplates/AlertTemplatesForm.tsx | 34 +- .../src/components/Avatar/Avatar.test.tsx | 2 +- .../CardButton/CardButton.module.css | 2 +- .../components/CardButton/CardButton.test.tsx | 5 +- .../src/components/CardButton/CardButton.tsx | 7 +- .../src/components/Collapse/Collapse.test.tsx | 6 +- .../CursorPagination.module.css | 3 - .../CursorPagination/CursorPagination.tsx | 5 - .../EscalationsFilters/EscalationsFilters.tsx | 2 +- .../src/components/GForm/GForm.module.css | 3 - grafana-plugin/src/components/GForm/GForm.tsx | 32 +- .../src/components/GForm/GForm.types.ts | 9 - grafana-plugin/src/components/GList/GList.tsx | 3 +- .../src/components/GTable/GTable.tsx | 4 +- grafana-plugin/src/components/Modal/Modal.tsx | 3 +- .../MonacoJinja2Editor.module.css | 3 - .../MonacoJinja2Editor/MonacoJinja2Editor.tsx | 7 +- .../NewScheduleSelector.tsx | 5 - .../PageErrorHandlingWrapper.tsx | 1 - .../components/Policy/EscalationPolicy.tsx | 5 +- .../ScheduleBorderedAvatar.tsx | 14 +- .../ScheduleCounter.module.css | 12 - .../ScheduleCounter/ScheduleCounter.tsx | 14 +- .../ScheduleUserDetails.module.css | 2 +- .../ScheduleUserDetails.tsx | 80 +---- .../SchedulesFilters.helpers.ts | 2 +- .../SchedulesFilters/SchedulesFilters.tsx | 26 +- .../SchedulesFilters.types.ts | 2 - .../SchedulesFilters.helpers.ts | 2 +- .../SchedulesFilters_NEW/SchedulesFilters.tsx | 5 +- .../SourceCode/SourceCode.module.scss | 2 +- .../components/SourceCode/SourceCode.test.tsx | 3 +- .../src/components/SourceCode/SourceCode.tsx | 10 +- grafana-plugin/src/components/Table/Table.tsx | 11 +- .../src/components/Text/Text.module.scss | 1 - grafana-plugin/src/components/Text/Text.tsx | 3 +- .../src/components/Timeline/Timeline.tsx | 2 +- .../src/components/Timeline/TimelineItem.tsx | 32 +- .../TimelineMarks/TimelineMarks.tsx | 3 +- .../src/components/Tutorial/Tutorial.tsx | 2 - .../UserGroups/UserGroups.helpers.ts | 2 +- .../UserGroups/UserGroups.module.css | 4 +- .../src/components/UserGroups/UserGroups.tsx | 6 +- .../UserTimezoneSelect/UserTimezoneSelect.tsx | 1 - .../components/UsersFilters/UsersFilters.tsx | 1 + .../VerticalTabsBar/VerticalTabsBar.tsx | 24 +- .../WithConfirm/WithConfirm.module.css | 3 - .../components/WithConfirm/WithConfirm.tsx | 7 +- .../WorkingHours/WorkingHours.helpers.ts | 2 +- .../components/WorkingHours/WorkingHours.tsx | 25 -- .../AlertReceiveChannelCard.tsx | 5 +- .../src/containers/AlertRules/AlertRules.tsx | 55 +--- .../parts/connectors/SlackConnector.tsx | 2 +- .../parts/connectors/TelegramConnector.tsx | 12 +- .../AlertRules/parts/index.module.css | 3 - .../src/containers/AlertRules/parts/index.tsx | 5 - .../AlertTemplatesFormContainer.tsx | 2 - .../ApiTokenSettings/ApiTokenForm.tsx | 1 - .../ApiTokenSettings/ApiTokenSettings.tsx | 9 +- .../AttachIncidentForm/AttachIncidentForm.tsx | 25 +- .../CreateAlertReceiveChannelContainer.tsx | 11 +- .../DefaultPageLayout.helpers.tsx | 2 +- .../containers/DefaultPageLayout/helper.ts | 2 - .../EscalationChainCard.tsx | 16 - .../EscalationChainForm.tsx | 1 - .../EscalationChainSteps.tsx | 4 - .../src/containers/GSelect/GSelect.tsx | 6 +- .../GrafanaTeamSelect/GrafanaTeamSelect.tsx | 6 +- .../HeartbeatModal/HeartbeatForm.tsx | 2 +- .../IncidentFilters.helpers.ts | 3 - .../IncidentsFilters/IncidentFilters.types.ts | 2 - .../IncidentsFilters/IncidentsFilters.tsx | 31 +- .../IntegrationSettings.tsx | 65 +--- .../IntegrationSettings/parts/Autoresolve.tsx | 4 +- .../IntegrationSettings/parts/LiveLogs.tsx | 4 +- .../MaintenanceForm.config.tsx | 2 +- .../MaintenanceForm.helpers.ts | 6 - .../MobileAppVerification.tsx | 74 +---- .../OrganizationLogFilters.tsx | 9 +- .../OutgoingWebhookForm.config.ts | 3 - .../PluginConfigPage/PluginConfigPage.tsx | 79 ++--- .../containers/PluginConfigPage/helpers.tsx | 7 +- .../RemoteSelect/RemoteSelect.module.css | 3 - .../containers/RemoteSelect/RemoteSelect.tsx | 5 - .../src/containers/Rotation/Rotation.tsx | 44 +-- .../RotationForm/DateTimePicker.tsx | 12 +- .../containers/RotationForm/RotationForm.tsx | 42 +-- .../RotationForm/ScheduleOverrideForm.tsx | 8 +- .../containers/Rotations/Rotations.helpers.ts | 6 +- .../src/containers/Rotations/Rotations.tsx | 12 +- .../containers/Rotations/ScheduleFinal.tsx | 16 +- .../Rotations/ScheduleOverrides.tsx | 15 +- .../ScheduleForm/ScheduleForm.config.ts | 9 - .../containers/ScheduleForm/ScheduleForm.tsx | 8 +- .../ScheduleIcalLink/ScheduleIcalLink.tsx | 2 +- .../ScheduleSlot/ScheduleSlot.helpers.ts | 20 -- .../containers/ScheduleSlot/ScheduleSlot.tsx | 21 +- .../SchedulesFilters.module.css | 3 - .../SchedulesFilters/SchedulesFilters.tsx | 24 -- .../SlackIntegrationButton.tsx | 1 - .../TelegramIntegrationButton.tsx | 5 +- .../TemplatePreview/TemplatePreview.tsx | 5 +- .../containers/UserSettings/UserSettings.tsx | 7 +- .../parts/connectors/ICalConnector.tsx | 4 +- .../parts/connectors/MobileAppConnector.tsx | 3 +- .../parts/connectors/PhoneConnector.tsx | 2 +- .../parts/connectors/SlackConnector.tsx | 2 +- .../parts/connectors/TelegramConnector.tsx | 2 +- .../containers/UserSettings/parts/index.tsx | 13 +- .../CloudPhoneSettings.module.css | 3 - .../CloudPhoneSettings/CloudPhoneSettings.tsx | 24 +- .../PhoneVerification/PhoneVerification.tsx | 61 ++-- .../parts/tabs/TelegramInfo/TelegramInfo.tsx | 2 +- .../containers/UserSummary/UserSummary.tsx | 2 +- .../UserTooltip/UserTooltip.module.css | 3 - .../containers/UserTooltip/UserTooltip.tsx | 5 - .../UsersTimezones/UsersTimezones.module.css | 9 +- .../UsersTimezones/UsersTimezones.tsx | 25 +- .../WithPermissionControl.tsx | 4 +- grafana-plugin/src/dummy/dummy.ts | 1 - grafana-plugin/src/icons/index.tsx | 32 +- .../src/jest/outgoingWebhooksStub.ts | 2 +- .../alert_receive_channel.ts | 14 +- .../alert_receive_channel_filters.ts | 2 +- .../src/models/alertgroup/alertgroup.types.ts | 4 - grafana-plugin/src/models/cloud/cloud.ts | 7 +- .../src/models/current_subscription.ts | 2 - .../escalation_chain/escalation_chain.ts | 6 +- .../escalation_policy.types.ts | 1 - .../models/global_setting/global_setting.ts | 4 - .../src/models/maintenance/helpers.ts | 2 +- .../models/resolution_note/resolution_note.ts | 3 +- .../src/models/schedule/schedule.helpers.ts | 11 +- .../src/models/schedule/schedule.ts | 37 +-- .../src/models/slack_channel/slack_channel.ts | 2 +- grafana-plugin/src/models/team/team.ts | 6 +- .../telegram_channel.helpers.ts | 1 - .../telegram_channel/telegram_channel.ts | 1 - .../src/models/timezone/timezone.types.ts | 2 - .../src/models/user/user.helpers.tsx | 4 - grafana-plugin/src/models/user/user.ts | 4 - grafana-plugin/src/models/webinar/webinar.ts | 2 +- grafana-plugin/src/pages/chat-ops/ChatOps.tsx | 2 - grafana-plugin/src/pages/cloud/CloudPage.tsx | 22 +- .../escalation-chains/EscalationChains.tsx | 7 +- .../src/pages/incident/Incident.helpers.tsx | 36 +-- .../src/pages/incident/Incident.tsx | 19 +- .../src/pages/incidents/Incidents.tsx | 6 +- .../src/pages/integrations/Integrations.tsx | 5 - .../pages/livesettings/LiveSettingsPage.tsx | 33 +- .../src/pages/maintenance/Maintenance.tsx | 14 +- .../pages/migration-tool/MigrationTool.tsx | 18 +- .../organization-logs/OrganizationLog.tsx | 6 +- .../OutgoingWebhooks.test.tsx | 1 - .../outgoing_webhooks/OutgoingWebhooks.tsx | 2 +- .../src/pages/schedule/Schedule.module.css | 1 - .../src/pages/schedule/Schedule.tsx | 56 +--- .../src/pages/schedules/Schedules.tsx | 14 +- .../src/pages/schedules_NEW/Schedules.tsx | 49 +-- .../src/pages/settings/SettingsPage.tsx | 25 +- grafana-plugin/src/pages/users/Users.tsx | 2 +- grafana-plugin/src/plugin.json | 14 +- grafana-plugin/src/state/helpers.ts | 2 +- grafana-plugin/src/state/incidents.ts | 3 - grafana-plugin/src/state/plugin.ts | 3 +- grafana-plugin/src/state/rootBaseStore.ts | 28 +- grafana-plugin/src/state/withStore.tsx | 6 +- grafana-plugin/src/style/index.css | 4 +- grafana-plugin/src/types.ts | 2 +- grafana-plugin/src/utils/DOM.ts | 20 +- grafana-plugin/src/utils/index.ts | 7 +- grafana-plugin/src/utils/loadCss.ts | 2 +- grafana-plugin/tsconfig.json | 5 +- grafana-plugin/webpack.config.js | 11 +- grafana-plugin/yarn.lock | 291 ++++++++++++++++-- 182 files changed, 822 insertions(+), 1468 deletions(-) delete mode 100644 grafana-plugin/src/components/CursorPagination/CursorPagination.module.css delete mode 100644 grafana-plugin/src/components/GForm/GForm.module.css delete mode 100644 grafana-plugin/src/components/MonacoJinja2Editor/MonacoJinja2Editor.module.css delete mode 100644 grafana-plugin/src/components/WithConfirm/WithConfirm.module.css delete mode 100644 grafana-plugin/src/containers/AlertRules/parts/index.module.css delete mode 100644 grafana-plugin/src/containers/MaintenanceForm/MaintenanceForm.helpers.ts delete mode 100644 grafana-plugin/src/containers/RemoteSelect/RemoteSelect.module.css delete mode 100644 grafana-plugin/src/containers/SchedulesFilters/SchedulesFilters.module.css delete mode 100644 grafana-plugin/src/containers/SchedulesFilters/SchedulesFilters.tsx delete mode 100644 grafana-plugin/src/containers/UserSettings/parts/tabs/CloudPhoneSettings/CloudPhoneSettings.module.css delete mode 100644 grafana-plugin/src/containers/UserTooltip/UserTooltip.module.css delete mode 100644 grafana-plugin/src/dummy/dummy.ts delete mode 100644 grafana-plugin/src/models/telegram_channel/telegram_channel.helpers.ts delete mode 100644 grafana-plugin/src/state/incidents.ts diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e2dbf2de..f61d3a85 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,16 +23,26 @@ repos: - flake8-tidy-imports - repo: https://github.com/pre-commit/mirrors-eslint - rev: v7.21.0 + rev: v8.25.0 hooks: - id: eslint - entry: bash -c 'cd grafana-plugin && eslint --fix ${@/grafana-plugin\//}' -- + entry: bash -c 'cd grafana-plugin && eslint --max-warnings=0 --fix ${@/grafana-plugin\//}' -- types: [file] files: ^grafana-plugin/src/.*\.(js|jsx|ts|tsx)$ additional_dependencies: - - eslint@7.21.0 + - eslint@^8.25.0 - eslint-plugin-import@^2.25.4 - eslint-plugin-rulesdir@^0.2.1 + - "@grafana/eslint-config@^5.0.0" + + - repo: https://github.com/pre-commit/mirrors-prettier + rev: "v2.7.1" + hooks: + - id: prettier + types_or: [css, javascript, jsx, ts, tsx, json] + files: ^grafana-plugin/src + additional_dependencies: + - prettier@^2.7.1 - repo: https://github.com/thibaudcolas/pre-commit-stylelint rev: v13.13.1 @@ -43,4 +53,6 @@ repos: files: ^grafana-plugin/src/.*\.css$ additional_dependencies: - stylelint@^13.13.1 + - stylelint-prettier@^2.0.0 - stylelint-config-standard@^22.0.0 + - stylelint-config-prettier@^9.0.3 diff --git a/grafana-plugin/.eslintrc.js b/grafana-plugin/.eslintrc.js index 87f1dd00..9bfe88c0 100644 --- a/grafana-plugin/.eslintrc.js +++ b/grafana-plugin/.eslintrc.js @@ -9,18 +9,7 @@ module.exports = { '^assets|^components|^containers|^declare|^icons|^img|^interceptors|^models|^network|^pages|^services|^state|^utils', }, rules: { - 'no-unused-vars': ['warn', { vars: 'all', args: 'after-used', ignoreRestSiblings: false }], - 'react/prop-types': 'warn', - 'react/display-name': 'warn', - 'react/jsx-key': 'warn', - 'react-hooks/exhaustive-deps': 'off', - 'react/no-unescaped-entities': 'warn', - 'react/jsx-no-target-blank': 'warn', - 'react-hooks/exhaustive-deps': 'warn', - 'no-restricted-imports': 'warn', eqeqeq: 'warn', - 'no-duplicate-imports': 'error', - 'rulesdir/no-relative-import-paths': ['error', { allowSameFolder: true }], 'import/order': [ 'error', { @@ -47,5 +36,33 @@ module.exports = { 'newlines-between': 'always', }, ], + 'no-unused-vars': [ + 'warn', + { + vars: 'all', + args: 'after-used', + argsIgnorePattern: '^_', + destructuredArrayIgnorePattern: '^_', + ignoreRestSiblings: true, + }, + ], + 'no-duplicate-imports': 'error', + 'no-restricted-imports': 'warn', + 'react/display-name': 'warn', + /** + * It appears as though the react/prop-types rule has a bug in it + * when your props extend an interface + * https://github.com/jsx-eslint/eslint-plugin-react/issues/3325 + */ + 'react/prop-types': 'off', + 'react/jsx-key': 'warn', + 'react/jsx-no-target-blank': 'warn', + 'react/no-unescaped-entities': 'off', + /** + * TODO: react-hooks/exhaustive-deps is temporarily disabled + * this will be turned back on, and the warnings fixed, in a forthcoming PR + */ + 'react-hooks/exhaustive-deps': 'off', + 'rulesdir/no-relative-import-paths': ['error', { allowSameFolder: true }], }, }; diff --git a/grafana-plugin/.stylelintrc b/grafana-plugin/.stylelintrc index 7cda5c91..c37d4c08 100644 --- a/grafana-plugin/.stylelintrc +++ b/grafana-plugin/.stylelintrc @@ -1,12 +1,14 @@ { - "extends": "stylelint-config-standard", - "rules": { - "block-no-empty": [true,{ "severity": "warning"}], + "extends": ["stylelint-config-standard", "stylelint-prettier/recommended"], + "plugins": ["stylelint-prettier"], + "rules": { + "block-no-empty": [true, { "severity": "warning" }], "selector-pseudo-class-no-unknown": [ true, { "ignorePseudoClasses": ["global"] } - ] + ], + "prettier/prettier": true } } diff --git a/grafana-plugin/package.json b/grafana-plugin/package.json index 021f0224..9398e5c9 100644 --- a/grafana-plugin/package.json +++ b/grafana-plugin/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "description": "Grafana OnCall Plugin", "scripts": { - "lint": "eslint --cache --ext .js,.jsx,.ts,.tsx ./src", - "lint:fix": "eslint --fix --cache --ext .js,.jsx,.ts,.tsx --quiet ./src", + "lint": "eslint --cache --ext .js,.jsx,.ts,.tsx --max-warnings=0 ./src", + "lint:fix": "eslint --fix --cache --ext .js,.jsx,.ts,.tsx --max-warnings=0 --quiet ./src", "stylelint": "stylelint ./src/**/*.css", "stylelint:fix": "stylelint --fix ./src/**/*.css", "build": "grafana-toolkit plugin:build", @@ -52,6 +52,7 @@ "@babel/preset-react": "^7.18.6", "@babel/preset-typescript": "^7.18.6", "@grafana/data": "^9.1.1", + "@grafana/eslint-config": "^5.0.0", "@grafana/runtime": "^9.1.1", "@grafana/toolkit": "^9.1.1", "@grafana/ui": "^9.1.1", @@ -67,8 +68,13 @@ "@types/react-router-dom": "^5.3.3", "@types/react-test-renderer": "^17.0.2", "@types/throttle-debounce": "^5.0.0", + "@typescript-eslint/eslint-plugin": "^5.40.1", "copy-webpack-plugin": "^11.0.0", "dompurify": "^2.3.12", + "eslint": "^8.25.0", + "eslint-plugin-jsdoc": "^39.3.14", + "eslint-plugin-react": "^7.31.10", + "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-rulesdir": "^0.2.1", "jest": "^27.5.1", "jest-environment-jsdom": "^27.5.1", @@ -78,8 +84,11 @@ "plop": "^2.7.4", "postcss-loader": "^7.0.1", "react-test-renderer": "^17.0.2", + "stylelint-config-prettier": "^9.0.3", + "stylelint-prettier": "^2.0.0", "ts-jest": "^27.1.3", "ts-loader": "^9.3.1", + "typescript": "4.6.4", "webpack-bundle-analyzer": "^4.6.1" }, "engines": { diff --git a/grafana-plugin/src/GrafanaPluginRootPage.tsx b/grafana-plugin/src/GrafanaPluginRootPage.tsx index 4e3f6467..ed69df65 100644 --- a/grafana-plugin/src/GrafanaPluginRootPage.tsx +++ b/grafana-plugin/src/GrafanaPluginRootPage.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useMemo } from 'react'; import { AppRootProps } from '@grafana/data'; -import { Button, HorizontalGroup, LinkButton, VerticalGroup } from '@grafana/ui'; +import { Button, HorizontalGroup, LinkButton } from '@grafana/ui'; import dayjs from 'dayjs'; import isSameOrAfter from 'dayjs/plugin/isSameOrAfter'; import isSameOrBefore from 'dayjs/plugin/isSameOrBefore'; @@ -30,8 +30,6 @@ dayjs.extend(isSameOrBefore); dayjs.extend(isSameOrAfter); dayjs.extend(isoWeek); -// dayjs().weekday(0); - import './style/vars.css'; import './style/index.css'; diff --git a/grafana-plugin/src/README.md b/grafana-plugin/src/README.md index 66e4b915..b3c76bb1 100644 --- a/grafana-plugin/src/README.md +++ b/grafana-plugin/src/README.md @@ -3,6 +3,7 @@ Developer-Friendly Alert Management with Brilliant Slack Integration + - Connect monitoring systems - Collect and analyze data - On-call rotation @@ -10,5 +11,6 @@ with Brilliant Slack Integration - Never miss alerts with calls and SMS ## Documentation + - [On Github](http://github.com/grafana/oncall) - [Grafana OnCall](https://grafana.com/docs/grafana-cloud/oncall/) diff --git a/grafana-plugin/src/components/AlertTemplates/AlertTemplatesForm.helper.tsx b/grafana-plugin/src/components/AlertTemplates/AlertTemplatesForm.helper.tsx index e2e01b17..d7bad53f 100644 --- a/grafana-plugin/src/components/AlertTemplates/AlertTemplatesForm.helper.tsx +++ b/grafana-plugin/src/components/AlertTemplates/AlertTemplatesForm.helper.tsx @@ -10,7 +10,3 @@ export function getLabelFromTemplateName(templateName: string, group: any) { } return arrayWithNeededValues.join(' '); } - -export function includeTemplateGroup(groupName: string) { - return true; -} diff --git a/grafana-plugin/src/components/AlertTemplates/AlertTemplatesForm.tsx b/grafana-plugin/src/components/AlertTemplates/AlertTemplatesForm.tsx index eaecbbfd..782ea07a 100644 --- a/grafana-plugin/src/components/AlertTemplates/AlertTemplatesForm.tsx +++ b/grafana-plugin/src/components/AlertTemplates/AlertTemplatesForm.tsx @@ -8,8 +8,7 @@ import cn from 'classnames/bind'; import { omit } from 'lodash-es'; import { templatesToRender, Template } from 'components/AlertTemplates/AlertTemplatesForm.config'; -import { getLabelFromTemplateName, includeTemplateGroup } from 'components/AlertTemplates/AlertTemplatesForm.helper'; -import Collapse from 'components/Collapse/Collapse'; +import { getLabelFromTemplateName } from 'components/AlertTemplates/AlertTemplatesForm.helper'; import Block from 'components/GBlock/Block'; import MonacoJinja2Editor from 'components/MonacoJinja2Editor/MonacoJinja2Editor'; import SourceCode from 'components/SourceCode/SourceCode'; @@ -41,7 +40,6 @@ const AlertTemplatesForm = (props: AlertTemplatesFormProps) => { const { onUpdateTemplates, templates, - errors, alertReceiveChannelId, alertGroupId, demoAlertEnabled, @@ -53,6 +51,8 @@ const AlertTemplatesForm = (props: AlertTemplatesFormProps) => { const [tempValues, setTempValues] = useState<{ [key: string]: string | null; }>({}); + const [activeGroup, setActiveGroup] = useState(); + const [activeTemplate, setActiveTemplate] = useState