From c22a6e9a7fe92183e1b7105d303b9e59673d904c Mon Sep 17 00:00:00 2001 From: rozetko Date: Tue, 27 Dec 2022 15:38:11 +0300 Subject: [PATCH] copy panel from the panel repo --- .config/jest.config.js | 2 +- .../components/Panel.tsx | 167 ++++++++++++++++++ .../corpglory-dataexporter-panel/module.ts | 7 + .../corpglory-dataexporter-panel/plugin.json | 18 ++ .../corpglory-dataexporter-panel/types.ts | 10 ++ src/plugin.json | 8 +- 6 files changed, 210 insertions(+), 2 deletions(-) create mode 100644 src/panels/corpglory-dataexporter-panel/components/Panel.tsx create mode 100644 src/panels/corpglory-dataexporter-panel/module.ts create mode 100644 src/panels/corpglory-dataexporter-panel/plugin.json create mode 100644 src/panels/corpglory-dataexporter-panel/types.ts diff --git a/.config/jest.config.js b/.config/jest.config.js index 82a6e3f..c593d6d 100644 --- a/.config/jest.config.js +++ b/.config/jest.config.js @@ -27,5 +27,5 @@ module.exports = { }, ], }, - setupFilesAfterEnv: ['/jest-setup.js'], + setupFilesAfterEnv: ['/.config/jest-setup.js'], }; diff --git a/src/panels/corpglory-dataexporter-panel/components/Panel.tsx b/src/panels/corpglory-dataexporter-panel/components/Panel.tsx new file mode 100644 index 0000000..8ebaa20 --- /dev/null +++ b/src/panels/corpglory-dataexporter-panel/components/Panel.tsx @@ -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 {} + +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 ( +
+ + + + + + ); +} + +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'; diff --git a/src/panels/corpglory-dataexporter-panel/module.ts b/src/panels/corpglory-dataexporter-panel/module.ts new file mode 100644 index 0000000..4a86816 --- /dev/null +++ b/src/panels/corpglory-dataexporter-panel/module.ts @@ -0,0 +1,7 @@ +import { PanelOptions } from './types'; + +import { Panel } from './components/Panel'; + +import { PanelPlugin } from '@grafana/data'; + +export const plugin = new PanelPlugin(Panel); diff --git a/src/panels/corpglory-dataexporter-panel/plugin.json b/src/panels/corpglory-dataexporter-panel/plugin.json new file mode 100644 index 0000000..ff3a93e --- /dev/null +++ b/src/panels/corpglory-dataexporter-panel/plugin.json @@ -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" + } + } +} diff --git a/src/panels/corpglory-dataexporter-panel/types.ts b/src/panels/corpglory-dataexporter-panel/types.ts new file mode 100644 index 0000000..8e83991 --- /dev/null +++ b/src/panels/corpglory-dataexporter-panel/types.ts @@ -0,0 +1,10 @@ +export interface PanelOptions {} + +export type TableRowConfig = { + timestamp: number; + user: string; + datasource: string; + rowsCount: number; + progress: number; + status: string; +}; diff --git a/src/plugin.json b/src/plugin.json index 5d16d92..c403b34 100644 --- a/src/plugin.json +++ b/src/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://raw.githubusercontent.com/grafana/grafana/master/docs/sources/developers/plugins/plugin.schema.json", "type": "app", - "name": "Data Exporter", + "name": "Data Exporter App", "id": "corpglory-dataexporter-app", "info": { "description": "", @@ -24,6 +24,12 @@ "url": "{{ .JsonData.dataExporterApiUrl }}/api/" } ], + "includes": [ + { + "name": "Data Exporter Panel", + "type": "panel" + } + ], "dependencies": { "grafanaDependency": ">=7.0.0", "plugins": []