From c36115c861c023f4dcb6cd5460f33e4c44b66984 Mon Sep 17 00:00:00 2001 From: vargburz Date: Fri, 13 Jan 2023 16:51:21 +0300 Subject: [PATCH 1/3] set dashboard timerange in date picker --- .../corpglory-dataexporter-panel/components/Panel.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/panels/corpglory-dataexporter-panel/components/Panel.tsx b/src/panels/corpglory-dataexporter-panel/components/Panel.tsx index 1af10d9..73527be 100644 --- a/src/panels/corpglory-dataexporter-panel/components/Panel.tsx +++ b/src/panels/corpglory-dataexporter-panel/components/Panel.tsx @@ -31,6 +31,7 @@ import { DataQuery, DataSourceSettings, TimeRange, + OrgRole, } from '@grafana/data'; import { RefreshEvent } from '@grafana/runtime'; @@ -40,6 +41,7 @@ import * as _ from 'lodash'; interface Props extends PanelProps {} export function Panel({ width, height, timeRange, eventBus }: Props) { + console.log('contextSrv', contextSrv, OrgRole.Admin); // TODO: Dashboard type const [dashboard, setDashboard] = useState(null); const [datasources, setDatasources] = useState(null); @@ -103,10 +105,10 @@ export function Panel({ width, height, timeRange, eventBus }: Props) { }, [dashboard, datasources]); // eslint-disable-line react-hooks/exhaustive-deps useEffect(() => { - if (tasks === null) { - return; - } - const dataFrame = getDataFrameForTaskTable(tasks); + // if (tasks === null) { + // return; + // } + const dataFrame = getDataFrameForTaskTable([]); setTasksDataFrame(dataFrame); }, [tasks]); // eslint-disable-line react-hooks/exhaustive-deps @@ -185,6 +187,7 @@ export function Panel({ width, height, timeRange, eventBus }: Props) { } function openDatasourceModal(): void { + setTimeRange(timeRange); setModalVisibility(true); } From ff567a6148efefda0d529e0df0b34d9a72a77753 Mon Sep 17 00:00:00 2001 From: vargburz Date: Fri, 13 Jan 2023 19:56:10 +0300 Subject: [PATCH 2/3] UX improve for bad cases --- .../components/Panel.tsx | 154 +++++++++++------- .../corpglory-dataexporter-panel/types.ts | 7 + 2 files changed, 100 insertions(+), 61 deletions(-) diff --git a/src/panels/corpglory-dataexporter-panel/components/Panel.tsx b/src/panels/corpglory-dataexporter-panel/components/Panel.tsx index 73527be..66a44f1 100644 --- a/src/panels/corpglory-dataexporter-panel/components/Panel.tsx +++ b/src/panels/corpglory-dataexporter-panel/components/Panel.tsx @@ -1,4 +1,4 @@ -import { PanelOptions, TaskTableRowConfig, QueryTableRowConfig, DatasourceType } from '../types'; +import { PanelOptions, TaskTableRowConfig, QueryTableRowConfig, DatasourceType, PanelStatus } from '../types'; import { convertTimestampToDate, getDashboardUid } from '../../../utils'; import { CLOSE_ICON_BASE_64, DOWNLOAD_ICON_BASE_64, SELECT_ICON_BASE_64, UNSELECT_ICON_BASE_64 } from '../../../icons'; @@ -38,10 +38,12 @@ import { RefreshEvent } from '@grafana/runtime'; import React, { useState, useEffect } from 'react'; import * as _ from 'lodash'; +const PANEL_ID = 'corpglory-dataexporter-panel'; +const APP_ID = 'corpglory-dataexporter-app'; + interface Props extends PanelProps {} export function Panel({ width, height, timeRange, eventBus }: Props) { - console.log('contextSrv', contextSrv, OrgRole.Admin); // TODO: Dashboard type const [dashboard, setDashboard] = useState(null); const [datasources, setDatasources] = useState(null); @@ -56,6 +58,13 @@ export function Panel({ width, height, timeRange, eventBus }: Props) { const [selectedTimeRange, setTimeRange] = useState(timeRange); + const [panelStatus, setPanelStatus] = useState(PanelStatus.LOADING); + + if (contextSrv.user.orgRole !== OrgRole.Admin) { + // TODO: it shouldn't be overriten + setPanelStatus(PanelStatus.PERMISSION_ERROR); + } + useEffect(() => { async function getCurrentDashboard(): Promise { const currentDashboardUid = getDashboardUid(window.location.toString()); @@ -82,8 +91,7 @@ export function Panel({ width, height, timeRange, eventBus }: Props) { const queries: QueryTableRowConfig[] = []; // @ts-ignore - // TODO: move plugin id to const - if (panel.type === 'corpglory-dataexporter-panel') { + if (panel.type === PANEL_ID) { return; } @@ -125,6 +133,7 @@ export function Panel({ width, height, timeRange, eventBus }: Props) { getTasks() .then((tasks) => { setTasks(tasks); + setPanelStatus(PanelStatus.OK); for (let task of tasks) { // TODO: ExportStatus enum if (task.status === 'exporting') { @@ -133,7 +142,10 @@ export function Panel({ width, height, timeRange, eventBus }: Props) { } } }) - .catch((err) => console.error(err)); + .catch((err) => { + setPanelStatus(PanelStatus.DATASOURCE_ERROR); + console.error('some error', err); + }); } eventBus.subscribe(RefreshEvent, refresh); @@ -367,65 +379,85 @@ export function Panel({ width, height, timeRange, eventBus }: Props) { const styles = useStyles2(getStyles); - return ( + const loadingDiv = ; + // TODO: add styles + const datasourceErrorDiv = (
- {tasksDataFrame === null ? ( - // TODO: if datasource responds with error, display the error - - ) : ( -
- - - - - {queriesDataFrame === null ? ( - // TODO: if datasource responds with error, display the error - - ) : ( -
- - - { - setTimeRange(newTimeRange); - }} - /> - -
- - - - - - )} - - - - )} +

