From af5e5ab4c66b469188f7132469b5c0964be6073c Mon Sep 17 00:00:00 2001 From: vargburz Date: Thu, 29 Dec 2022 15:46:20 +0300 Subject: [PATCH 1/2] subscrine && modal and new table UI --- .../components/Panel.tsx | 183 ++++++++++++++++-- .../corpglory-dataexporter-panel/types.ts | 12 +- 2 files changed, 179 insertions(+), 16 deletions(-) diff --git a/src/panels/corpglory-dataexporter-panel/components/Panel.tsx b/src/panels/corpglory-dataexporter-panel/components/Panel.tsx index 8ebaa20..3455776 100644 --- a/src/panels/corpglory-dataexporter-panel/components/Panel.tsx +++ b/src/panels/corpglory-dataexporter-panel/components/Panel.tsx @@ -1,6 +1,7 @@ -import { PanelOptions, TableRowConfig } from '../types'; +import { PanelOptions, TaskTableRowConfig, DatasourceTableRowConfig } from '../types'; -import { Table, Button, HorizontalGroup } from '@grafana/ui'; +import { Table, Button, HorizontalGroup, Modal } from '@grafana/ui'; +import { getBackendSrv } from '@grafana/runtime'; import { PanelProps, @@ -18,35 +19,104 @@ 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); + const taskConfigs: TaskTableRowConfig[] = []; + const [tasks, setTasks] = useState(taskConfigs); + const tasksDataFrame = getDataFrameForTaskTable(tasks, setTasks); + + const datasourceConfigs: DatasourceTableRowConfig[] = []; + const [datasources, setDatasources] = useState(datasourceConfigs); + const datasourceDataFrame = getDataFrameForDatasourceTable(datasources, setDatasources); + + const [isModalOpen, setModalVisibility] = useState(false); + + const timestampRange: [number, number] = [timeRange.from.unix(), timeRange.to.unix()]; + const backendSrv = getBackendSrv(); + // @ts-ignore + backendSrv.getInspectorStream().subscribe({ + next: (resp: any) => { + const queries = resp?.config?.data?.queries; + if (_.isEmpty(queries)) { + return; + } + + const datasource = queries[0].datasource.type; + const refId = queries[0].refId; + const rawSql = queries[0].rawSql; + const uid = queries[0].datasource.uid; + + const isDatasourceExist = _.some( + datasources, + (ds: DatasourceTableRowConfig) => + ds.datasource === datasource && ds.refId === refId && _.isEqual(ds.rawSql, rawSql) && ds.uid === uid + ); + if (isDatasourceExist) { + return; + } + + const newConfig = createDatasourceConfig({ datasource, refId, rawSql, uid }, timestampRange); + setDatasources([...datasources, newConfig]); + }, + }); function onAddTaskClick(): void { - const configs = [...tasks, createConfigItem()]; - setTasks(configs); + const selectedDatasources = _.filter(datasources, (datasource: DatasourceTableRowConfig) => datasource.select); + const newTasks = _.map(selectedDatasources, (datasource: DatasourceTableRowConfig) => + createTaskFromDatasource(datasource) + ); + setTasks([...tasks, ...newTasks]); + onCloseModal(); + unselectAllDatasources(); + } + + function unselectAllDatasources(): void { + const updatedDatasources = _.clone(datasources); + for (const ds of updatedDatasources) { + ds.select = false; + } + setDatasources(updatedDatasources); + } + + function openModal(): void { + setModalVisibility(true); + } + + function onCloseModal(): void { + setModalVisibility(false); + unselectAllDatasources(); } return (
- +
+ +
+ + + + ); } -function getDataFrameForTable(configs: TableRowConfig[], setTasks: any): DataFrame { +function getDataFrameForTaskTable(configs: TaskTableRowConfig[], setTasks: any): DataFrame { const dataFrame = toDataFrame({ name: 'A', fields: [ @@ -132,23 +202,102 @@ function getDataFrameForTable(configs: TableRowConfig[], setTasks: any): DataFra return dataFrames[0]; } -function onDeleteClick(e: DataLinkClickEvent, tasks: TableRowConfig[], setTasks: any): void { +function getDataFrameForDatasourceTable(configs: DatasourceTableRowConfig[], setDatasources: any): DataFrame { + const dataFrame = toDataFrame({ + name: 'A', + fields: [ + { + name: 'Select', + type: FieldType.string, + values: _.map( + configs, + (config) => `data:image/svg+xml;base64,${config.select ? SELECT_ICON_BASE_64 : UNSELECT_ICON_BASE_64}` + ), + config: { + custom: { + filterable: false, + displayMode: 'image', + }, + links: [ + { + targetBlank: false, + title: 'Select', + url: '#', + onClick: (event: DataLinkClickEvent) => onDatasourceSelectClick(event, configs, setDatasources), + }, + ], + }, + }, + { + name: 'Panel', + type: FieldType.string, + values: _.map(configs, (config) => config.panel), + }, + { + name: 'RefId', + type: FieldType.string, + values: _.map(configs, (config) => config.refId), + }, + { + name: 'Datasource', + type: FieldType.string, + values: _.map(configs, (config) => config.datasource), + }, + ], + }); + + const dataFrames = applyFieldOverrides({ + data: [dataFrame], + fieldConfig: { + overrides: [], + defaults: {}, + }, + theme: createTheme(), + replaceVariables: (value: string) => value, + }); + return dataFrames[0]; +} + +function onDeleteClick(e: DataLinkClickEvent, tasks: TaskTableRowConfig[], setTasks: any): void { const rowIndex = e.origin.rowIndex; const filteredTasks = _.filter(tasks, (task, idx) => idx !== rowIndex); setTasks(filteredTasks); } -function createConfigItem(): TableRowConfig { +function onDatasourceSelectClick( + e: DataLinkClickEvent, + datasources: DatasourceTableRowConfig[], + setDatasources: any +): void { + const rowIndex = e.origin.rowIndex; + const updatedDatasources = _.clone(datasources); + updatedDatasources[rowIndex].select = !updatedDatasources[rowIndex].select; + setDatasources(updatedDatasources); +} + +function createTaskFromDatasource(config: DatasourceTableRowConfig): TaskTableRowConfig { return { timestamp: Date.now(), user: 'admin', - datasource: 'Prometheus', + datasource: config.datasource, rowsCount: 3214, progress: 100, status: 'finished', }; } +function createDatasourceConfig(obj: any, timerange: [number, number]): DatasourceTableRowConfig { + return { + select: false, + panel: 'Panel', + refId: obj.refId, + datasource: obj.datasource, + rawSql: obj.rawSql, + uid: obj.uid, + timerange, + }; +} + function convertTimestampToDate(timestamp: number): string { const options: Intl.DateTimeFormatOptions = { year: 'numeric', @@ -165,3 +314,7 @@ const CLOSE_ICON_BASE_64 = 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACJSURBVHgB7ZPRCcAgDESv0lWc0zhC53OIjmAVUpCSamL76YEoyfFIiAGWfldK6SwnKHyhep9xJ3iPcqgH5RyxV1VlBWYJypXVHMEiCaqBbRhAy3W3B76j954wq6ZSVZsOY+WXt6i9l2ymGTlUq0VpOcIqaQC96Zth01DN1zBBefVI4SNp9Za+6wLcH6DKFrfpxgAAAABJRU5ErkJggg=='; const DOWNLOAD_ICON_BASE_64 = 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAADlSURBVHgB3ZPNDYJAEIVnN96lBA7A2RIsATuQiiwBSrAD7MAjCZBACXqFwPomMRtEwMVwgZeQhfn5mNnMEG1CaZoeiqKwTWJ3JkFCiEtVVU+8+r9iJRlKSrk3iqOFtWJglmXHf3yDwCRJbBxxnudh34cRYluMMbKGcgWNCIlnjEuIJ1JK2WzDWeKb7YHjONEsYBf6kTABY+mWuYX+3Xiex9UFU7D3FllfwLqueQvi/h8ZCtBprDLY703T6A0yWj2ArmSoxedQV4jSSz5xj4pmCi0/NKfrwNz5bdtaNENciOu6N1qNXhzZXHMb9Q+nAAAAAElFTkSuQmCC'; +const UNSELECT_ICON_BASE_64 = + 'PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3QgeD0iMC41IiB5PSIwLjUiIHdpZHRoPSIxNSIgaGVpZ2h0PSIxNSIgcng9IjEuNSIgZmlsbD0iIzExMTIxNiIgc3Ryb2tlPSIjMkQyRTM0Ii8+Cjwvc3ZnPgo='; +const SELECT_ICON_BASE_64 = + 'PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2IiByeD0iMiIgZmlsbD0iIzRBNzFEMiIvPgo8cGF0aCBkPSJNNS45ODI2NCAxMi41MjE3QzUuNzczOTUgMTIuNTIxNyA1LjU4MjY0IDEyLjQ1MjIgNS40MjYxMiAxMi4yOTU2TDEuOTY1MjUgOC44MzQ3NkMxLjY1MjIxIDguNTIxNzIgMS42NTIyMSA4LjAzNDc2IDEuOTY1MjUgNy43MjE3MkMyLjI3ODI5IDcuNDA4NjcgMi43NjUyNSA3LjQwODY3IDMuMDc4MjkgNy43MjE3Mkw2LjAwMDAzIDEwLjYyNjFMMTIuOTM5MiAzLjcwNDMzQzEzLjI1MjIgMy4zOTEyOCAxMy43MzkyIDMuMzkxMjggMTQuMDUyMiAzLjcwNDMzQzE0LjM2NTMgNC4wMTczNyAxNC4zNjUzIDQuNTA0MzMgMTQuMDUyMiA0LjgxNzM3TDYuNTU2NTYgMTIuMjk1NkM2LjM4MjY0IDEyLjQ1MjIgNi4xOTEzNCAxMi41MjE3IDUuOTgyNjQgMTIuNTIxN1YxMi41MjE3WiIgZmlsbD0iI0ZFRkZGRiIvPgo8L3N2Zz4K'; diff --git a/src/panels/corpglory-dataexporter-panel/types.ts b/src/panels/corpglory-dataexporter-panel/types.ts index 8e83991..9b2a525 100644 --- a/src/panels/corpglory-dataexporter-panel/types.ts +++ b/src/panels/corpglory-dataexporter-panel/types.ts @@ -1,6 +1,6 @@ export interface PanelOptions {} -export type TableRowConfig = { +export type TaskTableRowConfig = { timestamp: number; user: string; datasource: string; @@ -8,3 +8,13 @@ export type TableRowConfig = { progress: number; status: string; }; + +export type DatasourceTableRowConfig = { + select: boolean; + panel: string; + refId: string; + datasource: string; + rawSql: string; + uid: string; + timerange: [number, number]; +}; From 99e7dc2ffec87b3870c2ff5c973e49987f8d41eb Mon Sep 17 00:00:00 2001 From: vargburz Date: Thu, 29 Dec 2022 15:53:08 +0300 Subject: [PATCH 2/2] add todo --- src/panels/corpglory-dataexporter-panel/components/Panel.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/panels/corpglory-dataexporter-panel/components/Panel.tsx b/src/panels/corpglory-dataexporter-panel/components/Panel.tsx index 3455776..b89828d 100644 --- a/src/panels/corpglory-dataexporter-panel/components/Panel.tsx +++ b/src/panels/corpglory-dataexporter-panel/components/Panel.tsx @@ -43,7 +43,7 @@ export function Panel({ options, data, width, height, timeRange, onChangeTimeRan const refId = queries[0].refId; const rawSql = queries[0].rawSql; const uid = queries[0].datasource.uid; - + // TODO: it works only with sql (rawSql will be empty in prometheus) const isDatasourceExist = _.some( datasources, (ds: DatasourceTableRowConfig) => @@ -52,7 +52,6 @@ export function Panel({ options, data, width, height, timeRange, onChangeTimeRan if (isDatasourceExist) { return; } - const newConfig = createDatasourceConfig({ datasource, refId, rawSql, uid }, timestampRange); setDatasources([...datasources, newConfig]); },