Browse Source

Merge branch 'master' into dist

dist
rozetko 2 years ago
parent
commit
7c93db2b84
  1. 3
      src/components/PluginConfigPage/PluginConfigPage.tsx
  2. 6
      src/components/PluginConfigPage/parts/ConfigurationForm/index.tsx
  3. 50
      src/panels/corpglory-dataexporter-panel/components/Panel.tsx
  4. 22
      src/plugin_state.ts

3
src/components/PluginConfigPage/PluginConfigPage.tsx

@ -16,7 +16,7 @@ const PLUGIN_CONFIGURED_QUERY_PARAM_TRUTHY_VALUE = 'true';
const PLUGIN_CONFIGURED_VERSION_QUERY_PARAM = 'pluginConfiguredVersion'; const PLUGIN_CONFIGURED_VERSION_QUERY_PARAM = 'pluginConfiguredVersion';
const DEFAULT_API_URL = 'http://localhost:8080'; const DEFAULT_API_URL = 'http://localhost:8000';
/** /**
* When everything is successfully configured, reload the page, and pass along a few query parameters * When everything is successfully configured, reload the page, and pass along a few query parameters
@ -84,6 +84,7 @@ export const PluginConfigPage: FC<DataExporterPluginConfigPageProps> = ({
setPluginConnectionCheckError(pluginConnectionResponse); setPluginConnectionCheckError(pluginConnectionResponse);
} else { } else {
setPluginIsConnected(pluginConnectionResponse); setPluginIsConnected(pluginConnectionResponse);
reloadPageWithPluginConfiguredQueryParams(pluginConnectionResponse, true);
} }
setCheckingIfPluginIsConnected(false); setCheckingIfPluginIsConnected(false);

6
src/components/PluginConfigPage/parts/ConfigurationForm/index.tsx

@ -84,7 +84,7 @@ const ConfigurationForm: FC<Props> = ({ onSuccessfulSetup, defaultDataExporterAp
<div className={cx('info-block')}> <div className={cx('info-block')}>
<p>1. Launch the DataExporter backend</p> <p>1. Launch the DataExporter backend</p>
<Text type="secondary"> <Text type="secondary">
Run hobby, dev or production backend. See{' '} Run the backend. See{' '}
<a href="https://code.corpglory.net/corpglory/grafana-data-exporter" target="_blank" rel="noreferrer"> <a href="https://code.corpglory.net/corpglory/grafana-data-exporter" target="_blank" rel="noreferrer">
<Text type="link">here</Text> <Text type="link">here</Text>
</a>{' '} </a>{' '}
@ -97,8 +97,8 @@ const ConfigurationForm: FC<Props> = ({ onSuccessfulSetup, defaultDataExporterAp
<Text type="secondary"> <Text type="secondary">
The DataExporter backend must be reachable from your Grafana installation. Some examples are: The DataExporter backend must be reachable from your Grafana installation. Some examples are:
<br /> <br />
- http://host.docker.internal:8080 - http://host.docker.internal:8000
<br />- http://localhost:8080 <br />- http://localhost:8000
</Text> </Text>
</div> </div>

50
src/panels/corpglory-dataexporter-panel/components/Panel.tsx

@ -7,8 +7,18 @@ import { deleteTask, getStaticFile, getTasks, queryApi } from '../../../services
import { getDashboardByUid, getDatasources } from '../../../services/grafana_backend_service'; import { getDashboardByUid, getDatasources } from '../../../services/grafana_backend_service';
import { contextSrv } from 'grafana/app/core/core'; import { contextSrv } from 'grafana/app/core/core';
import { css } from '@emotion/css';
import { Table, Button, HorizontalGroup, Modal, LoadingPlaceholder } from '@grafana/ui'; import {
Table,
Button,
HorizontalGroup,
VerticalGroup,
Modal,
LoadingPlaceholder,
TimeRangeInput,
useStyles2,
} from '@grafana/ui';
import { import {
PanelProps, PanelProps,
toDataFrame, toDataFrame,
@ -20,6 +30,7 @@ import {
PanelModel, PanelModel,
DataQuery, DataQuery,
DataSourceSettings, DataSourceSettings,
TimeRange,
} from '@grafana/data'; } from '@grafana/data';
import { RefreshEvent } from '@grafana/runtime'; import { RefreshEvent } from '@grafana/runtime';
@ -41,6 +52,8 @@ export function Panel({ width, height, timeRange, eventBus }: Props) {
const [isModalOpen, setModalVisibility] = useState<boolean>(false); const [isModalOpen, setModalVisibility] = useState<boolean>(false);
const [selectedTimeRange, setTimeRange] = useState<TimeRange>(timeRange);
useEffect(() => { useEffect(() => {
async function getCurrentDashboard(): Promise<any> { async function getCurrentDashboard(): Promise<any> {
const currentDashboardUid = getDashboardUid(window.location.toString()); const currentDashboardUid = getDashboardUid(window.location.toString());
@ -143,9 +156,8 @@ export function Panel({ width, height, timeRange, eventBus }: Props) {
async function onAddTaskClick(): Promise<void> { async function onAddTaskClick(): Promise<void> {
const selectedQueries = _.filter(queries, (query: QueryTableRowConfig) => query.selected); const selectedQueries = _.filter(queries, (query: QueryTableRowConfig) => query.selected);
// TODO: timerange picker // TODO: timerange picker
const timerange: [number, number] = [timeRange.from.unix(), timeRange.to.unix()]; const timerange: [number, number] = [selectedTimeRange.from.unix(), selectedTimeRange.to.unix()];
// TODO: move this function to API Service // TODO: move this function to API Service
await queryApi('/task', { await queryApi('/task', {
method: 'POST', method: 'POST',
@ -350,6 +362,8 @@ export function Panel({ width, height, timeRange, eventBus }: Props) {
setQueries(updatedQueries); setQueries(updatedQueries);
} }
const styles = useStyles2(getStyles);
return ( return (
<div> <div>
{tasksDataFrame === null ? ( {tasksDataFrame === null ? (
@ -368,18 +382,31 @@ export function Panel({ width, height, timeRange, eventBus }: Props) {
> >
Add Task Add Task
</Button> </Button>
<Modal title="Select Queries" isOpen={isModalOpen} onDismiss={onCloseModal}> <Modal
title="Select Queries"
isOpen={isModalOpen}
onDismiss={onCloseModal}
className={styles.calendarModal}
>
{queriesDataFrame === null ? ( {queriesDataFrame === null ? (
// TODO: if datasource responds with error, display the error // TODO: if datasource responds with error, display the error
<LoadingPlaceholder text="Loading..."></LoadingPlaceholder> <LoadingPlaceholder text="Loading..."></LoadingPlaceholder>
) : ( ) : (
<div> <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} /> <Table width={width / 2 - 20} height={height - 40} data={queriesDataFrame} />
<HorizontalGroup justify="flex-end"> <HorizontalGroup justify="flex-end" spacing="md">
<Button <Button
variant="primary" variant="primary"
aria-label="Add task button" aria-label="Add task button"
style={{ marginTop: '8px' }}
onClick={onAddTaskClick} onClick={onAddTaskClick}
// TODO: move to function // TODO: move to function
disabled={!queries?.filter((query: QueryTableRowConfig) => query.selected)?.length} disabled={!queries?.filter((query: QueryTableRowConfig) => query.selected)?.length}
@ -387,6 +414,7 @@ export function Panel({ width, height, timeRange, eventBus }: Props) {
Add Task Add Task
</Button> </Button>
</HorizontalGroup> </HorizontalGroup>
</VerticalGroup>
</div> </div>
)} )}
</Modal> </Modal>
@ -396,3 +424,13 @@ export function Panel({ width, height, timeRange, eventBus }: Props) {
</div> </div>
); );
} }
const getStyles = () => ({
calendarModal: css`
section {
position: fixed;
top: 20%;
z-index: 1061;
}
`,
});

22
src/plugin_state.ts

@ -90,7 +90,13 @@ class PluginState {
this.grafanaBackend.get<DataExporterAppPluginMeta>(this.GRAFANA_PLUGIN_SETTINGS_URL); this.grafanaBackend.get<DataExporterAppPluginMeta>(this.GRAFANA_PLUGIN_SETTINGS_URL);
static updateGrafanaPluginSettings = async (data: UpdateGrafanaPluginSettingsProps, enabled = true) => static updateGrafanaPluginSettings = async (data: UpdateGrafanaPluginSettingsProps, enabled = true) =>
this.grafanaBackend.post(this.GRAFANA_PLUGIN_SETTINGS_URL, { ...data, enabled, pinned: true }); this.grafanaBackend.post(
this.GRAFANA_PLUGIN_SETTINGS_URL,
{ ...data, enabled, pinned: true },
// @ts-ignore
// for some reason, there is no `options` argument in Grafana's public types for BackendSrv but it exists
{ showSuccessAlert: false }
);
static createGrafanaToken = async () => { static createGrafanaToken = async () => {
const baseUrl = '/api/auth/keys'; const baseUrl = '/api/auth/keys';
@ -98,14 +104,22 @@ class PluginState {
const existingKey = keys.find((key: { id: number; name: string; role: string }) => key.name === 'DataExporter'); const existingKey = keys.find((key: { id: number; name: string; role: string }) => key.name === 'DataExporter');
if (existingKey) { if (existingKey) {
await this.grafanaBackend.delete(`${baseUrl}/${existingKey.id}`); // @ts-ignore
// for some reason, there is no `options` argument in Grafana's public types for BackendSrv but it exists
await this.grafanaBackend.delete(`${baseUrl}/${existingKey.id}`, undefined, { showSuccessAlert: false });
} }
return await this.grafanaBackend.post(baseUrl, { return await this.grafanaBackend.post(
baseUrl,
{
name: 'DataExporter', name: 'DataExporter',
role: 'Admin', role: 'Admin',
secondsToLive: null, secondsToLive: null,
}); },
// @ts-ignore
// for some reason, there is no `options` argument in Grafana's public types for BackendSrv but it exists
{ showSuccessAlert: false }
);
}; };
static timeout = (pollCount: number) => new Promise((resolve) => setTimeout(resolve, 10 * 2 ** pollCount)); static timeout = (pollCount: number) => new Promise((resolve) => setTimeout(resolve, 10 * 2 ** pollCount));

Loading…
Cancel
Save