Merge remote-tracking branch 'origin/main' into grafana-git-ui-sync
This commit is contained in:
54 files changed
+877
-216
No files matched your search
@@ -21,6 +21,8 @@ interface Props {
|
||||
onError?: (error: Error) => void;
|
||||
/** Callback error state is cleared due to recover props change */
|
||||
onRecover?: () => void;
|
||||
/** Default error logger - Faro by default */
|
||||
errorLogger?: (error: Error) => void;
|
||||
}
|
||||
|
||||
interface State {
|
||||
@@ -35,7 +37,12 @@ export class ErrorBoundary extends PureComponent<Props, State> {
|
||||
};
|
||||
|
||||
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
||||
faro?.api?.pushError(error);
|
||||
const logger = this.props.errorLogger ?? faro?.api?.pushError;
|
||||
|
||||
if (logger) {
|
||||
logger(error);
|
||||
}
|
||||
|
||||
this.setState({ error, errorInfo });
|
||||
|
||||
if (this.props.onError) {
|
||||
@@ -89,6 +96,8 @@ export interface ErrorBoundaryAlertProps {
|
||||
|
||||
/** Will re-render children after error if recover values changes */
|
||||
dependencies?: unknown[];
|
||||
/** Default error logger - Faro by default */
|
||||
errorLogger?: (error: Error) => void;
|
||||
}
|
||||
|
||||
export class ErrorBoundaryAlert extends PureComponent<ErrorBoundaryAlertProps> {
|
||||
@@ -98,10 +107,10 @@ export class ErrorBoundaryAlert extends PureComponent<ErrorBoundaryAlertProps> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { title, children, style, dependencies } = this.props;
|
||||
const { title, children, style, dependencies, errorLogger } = this.props;
|
||||
|
||||
return (
|
||||
<ErrorBoundary dependencies={dependencies}>
|
||||
<ErrorBoundary dependencies={dependencies} errorLogger={errorLogger}>
|
||||
{({ error, errorInfo }) => {
|
||||
if (!errorInfo) {
|
||||
return children;
|
||||
|
||||
@@ -6,7 +6,7 @@ type SchemaVersionMigrationFunc func(map[string]interface{}) error
|
||||
|
||||
const (
|
||||
MINIUM_VERSION = 36
|
||||
LATEST_VERSION = 40
|
||||
LATEST_VERSION = 41
|
||||
)
|
||||
|
||||
var Migrations = map[int]SchemaVersionMigrationFunc{
|
||||
@@ -14,6 +14,7 @@ var Migrations = map[int]SchemaVersionMigrationFunc{
|
||||
38: V38,
|
||||
39: V39,
|
||||
40: V40,
|
||||
41: V41,
|
||||
}
|
||||
|
||||
func GetSchemaVersion(dash map[string]interface{}) int {
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package schemaversion
|
||||
|
||||
func V41(dash map[string]interface{}) error {
|
||||
dash["schemaVersion"] = int(41)
|
||||
if timepicker, ok := dash["timepicker"].(map[string]interface{}); ok {
|
||||
// time_options is a legacy property that was not used since grafana version 5
|
||||
// therefore deprecating this property from the schema
|
||||
delete(timepicker, "time_options")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package schemaversion_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/apis/dashboard/migration/schemaversion"
|
||||
)
|
||||
|
||||
func TestV41(t *testing.T) {
|
||||
tests := []migrationTestCase{
|
||||
{
|
||||
name: "time_options is removed",
|
||||
input: map[string]interface{}{
|
||||
"title": "Test Dashboard",
|
||||
"timepicker": map[string]interface{}{
|
||||
"time_options": []string{"1m", "5m", "15m", "1h", "6h", "12h", "24h"},
|
||||
},
|
||||
},
|
||||
expected: map[string]interface{}{
|
||||
"title": "Test Dashboard",
|
||||
"schemaVersion": 41,
|
||||
"timepicker": map[string]interface{}{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "timepicker is not set",
|
||||
input: map[string]interface{}{
|
||||
"title": "Test Dashboard",
|
||||
},
|
||||
expected: map[string]interface{}{
|
||||
"title": "Test Dashboard",
|
||||
"schemaVersion": 41,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
runMigrationTests(t, tests, schemaversion.V41)
|
||||
}
|
||||
@@ -115,7 +115,9 @@
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timepicker": {
|
||||
"time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
|
||||
},
|
||||
"timezone": "utc",
|
||||
"title": "New dashboard",
|
||||
"version": 0,
|
||||
|
||||
+3
-1
@@ -352,7 +352,9 @@
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timepicker": {
|
||||
"time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
|
||||
},
|
||||
"timezone": "utc",
|
||||
"title": "New dashboard",
|
||||
"version": 0,
|
||||
|
||||
+3
-1
@@ -145,7 +145,9 @@
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timepicker": {
|
||||
"time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
|
||||
},
|
||||
"timezone": "utc",
|
||||
"title": "New dashboard",
|
||||
"version": 0,
|
||||
|
||||
@@ -124,7 +124,9 @@
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timepicker": {
|
||||
"time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
|
||||
},
|
||||
"timezone": "utc",
|
||||
"title": "New dashboard",
|
||||
"version": 0,
|
||||
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "grafana"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"barWidthFactor": 0.6,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 0,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"insertNulls": false,
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "auto",
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 1,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": {
|
||||
"hideZeros": false,
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "11.5.0-81438",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "grafana"
|
||||
},
|
||||
"queryType": "randomWalk",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Panel Title",
|
||||
"type": "timeseries"
|
||||
}
|
||||
],
|
||||
"preload": false,
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
|
||||
},
|
||||
"timezone": "utc",
|
||||
"title": "New dashboard",
|
||||
"version": 0,
|
||||
"weekStart": "",
|
||||
"refresh": "",
|
||||
"schemaVersion": 40
|
||||
}
|
||||
+13
-1
@@ -124,7 +124,19 @@
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timepicker": {
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"timezone": "utc",
|
||||
"title": "New dashboard",
|
||||
"version": 0,
|
||||
|
||||
+13
-1
@@ -124,7 +124,19 @@
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timepicker": {
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"timezone": "utc",
|
||||
"title": "New dashboard",
|
||||
"version": 0,
|
||||
|
||||
+13
-1
@@ -124,7 +124,19 @@
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timepicker": {
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"timezone": "utc",
|
||||
"title": "New dashboard",
|
||||
"version": 0,
|
||||
|
||||
+13
-1
@@ -124,7 +124,19 @@
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timepicker": {
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"timezone": "utc",
|
||||
"title": "New dashboard",
|
||||
"version": 0,
|
||||
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations \u0026 Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 1,
|
||||
"options": {},
|
||||
"title": "No Legend Config",
|
||||
"type": "graph"
|
||||
},
|
||||
{
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"options": {
|
||||
"legend": {
|
||||
"displayMode": "list",
|
||||
"showLegend": true
|
||||
}
|
||||
},
|
||||
"title": "Boolean Legend True"
|
||||
},
|
||||
{
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 8
|
||||
},
|
||||
"id": 3,
|
||||
"options": {
|
||||
"legend": {
|
||||
"displayMode": "list",
|
||||
"showLegend": false
|
||||
}
|
||||
},
|
||||
"title": "Boolean Legend False"
|
||||
},
|
||||
{
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 8
|
||||
},
|
||||
"id": 4,
|
||||
"options": {
|
||||
"legend": {
|
||||
"displayMode": "list",
|
||||
"showLegend": false
|
||||
}
|
||||
},
|
||||
"title": "Hidden DisplayMode"
|
||||
},
|
||||
{
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 16
|
||||
},
|
||||
"id": 5,
|
||||
"options": {
|
||||
"legend": {
|
||||
"displayMode": "list",
|
||||
"showLegend": false
|
||||
}
|
||||
},
|
||||
"title": "ShowLegend False"
|
||||
},
|
||||
{
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 16
|
||||
},
|
||||
"id": 6,
|
||||
"options": {
|
||||
"legend": {
|
||||
"displayMode": "table",
|
||||
"showLegend": true
|
||||
}
|
||||
},
|
||||
"title": "Visible Legend"
|
||||
}
|
||||
],
|
||||
"preload": false,
|
||||
"refresh": "",
|
||||
"schemaVersion": 41,
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "utc",
|
||||
"title": "New dashboard",
|
||||
"version": 0,
|
||||
"weekStart": ""
|
||||
}
|
||||
+13
-1
@@ -367,7 +367,19 @@
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timepicker": {
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"timezone": "utc",
|
||||
"title": "New dashboard",
|
||||
"version": 0,
|
||||
|
||||
+13
-1
@@ -367,7 +367,19 @@
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timepicker": {
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"timezone": "utc",
|
||||
"title": "New dashboard",
|
||||
"version": 0,
|
||||
|
||||
+13
-1
@@ -367,7 +367,19 @@
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timepicker": {
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"timezone": "utc",
|
||||
"title": "New dashboard",
|
||||
"version": 0,
|
||||
|
||||
+25
-8
@@ -31,7 +31,10 @@
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"displayMode": "basic"
|
||||
"cellOptions": {
|
||||
"mode": "basic",
|
||||
"type": "gauge"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
@@ -84,7 +87,10 @@
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"displayMode": "gradient-gauge"
|
||||
"cellOptions": {
|
||||
"mode": "gradient",
|
||||
"type": "gauge"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
@@ -137,7 +143,10 @@
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"displayMode": "lcd-gauge"
|
||||
"cellOptions": {
|
||||
"mode": "lcd",
|
||||
"type": "gauge"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
@@ -190,7 +199,10 @@
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"displayMode": "color-background"
|
||||
"cellOptions": {
|
||||
"mode": "gradient",
|
||||
"type": "color-background"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
@@ -243,7 +255,10 @@
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"displayMode": "color-background-solid"
|
||||
"cellOptions": {
|
||||
"mode": "basic",
|
||||
"type": "color-background"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
@@ -296,7 +311,9 @@
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"displayMode": "some-other-mode"
|
||||
"cellOptions": {
|
||||
"type": "some-other-mode"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
@@ -340,8 +357,8 @@
|
||||
}
|
||||
],
|
||||
"preload": false,
|
||||
"refresh": true,
|
||||
"schemaVersion": 37,
|
||||
"refresh": "",
|
||||
"schemaVersion": 41,
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": []
|
||||
+13
-1
@@ -147,7 +147,19 @@
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timepicker": {
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"timezone": "utc",
|
||||
"title": "New dashboard",
|
||||
"version": 0,
|
||||
|
||||
+13
-1
@@ -147,7 +147,19 @@
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timepicker": {
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"timezone": "utc",
|
||||
"title": "New dashboard",
|
||||
"version": 0,
|
||||
|
||||
+7
-5
@@ -124,9 +124,11 @@
|
||||
{
|
||||
"id": "timeSeriesTable",
|
||||
"options": {
|
||||
"refIdToStat": {
|
||||
"A": "mean",
|
||||
"B": "max"
|
||||
"A": {
|
||||
"stat": "mean"
|
||||
},
|
||||
"B": {
|
||||
"stat": "max"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,8 +137,8 @@
|
||||
}
|
||||
],
|
||||
"preload": false,
|
||||
"refresh": true,
|
||||
"schemaVersion": 38,
|
||||
"refresh": "",
|
||||
"schemaVersion": 41,
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": []
|
||||
@@ -126,7 +126,19 @@
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timepicker": {
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"timezone": "utc",
|
||||
"title": "New dashboard",
|
||||
"version": 0,
|
||||
|
||||
+2
-2
@@ -116,8 +116,8 @@
|
||||
}
|
||||
],
|
||||
"preload": false,
|
||||
"refresh": true,
|
||||
"schemaVersion": 39,
|
||||
"refresh": "",
|
||||
"schemaVersion": 41,
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": []
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations \u0026 Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "grafana"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"barWidthFactor": 0.6,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 0,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"insertNulls": false,
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "auto",
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 1,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": {
|
||||
"hideZeros": false,
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "11.5.0-81438",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "grafana"
|
||||
},
|
||||
"queryType": "randomWalk",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Panel Title",
|
||||
"type": "timeseries"
|
||||
}
|
||||
],
|
||||
"preload": false,
|
||||
"refresh": "",
|
||||
"schemaVersion": 41,
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "utc",
|
||||
"title": "New dashboard",
|
||||
"version": 0,
|
||||
"weekStart": ""
|
||||
}
|
||||
@@ -37,11 +37,12 @@ func WrapHandler(handler http.Handler) func(req *http.Request) (*http.Response,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cancel()
|
||||
// The cancel happens in the goroutine we spawn, so as to not cancel it too early.
|
||||
req = req.WithContext(ctx) // returns a shallow copy, so we can't do it as part of the adapter.
|
||||
|
||||
w := NewAdapter(req)
|
||||
go func() {
|
||||
defer cancel()
|
||||
handler.ServeHTTP(w, req)
|
||||
if err := w.CloseWriter(); err != nil {
|
||||
klog.Errorf("error closing writer: %v", err)
|
||||
|
||||
@@ -250,14 +250,17 @@ func (l *LibraryElementService) deleteLibraryElement(c context.Context, signedIn
|
||||
return err
|
||||
}
|
||||
|
||||
// then find the dashboards that were supposed to be connected to this element
|
||||
_, requester := identity.WithServiceIdentity(c, signedInUser.GetOrgID())
|
||||
dashs, err := l.dashboardsService.FindDashboards(c, &dashboards.FindPersistedDashboardsQuery{
|
||||
// then find the dashboards that were supposed to be connected to this element.
|
||||
// A identity may be able to delete a library element but not read all dashboards so we fetch then as the
|
||||
// service user so we can prevent deletion of those connections
|
||||
serviceCtx, serviceIdent := identity.WithServiceIdentity(c, signedInUser.GetOrgID())
|
||||
dashs, err := l.dashboardsService.FindDashboards(serviceCtx, &dashboards.FindPersistedDashboardsQuery{
|
||||
Type: searchstore.TypeDashboard,
|
||||
OrgId: signedInUser.GetOrgID(),
|
||||
OrgId: serviceIdent.GetOrgID(),
|
||||
DashboardIds: dashboardIDs,
|
||||
SignedInUser: requester, // a user may be able to delete a library element but not read all dashboards. We still need to run this check, so we don't allow deleting elements if dashboards are connected
|
||||
SignedInUser: serviceIdent,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import { NOTIFICATIONS_POLL_INTERVAL_MS } from './utils/constants';
|
||||
import { GRAFANA_RULES_SOURCE_NAME } from './utils/datasource';
|
||||
import { getFiltersFromUrlParams } from './utils/misc';
|
||||
import { initialAsyncRequestState } from './utils/redux';
|
||||
import { withPageErrorBoundary } from './withPageErrorBoundary';
|
||||
|
||||
const AlertGroups = () => {
|
||||
const { selectedAlertmanager } = useAlertmanager();
|
||||
@@ -89,10 +90,12 @@ const AlertGroups = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const AlertGroupsPage = () => (
|
||||
<AlertmanagerPageWrapper navId="groups" accessType="instance">
|
||||
<AlertGroups />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
function AlertGroupsPage() {
|
||||
return (
|
||||
<AlertmanagerPageWrapper navId="groups" accessType="instance">
|
||||
<AlertGroups />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default AlertGroupsPage;
|
||||
export default withPageErrorBoundary(AlertGroupsPage);
|
||||
@@ -1,7 +1,9 @@
|
||||
import { NavModel } from '@grafana/data';
|
||||
import { Page } from 'app/core/components/Page/Page';
|
||||
|
||||
export default function FeatureTogglePage() {
|
||||
import { withPageErrorBoundary } from './withPageErrorBoundary';
|
||||
|
||||
function FeatureTogglePage() {
|
||||
const navModel: NavModel = {
|
||||
node: {
|
||||
text: 'Alerting is not enabled',
|
||||
@@ -25,3 +27,5 @@ enabled = true
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
export default withPageErrorBoundary(FeatureTogglePage);
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useLocation } from 'react-router-dom-v5-compat';
|
||||
|
||||
import { withErrorBoundary } from '@grafana/ui';
|
||||
import {
|
||||
defaultsFromQuery,
|
||||
getDefaultSilenceFormValues,
|
||||
@@ -12,6 +11,7 @@ import { AlertmanagerPageWrapper } from './components/AlertingPageWrapper';
|
||||
import { GrafanaAlertmanagerDeliveryWarning } from './components/GrafanaAlertmanagerDeliveryWarning';
|
||||
import { SilencesEditor } from './components/silences/SilencesEditor';
|
||||
import { useAlertmanager } from './state/AlertmanagerContext';
|
||||
import { withPageErrorBoundary } from './withPageErrorBoundary';
|
||||
|
||||
const SilencesEditorComponent = () => {
|
||||
const location = useLocation();
|
||||
@@ -48,4 +48,5 @@ function NewSilencePage() {
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
export default withErrorBoundary(NewSilencePage, { style: 'page' });
|
||||
|
||||
export default withPageErrorBoundary(NewSilencePage);
|
||||
@@ -2,7 +2,7 @@ import { css } from '@emotion/css';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { GrafanaTheme2, UrlQueryMap } from '@grafana/data';
|
||||
import { Tab, TabContent, TabsBar, useStyles2, withErrorBoundary } from '@grafana/ui';
|
||||
import { Tab, TabContent, TabsBar, useStyles2 } from '@grafana/ui';
|
||||
import { useQueryParams } from 'app/core/hooks/useQueryParams';
|
||||
import { useMuteTimings } from 'app/features/alerting/unified/components/mute-timings/useMuteTimings';
|
||||
import { NotificationPoliciesList } from 'app/features/alerting/unified/components/notification-policies/NotificationPoliciesList';
|
||||
@@ -12,6 +12,7 @@ import { AlertmanagerPageWrapper } from './components/AlertingPageWrapper';
|
||||
import { GrafanaAlertmanagerDeliveryWarning } from './components/GrafanaAlertmanagerDeliveryWarning';
|
||||
import { MuteTimingsTable } from './components/mute-timings/MuteTimingsTable';
|
||||
import { useAlertmanager } from './state/AlertmanagerContext';
|
||||
import { withPageErrorBoundary } from './withPageErrorBoundary';
|
||||
|
||||
enum ActiveTab {
|
||||
NotificationPolicies = 'notification_policies',
|
||||
@@ -104,10 +105,12 @@ function getActiveTabFromUrl(queryParams: UrlQueryMap, defaultTab: ActiveTab): Q
|
||||
};
|
||||
}
|
||||
|
||||
const NotificationPoliciesPage = () => (
|
||||
<AlertmanagerPageWrapper navId="am-routes" accessType="notification">
|
||||
<NotificationPoliciesTabs />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
function NotificationPoliciesPage() {
|
||||
return (
|
||||
<AlertmanagerPageWrapper navId="am-routes" accessType="notification">
|
||||
<NotificationPoliciesTabs />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withErrorBoundary(NotificationPoliciesPage, { style: 'page' });
|
||||
export default withPageErrorBoundary(NotificationPoliciesPage);
|
||||
@@ -5,7 +5,7 @@ import { useLocation } from 'react-use';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { config, isFetchError } from '@grafana/runtime';
|
||||
import { Alert, Card, Icon, LoadingPlaceholder, useStyles2, withErrorBoundary } from '@grafana/ui';
|
||||
import { Alert, Card, Icon, LoadingPlaceholder, useStyles2 } from '@grafana/ui';
|
||||
|
||||
import { AlertLabels } from './components/AlertLabels';
|
||||
import { RuleViewerLayout } from './components/rule-viewer/RuleViewerLayout';
|
||||
@@ -13,6 +13,7 @@ import { useCloudCombinedRulesMatching } from './hooks/useCombinedRule';
|
||||
import { getRulesSourceByName } from './utils/datasource';
|
||||
import { createViewLink } from './utils/misc';
|
||||
import { unescapePathSeparators } from './utils/rule-id';
|
||||
import { withPageErrorBoundary } from './withPageErrorBoundary';
|
||||
|
||||
const pageTitle = 'Find rule';
|
||||
const subUrl = config.appSubUrl;
|
||||
@@ -153,4 +154,4 @@ function getStyles(theme: GrafanaTheme2) {
|
||||
};
|
||||
}
|
||||
|
||||
export default withErrorBoundary(RedirectToRuleViewer, { style: 'page' });
|
||||
export default withPageErrorBoundary(RedirectToRuleViewer);
|
||||
@@ -3,6 +3,7 @@ import { Suspense, lazy } from 'react';
|
||||
import { config } from '@grafana/runtime';
|
||||
|
||||
import RuleListV1 from './rule-list/RuleList.v1';
|
||||
import { withPageErrorBoundary } from './withPageErrorBoundary';
|
||||
const RuleListV2 = lazy(() => import('./rule-list/RuleList.v2'));
|
||||
|
||||
const RuleList = () => {
|
||||
@@ -11,4 +12,4 @@ const RuleList = () => {
|
||||
return <Suspense>{newView ? <RuleListV2 /> : <RuleListV1 />}</Suspense>;
|
||||
};
|
||||
|
||||
export default RuleList;
|
||||
export default withPageErrorBoundary(RuleList);
|
||||
@@ -3,7 +3,7 @@ import { useParams } from 'react-router-dom-v5-compat';
|
||||
|
||||
import { NavModelItem } from '@grafana/data';
|
||||
import { isFetchError } from '@grafana/runtime';
|
||||
import { Alert, withErrorBoundary } from '@grafana/ui';
|
||||
import { Alert } from '@grafana/ui';
|
||||
import { EntityNotFound } from 'app/core/components/PageNotFound/EntityNotFound';
|
||||
|
||||
import { AlertingPageWrapper } from './components/AlertingPageWrapper';
|
||||
@@ -12,6 +12,7 @@ import DetailView, { ActiveTab, useActiveTab } from './components/rule-viewer/Ru
|
||||
import { useCombinedRule } from './hooks/useCombinedRule';
|
||||
import { stringifyErrorLike } from './utils/misc';
|
||||
import { getRuleIdFromPathname, parse as parseRuleId } from './utils/rule-id';
|
||||
import { withPageErrorBoundary } from './withPageErrorBoundary';
|
||||
|
||||
const RuleViewer = (): JSX.Element => {
|
||||
const params = useParams();
|
||||
@@ -86,4 +87,4 @@ function ErrorMessage({ error }: ErrorMessageProps) {
|
||||
return <Alert title={'Something went wrong loading the rule'}>{stringifyErrorLike(error)}</Alert>;
|
||||
}
|
||||
|
||||
export default withErrorBoundary(RuleViewer, { style: 'page' });
|
||||
export default withPageErrorBoundary(RuleViewer);
|
||||
@@ -6,8 +6,9 @@ import { useEditConfigurationDrawer } from './components/settings/ConfigurationD
|
||||
import { ExternalAlertmanagers } from './components/settings/ExternalAlertmanagers';
|
||||
import InternalAlertmanager from './components/settings/InternalAlertmanager';
|
||||
import { SettingsProvider, useSettings } from './components/settings/SettingsContext';
|
||||
import { withPageErrorBoundary } from './withPageErrorBoundary';
|
||||
|
||||
export default function SettingsPage() {
|
||||
function SettingsPage() {
|
||||
return (
|
||||
<SettingsProvider>
|
||||
<SettingsContent />
|
||||
@@ -47,3 +48,5 @@ function SettingsContent() {
|
||||
</AlertingPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withPageErrorBoundary(SettingsPage);
|
||||
@@ -1,28 +1,29 @@
|
||||
import { Route, Routes } from 'react-router-dom-v5-compat';
|
||||
|
||||
import { withErrorBoundary } from '@grafana/ui';
|
||||
|
||||
import { AlertmanagerPageWrapper } from './components/AlertingPageWrapper';
|
||||
import DuplicateMessageTemplate from './components/contact-points/DuplicateMessageTemplate';
|
||||
import EditMessageTemplate from './components/contact-points/EditMessageTemplate';
|
||||
import NewMessageTemplate from './components/contact-points/NewMessageTemplate';
|
||||
import { withPageErrorBoundary } from './withPageErrorBoundary';
|
||||
|
||||
const NotificationTemplates = (): JSX.Element => (
|
||||
<AlertmanagerPageWrapper
|
||||
navId="receivers"
|
||||
accessType="notification"
|
||||
pageNav={{
|
||||
id: 'templates',
|
||||
text: 'Notification templates',
|
||||
subTitle: 'Create and edit a group of notification templates',
|
||||
}}
|
||||
>
|
||||
<Routes>
|
||||
<Route path=":name/edit" element={<EditMessageTemplate />} />
|
||||
<Route path="new" element={<NewMessageTemplate />} />
|
||||
<Route path=":name/duplicate" element={<DuplicateMessageTemplate />} />
|
||||
</Routes>
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
function NotificationTemplates() {
|
||||
return (
|
||||
<AlertmanagerPageWrapper
|
||||
navId="receivers"
|
||||
accessType="notification"
|
||||
pageNav={{
|
||||
id: 'templates',
|
||||
text: 'Notification templates',
|
||||
subTitle: 'Create and edit a group of notification templates',
|
||||
}}
|
||||
>
|
||||
<Routes>
|
||||
<Route path=":name/edit" element={<EditMessageTemplate />} />
|
||||
<Route path="new" element={<NewMessageTemplate />} />
|
||||
<Route path=":name/duplicate" element={<DuplicateMessageTemplate />} />
|
||||
</Routes>
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withErrorBoundary(NotificationTemplates, { style: 'page' });
|
||||
export default withPageErrorBoundary(NotificationTemplates);
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
TabContent,
|
||||
TabsBar,
|
||||
Text,
|
||||
withErrorBoundary,
|
||||
} from '@grafana/ui';
|
||||
import { contextSrv } from 'app/core/core';
|
||||
import { Trans, t } from 'app/core/internationalization';
|
||||
@@ -25,6 +24,7 @@ import { usePagination } from '../../hooks/usePagination';
|
||||
import { useURLSearchParams } from '../../hooks/useURLSearchParams';
|
||||
import { useAlertmanager } from '../../state/AlertmanagerContext';
|
||||
import { GRAFANA_RULES_SOURCE_NAME } from '../../utils/datasource';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
import { GrafanaAlertmanagerDeliveryWarning } from '../GrafanaAlertmanagerDeliveryWarning';
|
||||
|
||||
@@ -270,4 +270,4 @@ function ContactPointsPage() {
|
||||
);
|
||||
}
|
||||
|
||||
export default withErrorBoundary(ContactPointsPage, { style: 'page' });
|
||||
export default withPageErrorBoundary(ContactPointsPage);
|
||||
+12
-2
@@ -8,13 +8,15 @@ import { useAlertmanager } from '../../state/AlertmanagerContext';
|
||||
import { generateCopiedName } from '../../utils/duplicate';
|
||||
import { stringifyErrorLike } from '../../utils/misc';
|
||||
import { updateDefinesWithUniqueValue } from '../../utils/templates';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
import { TemplateForm } from '../receivers/TemplateForm';
|
||||
|
||||
import { useGetNotificationTemplate, useNotificationTemplates } from './useNotificationTemplates';
|
||||
|
||||
const notFoundComponent = <EntityNotFound entity="Notification template" />;
|
||||
|
||||
const DuplicateMessageTemplate = () => {
|
||||
const DuplicateMessageTemplateComponent = () => {
|
||||
const { selectedAlertmanager } = useAlertmanager();
|
||||
const { name } = useParams<{ name: string }>();
|
||||
const templateUid = name ? decodeURIComponent(name) : undefined;
|
||||
@@ -63,4 +65,12 @@ const DuplicateMessageTemplate = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default DuplicateMessageTemplate;
|
||||
function DuplicateMessageTemplate() {
|
||||
return (
|
||||
<AlertmanagerPageWrapper navId="receivers" accessType="notification">
|
||||
<DuplicateMessageTemplateComponent />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withPageErrorBoundary(DuplicateMessageTemplate);
|
||||
@@ -1,10 +1,11 @@
|
||||
import { useParams } from 'react-router-dom-v5-compat';
|
||||
|
||||
import { Alert, LoadingPlaceholder, withErrorBoundary } from '@grafana/ui';
|
||||
import { Alert, LoadingPlaceholder } from '@grafana/ui';
|
||||
import { useGetContactPoint } from 'app/features/alerting/unified/components/contact-points/useContactPoints';
|
||||
import { stringifyErrorLike } from 'app/features/alerting/unified/utils/misc';
|
||||
|
||||
import { useAlertmanager } from '../../state/AlertmanagerContext';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
import { EditReceiverView } from '../receivers/EditReceiverView';
|
||||
|
||||
@@ -50,4 +51,4 @@ function EditContactPointPage() {
|
||||
);
|
||||
}
|
||||
|
||||
export default withErrorBoundary(EditContactPointPage, { style: 'page' });
|
||||
export default withPageErrorBoundary(EditContactPointPage);
|
||||
+12
-2
@@ -6,13 +6,15 @@ import { EntityNotFound } from 'app/core/components/PageNotFound/EntityNotFound'
|
||||
import { isNotFoundError } from '../../api/util';
|
||||
import { useAlertmanager } from '../../state/AlertmanagerContext';
|
||||
import { stringifyErrorLike } from '../../utils/misc';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
import { TemplateForm } from '../receivers/TemplateForm';
|
||||
|
||||
import { useGetNotificationTemplate } from './useNotificationTemplates';
|
||||
|
||||
const notFoundComponent = <EntityNotFound entity="Notification template" />;
|
||||
|
||||
const EditMessageTemplate = () => {
|
||||
const EditMessageTemplateComponent = () => {
|
||||
const { name } = useParams<{ name: string }>();
|
||||
const templateUid = name ? decodeURIComponent(name) : undefined;
|
||||
|
||||
@@ -47,4 +49,12 @@ const EditMessageTemplate = () => {
|
||||
return <TemplateForm alertmanager={selectedAlertmanager ?? ''} originalTemplate={currentData} />;
|
||||
};
|
||||
|
||||
export default EditMessageTemplate;
|
||||
function EditMessageTemplate() {
|
||||
return (
|
||||
<AlertmanagerPageWrapper navId="receivers" accessType="notification">
|
||||
<EditMessageTemplateComponent />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withPageErrorBoundary(EditMessageTemplate);
|
||||
+10
-10
@@ -1,16 +1,16 @@
|
||||
import { EntityNotFound } from 'app/core/components/PageNotFound/EntityNotFound';
|
||||
|
||||
import { useAlertmanager } from '../../state/AlertmanagerContext';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
import { TemplateForm } from '../receivers/TemplateForm';
|
||||
|
||||
const NewMessageTemplate = () => {
|
||||
function NewMessageTemplate() {
|
||||
const { selectedAlertmanager } = useAlertmanager();
|
||||
|
||||
if (!selectedAlertmanager) {
|
||||
return <EntityNotFound entity="Alertmanager" />;
|
||||
}
|
||||
return (
|
||||
<AlertmanagerPageWrapper navId="receivers" accessType="notification">
|
||||
<TemplateForm alertmanager={selectedAlertmanager ?? ''} />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
return <TemplateForm alertmanager={selectedAlertmanager} />;
|
||||
};
|
||||
|
||||
export default NewMessageTemplate;
|
||||
export default withPageErrorBoundary(NewMessageTemplate);
|
||||
+6
-5
@@ -1,11 +1,12 @@
|
||||
import { Alert, withErrorBoundary } from '@grafana/ui';
|
||||
import { Alert } from '@grafana/ui';
|
||||
|
||||
import { useAlertmanagerConfig } from '../../../hooks/useAlertmanagerConfig';
|
||||
import { useAlertmanager } from '../../../state/AlertmanagerContext';
|
||||
import { withPageErrorBoundary } from '../../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../../AlertingPageWrapper';
|
||||
import { GlobalConfigForm } from '../../receivers/GlobalConfigForm';
|
||||
|
||||
const NewMessageTemplate = () => {
|
||||
const GlobalConfig = () => {
|
||||
const { selectedAlertmanager } = useAlertmanager();
|
||||
const { data, isLoading, error } = useAlertmanagerConfig(selectedAlertmanager);
|
||||
|
||||
@@ -28,12 +29,12 @@ const NewMessageTemplate = () => {
|
||||
return <GlobalConfigForm config={data} alertManagerSourceName={selectedAlertmanager!} />;
|
||||
};
|
||||
|
||||
function NewMessageTemplatePage() {
|
||||
function GlobalConfigPage() {
|
||||
return (
|
||||
<AlertmanagerPageWrapper navId="receivers" accessType="notification">
|
||||
<NewMessageTemplate />
|
||||
<GlobalConfig />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withErrorBoundary(NewMessageTemplatePage, { style: 'page' });
|
||||
export default withPageErrorBoundary(GlobalConfigPage);
|
||||
@@ -1,21 +1,8 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertingPageWrapper } from '../AlertingPageWrapper';
|
||||
import { ModifyExportRuleForm } from '../rule-editor/alert-rule-form/ModifyExportRuleForm';
|
||||
|
||||
export default function ExportNewGrafanaRule() {
|
||||
return (
|
||||
<ExportNewGrafanaRuleWrapper>
|
||||
<ModifyExportRuleForm />
|
||||
</ExportNewGrafanaRuleWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
interface ExportNewGrafanaRuleWrapperProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
function ExportNewGrafanaRuleWrapper({ children }: ExportNewGrafanaRuleWrapperProps) {
|
||||
function ExportNewGrafanaRulePage() {
|
||||
return (
|
||||
<AlertingPageWrapper
|
||||
navId="alert-list"
|
||||
@@ -24,7 +11,9 @@ function ExportNewGrafanaRuleWrapper({ children }: ExportNewGrafanaRuleWrapperPr
|
||||
subTitle: 'Export a new rule definition in Terraform(HCL) format. Any changes you make will not be saved.',
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
<ModifyExportRuleForm />
|
||||
</AlertingPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withPageErrorBoundary(ExportNewGrafanaRulePage);
|
||||
@@ -1,4 +1,3 @@
|
||||
import * as React from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import { useParams } from 'react-router-dom-v5-compat';
|
||||
|
||||
@@ -12,10 +11,11 @@ import { stringifyErrorLike } from '../../utils/misc';
|
||||
import * as ruleId from '../../utils/rule-id';
|
||||
import { isGrafanaRulerRule } from '../../utils/rules';
|
||||
import { createRelativeUrl } from '../../utils/url';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertingPageWrapper } from '../AlertingPageWrapper';
|
||||
import { ModifyExportRuleForm } from '../rule-editor/alert-rule-form/ModifyExportRuleForm';
|
||||
|
||||
export default function GrafanaModifyExport() {
|
||||
function GrafanaModifyExport() {
|
||||
const { id } = useParams();
|
||||
const ruleIdentifier = useMemo<RuleIdentifier | undefined>(() => {
|
||||
return ruleId.tryParse(id, true);
|
||||
@@ -23,38 +23,13 @@ export default function GrafanaModifyExport() {
|
||||
|
||||
if (!ruleIdentifier) {
|
||||
return (
|
||||
<ModifyExportWrapper>
|
||||
<Alert title="Invalid rule ID" severity="error">
|
||||
The rule UID in the page URL is invalid. Please check the URL and try again.
|
||||
</Alert>
|
||||
</ModifyExportWrapper>
|
||||
<Alert title="Invalid rule ID" severity="error">
|
||||
The rule UID in the page URL is invalid. Please check the URL and try again.
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ModifyExportWrapper>
|
||||
<RuleModifyExport ruleIdentifier={ruleIdentifier} />
|
||||
</ModifyExportWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
interface ModifyExportWrapperProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
function ModifyExportWrapper({ children }: ModifyExportWrapperProps) {
|
||||
return (
|
||||
<AlertingPageWrapper
|
||||
navId="alert-list"
|
||||
pageNav={{
|
||||
text: 'Modify export',
|
||||
subTitle:
|
||||
'Modify the current alert rule and export the rule definition in the format of your choice. Any changes you make will not be saved.',
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</AlertingPageWrapper>
|
||||
);
|
||||
return <RuleModifyExport ruleIdentifier={ruleIdentifier} />;
|
||||
}
|
||||
|
||||
function RuleModifyExport({ ruleIdentifier }: { ruleIdentifier: RuleIdentifier }) {
|
||||
@@ -105,3 +80,20 @@ function RuleModifyExport({ ruleIdentifier }: { ruleIdentifier: RuleIdentifier }
|
||||
|
||||
return <Alert title="Unknown error" />;
|
||||
}
|
||||
|
||||
function GrafanaModifyExportPage() {
|
||||
return (
|
||||
<AlertingPageWrapper
|
||||
navId="alert-list"
|
||||
pageNav={{
|
||||
text: 'Modify export',
|
||||
subTitle:
|
||||
'Modify the current alert rule and export the rule definition in the format of your choice. Any changes you make will not be saved.',
|
||||
}}
|
||||
>
|
||||
<GrafanaModifyExport />
|
||||
</AlertingPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withPageErrorBoundary(GrafanaModifyExportPage);
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Navigate } from 'react-router-dom-v5-compat';
|
||||
|
||||
import { withErrorBoundary } from '@grafana/ui';
|
||||
import { useGetMuteTiming } from 'app/features/alerting/unified/components/mute-timings/useMuteTimings';
|
||||
import { useURLSearchParams } from 'app/features/alerting/unified/hooks/useURLSearchParams';
|
||||
|
||||
import { useAlertmanager } from '../../state/AlertmanagerContext';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
|
||||
import MuteTimingForm from './MuteTimingForm';
|
||||
@@ -38,17 +38,16 @@ const EditTimingRoute = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const EditMuteTimingPage = () => (
|
||||
<AlertmanagerPageWrapper
|
||||
navId="am-routes"
|
||||
pageNav={{
|
||||
id: 'alert-policy-edit',
|
||||
text: 'Edit mute timing',
|
||||
}}
|
||||
accessType="notification"
|
||||
>
|
||||
<EditTimingRoute />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
function EditMuteTimingPage() {
|
||||
return (
|
||||
<AlertmanagerPageWrapper
|
||||
navId="am-routes"
|
||||
pageNav={{ id: 'alert-policy-edit', text: 'Edit mute timing' }}
|
||||
accessType="notification"
|
||||
>
|
||||
<EditTimingRoute />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withErrorBoundary(EditMuteTimingPage, { style: 'page' });
|
||||
export default withPageErrorBoundary(EditMuteTimingPage);
|
||||
@@ -1,20 +1,18 @@
|
||||
import { withErrorBoundary } from '@grafana/ui';
|
||||
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
|
||||
import MuteTimingForm from './MuteTimingForm';
|
||||
|
||||
const NewMuteTimingPage = () => (
|
||||
<AlertmanagerPageWrapper
|
||||
navId="am-routes"
|
||||
pageNav={{
|
||||
id: 'alert-policy-new',
|
||||
text: 'Add mute timing',
|
||||
}}
|
||||
accessType="notification"
|
||||
>
|
||||
<MuteTimingForm />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
function NewMuteTimingPage() {
|
||||
return (
|
||||
<AlertmanagerPageWrapper
|
||||
navId="am-routes"
|
||||
pageNav={{ id: 'alert-policy-new', text: 'Add mute timing' }}
|
||||
accessType="notification"
|
||||
>
|
||||
<MuteTimingForm />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withErrorBoundary(NewMuteTimingPage, { style: 'page' });
|
||||
export default withPageErrorBoundary(NewMuteTimingPage);
|
||||
@@ -1,7 +1,7 @@
|
||||
import { withErrorBoundary } from '@grafana/ui';
|
||||
import { useAlertmanager } from 'app/features/alerting/unified/state/AlertmanagerContext';
|
||||
|
||||
import { GRAFANA_RULES_SOURCE_NAME } from '../../utils/datasource';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
|
||||
import { CloudReceiverForm } from './form/CloudReceiverForm';
|
||||
@@ -24,4 +24,4 @@ function NewReceiverViewPage() {
|
||||
);
|
||||
}
|
||||
|
||||
export default withErrorBoundary(NewReceiverViewPage, { style: 'page' });
|
||||
export default withPageErrorBoundary(NewReceiverViewPage);
|
||||
+5
-5
@@ -1,14 +1,14 @@
|
||||
import { withErrorBoundary } from '@grafana/ui';
|
||||
|
||||
import { withPageErrorBoundary } from '../../../withPageErrorBoundary';
|
||||
import { AlertingPageWrapper } from '../../AlertingPageWrapper';
|
||||
|
||||
import { CentralAlertHistoryScene } from './CentralAlertHistoryScene';
|
||||
|
||||
const HistoryPage = () => {
|
||||
function HistoryPage() {
|
||||
return (
|
||||
<AlertingPageWrapper navId="alerts-history" isLoading={false}>
|
||||
<CentralAlertHistoryScene />
|
||||
</AlertingPageWrapper>
|
||||
);
|
||||
};
|
||||
export default withErrorBoundary(HistoryPage, { style: 'page' });
|
||||
}
|
||||
|
||||
export default withPageErrorBoundary(HistoryPage);
|
||||
@@ -25,7 +25,6 @@ import {
|
||||
Stack,
|
||||
TextArea,
|
||||
useStyles2,
|
||||
withErrorBoundary,
|
||||
} from '@grafana/ui';
|
||||
import { Trans } from 'app/core/internationalization';
|
||||
import { SilenceCreatedResponse, alertSilencesApi } from 'app/features/alerting/unified/api/alertSilencesApi';
|
||||
@@ -38,6 +37,7 @@ import { useAlertmanager } from '../../state/AlertmanagerContext';
|
||||
import { SilenceFormFields } from '../../types/silence-form';
|
||||
import { matcherFieldToMatcher } from '../../utils/alertmanager';
|
||||
import { makeAMLink } from '../../utils/misc';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
import { GrafanaAlertmanagerDeliveryWarning } from '../GrafanaAlertmanagerDeliveryWarning';
|
||||
|
||||
@@ -296,4 +296,5 @@ function ExistingSilenceEditorPage() {
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
export default withErrorBoundary(ExistingSilenceEditorPage, { style: 'page' });
|
||||
|
||||
export default withPageErrorBoundary(ExistingSilenceEditorPage);
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
LoadingPlaceholder,
|
||||
Stack,
|
||||
useStyles2,
|
||||
withErrorBoundary,
|
||||
} from '@grafana/ui';
|
||||
import { useQueryParams } from 'app/core/hooks/useQueryParams';
|
||||
import { Trans } from 'app/core/internationalization';
|
||||
@@ -27,6 +26,7 @@ import { AlertmanagerAction, useAlertmanagerAbility } from '../../hooks/useAbili
|
||||
import { useAlertmanager } from '../../state/AlertmanagerContext';
|
||||
import { parsePromQLStyleMatcherLooseSafe } from '../../utils/matchers';
|
||||
import { getSilenceFiltersFromUrlParams, makeAMLink, stringifyErrorLike } from '../../utils/misc';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
import { Authorize } from '../Authorize';
|
||||
import { DynamicTable, DynamicTableColumnProps, DynamicTableItemProps } from '../DynamicTable';
|
||||
@@ -393,4 +393,5 @@ function SilencesTablePage() {
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
export default withErrorBoundary(SilencesTablePage, { style: 'page' });
|
||||
|
||||
export default withPageErrorBoundary(SilencesTablePage);
|
||||
@@ -5,12 +5,13 @@ import { Box, Stack, Tab, TabContent, TabsBar } from '@grafana/ui';
|
||||
|
||||
import { AlertingPageWrapper } from '../components/AlertingPageWrapper';
|
||||
import { isLocalDevEnv } from '../utils/misc';
|
||||
import { withPageErrorBoundary } from '../withPageErrorBoundary';
|
||||
|
||||
import GettingStarted, { WelcomeHeader } from './GettingStarted';
|
||||
import { getInsightsScenes, insightsIsAvailable } from './Insights';
|
||||
import { PluginIntegrations } from './PluginIntegrations';
|
||||
|
||||
export default function Home() {
|
||||
function Home() {
|
||||
const insightsEnabled = (insightsIsAvailable() || isLocalDevEnv()) && Boolean(config.featureToggles.alertingInsights);
|
||||
|
||||
const [activeTab, setActiveTab] = useState<'insights' | 'overview'>(insightsEnabled ? 'insights' : 'overview');
|
||||
@@ -51,3 +52,5 @@ export default function Home() {
|
||||
</AlertingPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withPageErrorBoundary(Home);
|
||||
@@ -2,7 +2,6 @@ import { useCallback } from 'react';
|
||||
import { useParams } from 'react-router-dom-v5-compat';
|
||||
|
||||
import { NavModelItem } from '@grafana/data';
|
||||
import { withErrorBoundary } from '@grafana/ui';
|
||||
import { RuleIdentifier } from 'app/types/unified-alerting';
|
||||
|
||||
import { AlertWarning } from '../AlertWarning';
|
||||
@@ -11,6 +10,7 @@ import { AlertRuleForm } from '../components/rule-editor/alert-rule-form/AlertRu
|
||||
import { useURLSearchParams } from '../hooks/useURLSearchParams';
|
||||
import { useRulesAccess } from '../utils/accessControlHooks';
|
||||
import * as ruleId from '../utils/rule-id';
|
||||
import { withPageErrorBoundary } from '../withPageErrorBoundary';
|
||||
|
||||
import { CloneRuleEditor } from './CloneRuleEditor';
|
||||
import { ExistingRuleEditor } from './ExistingRuleEditor';
|
||||
@@ -78,7 +78,9 @@ const RuleEditor = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default withErrorBoundary(RuleEditor, { style: 'page' });
|
||||
// The pageNav property makes it difficult to only rely on AlertingPageWrapper
|
||||
// to catch errors.
|
||||
export default withPageErrorBoundary(RuleEditor);
|
||||
|
||||
function useRuleEditorPathParams() {
|
||||
const params = useParams<RuleEditorPathParams>();
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useAsyncFn, useInterval } from 'react-use';
|
||||
|
||||
import { urlUtil } from '@grafana/data';
|
||||
import { logInfo } from '@grafana/runtime';
|
||||
import { Button, LinkButton, Stack, withErrorBoundary } from '@grafana/ui';
|
||||
import { Button, LinkButton, Stack } from '@grafana/ui';
|
||||
import { useQueryParams } from 'app/core/hooks/useQueryParams';
|
||||
import { Trans } from 'app/core/internationalization';
|
||||
import { useDispatch } from 'app/types';
|
||||
@@ -155,7 +155,7 @@ const RuleListV1 = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default withErrorBoundary(RuleListV1, { style: 'page' });
|
||||
export default RuleListV1;
|
||||
|
||||
export function CreateAlertButton() {
|
||||
const [createRuleSupported, createRuleAllowed] = useAlertingAbility(AlertingAction.CreateAlertRule);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { withErrorBoundary } from '@grafana/ui';
|
||||
|
||||
import { AlertingPageWrapper } from '../components/AlertingPageWrapper';
|
||||
import RulesFilter from '../components/rules/Filter/RulesFilter';
|
||||
import { SupportedView } from '../components/rules/Filter/RulesViewModeSelector';
|
||||
@@ -9,24 +7,25 @@ import { useURLSearchParams } from '../hooks/useURLSearchParams';
|
||||
import { FilterView } from './FilterView';
|
||||
import { GroupedView } from './GroupedView';
|
||||
|
||||
const RuleList = withErrorBoundary(
|
||||
() => {
|
||||
const [queryParams] = useURLSearchParams();
|
||||
const { filterState, hasActiveFilters } = useRulesFilter();
|
||||
function RuleList() {
|
||||
const [queryParams] = useURLSearchParams();
|
||||
const { filterState, hasActiveFilters } = useRulesFilter();
|
||||
|
||||
const view: SupportedView = queryParams.get('view') === 'list' ? 'list' : 'grouped';
|
||||
const showListView = hasActiveFilters || view === 'list';
|
||||
const view: SupportedView = queryParams.get('view') === 'list' ? 'list' : 'grouped';
|
||||
const showListView = hasActiveFilters || view === 'list';
|
||||
|
||||
return (
|
||||
// We don't want to show the Loading... indicator for the whole page.
|
||||
// We show separate indicators for Grafana-managed and Cloud rules
|
||||
<AlertingPageWrapper navId="alert-list" isLoading={false} actions={null}>
|
||||
<RulesFilter onClear={() => {}} />
|
||||
{showListView ? <FilterView filterState={filterState} /> : <GroupedView />}
|
||||
</AlertingPageWrapper>
|
||||
);
|
||||
},
|
||||
{ style: 'page' }
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<RulesFilter onClear={() => {}} />
|
||||
{showListView ? <FilterView filterState={filterState} /> : <GroupedView />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default RuleList;
|
||||
export default function RuleListPage() {
|
||||
return (
|
||||
<AlertingPageWrapper navId="alert-list" isLoading={false} actions={null}>
|
||||
<RuleList />
|
||||
</AlertingPageWrapper>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentType } from 'react';
|
||||
|
||||
import { ErrorBoundaryAlertProps, withErrorBoundary } from '@grafana/ui';
|
||||
|
||||
import { logError } from './Analytics';
|
||||
|
||||
/**
|
||||
* HOC for wrapping alerting page in an error boundary.
|
||||
* It provides alerting-specific error handling.
|
||||
*
|
||||
* @param Component - the react component to wrap in error boundary
|
||||
* @param errorBoundaryProps - error boundary options
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export function withPageErrorBoundary<P extends {} = {}>(
|
||||
Component: ComponentType<P>,
|
||||
errorBoundaryProps: Omit<ErrorBoundaryAlertProps, 'children' | 'errorLogger' | 'style'> = {}
|
||||
): ComponentType<P> {
|
||||
return withErrorBoundary(Component, {
|
||||
...errorBoundaryProps,
|
||||
style: 'page',
|
||||
errorLogger: logError,
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user