Browse Source

UX improve for bad cases

pull/9/head
vargburz 2 years ago
parent
commit
ff567a6148
  1. 154
      src/panels/corpglory-dataexporter-panel/components/Panel.tsx
  2. 7
      src/panels/corpglory-dataexporter-panel/types.ts

154
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 { convertTimestampToDate, getDashboardUid } from '../../../utils';
import { CLOSE_ICON_BASE_64, DOWNLOAD_ICON_BASE_64, SELECT_ICON_BASE_64, UNSELECT_ICON_BASE_64 } from '../../../icons'; 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 React, { useState, useEffect } from 'react';
import * as _ from 'lodash'; import * as _ from 'lodash';
const PANEL_ID = 'corpglory-dataexporter-panel';
const APP_ID = 'corpglory-dataexporter-app';
interface Props extends PanelProps<PanelOptions> {} interface Props extends PanelProps<PanelOptions> {}
export function Panel({ width, height, timeRange, eventBus }: Props) { export function Panel({ width, height, timeRange, eventBus }: Props) {
console.log('contextSrv', contextSrv, OrgRole.Admin);
// TODO: Dashboard type // TODO: Dashboard type
const [dashboard, setDashboard] = useState<any | null>(null); const [dashboard, setDashboard] = useState<any | null>(null);
const [datasources, setDatasources] = useState<DataSourceSettings[] | null>(null); const [datasources, setDatasources] = useState<DataSourceSettings[] | null>(null);
@ -56,6 +58,13 @@ export function Panel({ width, height, timeRange, eventBus }: Props) {
const [selectedTimeRange, setTimeRange] = useState<TimeRange>(timeRange); const [selectedTimeRange, setTimeRange] = useState<TimeRange>(timeRange);
const [panelStatus, setPanelStatus] = useState<PanelStatus>(PanelStatus.LOADING);
if (contextSrv.user.orgRole !== OrgRole.Admin) {
// TODO: it shouldn't be overriten
setPanelStatus(PanelStatus.PERMISSION_ERROR);
}
useEffect(() => { useEffect(() => {
async function getCurrentDashboard(): Promise<any> { async function getCurrentDashboard(): Promise<any> {
const currentDashboardUid = getDashboardUid(window.location.toString()); const currentDashboardUid = getDashboardUid(window.location.toString());
@ -82,8 +91,7 @@ export function Panel({ width, height, timeRange, eventBus }: Props) {
const queries: QueryTableRowConfig[] = []; const queries: QueryTableRowConfig[] = [];
// @ts-ignore // @ts-ignore
// TODO: move plugin id to const if (panel.type === PANEL_ID) {
if (panel.type === 'corpglory-dataexporter-panel') {
return; return;
} }
@ -125,6 +133,7 @@ export function Panel({ width, height, timeRange, eventBus }: Props) {
getTasks() getTasks()
.then((tasks) => { .then((tasks) => {
setTasks(tasks); setTasks(tasks);
setPanelStatus(PanelStatus.OK);
for (let task of tasks) { for (let task of tasks) {
// TODO: ExportStatus enum // TODO: ExportStatus enum
if (task.status === 'exporting') { 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); eventBus.subscribe(RefreshEvent, refresh);
@ -367,65 +379,85 @@ export function Panel({ width, height, timeRange, eventBus }: Props) {
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
return ( const loadingDiv = <LoadingPlaceholder text="Loading..."></LoadingPlaceholder>;
// TODO: add styles
const datasourceErrorDiv = (
<div> <div>
{tasksDataFrame === null ? ( <p>Datasource is unavailable.</p>
// TODO: if datasource responds with error, display the error <div>
<LoadingPlaceholder text="Loading..."></LoadingPlaceholder> Click <a href={`/plugins/${APP_ID}`}>here</a> to configure DataExporter.
) : ( </div>
<div> {/* TODO: display error message? */}
<Table width={width} height={height - 40} data={tasksDataFrame} />
<HorizontalGroup justify="flex-end">
<Button
variant="primary"
aria-label="Rich history button"
icon="plus"
style={{ marginTop: '8px' }}
onClick={openDatasourceModal}
>
Add Task
</Button>
<Modal
title="Select Queries"
isOpen={isModalOpen}
onDismiss={onCloseModal}
className={styles.calendarModal}
>
{queriesDataFrame === null ? (
// TODO: if datasource responds with error, display the error
<LoadingPlaceholder text="Loading..."></LoadingPlaceholder>
) : (
<div>
<VerticalGroup spacing="xs">
<HorizontalGroup justify="flex-start" spacing="md">
<TimeRangeInput
value={selectedTimeRange}
onChange={(newTimeRange) => {
setTimeRange(newTimeRange);
}}
/>
</HorizontalGroup>
<Table width={width / 2 - 20} height={height - 40} data={queriesDataFrame} />
<HorizontalGroup justify="flex-end" spacing="md">
<Button
variant="primary"
aria-label="Add task button"
onClick={onAddTaskClick}
// TODO: move to function
disabled={!queries?.filter((query: QueryTableRowConfig) => query.selected)?.length}
>
Add Task
</Button>
</HorizontalGroup>
</VerticalGroup>
</div>
)}
</Modal>
</HorizontalGroup>
</div>
)}
</div> </div>
); );
const permissionErrorDiv = (
<div>
<p>Permission Error.</p>
<div> DataExporter panel availabel only for Admins </div>
</div>
);
const mainDiv = (
<div>
<Table width={width} height={height - 40} data={tasksDataFrame as DataFrame} />
<HorizontalGroup justify="flex-end">
<Button
variant="primary"
aria-label="Rich history button"
icon="plus"
style={{ marginTop: '8px' }}
onClick={openDatasourceModal}
>
Add Task
</Button>
<Modal title="Select Queries" isOpen={isModalOpen} onDismiss={onCloseModal} className={styles.calendarModal}>
{queriesDataFrame === null ? (
<LoadingPlaceholder text="Loading..."></LoadingPlaceholder>
) : (
<div>
<VerticalGroup spacing="xs">
<HorizontalGroup justify="flex-start" spacing="md">
<TimeRangeInput
value={selectedTimeRange}
onChange={(newTimeRange) => {
setTimeRange(newTimeRange);
}}
/>
</HorizontalGroup>
<Table width={width / 2 - 20} height={height - 40} data={queriesDataFrame} />
<HorizontalGroup justify="flex-end" spacing="md">
<Button
variant="primary"
aria-label="Add task button"
onClick={onAddTaskClick}
// TODO: move to function
disabled={!queries?.filter((query: QueryTableRowConfig) => query.selected)?.length}
>
Add Task
</Button>
</HorizontalGroup>
</VerticalGroup>
</div>
)}
</Modal>
</HorizontalGroup>
</div>
);
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 <div>{renderSwitch(panelStatus)}</div>;
} }
const getStyles = () => ({ const getStyles = () => ({

7
src/panels/corpglory-dataexporter-panel/types.ts

@ -26,3 +26,10 @@ export enum DatasourceType {
ELASTICSEARCH = 'elasticsearch', ELASTICSEARCH = 'elasticsearch',
MYSQL = 'mysql', MYSQL = 'mysql',
} }
export enum PanelStatus {
LOADING = 'Loading',
DATASOURCE_ERROR = 'Datasource Error',
PERMISSION_ERROR = 'Permission Error',
OK = 'Ok',
}

Loading…
Cancel
Save