Skip to content

Commit

Permalink
Added scoped vars for repeat by compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
diericd committed Sep 25, 2024
1 parent 719323a commit 7e63c69
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 49 deletions.
4 changes: 3 additions & 1 deletion src/QueryEditor/EventAssetProperties.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ export const EventAssetProperties = (props: Props): React.JSX.Element => {

const getSelectedAssetProperties = (): AssetProperty[] => {
const assetPropertiesSet = new Set<AssetProperty>()
const selectedAssetProperties = props.selectedAssetProperties.flatMap((e) => props.datasource.multiSelectReplace(e))
const selectedAssetProperties = props.selectedAssetProperties.flatMap((e) =>
props.datasource.multiSelectReplace(e, {})
)

for (const assetProperty of assetProperties) {
const propertySelected =
Expand Down
3 changes: 2 additions & 1 deletion src/QueryEditor/Events.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export const Events = (props: Props): JSX.Element => {
}

const getSelectedAssets = (selected: string | undefined, assets: Asset[]): Asset[] => {
const replacedAssets = props.datasource.multiSelectReplace(selected)
const replacedAssets = props.datasource.multiSelectReplace(selected, {})
return matchedAssets(replacedAssets, assets)
}

Expand Down Expand Up @@ -133,6 +133,7 @@ export const Events = (props: Props): JSX.Element => {
Condition: tag.condition || '',
Operator: tag.operator || '=',
Value: tag.value,
ScopedVars: {},
}
filter.push(eventPropertyFilter)
})
Expand Down
2 changes: 2 additions & 0 deletions src/QueryEditor/Measurements.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ export const Measurements = (props: Props): React.JSX.Element => {
const filter: MeasurementFilter = {
Keyword: props.query.Regex,
DatabaseUUIDs: props.query.Databases,
ScopedVars: {},
}
const measurementKeys = await props.datasource.getTagKeysForMeasurements(filter)
measurementKeys.forEach((e) => options.add(e))
Expand All @@ -134,6 +135,7 @@ export const Measurements = (props: Props): React.JSX.Element => {
const filter: MeasurementFilter = {
Keyword: props.query.Regex,
DatabaseUUIDs: props.query.Databases,
ScopedVars: {},
}
const tagValues = await props.datasource.getTagValuesForMeasurements(filter, key)
tagValues.forEach((e) => options.add(e))
Expand Down
76 changes: 45 additions & 31 deletions src/datasource.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CoreApp, DataQueryRequest, DataSourceInstanceSettings } from '@grafana/data'
import { CoreApp, DataQueryRequest, DataSourceInstanceSettings, ScopedVars } from '@grafana/data'
import { DataSourceWithBackend, TemplateSrv, getTemplateSrv } from '@grafana/runtime'
import { VariableSupport } from 'variable_support'
import { AnnotationsQueryEditor } from 'AnnotationsQueryEditor/AnnotationsQueryEditor'
Expand Down Expand Up @@ -71,53 +71,67 @@ export class DataSource extends DataSourceWithBackend<Query, HistorianDataSource
if (!target.seriesLimit) {
target.seriesLimit = 50
}

switch (target.queryType) {
case 'AssetMeasurementQuery': {
const assetMeasurementQuery = target.query as AssetMeasurementQuery
assetMeasurementQuery.Assets = assetMeasurementQuery.Assets?.flatMap((e) => this.multiSelectReplace(e))
assetMeasurementQuery.Assets = assetMeasurementQuery.Assets?.flatMap((e) =>
this.multiSelectReplace(e, request.scopedVars)
)
assetMeasurementQuery.AssetProperties = assetMeasurementQuery.AssetProperties.flatMap((e) => {
return this.multiSelectReplace(e)
return this.multiSelectReplace(e, request.scopedVars)
})
assetMeasurementQuery.Options = this.templateReplaceQueryOptions(assetMeasurementQuery.Options)
assetMeasurementQuery.Options = this.templateReplaceQueryOptions(
assetMeasurementQuery.Options,
request.scopedVars
)
target.query = assetMeasurementQuery
break
}
case 'MeasurementQuery': {
const measurementQuery = target.query as MeasurementQuery
measurementQuery.Databases = measurementQuery.Databases?.flatMap((e) => this.multiSelectReplace(e))
measurementQuery.Measurements = measurementQuery.Measurements?.flatMap((m) => this.multiSelectReplace(m))
measurementQuery.Options = this.templateReplaceQueryOptions(measurementQuery.Options)
measurementQuery.Databases = measurementQuery.Databases?.flatMap((e) =>
this.multiSelectReplace(e, request.scopedVars)
)
measurementQuery.Measurements = measurementQuery.Measurements?.flatMap((m) =>
this.multiSelectReplace(m, request.scopedVars)
)
measurementQuery.Options = this.templateReplaceQueryOptions(measurementQuery.Options, request.scopedVars)
target.query = measurementQuery
break
}
case 'RawQuery': {
const rawQuery = target.query as RawQuery
rawQuery.TimeseriesDatabase = this.templateSrv.replace(rawQuery.TimeseriesDatabase)
rawQuery.Query = this.templateSrv.replace(rawQuery.Query)
rawQuery.TimeseriesDatabase = this.templateSrv.replace(rawQuery.TimeseriesDatabase, request.scopedVars)
rawQuery.Query = this.templateSrv.replace(rawQuery.Query, request.scopedVars)
target.query = rawQuery
break
}
case 'EventQuery': {
const eventQuery = target.query as EventQuery
eventQuery.Assets = eventQuery.Assets?.flatMap((e) => this.multiSelectReplace(e))
eventQuery.EventTypes = eventQuery.EventTypes?.flatMap((e) => this.multiSelectReplace(e))
eventQuery.Statuses = eventQuery.Statuses?.flatMap((e) => this.multiSelectReplace(e))
eventQuery.Properties = eventQuery.Properties?.flatMap((e) => this.multiSelectReplace(e))
eventQuery.Assets = eventQuery.Assets?.flatMap((e) => this.multiSelectReplace(e, request.scopedVars))
eventQuery.EventTypes = eventQuery.EventTypes?.flatMap((e) =>
this.multiSelectReplace(e, request.scopedVars)
)
eventQuery.Statuses = eventQuery.Statuses?.flatMap((e) => this.multiSelectReplace(e, request.scopedVars))
eventQuery.Properties = eventQuery.Properties?.flatMap((e) =>
this.multiSelectReplace(e, request.scopedVars)
)
eventQuery.PropertyFilter = eventQuery.PropertyFilter?.map((e) => {
e.Property = this.templateSrv.replace(e.Property)
e.Property = this.templateSrv.replace(e.Property, request.scopedVars)
if (e.Value === 'select tag value') {
return e
}

switch (e.Datatype) {
case PropertyDatatype.Number:
e.Value = parseFloat(this.templateSrv.replace(String(e.Value)))
e.Value = parseFloat(this.templateSrv.replace(String(e.Value), request.scopedVars))
break
case PropertyDatatype.Bool:
e.Value = this.templateSrv.replace(String(e.Value)) === 'true'
e.Value = this.templateSrv.replace(String(e.Value), request.scopedVars) === 'true'
break
case PropertyDatatype.String:
e.Value = this.templateSrv.replace(String(e.Value))
e.Value = this.templateSrv.replace(String(e.Value), request.scopedVars)
break
}
return e
Expand All @@ -134,31 +148,31 @@ export class DataSource extends DataSourceWithBackend<Query, HistorianDataSource
}

// https://grafana.com/docs/grafana/latest/dashboards/variables/variable-syntax/
multiSelectReplace(value: string | undefined): string[] {
return this.templateSrv.replace(value, undefined, 'csv').split(',')
multiSelectReplace(value: string | undefined, scopedVars?: ScopedVars): string[] {
return this.templateSrv.replace(value, scopedVars, 'csv').split(',')
}

templateReplaceQueryOptions(options: MeasurementQueryOptions): MeasurementQueryOptions {
templateReplaceQueryOptions(options: MeasurementQueryOptions, scopedVars: ScopedVars): MeasurementQueryOptions {
if (options.GroupBy) {
options.GroupBy = options.GroupBy?.flatMap((e) => this.multiSelectReplace(e))
options.GroupBy = options.GroupBy?.flatMap((e) => this.multiSelectReplace(e, scopedVars))
}
if (options.Tags) {
const tags: Attributes = {}
for (const [key, value] of Object.entries(options.Tags)) {
tags[this.templateSrv.replace(key)] = this.templateSrv.replace(value)
tags[this.templateSrv.replace(key, scopedVars)] = this.templateSrv.replace(value, scopedVars)
}
options.Tags = tags
}
if (options.Aggregation) {
const aggregationArguments = options.Aggregation.Arguments
if (aggregationArguments) {
for (let i = 0; i < aggregationArguments.length; i++) {
aggregationArguments[i] = this.templateSrv.replace(aggregationArguments[i])
aggregationArguments[i] = this.templateSrv.replace(aggregationArguments[i], scopedVars)
}
}
options.Aggregation = {
Name: this.templateSrv.replace(options.Aggregation?.Name),
Period: this.templateSrv.replace(options.Aggregation?.Period),
Name: this.templateSrv.replace(options.Aggregation?.Name, scopedVars),
Period: this.templateSrv.replace(options.Aggregation?.Period, scopedVars),
Fill: options.Aggregation.Fill,
Arguments: aggregationArguments,
}
Expand All @@ -167,8 +181,8 @@ export class DataSource extends DataSourceWithBackend<Query, HistorianDataSource
}

templateReplaceMeasurementFilter(filter: MeasurementFilter): MeasurementFilter {
filter.DatabaseUUIDs = filter.DatabaseUUIDs?.flatMap((e) => this.multiSelectReplace(e))
filter.Keyword = this.templateSrv.replace(filter.Keyword)
filter.DatabaseUUIDs = filter.DatabaseUUIDs?.flatMap((e) => this.multiSelectReplace(e, filter.ScopedVars))
filter.Keyword = this.templateSrv.replace(filter.Keyword, filter.ScopedVars)
return filter
}

Expand Down Expand Up @@ -214,7 +228,7 @@ export class DataSource extends DataSourceWithBackend<Query, HistorianDataSource
...filter,
}
if (filter.ParentUUIDs) {
const parentUUIDs = filter.ParentUUIDs.flatMap((e) => this.multiSelectReplace(e))
const parentUUIDs = filter.ParentUUIDs.flatMap((e) => this.multiSelectReplace(e, filter.ScopedVars))
if (parentUUIDs.some((e) => e === '')) {
// empty string means there is no parent selected
return []
Expand All @@ -223,7 +237,7 @@ export class DataSource extends DataSourceWithBackend<Query, HistorianDataSource
}

if (filter.Keyword) {
params.Keyword = this.templateSrv.replace(filter.Keyword)
params.Keyword = this.templateSrv.replace(filter.Keyword, filter.ScopedVars)
}
}
return this.getResource('assets', params)
Expand All @@ -236,7 +250,7 @@ export class DataSource extends DataSourceWithBackend<Query, HistorianDataSource
...filter,
}
if (filter.AssetUUIDs) {
params.AssetUUIDs = filter.AssetUUIDs.flatMap((e) => this.multiSelectReplace(e))
params.AssetUUIDs = filter.AssetUUIDs.flatMap((e) => this.multiSelectReplace(e, filter.ScopedVars))
}
}
return this.getResource('asset-properties', params)
Expand All @@ -260,7 +274,7 @@ export class DataSource extends DataSourceWithBackend<Query, HistorianDataSource
}
if (eventTypePropertiesFilter.EventTypeUUIDs) {
eventTypePropertiesFilter.EventTypeUUIDs = eventTypePropertiesFilter.EventTypeUUIDs.flatMap((e) =>
this.multiSelectReplace(e)
this.multiSelectReplace(e, filter.ScopedVars)
)
}
params = {
Expand Down
20 changes: 12 additions & 8 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DataSourceJsonData } from '@grafana/data'
import { DataSourceJsonData, ScopedVars } from '@grafana/data'
import { DataQuery } from '@grafana/schema'

export const labelWidth = 25
Expand Down Expand Up @@ -128,40 +128,44 @@ export enum EventTypePropertyType {
Periodic = 'periodic',
}

export interface MeasurementFilter {
export interface ResourceFilter {
ScopedVars?: ScopedVars
}

export interface MeasurementFilter extends ResourceFilter {
Keyword?: string
DatabaseUUIDs?: string[]
CollectorUUID?: string
AssetUUID?: string
Statuses?: string[]
}

export interface AssetFilter {
export interface AssetFilter extends ResourceFilter {
Keyword?: string
Path?: string
ParentUUIDs?: string[]
UseAssetPath?: boolean
}

export interface AssetPropertyFilter {
export interface AssetPropertyFilter extends ResourceFilter {
AssetUUIDs?: string[]
Recursive?: boolean
}

export interface TimeseriesDatabaseFilter {
export interface TimeseriesDatabaseFilter extends ResourceFilter {
Keyword?: string
}

export interface EventTypeFilter {
export interface EventTypeFilter extends ResourceFilter {
Keyword?: string
}

export interface EventTypePropertiesFilter {
export interface EventTypePropertiesFilter extends ResourceFilter {
EventTypeUUIDs?: string[]
Types?: string[]
}

export interface EventPropertyFilter {
export interface EventPropertyFilter extends ResourceFilter {
Property: string
Datatype: string
Value?: string | number | boolean
Expand Down
41 changes: 33 additions & 8 deletions src/variable_support.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { forkJoin, from, map, of, Observable } from 'rxjs'

import { CustomVariableSupport, DataQueryRequest, DataQueryResponse, MetricFindValue } from '@grafana/data'
import { CustomVariableSupport, DataQueryRequest, DataQueryResponse, MetricFindValue, ScopedVars } from '@grafana/data'
import { DataSource } from 'datasource'
import { VariableQueryEditor } from 'CustomVariableEditor/VariableEditor'
import {
Expand Down Expand Up @@ -33,7 +33,7 @@ export interface DataAPI {
getEventTypes(filter?: EventTypeFilter): Promise<EventType[]>
getEventTypeProperties(filter?: EventTypePropertiesFilter): Promise<EventTypeProperty[]>
getEventConfigurations(): Promise<EventConfiguration[]>
multiSelectReplace(value: string | undefined): string[]
multiSelectReplace(value: string | undefined, scopedVars: ScopedVars): string[]
}

export class VariableSupport extends CustomVariableSupport<DataSource> {
Expand All @@ -50,6 +50,7 @@ export class VariableSupport extends CustomVariableSupport<DataSource> {
case 'MeasurementQuery': {
const filter = {
...request.targets[0].filter,
ScopedVars: request.scopedVars,
}
if (!filter) {
return of({ data: [] })
Expand All @@ -61,7 +62,9 @@ export class VariableSupport extends CustomVariableSupport<DataSource> {
}

if (filter.DatabaseUUIDs) {
filter.DatabaseUUIDs = filter.DatabaseUUIDs?.flatMap((e) => this.dataAPI.multiSelectReplace(e))
filter.DatabaseUUIDs = filter.DatabaseUUIDs?.flatMap((e) =>
this.dataAPI.multiSelectReplace(e, request.scopedVars)
)
}

return forkJoin({
Expand All @@ -85,32 +88,53 @@ export class VariableSupport extends CustomVariableSupport<DataSource> {
case 'AssetQuery': {
const filter = {
...request.targets[0].filter,
ScopedVars: request.scopedVars,
}
const useAssetPath = filter.UseAssetPath ?? false
return from(this.dataAPI.getAssets(filter)).pipe(
map((values) => {
return { data: values.map<MetricFindValue>((v) => ({ text: useAssetPath ? v.AssetPath ?? v.Name : v.Name, value: v.UUID })) }
return {
data: values.map<MetricFindValue>((v) => ({
text: useAssetPath ? v.AssetPath ?? v.Name : v.Name,
value: v.UUID,
})),
}
})
)
}
case 'EventTypeQuery': {
return from(this.dataAPI.getEventTypes(request.targets[0].filter)).pipe(
const filter = {
...request.targets[0].filter,
ScopedVars: request.scopedVars,
}

return from(this.dataAPI.getEventTypes(filter)).pipe(
map((values) => {
return { data: values.map<MetricFindValue>((v) => ({ text: v.Name, value: v.UUID })) }
})
)
}
case 'DatabaseQuery': {
return from(this.dataAPI.getTimeseriesDatabases(request.targets[0].filter)).pipe(
const filter = {
...request.targets[0].filter,
ScopedVars: request.scopedVars,
}

return from(this.dataAPI.getTimeseriesDatabases(filter)).pipe(
map((values) => {
return { data: values.map<MetricFindValue>((v) => ({ text: v.Name, value: v.UUID })) }
})
)
}
case 'EventTypePropertyQuery': {
const filter = {
...request.targets[0].filter,
ScopedVars: request.scopedVars,
}

return forkJoin({
eventTypes: this.dataAPI.getEventTypes(),
eventTypeProperties: this.dataAPI.getEventTypeProperties(request.targets[0].filter),
eventTypeProperties: this.dataAPI.getEventTypeProperties(filter),
}).pipe(
map((values) => {
return {
Expand All @@ -129,9 +153,10 @@ export class VariableSupport extends CustomVariableSupport<DataSource> {
case 'AssetPropertyQuery': {
const filter = {
...request.targets[0].filter,
ScopedVars: request.scopedVars,
}
if (filter.AssetUUIDs) {
filter.AssetUUIDs = filter.AssetUUIDs.flatMap((e) => this.dataAPI.multiSelectReplace(e))
filter.AssetUUIDs = filter.AssetUUIDs.flatMap((e) => this.dataAPI.multiSelectReplace(e, request.scopedVars))
}
return from(this.dataAPI.getAssetProperties(filter)).pipe(
map((values) => {
Expand Down

0 comments on commit 7e63c69

Please sign in to comment.