From 48d2dff987d4273770e6e83b3d7dc5d9adc1314c Mon Sep 17 00:00:00 2001 From: kay delaney <45561153+kaydelaney@users.noreply.github.com> Date: Thu, 11 Mar 2021 14:53:13 +0000 Subject: [PATCH] Migration/AlertList: Migrates AlertList from AngularJS to React (#31872) * Migration/AlertList: Migrates AlertList from AngularJS to React --- .../grafana-ui/src/components/Card/Card.tsx | 8 +- .../app/plugins/panel/alertlist/AlertList.tsx | 272 ++++++++++++++++++ .../alertlist/AlertListMigration.test.ts | 110 +++++++ .../alertlist/AlertListMigrationHandler.ts | 38 +++ .../app/plugins/panel/alertlist/editor.html | 64 ----- .../app/plugins/panel/alertlist/module.html | 50 ---- public/app/plugins/panel/alertlist/module.ts | 204 ------------- public/app/plugins/panel/alertlist/module.tsx | 142 +++++++++ public/app/plugins/panel/alertlist/types.ts | 31 ++ public/app/types/alerting.ts | 21 ++ 10 files changed, 621 insertions(+), 319 deletions(-) create mode 100644 public/app/plugins/panel/alertlist/AlertList.tsx create mode 100644 public/app/plugins/panel/alertlist/AlertListMigration.test.ts create mode 100644 public/app/plugins/panel/alertlist/AlertListMigrationHandler.ts delete mode 100644 public/app/plugins/panel/alertlist/editor.html delete mode 100644 public/app/plugins/panel/alertlist/module.html delete mode 100644 public/app/plugins/panel/alertlist/module.ts create mode 100644 public/app/plugins/panel/alertlist/module.tsx create mode 100644 public/app/plugins/panel/alertlist/types.ts diff --git a/packages/grafana-ui/src/components/Card/Card.tsx b/packages/grafana-ui/src/components/Card/Card.tsx index cdcee58d462..0dfe1fc6870 100644 --- a/packages/grafana-ui/src/components/Card/Card.tsx +++ b/packages/grafana-ui/src/components/Card/Card.tsx @@ -280,11 +280,17 @@ const Tags: FC = ({ children, styles }) => { }; Tags.displayName = 'Tags'; -const Figure: FC = ({ children, styles, align = 'top' }) => { +const Figure: FC = ({ + children, + styles, + align = 'top', + className, +}) => { return (
) { + const [noAlertsMessage, setNoAlertsMessage] = useState(''); + + const currentAlertState = useAsync(async () => { + if (props.options.showOptions !== ShowOption.Current) { + return; + } + + const params: any = { + state: getStateFilter(props.options.stateFilter), + }; + const panel = getDashboardSrv().getCurrent().getPanelById(props.id)!; + + if (props.options.alertName) { + params.query = getTemplateSrv().replace(props.options.alertName, panel.scopedVars); + } + + if (props.options.folderId >= 0) { + params.folderId = props.options.folderId; + } + + if (props.options.dashboardTitle) { + params.dashboardQuery = props.options.dashboardTitle; + } + + if (props.options.dashboardAlerts) { + params.dashboardId = getDashboardSrv().getCurrent().id; + } + + if (props.options.tags) { + params.dashboardTag = props.options.tags; + } + + const alerts: AlertRuleDTO[] = await getBackendSrv().get( + '/api/alerts', + params, + `alert-list-get-current-alert-state-${props.id}` + ); + let currentAlerts = sortAlerts( + props.options.sortOrder, + alerts.map((al) => ({ + ...al, + stateModel: alertDef.getStateDisplayModel(al.state), + newStateDateAgo: dateTime(al.newStateDate).locale('en').fromNow(true), + })) + ); + + if (currentAlerts.length > props.options.maxItems) { + currentAlerts = currentAlerts.slice(0, props.options.maxItems); + } + setNoAlertsMessage(currentAlerts.length === 0 ? 'No alerts' : ''); + + return currentAlerts; + }, [ + props.options.showOptions, + props.options.stateFilter.alerting, + props.options.stateFilter.execution_error, + props.options.stateFilter.no_data, + props.options.stateFilter.ok, + props.options.stateFilter.paused, + props.options.stateFilter.pending, + props.options.maxItems, + props.options.tags, + props.options.dashboardAlerts, + props.options.dashboardTitle, + props.options.folderId, + props.options.alertName, + props.options.sortOrder, + ]); + + const recentStateChanges = useAsync(async () => { + if (props.options.showOptions !== ShowOption.RecentChanges) { + return; + } + + const params: any = { + limit: props.options.maxItems, + type: 'alert', + newState: getStateFilter(props.options.stateFilter), + }; + const currentDashboard = getDashboardSrv().getCurrent(); + + if (props.options.dashboardAlerts) { + params.dashboardId = currentDashboard.id; + } + + params.from = dateMath.parse(currentDashboard.time.from)!.unix() * 1000; + params.to = dateMath.parse(currentDashboard.time.to)!.unix() * 1000; + + const data: AnnotationItemDTO[] = await getBackendSrv().get( + '/api/annotations', + params, + `alert-list-get-state-changes-${props.id}` + ); + const alertHistory = sortAlerts( + props.options.sortOrder, + data.map((al) => { + return { + ...al, + time: currentDashboard.formatDate(al.time, 'MMM D, YYYY HH:mm:ss'), + stateModel: alertDef.getStateDisplayModel(al.newState), + info: alertDef.getAlertAnnotationInfo(al), + }; + }) + ); + + setNoAlertsMessage(alertHistory.length === 0 ? 'No alerts in current time range' : ''); + return alertHistory; + }, [ + props.options.showOptions, + props.options.maxItems, + props.options.stateFilter.alerting, + props.options.stateFilter.execution_error, + props.options.stateFilter.no_data, + props.options.stateFilter.ok, + props.options.stateFilter.paused, + props.options.stateFilter.pending, + props.options.dashboardAlerts, + ]); + + const styles = useStyles(getStyles); + + return ( + +
+ {noAlertsMessage &&
{noAlertsMessage}
} +
+
    + {props.options.showOptions === ShowOption.Current + ? !currentAlertState.loading && + currentAlertState.value && + currentAlertState.value!.map((alert) => ( +
  1. + + + + + +
    + {alert.stateModel.text} + for {alert.newStateDateAgo} +
    +
    +
    +
  2. + )) + : !recentStateChanges.loading && + recentStateChanges.value && + recentStateChanges.value.map((alert) => ( +
  3. + + + + + + + {alert.stateModel.text} + + {alert.time} + {alert.info && {alert.info}} + + +
  4. + ))} +
+
+
+
+ ); +} + +function sortAlerts(sortOrder: SortOrder, alerts: any[]) { + if (sortOrder === SortOrder.Importance) { + // @ts-ignore + return sortBy(alerts, (a) => alertDef.alertStateSortScore[a.state || a.newState]); + } else if (sortOrder === SortOrder.TimeAsc) { + return sortBy(alerts, (a) => new Date(a.newStateDate || a.time)); + } else if (sortOrder === SortOrder.TimeDesc) { + return sortBy(alerts, (a) => new Date(a.newStateDate || a.time)).reverse(); + } + + const result = sortBy(alerts, (a) => (a.name || a.alertName).toLowerCase()); + if (sortOrder === SortOrder.AlphaDesc) { + result.reverse(); + } + + return result; +} + +function getStateFilter(stateFilter: Record) { + return Object.entries(stateFilter) + .filter(([_, val]) => val) + .map(([key, _]) => key); +} + +const getStyles = stylesFactory((theme: GrafanaTheme) => ({ + cardContainer: css` + padding: ${theme.spacing.xs} 0 ${theme.spacing.xxs} 0; + line-height: ${theme.typography.lineHeight.md}; + margin-bottom: 0px; + `, + container: css` + overflow-y: auto; + height: 100%; + `, + alertRuleList: css` + display: flex; + flex-wrap: wrap; + justify-content: space-between; + list-style-type: none; + `, + alertRuleItem: css` + display: flex; + align-items: center; + width: 100%; + height: 100%; + background: ${theme.colors.bg2}; + padding: ${theme.spacing.xs} ${theme.spacing.sm}; + border-radius: ${theme.border.radius.md}; + margin-bottom: ${theme.spacing.xs}; + `, + alertRuleItemIcon: css` + display: flex; + justify-content: center; + align-items: center; + width: ${theme.spacing.xl}; + padding: 0 ${theme.spacing.xs} 0 ${theme.spacing.xxs}; + margin-right: 0px; + `, + alertRuleItemText: css` + font-weight: ${theme.typography.weight.bold}; + font-size: ${theme.typography.size.sm}; + margin: 0; + `, + alertRuleItemTime: css` + color: ${theme.colors.textWeak}; + font-weight: normal; + white-space: nowrap; + `, + alertRuleItemInfo: css` + font-weight: normal; + flex-grow: 2; + display: flex; + align-items: flex-end; + `, + noAlertsMessage: css` + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + `, + alertIcon: css` + margin-right: ${theme.spacing.xs}; + `, +})); diff --git a/public/app/plugins/panel/alertlist/AlertListMigration.test.ts b/public/app/plugins/panel/alertlist/AlertListMigration.test.ts new file mode 100644 index 00000000000..45301afe55b --- /dev/null +++ b/public/app/plugins/panel/alertlist/AlertListMigration.test.ts @@ -0,0 +1,110 @@ +import { PanelModel } from '@grafana/data'; +import { alertListPanelMigrationHandler } from './AlertListMigrationHandler'; +import { AlertListOptions, ShowOption, SortOrder } from './types'; + +describe('AlertList Panel Migration', () => { + it('should migrate from < 7.5', () => { + const panel: Omit & Record = { + id: 7, + links: [], + pluginVersion: '7.4.0', + targets: [], + title: 'Usage', + type: 'alertlist', + nameFilter: 'Customer', + show: 'current', + sortOrder: 1, + stateFilter: ['ok', 'paused'], + dashboardTags: ['tag_a', 'tag_b'], + dashboardFilter: '', + limit: 10, + onlyAlertsOnDashboard: false, + options: {}, + }; + + const newOptions = alertListPanelMigrationHandler(panel as PanelModel); + expect(newOptions).toMatchObject({ + showOptions: ShowOption.Current, + maxItems: 10, + sortOrder: SortOrder.AlphaAsc, + dashboardAlerts: false, + alertName: 'Customer', + dashboardTitle: '', + tags: ['tag_a', 'tag_b'], + stateFilter: { + ok: true, + paused: true, + }, + folderId: undefined, + }); + + expect(panel).not.toHaveProperty('show'); + expect(panel).not.toHaveProperty('limit'); + expect(panel).not.toHaveProperty('sortOrder'); + expect(panel).not.toHaveProperty('onlyAlertsOnDashboard'); + expect(panel).not.toHaveProperty('nameFilter'); + expect(panel).not.toHaveProperty('dashboardFilter'); + expect(panel).not.toHaveProperty('folderId'); + expect(panel).not.toHaveProperty('dashboardTags'); + expect(panel).not.toHaveProperty('stateFilter'); + }); + + it('should handle >= 7.5', () => { + const panel: Omit, 'fieldConfig'> & Record = { + id: 7, + links: [], + pluginVersion: '7.5.0', + targets: [], + title: 'Usage', + type: 'alertlist', + options: { + showOptions: ShowOption.Current, + maxItems: 10, + sortOrder: SortOrder.AlphaAsc, + dashboardAlerts: false, + alertName: 'Customer', + dashboardTitle: '', + tags: ['tag_a', 'tag_b'], + stateFilter: { + ok: true, + paused: true, + no_data: false, + execution_error: false, + pending: false, + alerting: false, + }, + folderId: 1, + }, + }; + + const newOptions = alertListPanelMigrationHandler(panel as PanelModel); + expect(newOptions).toMatchObject({ + showOptions: 'current', + maxItems: 10, + sortOrder: SortOrder.AlphaAsc, + dashboardAlerts: false, + alertName: 'Customer', + dashboardTitle: '', + tags: ['tag_a', 'tag_b'], + stateFilter: { + ok: true, + paused: true, + no_data: false, + execution_error: false, + pending: false, + alerting: false, + }, + folderId: 1, + }); + + expect(panel).not.toHaveProperty('show'); + expect(panel).not.toHaveProperty('limit'); + expect(panel).not.toHaveProperty('sortOrder'); + expect(panel).not.toHaveProperty('onlyAlertsOnDashboard'); + expect(panel).not.toHaveProperty('nameFilter'); + expect(panel).not.toHaveProperty('dashboardFilter'); + expect(panel).not.toHaveProperty('folderId'); + expect(panel).not.toHaveProperty('dashboardTags'); + expect(panel).not.toHaveProperty('stateFilter'); + }); +}); diff --git a/public/app/plugins/panel/alertlist/AlertListMigrationHandler.ts b/public/app/plugins/panel/alertlist/AlertListMigrationHandler.ts new file mode 100644 index 00000000000..2dd52edb08f --- /dev/null +++ b/public/app/plugins/panel/alertlist/AlertListMigrationHandler.ts @@ -0,0 +1,38 @@ +import { PanelModel } from '@grafana/data'; +import { AlertListOptions } from './types'; + +export const alertListPanelMigrationHandler = ( + panel: PanelModel & Record +): Partial => { + const newOptions: AlertListOptions = { + showOptions: panel.options.showOptions ?? panel.show, + maxItems: panel.options.maxItems ?? panel.limit, + sortOrder: panel.options.sortOrder ?? panel.sortOrder, + dashboardAlerts: panel.options.dashboardAlerts ?? panel.onlyAlertsOnDashboard, + alertName: panel.options.alertName ?? panel.nameFilter, + dashboardTitle: panel.options.dashboardTitle ?? panel.dashboardFilter, + folderId: panel.options.folderId ?? panel.folderId, + tags: panel.options.tags ?? panel.dashboardTags, + stateFilter: + panel.options.stateFilter ?? + panel.stateFilter.reduce((filterObj: any, curFilter: any) => ({ ...filterObj, [curFilter]: true }), {}), + }; + + const previousVersion = parseFloat(panel.pluginVersion || '7.4'); + if (previousVersion < 7.5) { + const oldProps = [ + 'show', + 'limit', + 'sortOrder', + 'onlyAlertsOnDashboard', + 'nameFilter', + 'dashboardFilter', + 'folderId', + 'dashboardTags', + 'stateFilter', + ]; + oldProps.forEach((prop) => delete panel[prop]); + } + + return newOptions; +}; diff --git a/public/app/plugins/panel/alertlist/editor.html b/public/app/plugins/panel/alertlist/editor.html deleted file mode 100644 index e7e545086cc..00000000000 --- a/public/app/plugins/panel/alertlist/editor.html +++ /dev/null @@ -1,64 +0,0 @@ -
-
-
Options
-
- Show -
- -
-
-
- Max items - -
-
- Sort order -
- -
-
- -
-
-
Filter
-
- Alert name - -
-
- Dashboard title - -
-
- - -
-
- Dashboard tags - - -
-
-
-
State filter
- - - - - - -
-
diff --git a/public/app/plugins/panel/alertlist/module.html b/public/app/plugins/panel/alertlist/module.html deleted file mode 100644 index adf5e32b765..00000000000 --- a/public/app/plugins/panel/alertlist/module.html +++ /dev/null @@ -1,50 +0,0 @@ -
-
- {{ctrl.noAlertsMessage}} -
- -
-
    -
  1. -
    - -
    -
    -
    -

    - - {{alert.name}} - -

    -
    - {{alert.stateModel.text}} - for {{alert.newStateDateAgo}} -
    -
    -
    -
  2. -
-
- -
-
    -
  1. -
    - -
    -
    -
    -

    {{al.alertName}}

    -
    - {{al.stateModel.text}} -
    -
    - {{al.info}} -
    -
    - {{al.time}} -
    -
  2. -
-
-
diff --git a/public/app/plugins/panel/alertlist/module.ts b/public/app/plugins/panel/alertlist/module.ts deleted file mode 100644 index c1101692062..00000000000 --- a/public/app/plugins/panel/alertlist/module.ts +++ /dev/null @@ -1,204 +0,0 @@ -import _ from 'lodash'; -import { getBackendSrv } from '@grafana/runtime'; -import { dateMath, dateTime, PanelEvents } from '@grafana/data'; -import { auto, IScope } from 'angular'; - -import alertDef from '../../../features/alerting/state/alertDef'; -import { PanelCtrl } from 'app/plugins/sdk'; -import { promiseToDigest } from 'app/core/utils/promiseToDigest'; - -class AlertListPanel extends PanelCtrl { - static templateUrl = 'module.html'; - static scrollable = true; - - showOptions = [ - { text: 'Current state', value: 'current' }, - { text: 'Recent state changes', value: 'changes' }, - ]; - - sortOrderOptions = [ - { text: 'Alphabetical (asc)', value: 1 }, - { text: 'Alphabetical (desc)', value: 2 }, - { text: 'Importance', value: 3 }, - { text: 'Time (asc)', value: 4 }, - { text: 'Time (desc)', value: 5 }, - ]; - - stateFilter: any = {}; - currentAlerts: any = []; - alertHistory: any = []; - noAlertsMessage: string; - templateSrv: string; - - // Set and populate defaults - panelDefaults: any = { - show: 'current', - limit: 10, - stateFilter: [], - onlyAlertsOnDashboard: false, - sortOrder: 1, - dashboardFilter: '', - nameFilter: '', - folderId: null, - }; - - /** @ngInject */ - constructor($scope: IScope, $injector: auto.IInjectorService) { - super($scope, $injector); - _.defaults(this.panel, this.panelDefaults); - - this.events.on(PanelEvents.editModeInitialized, this.onInitEditMode.bind(this)); - this.events.on(PanelEvents.refresh, this.onRefresh.bind(this)); - this.templateSrv = this.$injector.get('templateSrv'); - - for (const key in this.panel.stateFilter) { - this.stateFilter[this.panel.stateFilter[key]] = true; - } - } - - sortResult(alerts: any[]) { - if (this.panel.sortOrder === 3) { - return _.sortBy(alerts, (a) => { - // @ts-ignore - return alertDef.alertStateSortScore[a.state || a.newState]; - }); - } else if (this.panel.sortOrder === 4) { - return _.sortBy(alerts, (a) => { - return new Date(a.newStateDate || a.time); - }); - } else if (this.panel.sortOrder === 5) { - return _.sortBy(alerts, (a) => { - return new Date(a.newStateDate || a.time); - }).reverse(); - } - - const result = _.sortBy(alerts, (a) => { - return (a.name || a.alertName).toLowerCase(); - }); - if (this.panel.sortOrder === 2) { - result.reverse(); - } - - return result; - } - - updateStateFilter() { - const result = []; - - for (const key in this.stateFilter) { - if (this.stateFilter[key]) { - result.push(key); - } - } - - this.panel.stateFilter = result; - this.onRefresh(); - } - - onRefresh() { - let getAlertsPromise; - - if (this.panel.show === 'current') { - getAlertsPromise = this.getCurrentAlertState(); - } else if (this.panel.show === 'changes') { - getAlertsPromise = this.getStateChanges(); - } else { - getAlertsPromise = Promise.resolve(); - } - - getAlertsPromise.then(() => { - this.renderingCompleted(); - }); - } - - onFolderChange = (folder: any) => { - this.panel.folderId = folder.id; - this.refresh(); - }; - - getStateChanges() { - const params: any = { - limit: this.panel.limit, - type: 'alert', - newState: this.panel.stateFilter, - }; - - if (this.panel.onlyAlertsOnDashboard) { - params.dashboardId = this.dashboard.id; - } - - params.from = dateMath.parse(this.dashboard.time.from)!.unix() * 1000; - params.to = dateMath.parse(this.dashboard.time.to)!.unix() * 1000; - - return promiseToDigest(this.$scope)( - getBackendSrv() - .get('/api/annotations', params, `alert-list-get-state-changes-${this.panel.id}`) - .then((data) => { - this.alertHistory = this.sortResult( - _.map(data, (al) => { - al.time = this.dashboard.formatDate(al.time, 'MMM D, YYYY HH:mm:ss'); - al.stateModel = alertDef.getStateDisplayModel(al.newState); - al.info = alertDef.getAlertAnnotationInfo(al); - return al; - }) - ); - - this.noAlertsMessage = this.alertHistory.length === 0 ? 'No alerts in current time range' : ''; - - return this.alertHistory; - }) - ); - } - - getCurrentAlertState() { - const params: any = { - state: this.panel.stateFilter, - }; - - if (this.panel.nameFilter) { - params.query = this.templateSrv.replace(this.panel.nameFilter, this.panel.scopedVars); - } - - if (this.panel.folderId >= 0) { - params.folderId = this.panel.folderId; - } - - if (this.panel.dashboardFilter) { - params.dashboardQuery = this.panel.dashboardFilter; - } - - if (this.panel.onlyAlertsOnDashboard) { - params.dashboardId = this.dashboard.id; - } - - if (this.panel.dashboardTags) { - params.dashboardTag = this.panel.dashboardTags; - } - - return promiseToDigest(this.$scope)( - getBackendSrv() - .get('/api/alerts', params, `alert-list-get-current-alert-state-${this.panel.id}`) - .then((data) => { - this.currentAlerts = this.sortResult( - _.map(data, (al) => { - al.stateModel = alertDef.getStateDisplayModel(al.state); - al.newStateDateAgo = dateTime(al.newStateDate).locale('en').fromNow(true); - return al; - }) - ); - if (this.currentAlerts.length > this.panel.limit) { - this.currentAlerts = this.currentAlerts.slice(0, this.panel.limit); - } - this.noAlertsMessage = this.currentAlerts.length === 0 ? 'No alerts' : ''; - - return this.currentAlerts; - }) - ); - } - - onInitEditMode() { - this.addEditorTab('Options', 'public/app/plugins/panel/alertlist/editor.html'); - } -} - -export { AlertListPanel, AlertListPanel as PanelCtrl }; diff --git a/public/app/plugins/panel/alertlist/module.tsx b/public/app/plugins/panel/alertlist/module.tsx new file mode 100644 index 00000000000..87711fd11f4 --- /dev/null +++ b/public/app/plugins/panel/alertlist/module.tsx @@ -0,0 +1,142 @@ +import React from 'react'; +import { PanelPlugin } from '@grafana/data'; +import { TagsInput } from '@grafana/ui'; +import { AlertList } from './AlertList'; +import { FolderPicker } from 'app/core/components/Select/FolderPicker'; +import { AlertListOptions, ShowOption, SortOrder } from './types'; +import { alertListPanelMigrationHandler } from './AlertListMigrationHandler'; + +function showIfCurrentState(options: AlertListOptions) { + return options.showOptions === ShowOption.Current; +} + +export const plugin = new PanelPlugin(AlertList) + .setPanelOptions((builder) => { + builder + .addSelect({ + name: 'Show', + path: 'showOptions', + settings: { + options: [ + { label: 'Current state', value: ShowOption.Current }, + { label: 'Recent state changes', value: ShowOption.RecentChanges }, + ], + }, + defaultValue: ShowOption.Current, + category: ['Options'], + }) + .addNumberInput({ + name: 'Max items', + path: 'maxItems', + defaultValue: 10, + category: ['Options'], + }) + .addSelect({ + name: 'Sort order', + path: 'sortOrder', + settings: { + options: [ + { label: 'Alphabetical (asc)', value: SortOrder.AlphaAsc }, + { label: 'Alphabetical (desc)', value: SortOrder.AlphaDesc }, + { label: 'Importance', value: SortOrder.Importance }, + { label: 'Time (asc)', value: SortOrder.TimeAsc }, + { label: 'Time (desc)', value: SortOrder.TimeDesc }, + ], + }, + defaultValue: SortOrder.AlphaAsc, + category: ['Options'], + }) + .addBooleanSwitch({ + path: 'dashboardAlerts', + name: 'Alerts from this dashboard', + defaultValue: false, + category: ['Options'], + }) + .addTextInput({ + path: 'alertName', + name: 'Alert name', + defaultValue: '', + category: ['Filter'], + showIf: showIfCurrentState, + }) + .addTextInput({ + path: 'dashboardTitle', + name: 'Dashboard title', + defaultValue: '', + category: ['Filter'], + showIf: showIfCurrentState, + }) + .addCustomEditor({ + path: 'folderId', + name: 'Folder', + id: 'folderId', + defaultValue: null, + editor: function RenderFolderPicker(props) { + return ( + props.onChange(id)} + /> + ); + }, + category: ['Filter'], + showIf: showIfCurrentState, + }) + .addCustomEditor({ + id: 'tags', + path: 'tags', + name: 'Tags', + description: '', + defaultValue: [], + editor(props) { + return ; + }, + category: ['Filter'], + showIf: showIfCurrentState, + }) + .addBooleanSwitch({ + path: 'stateFilter.ok', + name: 'Ok', + defaultValue: false, + category: ['State filter'], + showIf: showIfCurrentState, + }) + .addBooleanSwitch({ + path: 'stateFilter.paused', + name: 'Paused', + defaultValue: false, + category: ['State filter'], + showIf: showIfCurrentState, + }) + .addBooleanSwitch({ + path: 'stateFilter.no_data', + name: 'No data', + defaultValue: false, + category: ['State filter'], + showIf: showIfCurrentState, + }) + .addBooleanSwitch({ + path: 'stateFilter.execution_error', + name: 'Execution error', + defaultValue: false, + category: ['State filter'], + showIf: showIfCurrentState, + }) + .addBooleanSwitch({ + path: 'stateFilter.alerting', + name: 'Alerting', + defaultValue: false, + category: ['State filter'], + showIf: showIfCurrentState, + }) + .addBooleanSwitch({ + path: 'stateFilter.pending', + name: 'Pending', + defaultValue: false, + category: ['State filter'], + showIf: showIfCurrentState, + }); + }) + .setMigrationHandler(alertListPanelMigrationHandler); diff --git a/public/app/plugins/panel/alertlist/types.ts b/public/app/plugins/panel/alertlist/types.ts new file mode 100644 index 00000000000..cb074b49563 --- /dev/null +++ b/public/app/plugins/panel/alertlist/types.ts @@ -0,0 +1,31 @@ +export enum SortOrder { + AlphaAsc = 1, + AlphaDesc, + Importance, + TimeAsc, + TimeDesc, +} + +export enum ShowOption { + Current = 'current', + RecentChanges = 'changes', +} + +export interface AlertListOptions { + showOptions: ShowOption; + maxItems: number; + sortOrder: SortOrder; + dashboardAlerts: boolean; + alertName: string; + dashboardTitle: string; + tags: string[]; + stateFilter: { + ok: boolean; + paused: boolean; + no_data: boolean; + execution_error: boolean; + alerting: boolean; + pending: boolean; + }; + folderId: number; +} diff --git a/public/app/types/alerting.ts b/public/app/types/alerting.ts index f34490f2f2f..96aaf7daa07 100644 --- a/public/app/types/alerting.ts +++ b/public/app/types/alerting.ts @@ -174,3 +174,24 @@ export interface AlertDefinitionUiState { rightPaneSize: number; topPaneSize: number; } + +export interface AnnotationItemDTO { + id: number; + alertId: number; + alertName: string; + dashboardId: number; + panelId: number; + userId: number; + newState: string; + prevState: string; + created: number; + updated: number; + time: number; + timeEnd: number; + text: string; + tags: string[]; + login: string; + email: string; + avatarUrl: string; + data: any; +}