diff --git a/bitmovin-analytics-datasource/src/components/QueryEditor.tsx b/bitmovin-analytics-datasource/src/components/QueryEditor.tsx index 2952f65..b44ac5d 100644 --- a/bitmovin-analytics-datasource/src/components/QueryEditor.tsx +++ b/bitmovin-analytics-datasource/src/components/QueryEditor.tsx @@ -1,12 +1,13 @@ import React, { ChangeEvent, useEffect, useState } from 'react'; import { FieldSet, InlineField, InlineSwitch, Input, Select } from '@grafana/ui'; import { QueryEditorProps, SelectableValue } from '@grafana/data'; +import { defaults } from 'lodash'; import { DataSource } from '../datasource'; -import { BitmovinDataSourceOptions, BitmovinAnalyticsDataQuery } from '../types'; +import { BitmovinDataSourceOptions, BitmovinAnalyticsDataQuery, DEFAULT_QUERY } from '../types'; import { fetchLicenses } from '../utils/licenses'; import { DEFAULT_SELECTABLE_QUERY_INTERVAL, SELECTABLE_QUERY_INTERVALS } from '../utils/intervalUtils'; -import { DEFAULT_SELECTABLE_AGGREGATION, SELECTABLE_AGGREGATIONS } from '../types/aggregations'; +import { SELECTABLE_AGGREGATIONS } from '../types/aggregations'; import { QueryAdAttribute, SELECTABLE_QUERY_AD_ATTRIBUTES } from '../types/queryAdAttributes'; import { QueryAttribute, SELECTABLE_QUERY_ATTRIBUTES } from '../types/queryAttributes'; import { isMetric, SELECTABLE_METRICS } from '../types/metric'; @@ -25,7 +26,7 @@ enum LoadingState { type Props = QueryEditorProps; -export function QueryEditor({ query, onChange, onRunQuery, datasource }: Props) { +export function QueryEditor(props: Props) { const [selectableLicenses, setSelectableLicenses] = useState([]); const [licenseLoadingState, setLicenseLoadingState] = useState(LoadingState.Default); const [licenseErrorMessage, setLicenseErrorMessage] = useState(''); @@ -34,7 +35,7 @@ export function QueryEditor({ query, onChange, onRunQuery, datasource }: Props) useEffect(() => { setLicenseLoadingState(LoadingState.Loading); - fetchLicenses(datasource.apiKey, datasource.baseUrl) + fetchLicenses(props.datasource.apiKey, props.datasource.baseUrl) .then((licenses) => { setSelectableLicenses(licenses); setLicenseLoadingState(LoadingState.Success); @@ -43,63 +44,70 @@ export function QueryEditor({ query, onChange, onRunQuery, datasource }: Props) setLicenseLoadingState(LoadingState.Error); setLicenseErrorMessage(e.status + ' ' + e.statusText); }); - }, [datasource.apiKey, datasource.baseUrl]); + }, [props.datasource.apiKey, props.datasource.baseUrl]); - const onLicenseChange = (item: SelectableValue) => { - onChange({ ...query, licenseKey: item.value }); - onRunQuery(); + const query = defaults(props.query, DEFAULT_QUERY); + + const handleLicenseChange = (item: SelectableValue) => { + props.onChange({ ...query, licenseKey: item.value }); + props.onRunQuery(); }; - const onAggregationChange = (item: SelectableValue) => { - onChange({ ...query, aggregation: item.value, metric: undefined }); - onRunQuery(); + const handleAggregationChange = (item: SelectableValue) => { + props.onChange({ ...query, aggregation: item.value, metric: undefined }); + props.onRunQuery(); }; - const onDimensionChange = (item: SelectableValue) => { + const handleDimensionChange = (item: SelectableValue) => { if (isMetric(item.value)) { setIsDimensionMetricSelected(true); - onChange({ ...query, aggregation: undefined, dimension: undefined, metric: item.value }); + props.onChange({ ...query, aggregation: undefined, dimension: undefined, metric: item.value }); } else { setIsDimensionMetricSelected(false); - onChange({ ...query, dimension: item.value }); + props.onChange({ ...query, dimension: item.value }); } - onRunQuery(); + props.onRunQuery(); }; - const onGroupByChange = (newGroupBys: QueryAdAttribute[] | QueryAttribute[]) => { - onChange({ ...query, groupBy: newGroupBys }); - onRunQuery(); + const handleGroupByChange = (newGroupBys: QueryAdAttribute[] | QueryAttribute[]) => { + props.onChange({ ...query, groupBy: newGroupBys }); + props.onRunQuery(); }; - const onOrderByChange = (newOrderBys: QueryOrderBy[]) => { - onChange({ ...query, orderBy: newOrderBys }); - onRunQuery(); + const handleOrderByChange = (newOrderBys: QueryOrderBy[]) => { + props.onChange({ ...query, orderBy: newOrderBys }); + props.onRunQuery(); }; - const onFilterChange = (newFilters: QueryFilter[]) => { - onChange({ ...query, filters: newFilters }); - onRunQuery(); + const handleFilterChange = (newFilters: QueryFilter[]) => { + props.onChange({ ...query, filters: newFilters }); + props.onRunQuery(); }; - const onLimitChange = (event: ChangeEvent) => { + const handleLimitBlur = (event: ChangeEvent) => { const limit = parseInt(event.target.value, 10); - onChange({ ...query, limit: isNaN(limit) ? undefined : limit }); - onRunQuery(); + props.onChange({ ...query, limit: isNaN(limit) ? undefined : limit }); + props.onRunQuery(); }; - const onFormatAsTimeSeriesChange = (event: ChangeEvent) => { + const handleFormatAsTimeSeriesChange = (event: ChangeEvent) => { setIsTimeSeries(event.currentTarget.checked); if (event.currentTarget.checked) { - onChange({ ...query, interval: 'AUTO' }); + props.onChange({ ...query, interval: 'AUTO' }); } else { - onChange({ ...query, interval: undefined }); + props.onChange({ ...query, interval: undefined }); } - onRunQuery(); + props.onRunQuery(); + }; + + const handleIntervalChange = (item: SelectableValue) => { + props.onChange({ ...query, interval: item.value }); + props.onRunQuery(); }; - const onIntervalChange = (item: SelectableValue) => { - onChange({ ...query, interval: item.value }); - onRunQuery(); + const handleAliasByBlur = (event: ChangeEvent) => { + props.onChange({ ...query, aliasBy: event.target.value }); + props.onRunQuery(); }; const renderTimeSeriesOption = () => { @@ -108,7 +116,7 @@ export function QueryEditor({ query, onChange, onRunQuery, datasource }: Props) {!isDimensionMetricSelected && ( - - handleAggregationChange(item)} width={30} options={SELECTABLE_AGGREGATIONS} /> )} - + + - + {isTimeSeries && renderTimeSeriesOption()} + + + ); diff --git a/bitmovin-analytics-datasource/src/datasource.ts b/bitmovin-analytics-datasource/src/datasource.ts index 073a31e..b0a97fd 100644 --- a/bitmovin-analytics-datasource/src/datasource.ts +++ b/bitmovin-analytics-datasource/src/datasource.ts @@ -1,4 +1,5 @@ import { + CoreApp, createDataFrame, DataQueryRequest, DataQueryResponse, @@ -15,11 +16,13 @@ import { BitmovinAnalyticsDataQuery, NumberDataRowList, BitmovinAnalyticsRequestQuery, + DEFAULT_QUERY, } from './types'; import { transformGroupedTimeSeriesData, transformSimpleTimeSeries, transformTableData } from './utils/dataUtils'; import { calculateQueryInterval } from './utils/intervalUtils'; import { Metric } from './types/metric'; import { Aggregation } from './types/aggregations'; +import { filter } from 'lodash'; export class DataSource extends DataSourceApi { baseUrl: string; @@ -36,6 +39,10 @@ export class DataSource extends DataSourceApi { + return DEFAULT_QUERY; + } + /** * The Bitmovin API Response follows these rules: * - If the interval property is provided in the request query, time series data is returned and the first value of each row is a timestamp in milliseconds. @@ -50,7 +57,10 @@ export class DataSource extends DataSourceApi { + //filter disabled queries + const enabledQueries = (options.targets = filter(options.targets, (t) => !t.hide)); + + const promises = enabledQueries.map(async (target) => { const interval = target.interval ? calculateQueryInterval(target.interval!, from.getTime(), to.getTime()) : undefined; @@ -100,6 +110,7 @@ export class DataSource extends DataSourceApi = {}; +export const DEFAULT_QUERY: Partial = { + licenseKey: '', + interval: 'AUTO', + orderBy: [], + groupBy: [], + filters: [], +}; /** * These are options configured for each DataSource instance diff --git a/bitmovin-analytics-datasource/src/types/aggregations.ts b/bitmovin-analytics-datasource/src/types/aggregations.ts index 273a437..72072ad 100644 --- a/bitmovin-analytics-datasource/src/types/aggregations.ts +++ b/bitmovin-analytics-datasource/src/types/aggregations.ts @@ -11,5 +11,3 @@ export const SELECTABLE_AGGREGATIONS: Array<{ value: Aggregation; label: string { value: 'variance', label: 'Variance' }, { value: 'median', label: 'Median' }, ]; - -export const DEFAULT_SELECTABLE_AGGREGATION = SELECTABLE_AGGREGATIONS[0];