diff --git a/charts/client/Chart.yaml b/charts/client/Chart.yaml
index 76896324..9a650535 100644
--- a/charts/client/Chart.yaml
+++ b/charts/client/Chart.yaml
@@ -15,7 +15,7 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
-version: 1.1.23
+version: 1.1.24
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
diff --git a/charts/client/templates/configmap-azure-dashboard.yaml b/charts/client/templates/configmap-azure-dashboard.yaml
index ea290c78..98739e6a 100644
--- a/charts/client/templates/configmap-azure-dashboard.yaml
+++ b/charts/client/templates/configmap-azure-dashboard.yaml
@@ -26,7 +26,7 @@ data:
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
- "id": 33,
+ "id": 53,
"links": [],
"liveNow": false,
"panels": [
@@ -51,11 +51,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}",
+ "getOption": "// Check if data.series exists\nif (context.panel.data.series && context.panel.data.series.length > 0) {\n const eventTypes = context.panel.data.series[0].fields[0].values;\n const authors = context.panel.data.series[0].fields[1].values;\n const repoNames = context.panel.data.series[0].fields[2].values;\n const total = context.panel.data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}",
"google": {
"callback": "gmapReady",
"key": ""
@@ -66,8 +67,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -110,11 +117,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let options; // Initialize the options variable\n\nif (!data || !data.series || data.series.length === 0 || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n",
+ "getOption": "let options; // Initialize the options variable\n\nif (!context.panel.data || !context.panel.data.series || context.panel.data.series.length === 0 || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = context.panel.data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = context.panel.data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -125,8 +133,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -169,11 +183,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n",
+ "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = context.panel.data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = context.panel.data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -184,8 +199,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -223,7 +244,8 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -293,7 +315,8 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -370,7 +393,8 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
}
]
}
@@ -426,7 +450,11 @@ data:
"templating": {
"list": [
{
- "current": {},
+ "current": {
+ "selected": false,
+ "text": "All",
+ "value": "$__all"
+ },
"datasource": {
"type": "vertamedia-clickhouse-datasource",
"uid": "{{ .Values.datasources.uid }}"
@@ -445,7 +473,11 @@ data:
"type": "query"
},
{
- "current": {},
+ "current": {
+ "selected": false,
+ "text": "All",
+ "value": "$__all"
+ },
"datasource": {
"type": "vertamedia-clickhouse-datasource",
"uid": "{{ .Values.datasources.uid }}"
@@ -473,7 +505,8 @@ data:
"timezone": "",
"title": "Azure",
"uid": "dd66838a-ffda-4de2-944f-1828d1671fc9",
- "version": 1,
+ "version": 2,
"weekStart": ""
}
+
{{- end }}
\ No newline at end of file
diff --git a/charts/client/templates/configmap-bitbucket-dashboard.yaml b/charts/client/templates/configmap-bitbucket-dashboard.yaml
index fde60b9f..3b2722db 100644
--- a/charts/client/templates/configmap-bitbucket-dashboard.yaml
+++ b/charts/client/templates/configmap-bitbucket-dashboard.yaml
@@ -26,7 +26,7 @@ data:
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
- "id": 34,
+ "id": 60,
"links": [],
"liveNow": false,
"panels": [
@@ -51,11 +51,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}",
+ "getOption": "// Check if data.series exists\nif (context.panel.data.series && context.panel.data.series.length > 0) {\n const eventTypes = context.panel.data.series[0].fields[0].values;\n const authors = context.panel.data.series[0].fields[1].values;\n const repoNames = context.panel.data.series[0].fields[2].values;\n const total = context.panel.data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}",
"google": {
"callback": "gmapReady",
"key": ""
@@ -66,8 +67,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -110,11 +117,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let options; // Initialize the options variable\n\nif (!data || !data.series || data.series.length === 0 || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n",
+ "getOption": "let options; // Initialize the options variable\n\nif (!context.panel.data || !context.panel.data.series || context.panel.data.series.length === 0 || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = context.panel.data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = context.panel.data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -125,8 +133,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -169,11 +183,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n",
+ "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = context.panel.data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = context.panel.data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -184,8 +199,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -223,7 +244,8 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -293,7 +315,8 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -451,8 +474,8 @@ data:
{
"current": {
"selected": false,
- "text": "",
- "value": ""
+ "text": "All",
+ "value": "$__all"
},
"datasource": {
"type": "vertamedia-clickhouse-datasource",
@@ -481,7 +504,8 @@ data:
"timezone": "",
"title": "BitBucket",
"uid": "a7772dd5-76c7-48f3-8462-b39fbc20941c",
- "version": 1,
+ "version": 2,
"weekStart": ""
}
+
{{- end }}
\ No newline at end of file
diff --git a/charts/client/templates/configmap-gitea-dashboard.yaml b/charts/client/templates/configmap-gitea-dashboard.yaml
index 3c1a663f..5d53ed2b 100644
--- a/charts/client/templates/configmap-gitea-dashboard.yaml
+++ b/charts/client/templates/configmap-gitea-dashboard.yaml
@@ -26,7 +26,7 @@ data:
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
- "id": 35,
+ "id": 61,
"links": [],
"liveNow": false,
"panels": [
@@ -51,11 +51,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}",
+ "getOption": "// Check if data.series exists\nif (context.panel.data.series && context.panel.data.series.length > 0) {\n const eventTypes = context.panel.data.series[0].fields[0].values;\n const authors = context.panel.data.series[0].fields[1].values;\n const repoNames = context.panel.data.series[0].fields[2].values;\n const total = context.panel.data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}",
"google": {
"callback": "gmapReady",
"key": ""
@@ -66,8 +67,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -110,11 +117,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let options; // Initialize the options variable\n\nif (!data || !data.series || data.series.length === 0 || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n",
+ "getOption": "let options; // Initialize the options variable\n\nif (!context.panel.data || !context.panel.data.series || context.panel.data.series.length === 0 || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = context.panel.data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = context.panel.data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -125,8 +133,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -169,11 +183,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n",
+ "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = context.panel.data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = context.panel.data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -184,8 +199,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -223,7 +244,8 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -293,7 +315,8 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -370,7 +393,8 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
}
]
}
@@ -427,9 +451,13 @@ data:
"list": [
{
"current": {
- "selected": false,
- "text": "All",
- "value": "$__all"
+ "selected": true,
+ "text": [
+ "All"
+ ],
+ "value": [
+ "$__all"
+ ]
},
"datasource": {
"type": "vertamedia-clickhouse-datasource",
@@ -451,8 +479,8 @@ data:
{
"current": {
"selected": false,
- "text": "",
- "value": ""
+ "text": "All",
+ "value": "$__all"
},
"datasource": {
"type": "vertamedia-clickhouse-datasource",
@@ -481,7 +509,8 @@ data:
"timezone": "",
"title": "GiTea",
"uid": "a1c6d705-91b0-4718-99b2-d93b0221bca9",
- "version": 1,
+ "version": 2,
"weekStart": ""
}
+
{{- end }}
\ No newline at end of file
diff --git a/charts/client/templates/configmap-github-dashboard.yaml b/charts/client/templates/configmap-github-dashboard.yaml
index 860f77a1..38a98a43 100644
--- a/charts/client/templates/configmap-github-dashboard.yaml
+++ b/charts/client/templates/configmap-github-dashboard.yaml
@@ -26,7 +26,7 @@ data:
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
- "id": 37,
+ "id": 57,
"links": [],
"liveNow": false,
"panels": [
@@ -51,11 +51,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Handle the case when data.series does not exist\n return {};\n}",
+ "getOption": "// Check if data.series exists\nif (context.panel.data.series && context.panel.data.series.length > 0) {\n const eventTypes = context.panel.data.series[0].fields[0].values;\n const authors = context.panel.data.series[0].fields[1].values;\n const repoNames = context.panel.data.series[0].fields[2].values;\n const total = context.panel.data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Handle the case when data.series does not exist\n return {};\n}",
"google": {
"callback": "gmapReady",
"key": ""
@@ -66,9 +67,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
- "pluginVersion": "10.0.3",
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -111,11 +117,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let options; // Initialize the options variable\n\nif (!data || !data.series || data.series.length === 0 || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n",
+ "getOption": "let options; // Initialize the options variable\n\nif (!context.panel.data || !context.panel.data.series || context.panel.data.series.length === 0 || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = context.panel.data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = context.panel.data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -126,8 +133,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -170,11 +183,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n",
+ "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = context.panel.data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = context.panel.data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -185,8 +199,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -229,11 +249,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "const values = data.series[0].fields[0].values;\n\nreturn {\n series: [\n {\n type: 'liquidFill',\n radius: '90%',\n data: values, // Use the raw values here\n label: {\n formatter: '{a|{c}}',\n rich: {\n a: {\n color: '#000', // You can set the text color here\n },\n },\n },\n tooltip: {\n formatter: '{a}: {c}', // This formatter displays the raw values\n },\n },\n ],\n};\n",
+ "getOption": "const values = context.panel.data.series[0].fields[0].values;\n\nreturn {\n series: [\n {\n type: 'liquidFill',\n radius: '90%',\n data: values, // Use the raw values here\n label: {\n formatter: '{a|{c}}',\n rich: {\n a: {\n color: '#000', // You can set the text color here\n },\n },\n },\n tooltip: {\n formatter: '{a}: {c}', // This formatter displays the raw values\n },\n },\n ],\n};\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -244,8 +265,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -288,11 +315,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "const values = data.series[0].fields[0].values;\n\nreturn {\n series: [\n {\n type: 'liquidFill',\n radius: '90%',\n data: values, // Use the raw values here\n label: {\n formatter: '{a|{c}}',\n rich: {\n a: {\n color: '#000', // You can set the text color here\n },\n },\n },\n tooltip: {\n formatter: '{a}: {c}', // This formatter displays the raw values\n },\n },\n ],\n};\n",
+ "getOption": "const values = context.panel.data.series[0].fields[0].values;\n\nreturn {\n series: [\n {\n type: 'liquidFill',\n radius: '90%',\n data: values, // Use the raw values here\n label: {\n formatter: '{a|{c}}',\n rich: {\n a: {\n color: '#000', // You can set the text color here\n },\n },\n },\n tooltip: {\n formatter: '{a}: {c}', // This formatter displays the raw values\n },\n },\n ],\n};\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -303,8 +331,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -349,7 +383,8 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
}
]
}
@@ -406,9 +441,13 @@ data:
"list": [
{
"current": {
- "selected": false,
- "text": "",
- "value": ""
+ "selected": true,
+ "text": [
+ "ahinvinith"
+ ],
+ "value": [
+ "ahinvinith"
+ ]
},
"datasource": {
"type": "vertamedia-clickhouse-datasource",
@@ -467,4 +506,5 @@ data:
"version": 2,
"weekStart": ""
}
+
{{- end }}
\ No newline at end of file
diff --git a/charts/client/templates/configmap-gitlab-dashboard.yaml b/charts/client/templates/configmap-gitlab-dashboard.yaml
index bc1273b7..fd1840dc 100644
--- a/charts/client/templates/configmap-gitlab-dashboard.yaml
+++ b/charts/client/templates/configmap-gitlab-dashboard.yaml
@@ -26,7 +26,7 @@ data:
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
- "id": 36,
+ "id": 59,
"links": [],
"liveNow": false,
"panels": [
@@ -51,11 +51,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}",
+ "getOption": "// Check if data.series exists\nif (context.panel.data.series && context.panel.data.series.length > 0) {\n const eventTypes = context.panel.data.series[0].fields[0].values;\n const authors = context.panel.data.series[0].fields[1].values;\n const repoNames = context.panel.data.series[0].fields[2].values;\n const total = context.panel.data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}",
"google": {
"callback": "gmapReady",
"key": ""
@@ -66,8 +67,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -110,11 +117,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let options; // Initialize the options variable\n\nif (!data || !data.series || data.series.length === 0 || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n",
+ "getOption": "let options; // Initialize the options variable\n\nif (!context.panel.data || !context.panel.data.series || context.panel.data.series.length === 0 || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = context.panel.data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = context.panel.data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -125,8 +133,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -169,11 +183,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n",
+ "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = context.panel.data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = context.panel.data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -184,8 +199,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -223,7 +244,8 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -293,7 +315,8 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -370,7 +393,8 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -485,7 +509,8 @@ data:
"timezone": "",
"title": "GitLab",
"uid": "ec8b9cb1-f9ae-4139-b270-4824b6508eff",
- "version": 1,
+ "version": 2,
"weekStart": ""
}
+
{{- end }}
\ No newline at end of file
diff --git a/charts/client/templates/configmap-kubedata-dashboard.yaml b/charts/client/templates/configmap-kubedata-dashboard.yaml
index 7e275444..d479fd9b 100644
--- a/charts/client/templates/configmap-kubedata-dashboard.yaml
+++ b/charts/client/templates/configmap-kubedata-dashboard.yaml
@@ -32,7 +32,7 @@ data:
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
- "id": 146,
+ "id": 56,
"links": [],
"liveNow": false,
"panels": [
@@ -57,11 +57,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const clusterNames = data.series[0].fields[0].values;\n const namespaces = data.series[0].fields[1].values;\n const reasons = data.series[0].fields[2].values;\n const pods = data.series[0].fields[3].values;\n\n // Create a hierarchical structure from the data without a root node\n const hierarchy = {\n name: 'root', // Use 'root' as a placeholder\n children: [],\n };\n\n const seenClusterNames = new Set();\n const seenNamespaces = new Set();\n\n for (let i = 0; i < clusterNames.length; i++) {\n const clusterName = clusterNames[i];\n const namespace = namespaces[i];\n const reason = reasons[i];\n const pod = pods[i];\n\n if (!seenClusterNames.has(clusterName)) {\n seenClusterNames.add(clusterName);\n const clusterNode = { name: clusterName, children: [] };\n hierarchy.children.push(clusterNode);\n seenNamespaces.clear(); // Reset seenNamespaces for each cluster\n }\n\n const clusterNode = hierarchy.children.find((node) => node.name === clusterName);\n\n if (!seenNamespaces.has(namespace)) {\n seenNamespaces.add(namespace);\n const namespaceNode = { name: namespace, children: [] };\n clusterNode.children.push(namespaceNode);\n }\n\n const namespaceNode = clusterNode.children.find((node) => node.name === namespace);\n const reasonNode = { name: reason, children: [{ name: `Count: ${pod}` }] };\n namespaceNode.children.push(reasonNode);\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n formatter: function (params) {\n const node = params.data;\n let tooltip = '';\n if (node.column) {\n tooltip += `${node.column}: ${node.name}`;\n } else {\n tooltip += node.name;\n }\n return tooltip;\n },\n },\n series: [\n {\n type: 'tree',\n data: hierarchy.children, // Use the children directly\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%',\n symbolSize: 7,\n label: {\n position: 'left',\n verticalAlign: 'middle',\n align: 'centre',\n fontSize: 15, // Increase the text size for regular nodes\n fontWeight: 'bold', // Set the font weight to bold\n },\n leaves: {\n label: {\n position: 'right',\n verticalAlign: 'middle',\n align: 'left',\n fontSize: 15, // Increase the text size for leaves\n fontWeight: 'bold', // Set the font weight to bold\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;",
+ "getOption": "let option; // Initialize the option variable\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const clusterNames = context.panel.data.series[0].fields[0].values;\n const namespaces = context.panel.data.series[0].fields[1].values;\n const reasons = context.panel.data.series[0].fields[2].values;\n const pods = context.panel.data.series[0].fields[3].values;\n\n // Create a hierarchical structure from the data without a root node\n const hierarchy = {\n name: 'root', // Use 'root' as a placeholder\n children: [],\n };\n\n const seenClusterNames = new Set();\n const seenNamespaces = new Set();\n\n for (let i = 0; i < clusterNames.length; i++) {\n const clusterName = clusterNames[i];\n const namespace = namespaces[i];\n const reason = reasons[i];\n const pod = pods[i];\n\n if (!seenClusterNames.has(clusterName)) {\n seenClusterNames.add(clusterName);\n const clusterNode = { name: clusterName, children: [] };\n hierarchy.children.push(clusterNode);\n seenNamespaces.clear(); // Reset seenNamespaces for each cluster\n }\n\n const clusterNode = hierarchy.children.find((node) => node.name === clusterName);\n\n if (!seenNamespaces.has(namespace)) {\n seenNamespaces.add(namespace);\n const namespaceNode = { name: namespace, children: [] };\n clusterNode.children.push(namespaceNode);\n }\n\n const namespaceNode = clusterNode.children.find((node) => node.name === namespace);\n const reasonNode = { name: reason, children: [{ name: `Count: ${pod}` }] };\n namespaceNode.children.push(reasonNode);\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n formatter: function (params) {\n const node = params.data;\n let tooltip = '';\n if (node.column) {\n tooltip += `${node.column}: ${node.name}`;\n } else {\n tooltip += node.name;\n }\n return tooltip;\n },\n },\n series: [\n {\n type: 'tree',\n data: hierarchy.children, // Use the children directly\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%',\n symbolSize: 7,\n label: {\n position: 'left',\n verticalAlign: 'middle',\n align: 'centre',\n fontSize: 15, // Increase the text size for regular nodes\n fontWeight: 'bold', // Set the font weight to bold\n },\n leaves: {\n label: {\n position: 'right',\n verticalAlign: 'middle',\n align: 'left',\n fontSize: 15, // Increase the text size for leaves\n fontWeight: 'bold', // Set the font weight to bold\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;",
"google": {
"callback": "gmapReady",
"key": ""
@@ -72,8 +73,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -116,11 +123,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const reasons = data.series[0].fields[0].values;\n const counts = data.series[0].fields[1].values;\n\n // Check if reasons and counts are defined and not empty\n if (!reasons || !counts || reasons.length === 0 || counts.length === 0) {\n // Display a message when no data is available\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n } else {\n // Data is available, proceed with the chart creation\n // Create an array of data items, each containing name and value\n const seriesData = reasons.map((reason, index) => ({\n name: reason,\n value: counts[index],\n }));\n\n // Define a custom color for the bars\n const customColor = 'rgb(0, 123, 255)'; // Change this to your desired color\n\n // Apache ECharts option\n option = {\n xAxis: {\n type: 'category',\n data: reasons, // Use the reasons directly for xAxis data\n axisLabel: {\n interval: 0, // Display all labels on the xAxis\n },\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Pods'], // Legend name\n left: 'left', // Position the legend on the left side\n bottom: 'bottom', // Position the legend at the bottom\n },\n series: [\n {\n name: 'Pods', // Series name for the legend\n data: seriesData,\n type: 'bar',\n label: {\n show: true,\n position: 'top',\n formatter: '{c}',\n },\n itemStyle: {\n barBorderRadius: [5, 5, 0, 0], // Adjust the values to control the curvature\n color: customColor, // Set the custom color for the bars\n },\n },\n ],\n };\n }\n}\n\nreturn option;",
+ "getOption": "let option; // Initialize the option variable\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const reasons = context.panel.data.series[0].fields[0].values;\n const counts = context.panel.data.series[0].fields[1].values;\n\n // Check if reasons and counts are defined and not empty\n if (!reasons || !counts || reasons.length === 0 || counts.length === 0) {\n // Display a message when no data is available\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n } else {\n // Data is available, proceed with the chart creation\n // Create an array of data items, each containing name and value\n const seriesData = reasons.map((reason, index) => ({\n name: reason,\n value: counts[index],\n }));\n\n // Define a custom color for the bars\n const customColor = 'rgb(0, 123, 255)'; // Change this to your desired color\n\n // Apache ECharts option\n option = {\n xAxis: {\n type: 'category',\n data: reasons, // Use the reasons directly for xAxis data\n axisLabel: {\n interval: 0, // Display all labels on the xAxis\n },\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Pods'], // Legend name\n left: 'left', // Position the legend on the left side\n bottom: 'bottom', // Position the legend at the bottom\n },\n series: [\n {\n name: 'Pods', // Series name for the legend\n data: seriesData,\n type: 'bar',\n label: {\n show: true,\n position: 'top',\n formatter: '{c}',\n },\n itemStyle: {\n barBorderRadius: [5, 5, 0, 0], // Adjust the values to control the curvature\n color: customColor, // Set the custom color for the bars\n },\n },\n ],\n };\n }\n}\n\nreturn option;",
"google": {
"callback": "gmapReady",
"key": ""
@@ -131,8 +139,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -175,11 +189,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n\n // Define the data from your JSON\n const clusterNames = data.series[0].fields[0].values;\n const kinds = data.series[0].fields[1].values;\n const reasons = data.series[0].fields[2].values;\n const counts = data.series[0].fields[3].values;\n\n // Create the Sankey chart configuration\n option = {\n series: {\n type: 'sankey',\n layout: 'none',\n emphasis: {\n focus: 'adjacency',\n },\n data: [],\n links: [],\n },\n tooltip: {\n trigger: 'item',\n formatter: (params) => {\n if (params.dataType === 'node') {\n return params.name;\n }\n if (params.dataType === 'edge') {\n return `Count: ${counts[params.dataIndex]}`; // Display count values\n }\n return '';\n },\n },\n };\n\n // Create nodes for ClusterName, Kind, and Reason\n const uniqueClusterNames = Array.from(new Set(clusterNames));\n const uniqueKinds = Array.from(new Set(kinds));\n const uniqueReasons = Array.from(new Set(reasons));\n\n uniqueClusterNames.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueKinds.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueReasons.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n\n // Create links from Kind to Reason\n kinds.forEach((kind, index) => {\n const sourceIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kind);\n const targetIndex = 1 * uniqueClusterNames.length + uniqueKinds.length + uniqueReasons.indexOf(reasons[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: counts[index], // Use count values\n });\n });\n\n // Create links from ClusterName to Kind\n clusterNames.forEach((clusterName, index) => {\n const sourceIndex = uniqueClusterNames.indexOf(clusterName);\n const targetIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kinds[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: 1,\n });\n });\n}\n\n\nreturn option;\n// Render the chart\nmyChart.setOption(option);",
+ "getOption": "let option; // Initialize the option variable\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n\n // Define the data from your JSON\n const clusterNames = context.panel.data.series[0].fields[0].values;\n const kinds = context.panel.data.series[0].fields[1].values;\n const reasons = context.panel.data.series[0].fields[2].values;\n const counts = context.panel.data.series[0].fields[3].values;\n\n // Create the Sankey chart configuration\n option = {\n series: {\n type: 'sankey',\n layout: 'none',\n emphasis: {\n focus: 'adjacency',\n },\n data: [],\n links: [],\n },\n tooltip: {\n trigger: 'item',\n formatter: (params) => {\n if (params.dataType === 'node') {\n return params.name;\n }\n if (params.dataType === 'edge') {\n return `Count: ${counts[params.dataIndex]}`; // Display count values\n }\n return '';\n },\n },\n };\n\n // Create nodes for ClusterName, Kind, and Reason\n const uniqueClusterNames = Array.from(new Set(clusterNames));\n const uniqueKinds = Array.from(new Set(kinds));\n const uniqueReasons = Array.from(new Set(reasons));\n\n uniqueClusterNames.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueKinds.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueReasons.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n\n // Create links from Kind to Reason\n kinds.forEach((kind, index) => {\n const sourceIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kind);\n const targetIndex = 1 * uniqueClusterNames.length + uniqueKinds.length + uniqueReasons.indexOf(reasons[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: counts[index], // Use count values\n });\n });\n\n // Create links from ClusterName to Kind\n clusterNames.forEach((clusterName, index) => {\n const sourceIndex = uniqueClusterNames.indexOf(clusterName);\n const targetIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kinds[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: 1,\n });\n });\n}\n\n\nreturn option;\n// Render the chart\nmyChart.setOption(option);",
"google": {
"callback": "gmapReady",
"key": ""
@@ -190,8 +205,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -234,11 +255,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n\n // Define the data from your JSON\n const clusterNames = data.series[0].fields[0].values;\n const kinds = data.series[0].fields[1].values;\n const reasons = data.series[0].fields[2].values;\n const counts = data.series[0].fields[3].values;\n\n // Create the Sankey chart configuration\n option = {\n series: {\n type: 'sankey',\n layout: 'none',\n emphasis: {\n focus: 'adjacency',\n },\n data: [],\n links: [],\n },\n tooltip: {\n trigger: 'item',\n formatter: (params) => {\n if (params.dataType === 'node') {\n return params.name;\n }\n if (params.dataType === 'edge') {\n return `Count: ${counts[params.dataIndex]}`; // Display count values\n }\n return '';\n },\n },\n };\n\n // Create nodes for ClusterName, Kind, and Reason\n const uniqueClusterNames = Array.from(new Set(clusterNames));\n const uniqueKinds = Array.from(new Set(kinds));\n const uniqueReasons = Array.from(new Set(reasons));\n\n uniqueClusterNames.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueKinds.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueReasons.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n\n // Create links from Kind to Reason\n kinds.forEach((kind, index) => {\n const sourceIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kind);\n const targetIndex = 1 * uniqueClusterNames.length + uniqueKinds.length + uniqueReasons.indexOf(reasons[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: counts[index], // Use count values\n });\n });\n\n // Create links from ClusterName to Kind\n clusterNames.forEach((clusterName, index) => {\n const sourceIndex = uniqueClusterNames.indexOf(clusterName);\n const targetIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kinds[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: 1,\n });\n });\n}\n\n\n\nreturn option;\n// Render the chart\nmyChart.setOption(option);",
+ "getOption": "let option; // Initialize the option variable\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n\n // Define the data from your JSON\n const clusterNames = context.panel.data.series[0].fields[0].values;\n const kinds = context.panel.data.series[0].fields[1].values;\n const reasons = context.panel.data.series[0].fields[2].values;\n const counts = context.panel.data.series[0].fields[3].values;\n\n // Create the Sankey chart configuration\n option = {\n series: {\n type: 'sankey',\n layout: 'none',\n emphasis: {\n focus: 'adjacency',\n },\n data: [],\n links: [],\n },\n tooltip: {\n trigger: 'item',\n formatter: (params) => {\n if (params.dataType === 'node') {\n return params.name;\n }\n if (params.dataType === 'edge') {\n return `Count: ${counts[params.dataIndex]}`; // Display count values\n }\n return '';\n },\n },\n };\n\n // Create nodes for ClusterName, Kind, and Reason\n const uniqueClusterNames = Array.from(new Set(clusterNames));\n const uniqueKinds = Array.from(new Set(kinds));\n const uniqueReasons = Array.from(new Set(reasons));\n\n uniqueClusterNames.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueKinds.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueReasons.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n\n // Create links from Kind to Reason\n kinds.forEach((kind, index) => {\n const sourceIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kind);\n const targetIndex = 1 * uniqueClusterNames.length + uniqueKinds.length + uniqueReasons.indexOf(reasons[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: counts[index], // Use count values\n });\n });\n\n // Create links from ClusterName to Kind\n clusterNames.forEach((clusterName, index) => {\n const sourceIndex = uniqueClusterNames.indexOf(clusterName);\n const targetIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kinds[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: 1,\n });\n });\n}\n\n\n\nreturn option;\n// Render the chart\nmyChart.setOption(option);",
"google": {
"callback": "gmapReady",
"key": ""
@@ -249,8 +271,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -293,11 +321,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n\n // Define the data from your JSON\n const clusterNames = data.series[0].fields[0].values;\n const kinds = data.series[0].fields[1].values;\n const reasons = data.series[0].fields[2].values;\n const counts = data.series[0].fields[3].values;\n\n // Create the Sankey chart configuration\n option = {\n series: {\n type: 'sankey',\n layout: 'none',\n emphasis: {\n focus: 'adjacency',\n },\n data: [],\n links: [],\n },\n tooltip: {\n trigger: 'item',\n formatter: (params) => {\n if (params.dataType === 'node') {\n return params.name;\n }\n if (params.dataType === 'edge') {\n return `Count: ${counts[params.dataIndex]}`; // Display count values\n }\n return '';\n },\n },\n };\n\n // Create nodes for ClusterName, Kind, and Reason\n const uniqueClusterNames = Array.from(new Set(clusterNames));\n const uniqueKinds = Array.from(new Set(kinds));\n const uniqueReasons = Array.from(new Set(reasons));\n\n uniqueClusterNames.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueKinds.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueReasons.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n\n // Create links from Kind to Reason\n kinds.forEach((kind, index) => {\n const sourceIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kind);\n const targetIndex = 1 * uniqueClusterNames.length + uniqueKinds.length + uniqueReasons.indexOf(reasons[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: counts[index], // Use count values\n });\n });\n\n // Create links from ClusterName to Kind\n clusterNames.forEach((clusterName, index) => {\n const sourceIndex = uniqueClusterNames.indexOf(clusterName);\n const targetIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kinds[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: 1,\n });\n });\n}\n\n\nreturn option;\n// Render the chart\nmyChart.setOption(option);\n\n",
+ "getOption": "let option; // Initialize the option variable\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n\n // Define the data from your JSON\n const clusterNames = context.panel.data.series[0].fields[0].values;\n const kinds = context.panel.data.series[0].fields[1].values;\n const reasons = context.panel.data.series[0].fields[2].values;\n const counts = context.panel.data.series[0].fields[3].values;\n\n // Create the Sankey chart configuration\n option = {\n series: {\n type: 'sankey',\n layout: 'none',\n emphasis: {\n focus: 'adjacency',\n },\n data: [],\n links: [],\n },\n tooltip: {\n trigger: 'item',\n formatter: (params) => {\n if (params.dataType === 'node') {\n return params.name;\n }\n if (params.dataType === 'edge') {\n return `Count: ${counts[params.dataIndex]}`; // Display count values\n }\n return '';\n },\n },\n };\n\n // Create nodes for ClusterName, Kind, and Reason\n const uniqueClusterNames = Array.from(new Set(clusterNames));\n const uniqueKinds = Array.from(new Set(kinds));\n const uniqueReasons = Array.from(new Set(reasons));\n\n uniqueClusterNames.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueKinds.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueReasons.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n\n // Create links from Kind to Reason\n kinds.forEach((kind, index) => {\n const sourceIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kind);\n const targetIndex = 1 * uniqueClusterNames.length + uniqueKinds.length + uniqueReasons.indexOf(reasons[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: counts[index], // Use count values\n });\n });\n\n // Create links from ClusterName to Kind\n clusterNames.forEach((clusterName, index) => {\n const sourceIndex = uniqueClusterNames.indexOf(clusterName);\n const targetIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kinds[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: 1,\n });\n });\n}\n\n\nreturn option;\n// Render the chart\nmyChart.setOption(option);\n\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -308,8 +337,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -352,11 +387,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON\n const clusters = data.series[0].fields[0].values;\n const hosts = data.series[0].fields[1].values;\n const reasons = data.series[0].fields[2].values;\n const eventTimes = data.series[0].fields[3].values;\n\n // Create a hierarchical structure for the tree chart starting with ClusterName\n const hierarchy = {\n name: 'Root', // You can customize the name of the root node if needed\n children: [],\n };\n\n for (let i = 0; i < clusters.length; i++) {\n const cluster = clusters[i];\n const host = hosts[i];\n const reason = reasons[i];\n const eventTime = eventTimes[i];\n\n // Find or create the cluster node\n let clusterNode = hierarchy.children.find((node) => node.name === cluster);\n if (!clusterNode) {\n clusterNode = { name: cluster, children: [] };\n hierarchy.children.push(clusterNode);\n }\n\n // Find or create the host node under the cluster\n let hostNode = clusterNode.children.find((node) => node.name === host);\n if (!hostNode) {\n hostNode = { name: host, children: [] };\n clusterNode.children.push(hostNode);\n }\n\n // Find or create the reason node under the host\n let reasonNode = hostNode.children.find((node) => node.name === reason);\n if (!reasonNode) {\n reasonNode = { name: reason, children: [] };\n hostNode.children.push(reasonNode);\n }\n\n // Create the eventTime node under the reason\n reasonNode.children.push({ name: eventTime });\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n },\n series: [\n {\n type: 'tree',\n data: hierarchy.children, // Use the children directly as root nodes\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%', // Adjust the right margin to provide more space for labels\n symbolSize: 7,\n label: {\n position: 'inside', // Position labels inside the node\n verticalAlign: 'middle',\n align: 'center', // Center-align labels\n fontSize: 15,\n fontWeight: 'bold',\n },\n leaves: {\n label: {\n position: 'right', // Position labels inside the node\n verticalAlign: 'middle',\n align: 'left', // Center-align labels\n fontSize: 15,\n fontWeight: 'bold',\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;\n",
+ "getOption": "let option; // Initialize the option variable\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON\n const clusters = context.panel.data.series[0].fields[0].values;\n const hosts = context.panel.data.series[0].fields[1].values;\n const reasons = context.panel.data.series[0].fields[2].values;\n const eventTimes = context.panel.data.series[0].fields[3].values;\n\n // Create a hierarchical structure for the tree chart starting with ClusterName\n const hierarchy = {\n name: 'Root', // You can customize the name of the root node if needed\n children: [],\n };\n\n for (let i = 0; i < clusters.length; i++) {\n const cluster = clusters[i];\n const host = hosts[i];\n const reason = reasons[i];\n const eventTime = eventTimes[i];\n\n // Find or create the cluster node\n let clusterNode = hierarchy.children.find((node) => node.name === cluster);\n if (!clusterNode) {\n clusterNode = { name: cluster, children: [] };\n hierarchy.children.push(clusterNode);\n }\n\n // Find or create the host node under the cluster\n let hostNode = clusterNode.children.find((node) => node.name === host);\n if (!hostNode) {\n hostNode = { name: host, children: [] };\n clusterNode.children.push(hostNode);\n }\n\n // Find or create the reason node under the host\n let reasonNode = hostNode.children.find((node) => node.name === reason);\n if (!reasonNode) {\n reasonNode = { name: reason, children: [] };\n hostNode.children.push(reasonNode);\n }\n\n // Create the eventTime node under the reason\n reasonNode.children.push({ name: eventTime });\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n },\n series: [\n {\n type: 'tree',\n data: hierarchy.children, // Use the children directly as root nodes\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%', // Adjust the right margin to provide more space for labels\n symbolSize: 7,\n label: {\n position: 'inside', // Position labels inside the node\n verticalAlign: 'middle',\n align: 'center', // Center-align labels\n fontSize: 15,\n fontWeight: 'bold',\n },\n leaves: {\n label: {\n position: 'right', // Position labels inside the node\n verticalAlign: 'middle',\n align: 'left', // Center-align labels\n fontSize: 15,\n fontWeight: 'bold',\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -367,8 +403,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -411,11 +453,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const clusterNames = data.series[0].fields[0].values; // New column for ClusterName\n const namespaces = data.series[0].fields[1].values;\n const kinds = data.series[0].fields[2].values; // Adjusted index for Kind\n const counts = data.series[0].fields[3].values; // New column for Count\n\n // Create a hierarchical structure from the data without a root node\n const hierarchy = {\n name: 'root', // Use 'root' as a placeholder\n children: [],\n };\n\n const seenClusterNames = new Set();\n const seenNamespaces = new Set();\n\n for (let i = 0; i < clusterNames.length; i++) {\n const clusterName = clusterNames[i];\n const namespace = namespaces[i];\n const kind = kinds[i];\n const count = counts[i]; // Get the count value\n\n if (!seenClusterNames.has(clusterName)) {\n seenClusterNames.add(clusterName);\n const clusterNode = { name: clusterName, children: [] };\n hierarchy.children.push(clusterNode);\n seenNamespaces.clear(); // Reset seenNamespaces for each cluster\n }\n\n const clusterNode = hierarchy.children.find((node) => node.name === clusterName);\n\n if (!seenNamespaces.has(namespace)) {\n seenNamespaces.add(namespace);\n const namespaceNode = { name: namespace, children: [] };\n clusterNode.children.push(namespaceNode);\n }\n\n const namespaceNode = clusterNode.children.find((node) => node.name === namespace);\n const kindNode = { name: kind, children: [{ name: `Count: ${count}` }] }; // Include the count as a child node\n namespaceNode.children.push(kindNode);\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n formatter: function (params) {\n const node = params.data;\n let tooltip = '';\n if (node.column) {\n tooltip += `${node.column}: ${node.name}`;\n } else {\n tooltip += node.name;\n }\n return tooltip;\n },\n },\n series: [\n {\n type: 'tree',\n data: hierarchy.children, // Use the children directly\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%',\n symbolSize: 7,\n label: {\n position: 'left',\n verticalAlign: 'middle',\n align: 'right',\n fontSize: 15, // Increase the text size for regular nodes\n fontWeight: 'bold', // Set the font weight to bold\n },\n leaves: {\n label: {\n position: 'right',\n verticalAlign: 'middle',\n align: 'left',\n fontSize: 15, // Increase the text size for leaves\n fontWeight: 'bold', // Set the font weight to bold\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;\n",
+ "getOption": "let option; // Initialize the option variable\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const clusterNames = context.panel.data.series[0].fields[0].values; // New column for ClusterName\n const namespaces = context.panel.data.series[0].fields[1].values;\n const kinds = context.panel.data.series[0].fields[2].values; // Adjusted index for Kind\n const counts = context.panel.data.series[0].fields[3].values; // New column for Count\n\n // Create a hierarchical structure from the data without a root node\n const hierarchy = {\n name: 'root', // Use 'root' as a placeholder\n children: [],\n };\n\n const seenClusterNames = new Set();\n const seenNamespaces = new Set();\n\n for (let i = 0; i < clusterNames.length; i++) {\n const clusterName = clusterNames[i];\n const namespace = namespaces[i];\n const kind = kinds[i];\n const count = counts[i]; // Get the count value\n\n if (!seenClusterNames.has(clusterName)) {\n seenClusterNames.add(clusterName);\n const clusterNode = { name: clusterName, children: [] };\n hierarchy.children.push(clusterNode);\n seenNamespaces.clear(); // Reset seenNamespaces for each cluster\n }\n\n const clusterNode = hierarchy.children.find((node) => node.name === clusterName);\n\n if (!seenNamespaces.has(namespace)) {\n seenNamespaces.add(namespace);\n const namespaceNode = { name: namespace, children: [] };\n clusterNode.children.push(namespaceNode);\n }\n\n const namespaceNode = clusterNode.children.find((node) => node.name === namespace);\n const kindNode = { name: kind, children: [{ name: `Count: ${count}` }] }; // Include the count as a child node\n namespaceNode.children.push(kindNode);\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n formatter: function (params) {\n const node = params.data;\n let tooltip = '';\n if (node.column) {\n tooltip += `${node.column}: ${node.name}`;\n } else {\n tooltip += node.name;\n }\n return tooltip;\n },\n },\n series: [\n {\n type: 'tree',\n data: hierarchy.children, // Use the children directly\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%',\n symbolSize: 7,\n label: {\n position: 'left',\n verticalAlign: 'middle',\n align: 'right',\n fontSize: 15, // Increase the text size for regular nodes\n fontWeight: 'bold', // Set the font weight to bold\n },\n leaves: {\n label: {\n position: 'right',\n verticalAlign: 'middle',\n align: 'left',\n fontSize: 15, // Increase the text size for leaves\n fontWeight: 'bold', // Set the font weight to bold\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -426,8 +469,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -466,8 +515,7 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -706,8 +754,9 @@ data:
"timezone": "",
"title": "Kubedata",
"uid": "Qq-FK1rVz",
- "version": 2,
+ "version": 3,
"weekStart": ""
}
+
{{- end }}
\ No newline at end of file
diff --git a/charts/client/templates/configmap-kuberhealthy-dashboard.yaml b/charts/client/templates/configmap-kuberhealthy-dashboard.yaml
index 6221c6ac..70e94c26 100644
--- a/charts/client/templates/configmap-kuberhealthy-dashboard.yaml
+++ b/charts/client/templates/configmap-kuberhealthy-dashboard.yaml
@@ -56,7 +56,7 @@ data:
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const namespaces = data.series[0].fields[0].values;\n const counts = data.series[0].fields[1].values;\n\n // Create a hierarchical structure from the data with a default cluster node\n const hierarchy = {\n name: 'CheckName', // Default cluster node\n children: [],\n };\n\n // Create an object to store namespaces and their counts\n const namespaceCounts = {};\n\n // Populate the namespaceCounts object with namespaces and counts\n for (let i = 0; i < namespaces.length; i++) {\n const namespace = namespaces[i];\n const count = counts[i];\n\n if (!namespaceCounts[namespace]) {\n namespaceCounts[namespace] = count;\n } else {\n namespaceCounts[namespace] += count;\n }\n }\n\n // Create nodes for each namespace and add them as children of the default cluster node\n for (const namespace in namespaceCounts) {\n hierarchy.children.push({\n name: namespace,\n children: [{ name: `${namespaceCounts[namespace]}` }],\n });\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n formatter: function (params) {\n const node = params.data;\n let tooltip = '';\n if (node.column) {\n tooltip += `${node.column}: ${node.name}`;\n } else {\n tooltip += node.name;\n }\n return tooltip;\n },\n },\n series: [\n {\n type: 'tree',\n data: [hierarchy], // Use the hierarchy object as the data\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%',\n symbolSize: 7,\n label: {\n position: 'left',\n verticalAlign: 'middle',\n align: 'centre',\n fontSize: 15, // Increase the text size for regular nodes\n fontWeight: 'bold', // Set the font weight to bold\n },\n leaves: {\n label: {\n position: 'right',\n verticalAlign: 'middle',\n align: 'left',\n fontSize: 15, // Increase the text size for leaves\n fontWeight: 'bold', // Set the font weight to bold\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;\n",
+ "getOption": "let option; // Initialize the option variable\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const namespaces = context.panel.data.series[0].fields[0].values;\n const counts = context.panel.data.series[0].fields[1].values;\n\n // Create a hierarchical structure from the data with a default cluster node\n const hierarchy = {\n name: 'CheckName', // Default cluster node\n children: [],\n };\n\n // Create an object to store namespaces and their counts\n const namespaceCounts = {};\n\n // Populate the namespaceCounts object with namespaces and counts\n for (let i = 0; i < namespaces.length; i++) {\n const namespace = namespaces[i];\n const count = counts[i];\n\n if (!namespaceCounts[namespace]) {\n namespaceCounts[namespace] = count;\n } else {\n namespaceCounts[namespace] += count;\n }\n }\n\n // Create nodes for each namespace and add them as children of the default cluster node\n for (const namespace in namespaceCounts) {\n hierarchy.children.push({\n name: namespace,\n children: [{ name: `${namespaceCounts[namespace]}` }],\n });\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n formatter: function (params) {\n const node = params.data;\n let tooltip = '';\n if (node.column) {\n tooltip += `${node.column}: ${node.name}`;\n } else {\n tooltip += node.name;\n }\n return tooltip;\n },\n },\n series: [\n {\n type: 'tree',\n data: [hierarchy], // Use the hierarchy object as the data\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%',\n symbolSize: 7,\n label: {\n position: 'left',\n verticalAlign: 'middle',\n align: 'centre',\n fontSize: 15, // Increase the text size for regular nodes\n fontWeight: 'bold', // Set the font weight to bold\n },\n leaves: {\n label: {\n position: 'right',\n verticalAlign: 'middle',\n align: 'left',\n fontSize: 15, // Increase the text size for leaves\n fontWeight: 'bold', // Set the font weight to bold\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -124,7 +124,7 @@ data:
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const namespaces = data.series[0].fields[0].values;\n const counts = data.series[0].fields[1].values;\n\n // Create a hierarchical structure from the data with a default cluster node\n const hierarchy = {\n name: 'CheckName', // Default cluster node\n children: [],\n };\n\n // Create an object to store namespaces and their counts\n const namespaceCounts = {};\n\n // Populate the namespaceCounts object with namespaces and counts\n for (let i = 0; i < namespaces.length; i++) {\n const namespace = namespaces[i];\n const count = counts[i];\n\n if (!namespaceCounts[namespace]) {\n namespaceCounts[namespace] = count;\n } else {\n namespaceCounts[namespace] += count;\n }\n }\n\n // Create nodes for each namespace and add them as children of the default cluster node\n for (const namespace in namespaceCounts) {\n hierarchy.children.push({\n name: namespace,\n children: [{ name: `${namespaceCounts[namespace]}` }],\n });\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n formatter: function (params) {\n const node = params.data;\n let tooltip = '';\n if (node.column) {\n tooltip += `${node.column}: ${node.name}`;\n } else {\n tooltip += node.name;\n }\n return tooltip;\n },\n },\n series: [\n {\n type: 'tree',\n data: [hierarchy], // Use the hierarchy object as the data\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%',\n symbolSize: 7,\n label: {\n position: 'left',\n verticalAlign: 'middle',\n align: 'centre',\n fontSize: 15, // Increase the text size for regular nodes\n fontWeight: 'bold', // Set the font weight to bold\n },\n leaves: {\n label: {\n position: 'right',\n verticalAlign: 'middle',\n align: 'left',\n fontSize: 15, // Increase the text size for leaves\n fontWeight: 'bold', // Set the font weight to bold\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;\n",
+ "getOption": "let option; // Initialize the option variable\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const namespaces = context.panel.data.series[0].fields[0].values;\n const counts = context.panel.data.series[0].fields[1].values;\n\n // Create a hierarchical structure from the data with a default cluster node\n const hierarchy = {\n name: 'CheckName', // Default cluster node\n children: [],\n };\n\n // Create an object to store namespaces and their counts\n const namespaceCounts = {};\n\n // Populate the namespaceCounts object with namespaces and counts\n for (let i = 0; i < namespaces.length; i++) {\n const namespace = namespaces[i];\n const count = counts[i];\n\n if (!namespaceCounts[namespace]) {\n namespaceCounts[namespace] = count;\n } else {\n namespaceCounts[namespace] += count;\n }\n }\n\n // Create nodes for each namespace and add them as children of the default cluster node\n for (const namespace in namespaceCounts) {\n hierarchy.children.push({\n name: namespace,\n children: [{ name: `${namespaceCounts[namespace]}` }],\n });\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n formatter: function (params) {\n const node = params.data;\n let tooltip = '';\n if (node.column) {\n tooltip += `${node.column}: ${node.name}`;\n } else {\n tooltip += node.name;\n }\n return tooltip;\n },\n },\n series: [\n {\n type: 'tree',\n data: [hierarchy], // Use the hierarchy object as the data\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%',\n symbolSize: 7,\n label: {\n position: 'left',\n verticalAlign: 'middle',\n align: 'centre',\n fontSize: 15, // Increase the text size for regular nodes\n fontWeight: 'bold', // Set the font weight to bold\n },\n leaves: {\n label: {\n position: 'right',\n verticalAlign: 'middle',\n align: 'left',\n fontSize: 15, // Increase the text size for leaves\n fontWeight: 'bold', // Set the font weight to bold\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -1210,7 +1210,8 @@ data:
"timezone": "",
"title": "KuberHealth",
"uid": "d946c53c-8b1d-4e3c-9154-4219165342",
- "version": 2,
+ "version": 3,
"weekStart": ""
}
+
{{- end }}
\ No newline at end of file
diff --git a/charts/client/templates/configmap-kubviz-dashboard.yaml b/charts/client/templates/configmap-kubviz-dashboard.yaml
index 6ee2c56c..206fc3d8 100644
--- a/charts/client/templates/configmap-kubviz-dashboard.yaml
+++ b/charts/client/templates/configmap-kubviz-dashboard.yaml
@@ -32,7 +32,7 @@ data:
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
- "id": 32,
+ "id": 64,
"links": [],
"liveNow": false,
"panels": [
@@ -205,11 +205,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const reasons = data.series[0].fields[0].values;\n const kinds = data.series[0].fields[1].values;\n const eventTimes = data.series[0].fields[2].values;\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n reasons.forEach((reason, index) => {\n const sourceNode = {\n name: reason,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const kindNode = {\n name: kinds[index],\n category: 1, // Category for kind nodes\n symbolSize: 40, // Size for kind nodes\n };\n\n const eventTimeNode = {\n name: eventTimes[index],\n category: 2, // Category for eventTime nodes\n symbolSize: 20, // Size for eventTime nodes\n };\n\n // Ensure source, kind, and eventTime nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === kindNode.name)) {\n nodes.push(kindNode);\n }\n\n if (!nodes.some((node) => node.name === eventTimeNode.name)) {\n nodes.push(eventTimeNode);\n }\n\n // Create links between reason, kind, and eventTime nodes\n links.push({\n source: reason,\n target: kinds[index],\n });\n\n links.push({\n source: kinds[index],\n target: eventTimes[index],\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Reasons',\n },\n {\n name: 'Nodes',\n },\n {\n name: 'Event Times',\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Reasons', 'Nodes', 'Event Times'],\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: {\n color: '#000',\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n edgeSymbolSize: [12, 12],\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Handle the case when data.series does not exist\n return {};\n}",
+ "getOption": "// Check if context.panel.data.series exists\nif (context.panel.data.series && context.panel.data.series.length > 0) {\n const reasons = context.panel.data.series[0].fields[0].values;\n const kinds = context.panel.data.series[0].fields[1].values;\n const eventTimes = context.panel.data.series[0].fields[2].values;\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n reasons.forEach((reason, index) => {\n const sourceNode = {\n name: reason,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const kindNode = {\n name: kinds[index],\n category: 1, // Category for kind nodes\n symbolSize: 40, // Size for kind nodes\n };\n\n const eventTimeNode = {\n name: eventTimes[index],\n category: 2, // Category for eventTime nodes\n symbolSize: 20, // Size for eventTime nodes\n };\n\n // Ensure source, kind, and eventTime nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === kindNode.name)) {\n nodes.push(kindNode);\n }\n\n if (!nodes.some((node) => node.name === eventTimeNode.name)) {\n nodes.push(eventTimeNode);\n }\n\n // Create links between reason, kind, and eventTime nodes\n links.push({\n source: reason,\n target: kinds[index],\n });\n\n links.push({\n source: kinds[index],\n target: eventTimes[index],\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Reasons',\n },\n {\n name: 'Nodes',\n },\n {\n name: 'Event Times',\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Reasons', 'Nodes', 'Event Times'],\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: {\n color: '#000',\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n edgeSymbolSize: [12, 12],\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display \"Data not available\" in the panel\n return {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n}\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -220,8 +221,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -264,11 +271,12 @@ data:
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let kind = [];\nlet resources = [];\n\ndata.series.map((s) => {\n kind = s.fields.find((f) => f.name === 'Kind').values;\n resources = s.fields.find((f) => f.name === 'Resources').values;\n});\n\n// Create an empty array to store doughnut chart data\nconst doughnutChartData = [];\n\n// Define colors for doughnut slices\nconst doughnutSliceColors = ['#235894', '#FFFF00', '#FF0000', '#00FF00', '#FFA500'];\n\n// Map severity and counts to doughnut chart data\nkind.forEach((kinddata, index) => {\n doughnutChartData.push({\n value: resources[index],\n name: kinddata,\n itemStyle: {\n borderRadius: [10, 10, 10, 10], // Add rounded corners\n color: doughnutSliceColors[index % doughnutSliceColors.length],\n borderWidth: 2,\n borderColor: '#fff',\n },\n });\n});\n\nreturn {\n backgroundColor: '#FFFFFF', // Set the background color to white\n tooltip: {\n trigger: 'item',\n },\n legend: {\n top: '5%',\n left: 'center',\n },\n series: [\n {\n name: 'Access From',\n type: 'pie',\n radius: ['40%', '70%'],\n avoidLabelOverlap: false,\n label: {\n show: false,\n position: 'center',\n },\n emphasis: {\n label: {\n show: true,\n fontSize: 40,\n fontWeight: 'bold',\n },\n },\n labelLine: {\n show: false,\n },\n data: doughnutChartData, // Use the modified doughnut chart data\n },\n ],\n};",
+ "getOption": "let kind = [];\nlet resources = [];\n\ncontext.panel.data.series.forEach((s) => {\n const kindField = s.fields.find((f) => f.name === 'Kind');\n const resourcesField = s.fields.find((f) => f.name === 'Resources');\n if (kindField && resourcesField) {\n kind = kindField.values;\n resources = resourcesField.values;\n }\n});\n\n// Create an empty array to store doughnut chart data\nconst doughnutChartData = [];\n\n// Define colors for doughnut slices\nconst doughnutSliceColors = ['#235894', '#FFFF00', '#FF0000', '#00FF00', '#FFA500'];\n\n// Map kind and resources counts to doughnut chart data\nkind.forEach((kinddata, index) => {\n doughnutChartData.push({\n value: resources[index],\n name: kinddata,\n clusterName: context.panel.data.series[0].fields[0].values[index], // Extract cluster name\n itemStyle: {\n borderRadius: [10, 10, 10, 10], // Add rounded corners\n color: doughnutSliceColors[index % doughnutSliceColors.length],\n borderWidth: 2,\n borderColor: '#fff',\n },\n });\n});\n\nreturn {\n backgroundColor: '#FFFFFF', // Set the background color to white\n tooltip: {\n trigger: 'item',\n formatter: function (params) {\n return `Resource From
${params.data.clusterName} ${params.value}`;\n },\n },\n legend: {\n top: '5%',\n left: 'center',\n },\n series: [\n {\n name: '',\n type: 'pie',\n radius: ['40%', '70%'],\n avoidLabelOverlap: false,\n label: {\n show: false,\n position: 'center',\n },\n emphasis: {\n label: {\n show: true,\n fontSize: 40,\n fontWeight: 'bold',\n },\n },\n labelLine: {\n show: false,\n },\n data: doughnutChartData, // Use the modified doughnut chart data\n },\n ],\n};\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -279,8 +287,14 @@ data:
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -576,8 +590,7 @@ data:
"mode": "percentage",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -646,8 +659,7 @@ data:
"mode": "percentage",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -716,8 +728,7 @@ data:
"mode": "percentage",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -786,8 +797,7 @@ data:
"mode": "percentage",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -856,8 +866,7 @@ data:
"mode": "percentage",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -959,8 +968,7 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1060,8 +1068,7 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -3112,7 +3119,8 @@ data:
"timezone": "",
"title": "Kubviz Dashboard",
"uid": "eT4fox94z",
- "version": 1,
+ "version": 4,
"weekStart": ""
}
+
{{- end }}
\ No newline at end of file
diff --git a/charts/client/templates/configmap-trivy-dashboard.yaml b/charts/client/templates/configmap-trivy-dashboard.yaml
index d762bc19..93ef604e 100644
--- a/charts/client/templates/configmap-trivy-dashboard.yaml
+++ b/charts/client/templates/configmap-trivy-dashboard.yaml
@@ -32,7 +32,7 @@ data:
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
- "id": 106,
+ "id": 58,
"links": [],
"liveNow": false,
"panels": [
@@ -140,12 +140,13 @@ data:
"uid": "{{ .Values.datasources.uid }}"
},
"dateTimeType": "DATETIME",
+ "editorMode": "builder",
"extrapolate": true,
"format": "table",
"formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t",
"intervalFactor": 1,
- "query": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_severity = 'LOW'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
- "rawQuery": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_severity = 'LOW'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
+ "query": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE $timeFilterByColumn(vul_last_modified_date) AND vul_severity = 'LOW'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
+ "rawQuery": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_last_modified_date >= toDateTime(1712241666) AND vul_last_modified_date <= toDateTime(1712328066) AND vul_severity = 'LOW'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
"refId": "A",
"round": "0s",
"skip_comments": true
@@ -247,12 +248,13 @@ data:
"uid": "{{ .Values.datasources.uid }}"
},
"dateTimeType": "DATETIME",
+ "editorMode": "builder",
"extrapolate": true,
"format": "table",
"formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t",
"intervalFactor": 1,
- "query": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_severity = 'HIGH'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
- "rawQuery": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_severity = 'HIGH'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
+ "query": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE $timeFilterByColumn(vul_last_modified_date) AND vul_severity = 'HIGH'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
+ "rawQuery": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_last_modified_date >= toDateTime(1712241678) AND vul_last_modified_date <= toDateTime(1712328078) AND vul_severity = 'HIGH'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
"refId": "A",
"round": "0s",
"skip_comments": true
@@ -354,12 +356,13 @@ data:
"uid": "{{ .Values.datasources.uid }}"
},
"dateTimeType": "DATETIME",
+ "editorMode": "builder",
"extrapolate": true,
"format": "table",
"formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t",
"intervalFactor": 1,
- "query": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_severity = 'MEDIUM'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
- "rawQuery": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_severity = 'MEDIUM'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
+ "query": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE $timeFilterByColumn(vul_last_modified_date) AND vul_severity = 'MEDIUM'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
+ "rawQuery": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_last_modified_date >= toDateTime(1712241603) AND vul_last_modified_date <= toDateTime(1712328003) AND vul_severity = 'MEDIUM'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
"refId": "A",
"round": "0s",
"skip_comments": true
@@ -461,12 +464,13 @@ data:
"uid": "{{ .Values.datasources.uid }}"
},
"dateTimeType": "DATETIME",
+ "editorMode": "builder",
"extrapolate": true,
"format": "table",
"formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t",
"intervalFactor": 1,
- "query": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_severity = 'CRITICAL'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
- "rawQuery": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_severity = 'CRITICAL'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
+ "query": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE $timeFilterByColumn(vul_last_modified_date) AND vul_severity = 'CRITICAL'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
+ "rawQuery": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_last_modified_date >= toDateTime(1712241618) AND vul_last_modified_date <= toDateTime(1712328018) AND vul_severity = 'CRITICAL'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
"refId": "A",
"round": "0s",
"skip_comments": true
@@ -498,8 +502,7 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "light-blue",
- "value": null
+ "color": "light-blue"
}
]
}
@@ -549,12 +552,13 @@ data:
"uid": "{{ .Values.datasources.uid }}"
},
"dateTimeType": "DATETIME",
+ "editorMode": "builder",
"extrapolate": true,
"format": "table",
"formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t",
"intervalFactor": 1,
- "query": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_severity = 'LOW'",
- "rawQuery": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_severity = 'LOW'",
+ "query": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE $timeFilterByColumn(vul_last_modified_date) AND vul_severity = 'LOW'",
+ "rawQuery": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_last_modified_date >= toDateTime(1712241558) AND vul_last_modified_date <= toDateTime(1712327958) AND vul_severity = 'LOW'",
"refId": "A",
"round": "0s",
"skip_comments": true
@@ -586,8 +590,7 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
}
]
}
@@ -637,12 +640,13 @@ data:
"uid": "{{ .Values.datasources.uid }}"
},
"dateTimeType": "DATETIME",
+ "editorMode": "builder",
"extrapolate": true,
"format": "table",
"formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t",
"intervalFactor": 1,
- "query": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_severity = 'MEDIUM'",
- "rawQuery": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_severity = 'MEDIUM'",
+ "query": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE $timeFilterByColumn(vul_last_modified_date) AND vul_severity = 'MEDIUM'",
+ "rawQuery": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_last_modified_date >= toDateTime(1712241583) AND vul_last_modified_date <= toDateTime(1712327983) AND vul_severity = 'MEDIUM'",
"refId": "A",
"round": "0s",
"skip_comments": true
@@ -674,8 +678,7 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "super-light-orange",
- "value": null
+ "color": "super-light-orange"
}
]
}
@@ -725,12 +728,13 @@ data:
"uid": "{{ .Values.datasources.uid }}"
},
"dateTimeType": "DATETIME",
+ "editorMode": "builder",
"extrapolate": true,
"format": "table",
"formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t",
"intervalFactor": 1,
- "query": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_severity = 'HIGH'",
- "rawQuery": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_severity = 'HIGH'",
+ "query": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE $timeFilterByColumn(vul_last_modified_date) AND vul_severity = 'HIGH'",
+ "rawQuery": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_last_modified_date >= toDateTime(1712241526) AND vul_last_modified_date <= toDateTime(1712327926) AND vul_severity = 'HIGH'",
"refId": "A",
"round": "0s",
"skip_comments": true
@@ -762,8 +766,7 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "red",
- "value": null
+ "color": "red"
}
]
}
@@ -813,12 +816,13 @@ data:
"uid": "{{ .Values.datasources.uid }}"
},
"dateTimeType": "DATETIME",
+ "editorMode": "builder",
"extrapolate": true,
"format": "table",
"formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t",
"intervalFactor": 1,
- "query": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_severity = 'CRITICAL'",
- "rawQuery": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_severity = 'CRITICAL'",
+ "query": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE $timeFilterByColumn(vul_last_modified_date) AND vul_severity = 'CRITICAL'",
+ "rawQuery": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_last_modified_date >= toDateTime(1712241543) AND vul_last_modified_date <= toDateTime(1712327943) AND vul_severity = 'CRITICAL'",
"refId": "A",
"round": "0s",
"skip_comments": true
@@ -850,8 +854,7 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -923,8 +926,7 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -978,12 +980,13 @@ data:
"uid": "{{ .Values.datasources.uid }}"
},
"dateTimeType": "DATETIME",
+ "editorMode": "builder",
"extrapolate": true,
"format": "table",
"formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t",
"intervalFactor": 1,
- "query": "SELECT vul_id, count(artifact_name) AS images\nFROM default.trivyimage\nGROUP BY vul_id",
- "rawQuery": "SELECT vul_id, count(artifact_name) AS images\nFROM default.trivyimage\nGROUP BY vul_id",
+ "query": "SELECT vul_id, count(artifact_name) AS images\nFROM default.trivyimage\nWHERE $timeFilterByColumn(vul_last_modified_date)\nGROUP BY vul_id",
+ "rawQuery": "SELECT vul_id, count(artifact_name) AS images\nFROM default.trivyimage\nWHERE vul_last_modified_date >= toDateTime(1712241498) AND vul_last_modified_date <= toDateTime(1712327898)\nGROUP BY vul_id",
"refId": "A",
"round": "0s",
"skip_comments": true
@@ -1016,8 +1019,7 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
}
]
}
@@ -1089,8 +1091,7 @@ data:
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
}
]
}
@@ -2407,7 +2408,8 @@ data:
"timezone": "",
"title": "Trivy",
"uid": "f9b0a865-f419-410a-b7d9-9a3f79a70d48",
- "version": 13,
+ "version": 2,
"weekStart": ""
}
+
{{- end }}
\ No newline at end of file
diff --git a/grafana/azure-dashboard.json b/grafana/azure-dashboard.json
index bea62afc..b90566c4 100644
--- a/grafana/azure-dashboard.json
+++ b/grafana/azure-dashboard.json
@@ -15,7 +15,7 @@
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
- "id": 33,
+ "id": 53,
"links": [],
"liveNow": false,
"panels": [
@@ -40,11 +40,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}",
+ "getOption": "// Check if data.series exists\nif (context.panel.data.series && context.panel.data.series.length > 0) {\n const eventTypes = context.panel.data.series[0].fields[0].values;\n const authors = context.panel.data.series[0].fields[1].values;\n const repoNames = context.panel.data.series[0].fields[2].values;\n const total = context.panel.data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}",
"google": {
"callback": "gmapReady",
"key": ""
@@ -55,8 +56,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -99,11 +106,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let options; // Initialize the options variable\n\nif (!data || !data.series || data.series.length === 0 || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n",
+ "getOption": "let options; // Initialize the options variable\n\nif (!context.panel.data || !context.panel.data.series || context.panel.data.series.length === 0 || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = context.panel.data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = context.panel.data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -114,8 +122,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -158,11 +172,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n",
+ "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = context.panel.data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = context.panel.data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -173,8 +188,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -212,7 +233,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -282,7 +304,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -359,7 +382,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
}
]
}
@@ -415,7 +439,11 @@
"templating": {
"list": [
{
- "current": {},
+ "current": {
+ "selected": false,
+ "text": "All",
+ "value": "$__all"
+ },
"datasource": {
"type": "vertamedia-clickhouse-datasource",
"uid": "vertamedia-clickhouse-datasource"
@@ -434,7 +462,11 @@
"type": "query"
},
{
- "current": {},
+ "current": {
+ "selected": false,
+ "text": "All",
+ "value": "$__all"
+ },
"datasource": {
"type": "vertamedia-clickhouse-datasource",
"uid": "vertamedia-clickhouse-datasource"
@@ -462,6 +494,6 @@
"timezone": "",
"title": "Azure",
"uid": "dd66838a-ffda-4de2-944f-1828d1671fc9",
- "version": 1,
+ "version": 2,
"weekStart": ""
-}
\ No newline at end of file
+}
diff --git a/grafana/bitBucket-dashboard.json b/grafana/bitBucket-dashboard.json
index 389c001c..63d77351 100644
--- a/grafana/bitBucket-dashboard.json
+++ b/grafana/bitBucket-dashboard.json
@@ -15,7 +15,7 @@
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
- "id": 34,
+ "id": 60,
"links": [],
"liveNow": false,
"panels": [
@@ -40,11 +40,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}",
+ "getOption": "// Check if data.series exists\nif (context.panel.data.series && context.panel.data.series.length > 0) {\n const eventTypes = context.panel.data.series[0].fields[0].values;\n const authors = context.panel.data.series[0].fields[1].values;\n const repoNames = context.panel.data.series[0].fields[2].values;\n const total = context.panel.data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}",
"google": {
"callback": "gmapReady",
"key": ""
@@ -55,8 +56,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -99,11 +106,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let options; // Initialize the options variable\n\nif (!data || !data.series || data.series.length === 0 || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n",
+ "getOption": "let options; // Initialize the options variable\n\nif (!context.panel.data || !context.panel.data.series || context.panel.data.series.length === 0 || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = context.panel.data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = context.panel.data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -114,8 +122,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -158,11 +172,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n",
+ "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = context.panel.data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = context.panel.data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -173,8 +188,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -212,7 +233,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -282,7 +304,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -440,8 +463,8 @@
{
"current": {
"selected": false,
- "text": "",
- "value": ""
+ "text": "All",
+ "value": "$__all"
},
"datasource": {
"type": "vertamedia-clickhouse-datasource",
@@ -470,6 +493,6 @@
"timezone": "",
"title": "BitBucket",
"uid": "a7772dd5-76c7-48f3-8462-b39fbc20941c",
- "version": 1,
+ "version": 2,
"weekStart": ""
-}
\ No newline at end of file
+}
diff --git a/grafana/giTea-dashboard.json b/grafana/giTea-dashboard.json
index da0e63a2..9dccd2af 100644
--- a/grafana/giTea-dashboard.json
+++ b/grafana/giTea-dashboard.json
@@ -15,7 +15,7 @@
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
- "id": 35,
+ "id": 61,
"links": [],
"liveNow": false,
"panels": [
@@ -40,11 +40,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}",
+ "getOption": "// Check if data.series exists\nif (context.panel.data.series && context.panel.data.series.length > 0) {\n const eventTypes = context.panel.data.series[0].fields[0].values;\n const authors = context.panel.data.series[0].fields[1].values;\n const repoNames = context.panel.data.series[0].fields[2].values;\n const total = context.panel.data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}",
"google": {
"callback": "gmapReady",
"key": ""
@@ -55,8 +56,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -99,11 +106,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let options; // Initialize the options variable\n\nif (!data || !data.series || data.series.length === 0 || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n",
+ "getOption": "let options; // Initialize the options variable\n\nif (!context.panel.data || !context.panel.data.series || context.panel.data.series.length === 0 || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = context.panel.data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = context.panel.data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -114,8 +122,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -158,11 +172,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n",
+ "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = context.panel.data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = context.panel.data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -173,8 +188,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -212,7 +233,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -282,7 +304,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -359,7 +382,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
}
]
}
@@ -416,9 +440,13 @@
"list": [
{
"current": {
- "selected": false,
- "text": "All",
- "value": "$__all"
+ "selected": true,
+ "text": [
+ "All"
+ ],
+ "value": [
+ "$__all"
+ ]
},
"datasource": {
"type": "vertamedia-clickhouse-datasource",
@@ -440,8 +468,8 @@
{
"current": {
"selected": false,
- "text": "",
- "value": ""
+ "text": "All",
+ "value": "$__all"
},
"datasource": {
"type": "vertamedia-clickhouse-datasource",
@@ -470,6 +498,6 @@
"timezone": "",
"title": "GiTea",
"uid": "a1c6d705-91b0-4718-99b2-d93b0221bca9",
- "version": 1,
+ "version": 2,
"weekStart": ""
-}
\ No newline at end of file
+}
diff --git a/grafana/gitHub-dashboard.json b/grafana/gitHub-dashboard.json
index 8b3930db..2c3a5786 100644
--- a/grafana/gitHub-dashboard.json
+++ b/grafana/gitHub-dashboard.json
@@ -15,7 +15,7 @@
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
- "id": 37,
+ "id": 57,
"links": [],
"liveNow": false,
"panels": [
@@ -40,11 +40,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Handle the case when data.series does not exist\n return {};\n}",
+ "getOption": "// Check if data.series exists\nif (context.panel.data.series && context.panel.data.series.length > 0) {\n const eventTypes = context.panel.data.series[0].fields[0].values;\n const authors = context.panel.data.series[0].fields[1].values;\n const repoNames = context.panel.data.series[0].fields[2].values;\n const total = context.panel.data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Handle the case when data.series does not exist\n return {};\n}",
"google": {
"callback": "gmapReady",
"key": ""
@@ -55,9 +56,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
- "pluginVersion": "10.0.3",
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -100,11 +106,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let options; // Initialize the options variable\n\nif (!data || !data.series || data.series.length === 0 || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n",
+ "getOption": "let options; // Initialize the options variable\n\nif (!context.panel.data || !context.panel.data.series || context.panel.data.series.length === 0 || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = context.panel.data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = context.panel.data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -115,8 +122,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -159,11 +172,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n",
+ "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = context.panel.data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = context.panel.data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -174,8 +188,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -218,11 +238,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "const values = data.series[0].fields[0].values;\n\nreturn {\n series: [\n {\n type: 'liquidFill',\n radius: '90%',\n data: values, // Use the raw values here\n label: {\n formatter: '{a|{c}}',\n rich: {\n a: {\n color: '#000', // You can set the text color here\n },\n },\n },\n tooltip: {\n formatter: '{a}: {c}', // This formatter displays the raw values\n },\n },\n ],\n};\n",
+ "getOption": "const values = context.panel.data.series[0].fields[0].values;\n\nreturn {\n series: [\n {\n type: 'liquidFill',\n radius: '90%',\n data: values, // Use the raw values here\n label: {\n formatter: '{a|{c}}',\n rich: {\n a: {\n color: '#000', // You can set the text color here\n },\n },\n },\n tooltip: {\n formatter: '{a}: {c}', // This formatter displays the raw values\n },\n },\n ],\n};\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -233,8 +254,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -277,11 +304,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "const values = data.series[0].fields[0].values;\n\nreturn {\n series: [\n {\n type: 'liquidFill',\n radius: '90%',\n data: values, // Use the raw values here\n label: {\n formatter: '{a|{c}}',\n rich: {\n a: {\n color: '#000', // You can set the text color here\n },\n },\n },\n tooltip: {\n formatter: '{a}: {c}', // This formatter displays the raw values\n },\n },\n ],\n};\n",
+ "getOption": "const values = context.panel.data.series[0].fields[0].values;\n\nreturn {\n series: [\n {\n type: 'liquidFill',\n radius: '90%',\n data: values, // Use the raw values here\n label: {\n formatter: '{a|{c}}',\n rich: {\n a: {\n color: '#000', // You can set the text color here\n },\n },\n },\n tooltip: {\n formatter: '{a}: {c}', // This formatter displays the raw values\n },\n },\n ],\n};\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -292,8 +320,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -338,7 +372,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
}
]
}
@@ -395,9 +430,13 @@
"list": [
{
"current": {
- "selected": false,
- "text": "",
- "value": ""
+ "selected": true,
+ "text": [
+ "ahinvinith"
+ ],
+ "value": [
+ "ahinvinith"
+ ]
},
"datasource": {
"type": "vertamedia-clickhouse-datasource",
@@ -455,4 +494,4 @@
"uid": "ef91218c-94cb-48b1-be1d-0bafe848b75c",
"version": 2,
"weekStart": ""
-}
\ No newline at end of file
+}
diff --git a/grafana/gitLab-dashboard.json b/grafana/gitLab-dashboard.json
index 00c49d0b..b6517a4c 100644
--- a/grafana/gitLab-dashboard.json
+++ b/grafana/gitLab-dashboard.json
@@ -15,7 +15,7 @@
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
- "id": 36,
+ "id": 59,
"links": [],
"liveNow": false,
"panels": [
@@ -40,11 +40,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}",
+ "getOption": "// Check if data.series exists\nif (context.panel.data.series && context.panel.data.series.length > 0) {\n const eventTypes = context.panel.data.series[0].fields[0].values;\n const authors = context.panel.data.series[0].fields[1].values;\n const repoNames = context.panel.data.series[0].fields[2].values;\n const total = context.panel.data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}",
"google": {
"callback": "gmapReady",
"key": ""
@@ -55,8 +56,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -99,11 +106,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let options; // Initialize the options variable\n\nif (!data || !data.series || data.series.length === 0 || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n",
+ "getOption": "let options; // Initialize the options variable\n\nif (!context.panel.data || !context.panel.data.series || context.panel.data.series.length === 0 || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = context.panel.data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = context.panel.data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -114,8 +122,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -158,11 +172,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n",
+ "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = context.panel.data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = context.panel.data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -173,8 +188,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -212,7 +233,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -282,7 +304,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -359,7 +382,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -474,6 +498,6 @@
"timezone": "",
"title": "GitLab",
"uid": "ec8b9cb1-f9ae-4139-b270-4824b6508eff",
- "version": 1,
+ "version": 2,
"weekStart": ""
-}
\ No newline at end of file
+}
diff --git a/grafana/kubeData-dashboard.json b/grafana/kubeData-dashboard.json
index 5b351bf5..998bc514 100644
--- a/grafana/kubeData-dashboard.json
+++ b/grafana/kubeData-dashboard.json
@@ -21,7 +21,7 @@
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
- "id": 146,
+ "id": 56,
"links": [],
"liveNow": false,
"panels": [
@@ -46,11 +46,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const clusterNames = data.series[0].fields[0].values;\n const namespaces = data.series[0].fields[1].values;\n const reasons = data.series[0].fields[2].values;\n const pods = data.series[0].fields[3].values;\n\n // Create a hierarchical structure from the data without a root node\n const hierarchy = {\n name: 'root', // Use 'root' as a placeholder\n children: [],\n };\n\n const seenClusterNames = new Set();\n const seenNamespaces = new Set();\n\n for (let i = 0; i < clusterNames.length; i++) {\n const clusterName = clusterNames[i];\n const namespace = namespaces[i];\n const reason = reasons[i];\n const pod = pods[i];\n\n if (!seenClusterNames.has(clusterName)) {\n seenClusterNames.add(clusterName);\n const clusterNode = { name: clusterName, children: [] };\n hierarchy.children.push(clusterNode);\n seenNamespaces.clear(); // Reset seenNamespaces for each cluster\n }\n\n const clusterNode = hierarchy.children.find((node) => node.name === clusterName);\n\n if (!seenNamespaces.has(namespace)) {\n seenNamespaces.add(namespace);\n const namespaceNode = { name: namespace, children: [] };\n clusterNode.children.push(namespaceNode);\n }\n\n const namespaceNode = clusterNode.children.find((node) => node.name === namespace);\n const reasonNode = { name: reason, children: [{ name: `Count: ${pod}` }] };\n namespaceNode.children.push(reasonNode);\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n formatter: function (params) {\n const node = params.data;\n let tooltip = '';\n if (node.column) {\n tooltip += `${node.column}: ${node.name}`;\n } else {\n tooltip += node.name;\n }\n return tooltip;\n },\n },\n series: [\n {\n type: 'tree',\n data: hierarchy.children, // Use the children directly\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%',\n symbolSize: 7,\n label: {\n position: 'left',\n verticalAlign: 'middle',\n align: 'centre',\n fontSize: 15, // Increase the text size for regular nodes\n fontWeight: 'bold', // Set the font weight to bold\n },\n leaves: {\n label: {\n position: 'right',\n verticalAlign: 'middle',\n align: 'left',\n fontSize: 15, // Increase the text size for leaves\n fontWeight: 'bold', // Set the font weight to bold\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;",
+ "getOption": "let option; // Initialize the option variable\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const clusterNames = context.panel.data.series[0].fields[0].values;\n const namespaces = context.panel.data.series[0].fields[1].values;\n const reasons = context.panel.data.series[0].fields[2].values;\n const pods = context.panel.data.series[0].fields[3].values;\n\n // Create a hierarchical structure from the data without a root node\n const hierarchy = {\n name: 'root', // Use 'root' as a placeholder\n children: [],\n };\n\n const seenClusterNames = new Set();\n const seenNamespaces = new Set();\n\n for (let i = 0; i < clusterNames.length; i++) {\n const clusterName = clusterNames[i];\n const namespace = namespaces[i];\n const reason = reasons[i];\n const pod = pods[i];\n\n if (!seenClusterNames.has(clusterName)) {\n seenClusterNames.add(clusterName);\n const clusterNode = { name: clusterName, children: [] };\n hierarchy.children.push(clusterNode);\n seenNamespaces.clear(); // Reset seenNamespaces for each cluster\n }\n\n const clusterNode = hierarchy.children.find((node) => node.name === clusterName);\n\n if (!seenNamespaces.has(namespace)) {\n seenNamespaces.add(namespace);\n const namespaceNode = { name: namespace, children: [] };\n clusterNode.children.push(namespaceNode);\n }\n\n const namespaceNode = clusterNode.children.find((node) => node.name === namespace);\n const reasonNode = { name: reason, children: [{ name: `Count: ${pod}` }] };\n namespaceNode.children.push(reasonNode);\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n formatter: function (params) {\n const node = params.data;\n let tooltip = '';\n if (node.column) {\n tooltip += `${node.column}: ${node.name}`;\n } else {\n tooltip += node.name;\n }\n return tooltip;\n },\n },\n series: [\n {\n type: 'tree',\n data: hierarchy.children, // Use the children directly\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%',\n symbolSize: 7,\n label: {\n position: 'left',\n verticalAlign: 'middle',\n align: 'centre',\n fontSize: 15, // Increase the text size for regular nodes\n fontWeight: 'bold', // Set the font weight to bold\n },\n leaves: {\n label: {\n position: 'right',\n verticalAlign: 'middle',\n align: 'left',\n fontSize: 15, // Increase the text size for leaves\n fontWeight: 'bold', // Set the font weight to bold\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;",
"google": {
"callback": "gmapReady",
"key": ""
@@ -61,8 +62,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -105,11 +112,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const reasons = data.series[0].fields[0].values;\n const counts = data.series[0].fields[1].values;\n\n // Check if reasons and counts are defined and not empty\n if (!reasons || !counts || reasons.length === 0 || counts.length === 0) {\n // Display a message when no data is available\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n } else {\n // Data is available, proceed with the chart creation\n // Create an array of data items, each containing name and value\n const seriesData = reasons.map((reason, index) => ({\n name: reason,\n value: counts[index],\n }));\n\n // Define a custom color for the bars\n const customColor = 'rgb(0, 123, 255)'; // Change this to your desired color\n\n // Apache ECharts option\n option = {\n xAxis: {\n type: 'category',\n data: reasons, // Use the reasons directly for xAxis data\n axisLabel: {\n interval: 0, // Display all labels on the xAxis\n },\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Pods'], // Legend name\n left: 'left', // Position the legend on the left side\n bottom: 'bottom', // Position the legend at the bottom\n },\n series: [\n {\n name: 'Pods', // Series name for the legend\n data: seriesData,\n type: 'bar',\n label: {\n show: true,\n position: 'top',\n formatter: '{c}',\n },\n itemStyle: {\n barBorderRadius: [5, 5, 0, 0], // Adjust the values to control the curvature\n color: customColor, // Set the custom color for the bars\n },\n },\n ],\n };\n }\n}\n\nreturn option;",
+ "getOption": "let option; // Initialize the option variable\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const reasons = context.panel.data.series[0].fields[0].values;\n const counts = context.panel.data.series[0].fields[1].values;\n\n // Check if reasons and counts are defined and not empty\n if (!reasons || !counts || reasons.length === 0 || counts.length === 0) {\n // Display a message when no data is available\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n } else {\n // Data is available, proceed with the chart creation\n // Create an array of data items, each containing name and value\n const seriesData = reasons.map((reason, index) => ({\n name: reason,\n value: counts[index],\n }));\n\n // Define a custom color for the bars\n const customColor = 'rgb(0, 123, 255)'; // Change this to your desired color\n\n // Apache ECharts option\n option = {\n xAxis: {\n type: 'category',\n data: reasons, // Use the reasons directly for xAxis data\n axisLabel: {\n interval: 0, // Display all labels on the xAxis\n },\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Pods'], // Legend name\n left: 'left', // Position the legend on the left side\n bottom: 'bottom', // Position the legend at the bottom\n },\n series: [\n {\n name: 'Pods', // Series name for the legend\n data: seriesData,\n type: 'bar',\n label: {\n show: true,\n position: 'top',\n formatter: '{c}',\n },\n itemStyle: {\n barBorderRadius: [5, 5, 0, 0], // Adjust the values to control the curvature\n color: customColor, // Set the custom color for the bars\n },\n },\n ],\n };\n }\n}\n\nreturn option;",
"google": {
"callback": "gmapReady",
"key": ""
@@ -120,8 +128,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -164,11 +178,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n\n // Define the data from your JSON\n const clusterNames = data.series[0].fields[0].values;\n const kinds = data.series[0].fields[1].values;\n const reasons = data.series[0].fields[2].values;\n const counts = data.series[0].fields[3].values;\n\n // Create the Sankey chart configuration\n option = {\n series: {\n type: 'sankey',\n layout: 'none',\n emphasis: {\n focus: 'adjacency',\n },\n data: [],\n links: [],\n },\n tooltip: {\n trigger: 'item',\n formatter: (params) => {\n if (params.dataType === 'node') {\n return params.name;\n }\n if (params.dataType === 'edge') {\n return `Count: ${counts[params.dataIndex]}`; // Display count values\n }\n return '';\n },\n },\n };\n\n // Create nodes for ClusterName, Kind, and Reason\n const uniqueClusterNames = Array.from(new Set(clusterNames));\n const uniqueKinds = Array.from(new Set(kinds));\n const uniqueReasons = Array.from(new Set(reasons));\n\n uniqueClusterNames.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueKinds.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueReasons.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n\n // Create links from Kind to Reason\n kinds.forEach((kind, index) => {\n const sourceIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kind);\n const targetIndex = 1 * uniqueClusterNames.length + uniqueKinds.length + uniqueReasons.indexOf(reasons[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: counts[index], // Use count values\n });\n });\n\n // Create links from ClusterName to Kind\n clusterNames.forEach((clusterName, index) => {\n const sourceIndex = uniqueClusterNames.indexOf(clusterName);\n const targetIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kinds[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: 1,\n });\n });\n}\n\n\nreturn option;\n// Render the chart\nmyChart.setOption(option);",
+ "getOption": "let option; // Initialize the option variable\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n\n // Define the data from your JSON\n const clusterNames = context.panel.data.series[0].fields[0].values;\n const kinds = context.panel.data.series[0].fields[1].values;\n const reasons = context.panel.data.series[0].fields[2].values;\n const counts = context.panel.data.series[0].fields[3].values;\n\n // Create the Sankey chart configuration\n option = {\n series: {\n type: 'sankey',\n layout: 'none',\n emphasis: {\n focus: 'adjacency',\n },\n data: [],\n links: [],\n },\n tooltip: {\n trigger: 'item',\n formatter: (params) => {\n if (params.dataType === 'node') {\n return params.name;\n }\n if (params.dataType === 'edge') {\n return `Count: ${counts[params.dataIndex]}`; // Display count values\n }\n return '';\n },\n },\n };\n\n // Create nodes for ClusterName, Kind, and Reason\n const uniqueClusterNames = Array.from(new Set(clusterNames));\n const uniqueKinds = Array.from(new Set(kinds));\n const uniqueReasons = Array.from(new Set(reasons));\n\n uniqueClusterNames.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueKinds.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueReasons.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n\n // Create links from Kind to Reason\n kinds.forEach((kind, index) => {\n const sourceIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kind);\n const targetIndex = 1 * uniqueClusterNames.length + uniqueKinds.length + uniqueReasons.indexOf(reasons[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: counts[index], // Use count values\n });\n });\n\n // Create links from ClusterName to Kind\n clusterNames.forEach((clusterName, index) => {\n const sourceIndex = uniqueClusterNames.indexOf(clusterName);\n const targetIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kinds[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: 1,\n });\n });\n}\n\n\nreturn option;\n// Render the chart\nmyChart.setOption(option);",
"google": {
"callback": "gmapReady",
"key": ""
@@ -179,8 +194,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -223,11 +244,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n\n // Define the data from your JSON\n const clusterNames = data.series[0].fields[0].values;\n const kinds = data.series[0].fields[1].values;\n const reasons = data.series[0].fields[2].values;\n const counts = data.series[0].fields[3].values;\n\n // Create the Sankey chart configuration\n option = {\n series: {\n type: 'sankey',\n layout: 'none',\n emphasis: {\n focus: 'adjacency',\n },\n data: [],\n links: [],\n },\n tooltip: {\n trigger: 'item',\n formatter: (params) => {\n if (params.dataType === 'node') {\n return params.name;\n }\n if (params.dataType === 'edge') {\n return `Count: ${counts[params.dataIndex]}`; // Display count values\n }\n return '';\n },\n },\n };\n\n // Create nodes for ClusterName, Kind, and Reason\n const uniqueClusterNames = Array.from(new Set(clusterNames));\n const uniqueKinds = Array.from(new Set(kinds));\n const uniqueReasons = Array.from(new Set(reasons));\n\n uniqueClusterNames.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueKinds.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueReasons.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n\n // Create links from Kind to Reason\n kinds.forEach((kind, index) => {\n const sourceIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kind);\n const targetIndex = 1 * uniqueClusterNames.length + uniqueKinds.length + uniqueReasons.indexOf(reasons[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: counts[index], // Use count values\n });\n });\n\n // Create links from ClusterName to Kind\n clusterNames.forEach((clusterName, index) => {\n const sourceIndex = uniqueClusterNames.indexOf(clusterName);\n const targetIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kinds[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: 1,\n });\n });\n}\n\n\n\nreturn option;\n// Render the chart\nmyChart.setOption(option);",
+ "getOption": "let option; // Initialize the option variable\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n\n // Define the data from your JSON\n const clusterNames = context.panel.data.series[0].fields[0].values;\n const kinds = context.panel.data.series[0].fields[1].values;\n const reasons = context.panel.data.series[0].fields[2].values;\n const counts = context.panel.data.series[0].fields[3].values;\n\n // Create the Sankey chart configuration\n option = {\n series: {\n type: 'sankey',\n layout: 'none',\n emphasis: {\n focus: 'adjacency',\n },\n data: [],\n links: [],\n },\n tooltip: {\n trigger: 'item',\n formatter: (params) => {\n if (params.dataType === 'node') {\n return params.name;\n }\n if (params.dataType === 'edge') {\n return `Count: ${counts[params.dataIndex]}`; // Display count values\n }\n return '';\n },\n },\n };\n\n // Create nodes for ClusterName, Kind, and Reason\n const uniqueClusterNames = Array.from(new Set(clusterNames));\n const uniqueKinds = Array.from(new Set(kinds));\n const uniqueReasons = Array.from(new Set(reasons));\n\n uniqueClusterNames.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueKinds.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueReasons.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n\n // Create links from Kind to Reason\n kinds.forEach((kind, index) => {\n const sourceIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kind);\n const targetIndex = 1 * uniqueClusterNames.length + uniqueKinds.length + uniqueReasons.indexOf(reasons[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: counts[index], // Use count values\n });\n });\n\n // Create links from ClusterName to Kind\n clusterNames.forEach((clusterName, index) => {\n const sourceIndex = uniqueClusterNames.indexOf(clusterName);\n const targetIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kinds[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: 1,\n });\n });\n}\n\n\n\nreturn option;\n// Render the chart\nmyChart.setOption(option);",
"google": {
"callback": "gmapReady",
"key": ""
@@ -238,8 +260,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -282,11 +310,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n\n // Define the data from your JSON\n const clusterNames = data.series[0].fields[0].values;\n const kinds = data.series[0].fields[1].values;\n const reasons = data.series[0].fields[2].values;\n const counts = data.series[0].fields[3].values;\n\n // Create the Sankey chart configuration\n option = {\n series: {\n type: 'sankey',\n layout: 'none',\n emphasis: {\n focus: 'adjacency',\n },\n data: [],\n links: [],\n },\n tooltip: {\n trigger: 'item',\n formatter: (params) => {\n if (params.dataType === 'node') {\n return params.name;\n }\n if (params.dataType === 'edge') {\n return `Count: ${counts[params.dataIndex]}`; // Display count values\n }\n return '';\n },\n },\n };\n\n // Create nodes for ClusterName, Kind, and Reason\n const uniqueClusterNames = Array.from(new Set(clusterNames));\n const uniqueKinds = Array.from(new Set(kinds));\n const uniqueReasons = Array.from(new Set(reasons));\n\n uniqueClusterNames.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueKinds.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueReasons.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n\n // Create links from Kind to Reason\n kinds.forEach((kind, index) => {\n const sourceIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kind);\n const targetIndex = 1 * uniqueClusterNames.length + uniqueKinds.length + uniqueReasons.indexOf(reasons[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: counts[index], // Use count values\n });\n });\n\n // Create links from ClusterName to Kind\n clusterNames.forEach((clusterName, index) => {\n const sourceIndex = uniqueClusterNames.indexOf(clusterName);\n const targetIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kinds[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: 1,\n });\n });\n}\n\n\nreturn option;\n// Render the chart\nmyChart.setOption(option);\n\n",
+ "getOption": "let option; // Initialize the option variable\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n\n // Define the data from your JSON\n const clusterNames = context.panel.data.series[0].fields[0].values;\n const kinds = context.panel.data.series[0].fields[1].values;\n const reasons = context.panel.data.series[0].fields[2].values;\n const counts = context.panel.data.series[0].fields[3].values;\n\n // Create the Sankey chart configuration\n option = {\n series: {\n type: 'sankey',\n layout: 'none',\n emphasis: {\n focus: 'adjacency',\n },\n data: [],\n links: [],\n },\n tooltip: {\n trigger: 'item',\n formatter: (params) => {\n if (params.dataType === 'node') {\n return params.name;\n }\n if (params.dataType === 'edge') {\n return `Count: ${counts[params.dataIndex]}`; // Display count values\n }\n return '';\n },\n },\n };\n\n // Create nodes for ClusterName, Kind, and Reason\n const uniqueClusterNames = Array.from(new Set(clusterNames));\n const uniqueKinds = Array.from(new Set(kinds));\n const uniqueReasons = Array.from(new Set(reasons));\n\n uniqueClusterNames.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueKinds.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueReasons.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n\n // Create links from Kind to Reason\n kinds.forEach((kind, index) => {\n const sourceIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kind);\n const targetIndex = 1 * uniqueClusterNames.length + uniqueKinds.length + uniqueReasons.indexOf(reasons[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: counts[index], // Use count values\n });\n });\n\n // Create links from ClusterName to Kind\n clusterNames.forEach((clusterName, index) => {\n const sourceIndex = uniqueClusterNames.indexOf(clusterName);\n const targetIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kinds[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: 1,\n });\n });\n}\n\n\nreturn option;\n// Render the chart\nmyChart.setOption(option);\n\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -297,8 +326,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -341,11 +376,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON\n const clusters = data.series[0].fields[0].values;\n const hosts = data.series[0].fields[1].values;\n const reasons = data.series[0].fields[2].values;\n const eventTimes = data.series[0].fields[3].values;\n\n // Create a hierarchical structure for the tree chart starting with ClusterName\n const hierarchy = {\n name: 'Root', // You can customize the name of the root node if needed\n children: [],\n };\n\n for (let i = 0; i < clusters.length; i++) {\n const cluster = clusters[i];\n const host = hosts[i];\n const reason = reasons[i];\n const eventTime = eventTimes[i];\n\n // Find or create the cluster node\n let clusterNode = hierarchy.children.find((node) => node.name === cluster);\n if (!clusterNode) {\n clusterNode = { name: cluster, children: [] };\n hierarchy.children.push(clusterNode);\n }\n\n // Find or create the host node under the cluster\n let hostNode = clusterNode.children.find((node) => node.name === host);\n if (!hostNode) {\n hostNode = { name: host, children: [] };\n clusterNode.children.push(hostNode);\n }\n\n // Find or create the reason node under the host\n let reasonNode = hostNode.children.find((node) => node.name === reason);\n if (!reasonNode) {\n reasonNode = { name: reason, children: [] };\n hostNode.children.push(reasonNode);\n }\n\n // Create the eventTime node under the reason\n reasonNode.children.push({ name: eventTime });\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n },\n series: [\n {\n type: 'tree',\n data: hierarchy.children, // Use the children directly as root nodes\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%', // Adjust the right margin to provide more space for labels\n symbolSize: 7,\n label: {\n position: 'inside', // Position labels inside the node\n verticalAlign: 'middle',\n align: 'center', // Center-align labels\n fontSize: 15,\n fontWeight: 'bold',\n },\n leaves: {\n label: {\n position: 'right', // Position labels inside the node\n verticalAlign: 'middle',\n align: 'left', // Center-align labels\n fontSize: 15,\n fontWeight: 'bold',\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;\n",
+ "getOption": "let option; // Initialize the option variable\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON\n const clusters = context.panel.data.series[0].fields[0].values;\n const hosts = context.panel.data.series[0].fields[1].values;\n const reasons = context.panel.data.series[0].fields[2].values;\n const eventTimes = context.panel.data.series[0].fields[3].values;\n\n // Create a hierarchical structure for the tree chart starting with ClusterName\n const hierarchy = {\n name: 'Root', // You can customize the name of the root node if needed\n children: [],\n };\n\n for (let i = 0; i < clusters.length; i++) {\n const cluster = clusters[i];\n const host = hosts[i];\n const reason = reasons[i];\n const eventTime = eventTimes[i];\n\n // Find or create the cluster node\n let clusterNode = hierarchy.children.find((node) => node.name === cluster);\n if (!clusterNode) {\n clusterNode = { name: cluster, children: [] };\n hierarchy.children.push(clusterNode);\n }\n\n // Find or create the host node under the cluster\n let hostNode = clusterNode.children.find((node) => node.name === host);\n if (!hostNode) {\n hostNode = { name: host, children: [] };\n clusterNode.children.push(hostNode);\n }\n\n // Find or create the reason node under the host\n let reasonNode = hostNode.children.find((node) => node.name === reason);\n if (!reasonNode) {\n reasonNode = { name: reason, children: [] };\n hostNode.children.push(reasonNode);\n }\n\n // Create the eventTime node under the reason\n reasonNode.children.push({ name: eventTime });\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n },\n series: [\n {\n type: 'tree',\n data: hierarchy.children, // Use the children directly as root nodes\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%', // Adjust the right margin to provide more space for labels\n symbolSize: 7,\n label: {\n position: 'inside', // Position labels inside the node\n verticalAlign: 'middle',\n align: 'center', // Center-align labels\n fontSize: 15,\n fontWeight: 'bold',\n },\n leaves: {\n label: {\n position: 'right', // Position labels inside the node\n verticalAlign: 'middle',\n align: 'left', // Center-align labels\n fontSize: 15,\n fontWeight: 'bold',\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -356,8 +392,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -400,11 +442,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const clusterNames = data.series[0].fields[0].values; // New column for ClusterName\n const namespaces = data.series[0].fields[1].values;\n const kinds = data.series[0].fields[2].values; // Adjusted index for Kind\n const counts = data.series[0].fields[3].values; // New column for Count\n\n // Create a hierarchical structure from the data without a root node\n const hierarchy = {\n name: 'root', // Use 'root' as a placeholder\n children: [],\n };\n\n const seenClusterNames = new Set();\n const seenNamespaces = new Set();\n\n for (let i = 0; i < clusterNames.length; i++) {\n const clusterName = clusterNames[i];\n const namespace = namespaces[i];\n const kind = kinds[i];\n const count = counts[i]; // Get the count value\n\n if (!seenClusterNames.has(clusterName)) {\n seenClusterNames.add(clusterName);\n const clusterNode = { name: clusterName, children: [] };\n hierarchy.children.push(clusterNode);\n seenNamespaces.clear(); // Reset seenNamespaces for each cluster\n }\n\n const clusterNode = hierarchy.children.find((node) => node.name === clusterName);\n\n if (!seenNamespaces.has(namespace)) {\n seenNamespaces.add(namespace);\n const namespaceNode = { name: namespace, children: [] };\n clusterNode.children.push(namespaceNode);\n }\n\n const namespaceNode = clusterNode.children.find((node) => node.name === namespace);\n const kindNode = { name: kind, children: [{ name: `Count: ${count}` }] }; // Include the count as a child node\n namespaceNode.children.push(kindNode);\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n formatter: function (params) {\n const node = params.data;\n let tooltip = '';\n if (node.column) {\n tooltip += `${node.column}: ${node.name}`;\n } else {\n tooltip += node.name;\n }\n return tooltip;\n },\n },\n series: [\n {\n type: 'tree',\n data: hierarchy.children, // Use the children directly\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%',\n symbolSize: 7,\n label: {\n position: 'left',\n verticalAlign: 'middle',\n align: 'right',\n fontSize: 15, // Increase the text size for regular nodes\n fontWeight: 'bold', // Set the font weight to bold\n },\n leaves: {\n label: {\n position: 'right',\n verticalAlign: 'middle',\n align: 'left',\n fontSize: 15, // Increase the text size for leaves\n fontWeight: 'bold', // Set the font weight to bold\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;\n",
+ "getOption": "let option; // Initialize the option variable\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const clusterNames = context.panel.data.series[0].fields[0].values; // New column for ClusterName\n const namespaces = context.panel.data.series[0].fields[1].values;\n const kinds = context.panel.data.series[0].fields[2].values; // Adjusted index for Kind\n const counts = context.panel.data.series[0].fields[3].values; // New column for Count\n\n // Create a hierarchical structure from the data without a root node\n const hierarchy = {\n name: 'root', // Use 'root' as a placeholder\n children: [],\n };\n\n const seenClusterNames = new Set();\n const seenNamespaces = new Set();\n\n for (let i = 0; i < clusterNames.length; i++) {\n const clusterName = clusterNames[i];\n const namespace = namespaces[i];\n const kind = kinds[i];\n const count = counts[i]; // Get the count value\n\n if (!seenClusterNames.has(clusterName)) {\n seenClusterNames.add(clusterName);\n const clusterNode = { name: clusterName, children: [] };\n hierarchy.children.push(clusterNode);\n seenNamespaces.clear(); // Reset seenNamespaces for each cluster\n }\n\n const clusterNode = hierarchy.children.find((node) => node.name === clusterName);\n\n if (!seenNamespaces.has(namespace)) {\n seenNamespaces.add(namespace);\n const namespaceNode = { name: namespace, children: [] };\n clusterNode.children.push(namespaceNode);\n }\n\n const namespaceNode = clusterNode.children.find((node) => node.name === namespace);\n const kindNode = { name: kind, children: [{ name: `Count: ${count}` }] }; // Include the count as a child node\n namespaceNode.children.push(kindNode);\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n formatter: function (params) {\n const node = params.data;\n let tooltip = '';\n if (node.column) {\n tooltip += `${node.column}: ${node.name}`;\n } else {\n tooltip += node.name;\n }\n return tooltip;\n },\n },\n series: [\n {\n type: 'tree',\n data: hierarchy.children, // Use the children directly\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%',\n symbolSize: 7,\n label: {\n position: 'left',\n verticalAlign: 'middle',\n align: 'right',\n fontSize: 15, // Increase the text size for regular nodes\n fontWeight: 'bold', // Set the font weight to bold\n },\n leaves: {\n label: {\n position: 'right',\n verticalAlign: 'middle',\n align: 'left',\n fontSize: 15, // Increase the text size for leaves\n fontWeight: 'bold', // Set the font weight to bold\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -415,8 +458,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -455,8 +504,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -695,6 +743,6 @@
"timezone": "",
"title": "Kubedata",
"uid": "Qq-FK1rVz",
- "version": 2,
+ "version": 3,
"weekStart": ""
}
diff --git a/grafana/kuberhealthy-dashboard.json b/grafana/kuberhealthy-dashboard.json
index 915b7747..76e2c6e6 100644
--- a/grafana/kuberhealthy-dashboard.json
+++ b/grafana/kuberhealthy-dashboard.json
@@ -45,7 +45,7 @@
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const namespaces = data.series[0].fields[0].values;\n const counts = data.series[0].fields[1].values;\n\n // Create a hierarchical structure from the data with a default cluster node\n const hierarchy = {\n name: 'CheckName', // Default cluster node\n children: [],\n };\n\n // Create an object to store namespaces and their counts\n const namespaceCounts = {};\n\n // Populate the namespaceCounts object with namespaces and counts\n for (let i = 0; i < namespaces.length; i++) {\n const namespace = namespaces[i];\n const count = counts[i];\n\n if (!namespaceCounts[namespace]) {\n namespaceCounts[namespace] = count;\n } else {\n namespaceCounts[namespace] += count;\n }\n }\n\n // Create nodes for each namespace and add them as children of the default cluster node\n for (const namespace in namespaceCounts) {\n hierarchy.children.push({\n name: namespace,\n children: [{ name: `${namespaceCounts[namespace]}` }],\n });\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n formatter: function (params) {\n const node = params.data;\n let tooltip = '';\n if (node.column) {\n tooltip += `${node.column}: ${node.name}`;\n } else {\n tooltip += node.name;\n }\n return tooltip;\n },\n },\n series: [\n {\n type: 'tree',\n data: [hierarchy], // Use the hierarchy object as the data\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%',\n symbolSize: 7,\n label: {\n position: 'left',\n verticalAlign: 'middle',\n align: 'centre',\n fontSize: 15, // Increase the text size for regular nodes\n fontWeight: 'bold', // Set the font weight to bold\n },\n leaves: {\n label: {\n position: 'right',\n verticalAlign: 'middle',\n align: 'left',\n fontSize: 15, // Increase the text size for leaves\n fontWeight: 'bold', // Set the font weight to bold\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;\n",
+ "getOption": "let option; // Initialize the option variable\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const namespaces = context.panel.data.series[0].fields[0].values;\n const counts = context.panel.data.series[0].fields[1].values;\n\n // Create a hierarchical structure from the data with a default cluster node\n const hierarchy = {\n name: 'CheckName', // Default cluster node\n children: [],\n };\n\n // Create an object to store namespaces and their counts\n const namespaceCounts = {};\n\n // Populate the namespaceCounts object with namespaces and counts\n for (let i = 0; i < namespaces.length; i++) {\n const namespace = namespaces[i];\n const count = counts[i];\n\n if (!namespaceCounts[namespace]) {\n namespaceCounts[namespace] = count;\n } else {\n namespaceCounts[namespace] += count;\n }\n }\n\n // Create nodes for each namespace and add them as children of the default cluster node\n for (const namespace in namespaceCounts) {\n hierarchy.children.push({\n name: namespace,\n children: [{ name: `${namespaceCounts[namespace]}` }],\n });\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n formatter: function (params) {\n const node = params.data;\n let tooltip = '';\n if (node.column) {\n tooltip += `${node.column}: ${node.name}`;\n } else {\n tooltip += node.name;\n }\n return tooltip;\n },\n },\n series: [\n {\n type: 'tree',\n data: [hierarchy], // Use the hierarchy object as the data\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%',\n symbolSize: 7,\n label: {\n position: 'left',\n verticalAlign: 'middle',\n align: 'centre',\n fontSize: 15, // Increase the text size for regular nodes\n fontWeight: 'bold', // Set the font weight to bold\n },\n leaves: {\n label: {\n position: 'right',\n verticalAlign: 'middle',\n align: 'left',\n fontSize: 15, // Increase the text size for leaves\n fontWeight: 'bold', // Set the font weight to bold\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -113,7 +113,7 @@
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const namespaces = data.series[0].fields[0].values;\n const counts = data.series[0].fields[1].values;\n\n // Create a hierarchical structure from the data with a default cluster node\n const hierarchy = {\n name: 'CheckName', // Default cluster node\n children: [],\n };\n\n // Create an object to store namespaces and their counts\n const namespaceCounts = {};\n\n // Populate the namespaceCounts object with namespaces and counts\n for (let i = 0; i < namespaces.length; i++) {\n const namespace = namespaces[i];\n const count = counts[i];\n\n if (!namespaceCounts[namespace]) {\n namespaceCounts[namespace] = count;\n } else {\n namespaceCounts[namespace] += count;\n }\n }\n\n // Create nodes for each namespace and add them as children of the default cluster node\n for (const namespace in namespaceCounts) {\n hierarchy.children.push({\n name: namespace,\n children: [{ name: `${namespaceCounts[namespace]}` }],\n });\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n formatter: function (params) {\n const node = params.data;\n let tooltip = '';\n if (node.column) {\n tooltip += `${node.column}: ${node.name}`;\n } else {\n tooltip += node.name;\n }\n return tooltip;\n },\n },\n series: [\n {\n type: 'tree',\n data: [hierarchy], // Use the hierarchy object as the data\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%',\n symbolSize: 7,\n label: {\n position: 'left',\n verticalAlign: 'middle',\n align: 'centre',\n fontSize: 15, // Increase the text size for regular nodes\n fontWeight: 'bold', // Set the font weight to bold\n },\n leaves: {\n label: {\n position: 'right',\n verticalAlign: 'middle',\n align: 'left',\n fontSize: 15, // Increase the text size for leaves\n fontWeight: 'bold', // Set the font weight to bold\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;\n",
+ "getOption": "let option; // Initialize the option variable\n\nif (typeof context.panel.data === 'undefined' || !context.panel.data.series || !context.panel.data.series[0] || !context.panel.data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const namespaces = context.panel.data.series[0].fields[0].values;\n const counts = context.panel.data.series[0].fields[1].values;\n\n // Create a hierarchical structure from the data with a default cluster node\n const hierarchy = {\n name: 'CheckName', // Default cluster node\n children: [],\n };\n\n // Create an object to store namespaces and their counts\n const namespaceCounts = {};\n\n // Populate the namespaceCounts object with namespaces and counts\n for (let i = 0; i < namespaces.length; i++) {\n const namespace = namespaces[i];\n const count = counts[i];\n\n if (!namespaceCounts[namespace]) {\n namespaceCounts[namespace] = count;\n } else {\n namespaceCounts[namespace] += count;\n }\n }\n\n // Create nodes for each namespace and add them as children of the default cluster node\n for (const namespace in namespaceCounts) {\n hierarchy.children.push({\n name: namespace,\n children: [{ name: `${namespaceCounts[namespace]}` }],\n });\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n formatter: function (params) {\n const node = params.data;\n let tooltip = '';\n if (node.column) {\n tooltip += `${node.column}: ${node.name}`;\n } else {\n tooltip += node.name;\n }\n return tooltip;\n },\n },\n series: [\n {\n type: 'tree',\n data: [hierarchy], // Use the hierarchy object as the data\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%',\n symbolSize: 7,\n label: {\n position: 'left',\n verticalAlign: 'middle',\n align: 'centre',\n fontSize: 15, // Increase the text size for regular nodes\n fontWeight: 'bold', // Set the font weight to bold\n },\n leaves: {\n label: {\n position: 'right',\n verticalAlign: 'middle',\n align: 'left',\n fontSize: 15, // Increase the text size for leaves\n fontWeight: 'bold', // Set the font weight to bold\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -1199,6 +1199,6 @@
"timezone": "",
"title": "KuberHealth",
"uid": "d946c53c-8b1d-4e3c-9154-4219165342",
- "version": 2,
+ "version": 3,
"weekStart": ""
}
diff --git a/grafana/kubvizDsahboard.json b/grafana/kubvizDsahboard.json
index 374d131b..740b4baa 100644
--- a/grafana/kubvizDsahboard.json
+++ b/grafana/kubvizDsahboard.json
@@ -21,7 +21,7 @@
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
- "id": 32,
+ "id": 64,
"links": [],
"liveNow": false,
"panels": [
@@ -194,11 +194,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const reasons = data.series[0].fields[0].values;\n const kinds = data.series[0].fields[1].values;\n const eventTimes = data.series[0].fields[2].values;\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n reasons.forEach((reason, index) => {\n const sourceNode = {\n name: reason,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const kindNode = {\n name: kinds[index],\n category: 1, // Category for kind nodes\n symbolSize: 40, // Size for kind nodes\n };\n\n const eventTimeNode = {\n name: eventTimes[index],\n category: 2, // Category for eventTime nodes\n symbolSize: 20, // Size for eventTime nodes\n };\n\n // Ensure source, kind, and eventTime nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === kindNode.name)) {\n nodes.push(kindNode);\n }\n\n if (!nodes.some((node) => node.name === eventTimeNode.name)) {\n nodes.push(eventTimeNode);\n }\n\n // Create links between reason, kind, and eventTime nodes\n links.push({\n source: reason,\n target: kinds[index],\n });\n\n links.push({\n source: kinds[index],\n target: eventTimes[index],\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Reasons',\n },\n {\n name: 'Nodes',\n },\n {\n name: 'Event Times',\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Reasons', 'Nodes', 'Event Times'],\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: {\n color: '#000',\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n edgeSymbolSize: [12, 12],\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Handle the case when data.series does not exist\n return {};\n}",
+ "getOption": "// Check if context.panel.data.series exists\nif (context.panel.data.series && context.panel.data.series.length > 0) {\n const reasons = context.panel.data.series[0].fields[0].values;\n const kinds = context.panel.data.series[0].fields[1].values;\n const eventTimes = context.panel.data.series[0].fields[2].values;\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n reasons.forEach((reason, index) => {\n const sourceNode = {\n name: reason,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const kindNode = {\n name: kinds[index],\n category: 1, // Category for kind nodes\n symbolSize: 40, // Size for kind nodes\n };\n\n const eventTimeNode = {\n name: eventTimes[index],\n category: 2, // Category for eventTime nodes\n symbolSize: 20, // Size for eventTime nodes\n };\n\n // Ensure source, kind, and eventTime nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === kindNode.name)) {\n nodes.push(kindNode);\n }\n\n if (!nodes.some((node) => node.name === eventTimeNode.name)) {\n nodes.push(eventTimeNode);\n }\n\n // Create links between reason, kind, and eventTime nodes\n links.push({\n source: reason,\n target: kinds[index],\n });\n\n links.push({\n source: kinds[index],\n target: eventTimes[index],\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Reasons',\n },\n {\n name: 'Nodes',\n },\n {\n name: 'Event Times',\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Reasons', 'Nodes', 'Event Times'],\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: {\n color: '#000',\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n edgeSymbolSize: [12, 12],\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display \"Data not available\" in the panel\n return {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n}\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -209,8 +210,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -253,11 +260,12 @@
"format": "auto",
"height": 600
},
+ "editorMode": "code",
"gaode": {
"key": "",
"plugin": "AMap.Scale,AMap.ToolBar"
},
- "getOption": "let kind = [];\nlet resources = [];\n\ndata.series.map((s) => {\n kind = s.fields.find((f) => f.name === 'Kind').values;\n resources = s.fields.find((f) => f.name === 'Resources').values;\n});\n\n// Create an empty array to store doughnut chart data\nconst doughnutChartData = [];\n\n// Define colors for doughnut slices\nconst doughnutSliceColors = ['#235894', '#FFFF00', '#FF0000', '#00FF00', '#FFA500'];\n\n// Map severity and counts to doughnut chart data\nkind.forEach((kinddata, index) => {\n doughnutChartData.push({\n value: resources[index],\n name: kinddata,\n itemStyle: {\n borderRadius: [10, 10, 10, 10], // Add rounded corners\n color: doughnutSliceColors[index % doughnutSliceColors.length],\n borderWidth: 2,\n borderColor: '#fff',\n },\n });\n});\n\nreturn {\n backgroundColor: '#FFFFFF', // Set the background color to white\n tooltip: {\n trigger: 'item',\n },\n legend: {\n top: '5%',\n left: 'center',\n },\n series: [\n {\n name: 'Access From',\n type: 'pie',\n radius: ['40%', '70%'],\n avoidLabelOverlap: false,\n label: {\n show: false,\n position: 'center',\n },\n emphasis: {\n label: {\n show: true,\n fontSize: 40,\n fontWeight: 'bold',\n },\n },\n labelLine: {\n show: false,\n },\n data: doughnutChartData, // Use the modified doughnut chart data\n },\n ],\n};",
+ "getOption": "let kind = [];\nlet resources = [];\n\ncontext.panel.data.series.forEach((s) => {\n const kindField = s.fields.find((f) => f.name === 'Kind');\n const resourcesField = s.fields.find((f) => f.name === 'Resources');\n if (kindField && resourcesField) {\n kind = kindField.values;\n resources = resourcesField.values;\n }\n});\n\n// Create an empty array to store doughnut chart data\nconst doughnutChartData = [];\n\n// Define colors for doughnut slices\nconst doughnutSliceColors = ['#235894', '#FFFF00', '#FF0000', '#00FF00', '#FFA500'];\n\n// Map kind and resources counts to doughnut chart data\nkind.forEach((kinddata, index) => {\n doughnutChartData.push({\n value: resources[index],\n name: kinddata,\n clusterName: context.panel.data.series[0].fields[0].values[index], // Extract cluster name\n itemStyle: {\n borderRadius: [10, 10, 10, 10], // Add rounded corners\n color: doughnutSliceColors[index % doughnutSliceColors.length],\n borderWidth: 2,\n borderColor: '#fff',\n },\n });\n});\n\nreturn {\n backgroundColor: '#FFFFFF', // Set the background color to white\n tooltip: {\n trigger: 'item',\n formatter: function (params) {\n return `Resource From
${params.data.clusterName} ${params.value}`;\n },\n },\n legend: {\n top: '5%',\n left: 'center',\n },\n series: [\n {\n name: '',\n type: 'pie',\n radius: ['40%', '70%'],\n avoidLabelOverlap: false,\n label: {\n show: false,\n position: 'center',\n },\n emphasis: {\n label: {\n show: true,\n fontSize: 40,\n fontWeight: 'bold',\n },\n },\n labelLine: {\n show: false,\n },\n data: doughnutChartData, // Use the modified doughnut chart data\n },\n ],\n};\n",
"google": {
"callback": "gmapReady",
"key": ""
@@ -268,8 +276,14 @@
"config": "{}",
"height": 400,
"name": "default"
+ },
+ "visualEditor": {
+ "code": "return {\n dataset: context.editor.dataset,\n series: context.editor.series,\n xAxis: {\n type: 'time',\n },\n yAxis: {\n type: 'value',\n min: 'dataMin',\n },\n}\n",
+ "dataset": [],
+ "series": []
}
},
+ "pluginVersion": "6.0.0",
"targets": [
{
"datasource": {
@@ -565,8 +579,7 @@
"mode": "percentage",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -635,8 +648,7 @@
"mode": "percentage",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -705,8 +717,7 @@
"mode": "percentage",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -775,8 +786,7 @@
"mode": "percentage",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -845,8 +855,7 @@
"mode": "percentage",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -948,8 +957,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1049,8 +1057,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -3101,6 +3108,6 @@
"timezone": "",
"title": "Kubviz Dashboard",
"uid": "eT4fox94z",
- "version": 1,
+ "version": 4,
"weekStart": ""
-}
\ No newline at end of file
+}
diff --git a/grafana/trivy-dashboard.json b/grafana/trivy-dashboard.json
index db35cd83..52b06fab 100644
--- a/grafana/trivy-dashboard.json
+++ b/grafana/trivy-dashboard.json
@@ -21,7 +21,7 @@
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
- "id": 106,
+ "id": 58,
"links": [],
"liveNow": false,
"panels": [
@@ -129,12 +129,13 @@
"uid": "vertamedia-clickhouse-datasource"
},
"dateTimeType": "DATETIME",
+ "editorMode": "builder",
"extrapolate": true,
"format": "table",
"formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t",
"intervalFactor": 1,
- "query": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_severity = 'LOW'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
- "rawQuery": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_severity = 'LOW'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
+ "query": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE $timeFilterByColumn(vul_last_modified_date) AND vul_severity = 'LOW'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
+ "rawQuery": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_last_modified_date >= toDateTime(1712241666) AND vul_last_modified_date <= toDateTime(1712328066) AND vul_severity = 'LOW'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
"refId": "A",
"round": "0s",
"skip_comments": true
@@ -236,12 +237,13 @@
"uid": "vertamedia-clickhouse-datasource"
},
"dateTimeType": "DATETIME",
+ "editorMode": "builder",
"extrapolate": true,
"format": "table",
"formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t",
"intervalFactor": 1,
- "query": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_severity = 'HIGH'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
- "rawQuery": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_severity = 'HIGH'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
+ "query": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE $timeFilterByColumn(vul_last_modified_date) AND vul_severity = 'HIGH'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
+ "rawQuery": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_last_modified_date >= toDateTime(1712241678) AND vul_last_modified_date <= toDateTime(1712328078) AND vul_severity = 'HIGH'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
"refId": "A",
"round": "0s",
"skip_comments": true
@@ -343,12 +345,13 @@
"uid": "vertamedia-clickhouse-datasource"
},
"dateTimeType": "DATETIME",
+ "editorMode": "builder",
"extrapolate": true,
"format": "table",
"formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t",
"intervalFactor": 1,
- "query": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_severity = 'MEDIUM'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
- "rawQuery": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_severity = 'MEDIUM'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
+ "query": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE $timeFilterByColumn(vul_last_modified_date) AND vul_severity = 'MEDIUM'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
+ "rawQuery": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_last_modified_date >= toDateTime(1712241603) AND vul_last_modified_date <= toDateTime(1712328003) AND vul_severity = 'MEDIUM'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
"refId": "A",
"round": "0s",
"skip_comments": true
@@ -450,12 +453,13 @@
"uid": "vertamedia-clickhouse-datasource"
},
"dateTimeType": "DATETIME",
+ "editorMode": "builder",
"extrapolate": true,
"format": "table",
"formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t",
"intervalFactor": 1,
- "query": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_severity = 'CRITICAL'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
- "rawQuery": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_severity = 'CRITICAL'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
+ "query": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE $timeFilterByColumn(vul_last_modified_date) AND vul_severity = 'CRITICAL'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
+ "rawQuery": "SELECT cluster_name, artifact_name, vul_pkg_name, count(vul_severity) AS Counts\nFROM default.trivyimage\nWHERE vul_last_modified_date >= toDateTime(1712241618) AND vul_last_modified_date <= toDateTime(1712328018) AND vul_severity = 'CRITICAL'\nGROUP BY cluster_name, artifact_name, vul_pkg_name\nHAVING count(vul_severity) > 1\nORDER BY count(vul_severity) DESC",
"refId": "A",
"round": "0s",
"skip_comments": true
@@ -487,8 +491,7 @@
"mode": "absolute",
"steps": [
{
- "color": "light-blue",
- "value": null
+ "color": "light-blue"
}
]
}
@@ -538,12 +541,13 @@
"uid": "vertamedia-clickhouse-datasource"
},
"dateTimeType": "DATETIME",
+ "editorMode": "builder",
"extrapolate": true,
"format": "table",
"formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t",
"intervalFactor": 1,
- "query": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_severity = 'LOW'",
- "rawQuery": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_severity = 'LOW'",
+ "query": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE $timeFilterByColumn(vul_last_modified_date) AND vul_severity = 'LOW'",
+ "rawQuery": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_last_modified_date >= toDateTime(1712241558) AND vul_last_modified_date <= toDateTime(1712327958) AND vul_severity = 'LOW'",
"refId": "A",
"round": "0s",
"skip_comments": true
@@ -575,8 +579,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
}
]
}
@@ -626,12 +629,13 @@
"uid": "vertamedia-clickhouse-datasource"
},
"dateTimeType": "DATETIME",
+ "editorMode": "builder",
"extrapolate": true,
"format": "table",
"formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t",
"intervalFactor": 1,
- "query": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_severity = 'MEDIUM'",
- "rawQuery": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_severity = 'MEDIUM'",
+ "query": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE $timeFilterByColumn(vul_last_modified_date) AND vul_severity = 'MEDIUM'",
+ "rawQuery": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_last_modified_date >= toDateTime(1712241583) AND vul_last_modified_date <= toDateTime(1712327983) AND vul_severity = 'MEDIUM'",
"refId": "A",
"round": "0s",
"skip_comments": true
@@ -663,8 +667,7 @@
"mode": "absolute",
"steps": [
{
- "color": "super-light-orange",
- "value": null
+ "color": "super-light-orange"
}
]
}
@@ -714,12 +717,13 @@
"uid": "vertamedia-clickhouse-datasource"
},
"dateTimeType": "DATETIME",
+ "editorMode": "builder",
"extrapolate": true,
"format": "table",
"formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t",
"intervalFactor": 1,
- "query": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_severity = 'HIGH'",
- "rawQuery": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_severity = 'HIGH'",
+ "query": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE $timeFilterByColumn(vul_last_modified_date) AND vul_severity = 'HIGH'",
+ "rawQuery": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_last_modified_date >= toDateTime(1712241526) AND vul_last_modified_date <= toDateTime(1712327926) AND vul_severity = 'HIGH'",
"refId": "A",
"round": "0s",
"skip_comments": true
@@ -751,8 +755,7 @@
"mode": "absolute",
"steps": [
{
- "color": "red",
- "value": null
+ "color": "red"
}
]
}
@@ -802,12 +805,13 @@
"uid": "vertamedia-clickhouse-datasource"
},
"dateTimeType": "DATETIME",
+ "editorMode": "builder",
"extrapolate": true,
"format": "table",
"formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t",
"intervalFactor": 1,
- "query": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_severity = 'CRITICAL'",
- "rawQuery": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_severity = 'CRITICAL'",
+ "query": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE $timeFilterByColumn(vul_last_modified_date) AND vul_severity = 'CRITICAL'",
+ "rawQuery": "SELECT cluster_name, artifact_name AS image_name, vul_id, vul_pkg_name, vul_severity\nFROM default.trivyimage\nWHERE vul_last_modified_date >= toDateTime(1712241543) AND vul_last_modified_date <= toDateTime(1712327943) AND vul_severity = 'CRITICAL'",
"refId": "A",
"round": "0s",
"skip_comments": true
@@ -839,8 +843,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -912,8 +915,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -967,12 +969,13 @@
"uid": "vertamedia-clickhouse-datasource"
},
"dateTimeType": "DATETIME",
+ "editorMode": "builder",
"extrapolate": true,
"format": "table",
"formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t",
"intervalFactor": 1,
- "query": "SELECT vul_id, count(artifact_name) AS images\nFROM default.trivyimage\nGROUP BY vul_id",
- "rawQuery": "SELECT vul_id, count(artifact_name) AS images\nFROM default.trivyimage\nGROUP BY vul_id",
+ "query": "SELECT vul_id, count(artifact_name) AS images\nFROM default.trivyimage\nWHERE $timeFilterByColumn(vul_last_modified_date)\nGROUP BY vul_id",
+ "rawQuery": "SELECT vul_id, count(artifact_name) AS images\nFROM default.trivyimage\nWHERE vul_last_modified_date >= toDateTime(1712241498) AND vul_last_modified_date <= toDateTime(1712327898)\nGROUP BY vul_id",
"refId": "A",
"round": "0s",
"skip_comments": true
@@ -1005,8 +1008,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
}
]
}
@@ -1078,8 +1080,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
}
]
}
@@ -2396,6 +2397,6 @@
"timezone": "",
"title": "Trivy",
"uid": "f9b0a865-f419-410a-b7d9-9a3f79a70d48",
- "version": 13,
+ "version": 2,
"weekStart": ""
-}
\ No newline at end of file
+}