Datasource is unavailable.

+
+ Click here to configure DataExporter. +
+ {/* TODO: display error message? */} ); + const permissionErrorDiv = ( +
+

Permission Error.

+
DataExporter panel availabel only for Admins
+
+ ); + const mainDiv = ( +
+
+ + + + {queriesDataFrame === null ? ( + + ) : ( +
+ + + { + setTimeRange(newTimeRange); + }} + /> + +
+ + + + + + )} + + + + ); + + function renderSwitch(panelStatus: PanelStatus): JSX.Element { + switch (panelStatus) { + case PanelStatus.LOADING: + return loadingDiv; + case PanelStatus.DATASOURCE_ERROR: + return datasourceErrorDiv; + case PanelStatus.PERMISSION_ERROR: + return permissionErrorDiv; + case PanelStatus.OK: + return mainDiv; + default: + return datasourceErrorDiv; + } + } + return
{renderSwitch(panelStatus)}
; } const getStyles = () => ({ diff --git a/src/panels/corpglory-dataexporter-panel/types.ts b/src/panels/corpglory-dataexporter-panel/types.ts index c83ef92..421660e 100644 --- a/src/panels/corpglory-dataexporter-panel/types.ts +++ b/src/panels/corpglory-dataexporter-panel/types.ts @@ -26,3 +26,10 @@ export enum DatasourceType { ELASTICSEARCH = 'elasticsearch', MYSQL = 'mysql', } + +export enum PanelStatus { + LOADING = 'Loading', + DATASOURCE_ERROR = 'Datasource Error', + PERMISSION_ERROR = 'Permission Error', + OK = 'Ok', +} From 29d7c5393c885f4270dfc2dcae507464b3e2018f Mon Sep 17 00:00:00 2001 From: vargburz Date: Fri, 13 Jan 2023 20:07:57 +0300 Subject: [PATCH 3/3] return tassks --- .../corpglory-dataexporter-panel/components/Panel.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/panels/corpglory-dataexporter-panel/components/Panel.tsx b/src/panels/corpglory-dataexporter-panel/components/Panel.tsx index ce92b46..e2b1b17 100644 --- a/src/panels/corpglory-dataexporter-panel/components/Panel.tsx +++ b/src/panels/corpglory-dataexporter-panel/components/Panel.tsx @@ -113,10 +113,10 @@ export function Panel({ width, height, timeRange, eventBus }: Props) { }, [dashboard, datasources]); // eslint-disable-line react-hooks/exhaustive-deps useEffect(() => { - // if (tasks === null) { - // return; - // } - const dataFrame = getDataFrameForTaskTable([]); + if (tasks === null) { + return; + } + const dataFrame = getDataFrameForTaskTable(tasks); setTasksDataFrame(dataFrame); }, [tasks]); // eslint-disable-line react-hooks/exhaustive-deps