From 427f75d9b0a91486fa6289d020c2f6e7a4698713 Mon Sep 17 00:00:00 2001 From: Nathan Rodman Date: Fri, 1 Oct 2021 15:15:55 -0700 Subject: [PATCH] Alerting: UI standardization and fixes (#38770) * Add expand all button for rule list group view * filter out recording rules by default * Create rule type filter * Add placeholder text for inputs * WIP move Silences to use DynamicTable * Use dynamic table for silences page * hide expand all for state list view * Add placeholders for inputs * Update selector in receivers test * Fix strict error for ruleType * remove redundant placeholder text and cleanup hooks * add fixed width for schedule * Rebase with dynamic table for silences * only show expand/collapse when filters are active --- packages/grafana-ui/src/types/icon.ts | 1 + .../features/alerting/unified/AmRoutes.tsx | 1 - .../alerting/unified/Receivers.test.tsx | 6 +- .../features/alerting/unified/RuleList.tsx | 33 ++- .../alerting/unified/Silences.test.tsx | 8 +- .../components/amroutes/AmRootRouteForm.tsx | 22 +- .../amroutes/AmRoutesExpandedForm.tsx | 6 +- .../unified/components/amroutes/formStyles.ts | 8 + .../components/receivers/TemplateForm.tsx | 5 +- .../receivers/form/ReceiverForm.tsx | 3 +- .../unified/components/rules/CloudRules.tsx | 4 +- .../unified/components/rules/GrafanaRules.tsx | 10 +- .../components/rules/RuleListGroupView.tsx | 7 +- .../components/rules/RuleListStateView.tsx | 1 + .../unified/components/rules/RulesFilter.tsx | 30 ++- .../unified/components/rules/RulesGroup.tsx | 11 +- .../unified/components/rules/RulesTable.tsx | 24 --- .../components/silences/SilenceDetails.tsx | 49 +++++ .../silences/SilencedAlertsTableRow.tsx | 10 +- .../components/silences/SilencesEditor.tsx | 5 +- .../components/silences/SilencesTable.tsx | 200 ++++++++++++------ .../unified/hooks/useFilteredRules.ts | 6 +- .../features/alerting/unified/utils/misc.ts | 4 +- public/app/types/unified-alerting.ts | 2 +- 24 files changed, 323 insertions(+), 133 deletions(-) create mode 100644 public/app/features/alerting/unified/components/silences/SilenceDetails.tsx diff --git a/packages/grafana-ui/src/types/icon.ts b/packages/grafana-ui/src/types/icon.ts index eb06b512fe9..86e1fe92804 100644 --- a/packages/grafana-ui/src/types/icon.ts +++ b/packages/grafana-ui/src/types/icon.ts @@ -7,6 +7,7 @@ export const getAvailableIcons = () => [ 'angle-double-down', 'angle-double-right', + 'angle-double-up', 'angle-down', 'angle-left', 'angle-right', diff --git a/public/app/features/alerting/unified/AmRoutes.tsx b/public/app/features/alerting/unified/AmRoutes.tsx index c47fbfc4341..b78e398769c 100644 --- a/public/app/features/alerting/unified/AmRoutes.tsx +++ b/public/app/features/alerting/unified/AmRoutes.tsx @@ -132,6 +132,5 @@ const getStyles = (theme: GrafanaTheme2) => ({ width: 100%; height: 0; margin-bottom: ${theme.spacing(2)}; - border-bottom: solid 1px ${theme.colors.border.medium}; `, }); diff --git a/public/app/features/alerting/unified/Receivers.test.tsx b/public/app/features/alerting/unified/Receivers.test.tsx index 103c8b96ec1..475fc31964c 100644 --- a/public/app/features/alerting/unified/Receivers.test.tsx +++ b/public/app/features/alerting/unified/Receivers.test.tsx @@ -18,7 +18,7 @@ import { import { DataSourceType, GRAFANA_RULES_SOURCE_NAME } from './utils/datasource'; import { fetchNotifiers } from './api/grafana'; import { grafanaNotifiersMock } from './mocks/grafana-notifiers'; -import { byLabelText, byRole, byTestId, byText } from 'testing-library-selector'; +import { byLabelText, byPlaceholderText, byRole, byTestId, byText } from 'testing-library-selector'; import userEvent from '@testing-library/user-event'; import { ALERTMANAGER_NAME_LOCAL_STORAGE_KEY, ALERTMANAGER_NAME_QUERY_KEY } from './utils/constants'; import store from 'app/core/store'; @@ -87,7 +87,7 @@ const ui = { channelFormContainer: byTestId('item-container'), inputs: { - name: byLabelText('Name'), + name: byPlaceholderText('Name'), email: { addresses: byLabelText(/Addresses/), toEmails: byLabelText(/To/), @@ -213,7 +213,7 @@ describe('Receivers', () => { expect(locationService.getLocation().pathname).toEqual('/alerting/notifications/receivers/new'); // type in a name for the new receiver - await userEvent.type(byLabelText('Name').get(), 'my new receiver'); + await userEvent.type(byPlaceholderText('Name').get(), 'my new receiver'); // check that default email form is rendered await ui.inputs.email.addresses.find(); diff --git a/public/app/features/alerting/unified/RuleList.tsx b/public/app/features/alerting/unified/RuleList.tsx index dae426394e6..cf42aecee17 100644 --- a/public/app/features/alerting/unified/RuleList.tsx +++ b/public/app/features/alerting/unified/RuleList.tsx @@ -1,6 +1,6 @@ import { GrafanaTheme2, urlUtil } from '@grafana/data'; -import { useStyles2, LinkButton, withErrorBoundary } from '@grafana/ui'; -import React, { useEffect, useMemo } from 'react'; +import { useStyles2, LinkButton, withErrorBoundary, Button } from '@grafana/ui'; +import React, { useEffect, useMemo, useState } from 'react'; import { useDispatch } from 'react-redux'; import { AlertingPageWrapper } from './components/AlertingPageWrapper'; import { NoRulesSplash } from './components/rules/NoRulesCTA'; @@ -19,6 +19,7 @@ import { useLocation } from 'react-router-dom'; import { contextSrv } from 'app/core/services/context_srv'; import { RuleStats } from './components/rules/RuleStats'; import { RuleListErrors } from './components/rules/RuleListErrors'; +import { getFiltersFromUrlParams } from './utils/misc'; const VIEWS = { groups: RuleListGroupView, @@ -31,8 +32,11 @@ export const RuleList = withErrorBoundary( const styles = useStyles2(getStyles); const rulesDataSourceNames = useMemo(getAllRulesSourceNames, []); const location = useLocation(); + const [expandAll, setExpandAll] = useState(false); const [queryParams] = useQueryParams(); + const filters = getFiltersFromUrlParams(queryParams); + const filtersActive = Object.values(filters).some((filter) => filter !== undefined); const view = VIEWS[queryParams['view'] as keyof typeof VIEWS] ? (queryParams['view'] as keyof typeof VIEWS) @@ -76,8 +80,19 @@ export const RuleList = withErrorBoundary(
- -
+
+ {view === 'groups' && filtersActive && ( + + )} + +
{(contextSrv.hasEditPermissionInFolders || contextSrv.isEditor) && ( )} {showNewAlertSplash && } - {haveResults && } + {haveResults && } ); }, @@ -109,4 +124,12 @@ const getStyles = (theme: GrafanaTheme2) => ({ display: flex; justify-content: space-between; `, + statsContainer: css` + display: flex; + flex-direction: row; + align-items: center; + `, + expandAllButton: css` + margin-right: ${theme.spacing(1)}; + `, }); diff --git a/public/app/features/alerting/unified/Silences.test.tsx b/public/app/features/alerting/unified/Silences.test.tsx index 4b8280c9c65..3e787e6881c 100644 --- a/public/app/features/alerting/unified/Silences.test.tsx +++ b/public/app/features/alerting/unified/Silences.test.tsx @@ -46,9 +46,9 @@ const dataSources = { }; const ui = { - silencesTable: byTestId('silences-table'), - silenceRow: byTestId('silence-table-row'), - silencedAlertCell: byTestId('silenced-alerts'), + silencesTable: byTestId('dynamic-table'), + silenceRow: byTestId('row'), + silencedAlertCell: byTestId('alerts'), queryBar: byPlaceholderText('Search'), editor: { timeRange: byLabelText('Timepicker', { exact: false }), @@ -58,7 +58,7 @@ const ui = { matcherName: byPlaceholderText('label'), matcherValue: byPlaceholderText('value'), comment: byPlaceholderText('Details about the silence'), - createdBy: byPlaceholderText('Username'), + createdBy: byPlaceholderText('User'), matcherOperatorSelect: byLabelText('operator'), matcherOperator: (operator: MatcherOperator) => byText(operator, { exact: true }), addMatcherButton: byRole('button', { name: 'Add matcher' }), diff --git a/public/app/features/alerting/unified/components/amroutes/AmRootRouteForm.tsx b/public/app/features/alerting/unified/components/amroutes/AmRootRouteForm.tsx index e394930b33f..cf9244068d5 100644 --- a/public/app/features/alerting/unified/components/amroutes/AmRootRouteForm.tsx +++ b/public/app/features/alerting/unified/components/amroutes/AmRootRouteForm.tsx @@ -54,7 +54,10 @@ export const AmRootRouteForm: FC = ({ rules={{ required: { value: true, message: 'Required.' } }} /> or - + Create a contact point
@@ -89,6 +92,7 @@ export const AmRootRouteForm: FC = ({ = ({
( - + )} control={control} name="groupWaitValue" @@ -139,7 +148,12 @@ export const AmRootRouteForm: FC = ({
( - + )} control={control} name="groupIntervalValue" @@ -174,7 +188,7 @@ export const AmRootRouteForm: FC = ({
( - + )} control={control} name="repeatIntervalValue" diff --git a/public/app/features/alerting/unified/components/amroutes/AmRoutesExpandedForm.tsx b/public/app/features/alerting/unified/components/amroutes/AmRoutesExpandedForm.tsx index 89480432529..0a51c5a1396 100644 --- a/public/app/features/alerting/unified/components/amroutes/AmRoutesExpandedForm.tsx +++ b/public/app/features/alerting/unified/components/amroutes/AmRoutesExpandedForm.tsx @@ -189,7 +189,7 @@ export const AmRoutesExpandedForm: FC = ({ onCancel,
( - + )} control={control} name="groupWaitValue" @@ -223,7 +223,7 @@ export const AmRoutesExpandedForm: FC = ({ onCancel,
( - + )} control={control} name="groupIntervalValue" @@ -257,7 +257,7 @@ export const AmRoutesExpandedForm: FC = ({ onCancel,
( - + )} control={control} name="repeatIntervalValue" diff --git a/public/app/features/alerting/unified/components/amroutes/formStyles.ts b/public/app/features/alerting/unified/components/amroutes/formStyles.ts index c12b3ecab54..60cde9d1fb9 100644 --- a/public/app/features/alerting/unified/components/amroutes/formStyles.ts +++ b/public/app/features/alerting/unified/components/amroutes/formStyles.ts @@ -21,5 +21,13 @@ export const getFormStyles = (theme: GrafanaTheme2) => { smallInput: css` width: ${theme.spacing(6.5)}; `, + linkText: css` + text-decoration: underline; + `, + collapse: css` + border: none; + background: none; + color: ${theme.colors.text.primary}; + `, }; }; diff --git a/public/app/features/alerting/unified/components/receivers/TemplateForm.tsx b/public/app/features/alerting/unified/components/receivers/TemplateForm.tsx index 2f39e901256..073759a560a 100644 --- a/public/app/features/alerting/unified/components/receivers/TemplateForm.tsx +++ b/public/app/features/alerting/unified/components/receivers/TemplateForm.tsx @@ -98,12 +98,13 @@ export const TemplateForm: FC = ({ existing, alertManagerSourceName, conf {error.message || (error as any)?.data?.message || String(error)} )} - + @@ -134,10 +135,12 @@ export const TemplateForm: FC = ({ existing, alertManagerSourceName, conf label="Content" error={errors?.content?.message} invalid={!!errors.content?.message} + required >