rozetko
2 years ago
6 changed files with 210 additions and 2 deletions
@ -0,0 +1,167 @@
|
||||
import { PanelOptions, TableRowConfig } from '../types'; |
||||
|
||||
import { Table, Button, HorizontalGroup } from '@grafana/ui'; |
||||
|
||||
import { |
||||
PanelProps, |
||||
toDataFrame, |
||||
FieldType, |
||||
applyFieldOverrides, |
||||
createTheme, |
||||
DataFrame, |
||||
DataLinkClickEvent, |
||||
} from '@grafana/data'; |
||||
|
||||
import React, { useState } from 'react'; |
||||
import * as _ from 'lodash'; |
||||
|
||||
interface Props extends PanelProps<PanelOptions> {} |
||||
|
||||
export function Panel({ options, data, width, height, timeRange, onChangeTimeRange }: Props) { |
||||
console.log('panel', data); |
||||
const configs: TableRowConfig[] = []; |
||||
const [tasks, setTasks] = useState(configs); |
||||
const dataFrame = getDataFrameForTable(tasks, setTasks); |
||||
|
||||
function onAddTaskClick(): void { |
||||
const configs = [...tasks, createConfigItem()]; |
||||
setTasks(configs); |
||||
} |
||||
|
||||
return ( |
||||
<div> |
||||
<Table width={width} height={height - 40} data={dataFrame} /> |
||||
<HorizontalGroup justify="flex-end"> |
||||
<Button |
||||
variant="primary" |
||||
aria-label="Rich history button" |
||||
icon="plus" |
||||
style={{ marginTop: '8px' }} |
||||
onClick={onAddTaskClick} |
||||
> |
||||
Add Task |
||||
</Button> |
||||
</HorizontalGroup> |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
function getDataFrameForTable(configs: TableRowConfig[], setTasks: any): DataFrame { |
||||
const dataFrame = toDataFrame({ |
||||
name: 'A', |
||||
fields: [ |
||||
{ |
||||
name: 'Time', |
||||
type: FieldType.number, |
||||
values: _.map(configs, (config) => convertTimestampToDate(config.timestamp)), |
||||
}, |
||||
{ |
||||
name: 'User', |
||||
type: FieldType.string, |
||||
values: _.map(configs, (config) => config.user), |
||||
}, |
||||
{ |
||||
name: 'Datasource', |
||||
type: FieldType.string, |
||||
values: _.map(configs, (config) => config.datasource), |
||||
}, |
||||
{ |
||||
name: 'Exported Rows', |
||||
type: FieldType.number, |
||||
values: _.map(configs, (config) => config.rowsCount), |
||||
}, |
||||
{ |
||||
name: 'Progress', |
||||
type: FieldType.string, |
||||
values: _.map(configs, (config) => `${config.progress}%`), |
||||
}, |
||||
{ |
||||
name: 'Status', |
||||
type: FieldType.string, |
||||
values: _.map(configs, (config) => config.status), |
||||
}, |
||||
{ |
||||
name: 'Download CSV', |
||||
type: FieldType.string, |
||||
values: _.map(configs, (config) => `data:image/png;base64,${DOWNLOAD_ICON_BASE_64}`), |
||||
config: { |
||||
custom: { |
||||
filterable: false, |
||||
displayMode: 'image', |
||||
}, |
||||
links: [ |
||||
{ |
||||
targetBlank: false, |
||||
title: 'CSV link', |
||||
url: 'https://chartwerk.io/', |
||||
}, |
||||
], |
||||
}, |
||||
}, |
||||
{ |
||||
name: 'Delete task', |
||||
type: FieldType.string, |
||||
values: _.map(configs, (config) => `data:image/png;base64,${CLOSE_ICON_BASE_64}`), |
||||
config: { |
||||
custom: { |
||||
filterable: false, |
||||
displayMode: 'image', |
||||
}, |
||||
links: [ |
||||
{ |
||||
targetBlank: false, |
||||
title: 'Delete', |
||||
url: '#', |
||||
onClick: (event: DataLinkClickEvent) => onDeleteClick(event, configs, setTasks), |
||||
}, |
||||
], |
||||
}, |
||||
}, |
||||
], |
||||
}); |
||||
|
||||
const dataFrames = applyFieldOverrides({ |
||||
data: [dataFrame], |
||||
fieldConfig: { |
||||
overrides: [], |
||||
defaults: {}, |
||||
}, |
||||
theme: createTheme(), |
||||
replaceVariables: (value: string) => value, |
||||
}); |
||||
return dataFrames[0]; |
||||
} |
||||
|
||||
function onDeleteClick(e: DataLinkClickEvent, tasks: TableRowConfig[], setTasks: any): void { |
||||
const rowIndex = e.origin.rowIndex; |
||||
const filteredTasks = _.filter(tasks, (task, idx) => idx !== rowIndex); |
||||
setTasks(filteredTasks); |
||||
} |
||||
|
||||
function createConfigItem(): TableRowConfig { |
||||
return { |
||||
timestamp: Date.now(), |
||||
user: 'admin', |
||||
datasource: 'Prometheus', |
||||
rowsCount: 3214, |
||||
progress: 100, |
||||
status: 'finished', |
||||
}; |
||||
} |
||||
|
||||
function convertTimestampToDate(timestamp: number): string { |
||||
const options: Intl.DateTimeFormatOptions = { |
||||
year: 'numeric', |
||||
month: 'short', |
||||
day: 'numeric', |
||||
hour: 'numeric', |
||||
minute: 'numeric', |
||||
second: 'numeric', |
||||
}; |
||||
return new Date(timestamp).toLocaleString('en-GB', options); |
||||
} |
||||
|
||||
const CLOSE_ICON_BASE_64 = |
||||
'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACJSURBVHgB7ZPRCcAgDESv0lWc0zhC53OIjmAVUpCSamL76YEoyfFIiAGWfldK6SwnKHyhep9xJ3iPcqgH5RyxV1VlBWYJypXVHMEiCaqBbRhAy3W3B76j954wq6ZSVZsOY+WXt6i9l2ymGTlUq0VpOcIqaQC96Zth01DN1zBBefVI4SNp9Za+6wLcH6DKFrfpxgAAAABJRU5ErkJggg=='; |
||||
const DOWNLOAD_ICON_BASE_64 = |
||||
'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAADlSURBVHgB3ZPNDYJAEIVnN96lBA7A2RIsATuQiiwBSrAD7MAjCZBACXqFwPomMRtEwMVwgZeQhfn5mNnMEG1CaZoeiqKwTWJ3JkFCiEtVVU+8+r9iJRlKSrk3iqOFtWJglmXHf3yDwCRJbBxxnudh34cRYluMMbKGcgWNCIlnjEuIJ1JK2WzDWeKb7YHjONEsYBf6kTABY+mWuYX+3Xiex9UFU7D3FllfwLqueQvi/h8ZCtBprDLY703T6A0yWj2ArmSoxedQV4jSSz5xj4pmCi0/NKfrwNz5bdtaNENciOu6N1qNXhzZXHMb9Q+nAAAAAElFTkSuQmCC'; |
@ -0,0 +1,7 @@
|
||||
import { PanelOptions } from './types'; |
||||
|
||||
import { Panel } from './components/Panel'; |
||||
|
||||
import { PanelPlugin } from '@grafana/data'; |
||||
|
||||
export const plugin = new PanelPlugin<PanelOptions>(Panel); |
@ -0,0 +1,18 @@
|
||||
{ |
||||
"$schema": "https://raw.githubusercontent.com/grafana/grafana/master/docs/sources/developers/plugins/plugin.schema.json", |
||||
"type": "panel", |
||||
"name": "Data Exporter Panel", |
||||
"id": "corpglory-dataexporter-panel", |
||||
"skipDataQuery": true, |
||||
"info": { |
||||
"description": "Panel for exporting metrics from Grafana dashboards", |
||||
"author": { |
||||
"name": "CorpGlory Inc.", |
||||
"url": "https://corpglory.com" |
||||
}, |
||||
"logos": { |
||||
"small": "../corpglory-dataexporter-app/img/logo.svg", |
||||
"large": "../corpglory-dataexporter-app/img/logo.svg" |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,10 @@
|
||||
export interface PanelOptions {} |
||||
|
||||
export type TableRowConfig = { |
||||
timestamp: number; |
||||
user: string; |
||||
datasource: string; |
||||
rowsCount: number; |
||||
progress: number; |
||||
status: string; |
||||
}; |
Loading…
Reference in new issue