Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/release-9.x' into main-9
Browse files Browse the repository at this point in the history
  • Loading branch information
mershad-manesh committed Feb 13, 2024
2 parents 84b4288 + de9fcf5 commit 15890ce
Show file tree
Hide file tree
Showing 18 changed files with 343 additions and 111 deletions.
2 changes: 1 addition & 1 deletion docs/antora.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version: '9'
title: Plugin for Grafana
asciidoc:
attributes:
full-display-version: '9.0.12'
full-display-version: '9.0.13-SNAPSHOT'
grafana-version-required: '9.x'
grafana-version-tested: '9.0'
node-js-build-version: '16.x'
Expand Down
2 changes: 1 addition & 1 deletion grafana.version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9.5.14
9.5.15
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "opennms-grafana-plugin",
"version": "9.0.12",
"version": "9.0.13-SNAPSHOT",
"description": "An OpenNMS Integration for Grafana",
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion site.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ asciidoc:
attributes:
experimental: true
stem: latexmath
full-display-version: '9.0.12'
full-display-version: '9.0.13-SNAPSHOT'
grafana-version-required: '9.x'
grafana-version-tested: '9.0'
node-js-build-version: '16.x'
Expand Down
53 changes: 53 additions & 0 deletions src/components/ValueOverrideSwitch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React from 'react'
import { InlineField, SegmentInput, Switch } from '@grafana/ui'

export interface ValueOverrideSwitchProps {
override: boolean
setOverride: (value: boolean) => void
value: string
setValue: (value: any) => void
label?: string
placeholder?: string
tooltip?: string
}

export const ValueOverrideSwitch = (props: ValueOverrideSwitchProps) => {
const defaultLabel = 'Enter value:'
const defaultPlaceholder = 'Enter variable or value'
const defaultTooltip = 'Enter a value or template variable manually'

return (
<>
<style>
{`
.value-override-switch-field .value-override-switch-wrapper {
display: flex;
align-items: center;
height: 32px;
width: 32px;
}
.value-override-switch-field .value-override-switch-wrapper label {
min-width: 32px;
width: 32px;
}
`}
</style>
<InlineField className='value-override-switch-field' label={props.label || defaultLabel} tooltip={props.tooltip || defaultTooltip}>
<div className='value-override-switch-wrapper'>
<Switch
value={props.override}
onChange={() => props.setOverride(!props.override)} />
</div>
</InlineField>
{
(props.override || !!props.value?.length) &&
<SegmentInput
disabled={!props.override}
value={props.value}
placeholder={props.placeholder || defaultPlaceholder}
onChange={(value) => props.setValue(value.toString())}
/>
}
</>
)
}
2 changes: 1 addition & 1 deletion src/datasources/entity-ds/EntityQueryEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ const addClause = (clauses: OnmsEntityClause[], clause: OnmsEntityClause, index:
}

export const EntityQueryEditor: React.FC<EntityQueryEditorProps> = ({ onChange, query, onRunQuery, datasource, ...rest }) => {
const client = datasource.client;
const client = datasource.client
const [value, setValue] = useState<SelectableValue<string>>(query.selectType || { label: 'Alarms' })
const [clauses, dispatchClauses] = useReducer(clausesReducer, query.clauses || [{ ...defaultClause }])
const [loading, setLoading] = useState(false)
Expand Down
61 changes: 61 additions & 0 deletions src/datasources/perf-ds/ManualOverrideExtensionConfig.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React from 'react'
import { DataSourceSettings } from '@grafana/data'
import { InlineField, Switch } from '@grafana/ui'
import { PerformanceDataSourceOptions } from './types'

interface Props {
onOptionsChange: (o: DataSourceSettings<PerformanceDataSourceOptions>) => void
options: DataSourceSettings<PerformanceDataSourceOptions>
}

export const ManualOverrideExtensionConfig: React.FC<Props> = ({ onOptionsChange, options}) => {
const tooltipText = 'Enable manual override UI components for some fields, e.g. Performance Attribute Node, ' +
'where you can enter a template variable or other value manually. ' +
'Generally should not be needed.'

const onChange = (value: boolean) => {
const newOptions = {
...options,
jsonData: {
...options.jsonData,
allowManualOverrideExtensions: value
}
}

onOptionsChange(newOptions)
}

return (
<>
<style>
{
`
.spacer {
margin-top: 10px;
margin-bottom: 10px;
}
.perf-config-editor-switch {
display: flex;
align-items: center;
height: 32px;
width: 32px;
}
.perf-config-editor-switch label {
min-width: 32px;
width: 32px;
}
`
}
</style>
<h3 className='spacer'>Additional Options</h3>

<InlineField className='perf-config-editor-switch-field' label='Allow manual override extensions:' tooltip={tooltipText}>
<div className='perf-config-editor-switch'>
<Switch
value={options.jsonData.allowManualOverrideExtensions}
onChange={() => onChange(!options.jsonData.allowManualOverrideExtensions)} />
</div>
</InlineField>
</>
)
}
111 changes: 94 additions & 17 deletions src/datasources/perf-ds/PerformanceAttribute.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { SelectableValue } from '@grafana/data';
import {
Segment,
SegmentAsync,
SegmentInput
} from '@grafana/ui'
import { SegmentSectionWithIcon } from 'components/SegmentSectionWithIcon';
import React, { useState, useEffect } from 'react'
import { PerformanceAttributeItemState, PerformanceAttributeState } from './types'
import React, { useEffect, useState } from 'react'
import { SelectableValue } from '@grafana/data'
import { Segment, SegmentAsync, SegmentInput } from '@grafana/ui'
import { SegmentSectionWithIcon } from 'components/SegmentSectionWithIcon'
import { ValueOverrideSwitch } from 'components/ValueOverrideSwitch'
import { getTemplateVariables } from 'lib/variableHelpers'
import { OnmsResourceDto } from '../../lib/api_types'
import { PerformanceAttributeItemState, PerformanceAttributeState } from './types'

export interface PerformanceAttributesProps {
allowManualOverrideExtensions: boolean
performanceAttributeState: PerformanceAttributeState
updateQuery: Function
loadNodes: (query?: string | undefined) => Promise<Array<SelectableValue<PerformanceAttributeItemState>>>
Expand All @@ -28,14 +27,18 @@ export const defaultPerformanceState: PerformanceAttributeState = {
}

export const PerformanceAttribute: React.FC<PerformanceAttributesProps> = ({
allowManualOverrideExtensions,
performanceAttributeState,
updateQuery,
loadNodes,
loadResourcesByNode,
loadAttributesByResourceAndNode
}) => {

const [performanceState, setPerformanceState] = useState<PerformanceAttributeState>(performanceAttributeState)
const [isNodeOverride, setIsNodeOverride] = useState<boolean>(false)
const [nodeOverrideValue, setNodeOverrideValue] = useState<string>('')
const [isResourceOverride, setIsResourceOverride] = useState<boolean>(false)
const [resourceOverrideValue, setResourceOverrideValue] = useState<string>('')

useEffect(() => {
// Note: this could result in invalid queries if not all parameters have been selected.
Expand All @@ -48,17 +51,62 @@ export const PerformanceAttribute: React.FC<PerformanceAttributesProps> = ({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [performanceState])

useEffect(() => {
if (isNodeOverride) {
const propertyValue = { id: nodeOverrideValue, label: nodeOverrideValue }
setPerformanceStateNode(propertyValue)
} else {
setPerformanceStateNode(performanceState?.node)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isNodeOverride, nodeOverrideValue])

useEffect(() => {
if (isResourceOverride) {
const propertyValue = { id: resourceOverrideValue, label: resourceOverrideValue }
setPerformanceStateProperty('resource', propertyValue)
} else {
setPerformanceStateProperty('resource', performanceState?.resource)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isResourceOverride, resourceOverrideValue])

const loadNodesAndVariables = async () => {
const nodeItems = await loadNodes()
const variables = getTemplateVariables()
const result = variables.map(x => { return { id: `$${x.name}`, label: `$${x.name}` }})
nodeItems.forEach(x => result.push(x as any))

return result
}

const loadResourcesByNodeAndVariables = async (value?: string | number) => {
const resources = await loadResourcesByNode(value)

const variables = getTemplateVariables()
const result = variables.map(x => { return { id: `$${x.name}`, label: `$${x.name}` }})
resources.forEach(x => result.push(x as any))

return result
}

const setPerformanceStateProperty = (propertyName: string, propertyValue: unknown) => {
setPerformanceState({...performanceState, [propertyName]: propertyValue})
}

/**
* If node changed, need to repopulate the resource part of the query with resources
* for the newly selected node.
* Attempt to find the same resource label as existing; otherwise the new node
* doesn't have the same resources, so clear them
*/
const setPerformanceStateNode = async (propertyValue: unknown) => {
// If node changed, need to repopulate the resource part of the query with resources
// for the newly selected node.
// Attempt to find the same resource label as existing; otherwise the new node
// doesn't have the same resources, so clear them
const node = propertyValue as PerformanceAttributeItemState

if (!node) {
return
}

const resourceOptions: OnmsResourceDto[] = await loadResourcesByNode(node.id || node.label)
const existingLabel = performanceState?.resource?.label
const resource = (existingLabel && resourceOptions && resourceOptions.filter(r => r.label === existingLabel)?.[0]) || {}
Expand All @@ -74,31 +122,60 @@ export const PerformanceAttribute: React.FC<PerformanceAttributesProps> = ({

return (
<>
<style>
{`
.pf-query-editor .pf-query-editor-attr-switch-field .pf-query-editor-switch-wrapper {
display: flex;
align-items: center;
height: 32px;
width: 32px;
}
.pf-query-editor .pf-query-editor-attr-switch-field .pf-query-editor-switch-wrapper label {
min-width: 32px;
width: 32px;
}
`}
</style>
<div className='spacer' />
<SegmentSectionWithIcon label='Node' icon='tree'>
<SegmentAsync
value={performanceState?.node}
placeholder='Select Node'
loadOptions={loadNodes}
loadOptions={loadNodesAndVariables}
onChange={(value) => {
(async () => {
await setPerformanceStateNode(value)
})()
}}
/>
{ allowManualOverrideExtensions &&
<ValueOverrideSwitch
override={isNodeOverride}
value={nodeOverrideValue}
setOverride={setIsNodeOverride}
setValue={setNodeOverrideValue}
/>
}
</SegmentSectionWithIcon>

<div className='spacer' />
{
(performanceState?.node?.id || performanceState?.node?.label) &&

<SegmentSectionWithIcon label='Resource' icon='leaf'>
<SegmentAsync
value={performanceState?.resource}
placeholder='Select Resource'
loadOptions={() => loadResourcesByNode(performanceState?.node?.id || performanceState?.node?.label)}
loadOptions={() => loadResourcesByNodeAndVariables(performanceState?.node?.id || performanceState?.node?.label)}
onChange={(value) => { setPerformanceStateProperty('resource', value) }}
/>
{ allowManualOverrideExtensions &&
<ValueOverrideSwitch
override={isResourceOverride}
value={resourceOverrideValue}
setOverride={setIsResourceOverride}
setValue={setResourceOverrideValue}
/>
}
</SegmentSectionWithIcon>
}
<div className='spacer' />
Expand Down
18 changes: 13 additions & 5 deletions src/datasources/perf-ds/PerformanceConfigEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
import React from 'react';
import { DataSourcePluginOptionsEditorProps } from '@grafana/data';
import { DataSourceHttpSettings } from '@grafana/ui';
import { ManualOverrideExtensionConfig } from './ManualOverrideExtensionConfig'
import { PerformanceDataSourceOptions } from './types';

interface Props extends DataSourcePluginOptionsEditorProps<PerformanceDataSourceOptions> { }

export const PerformanceConfigEditor: React.FC<Props> = ({ onOptionsChange, options }) => {
return (
<DataSourceHttpSettings
defaultUrl="https://api.example.com"
dataSourceConfig={options}
onChange={onOptionsChange}
/>
<>
<DataSourceHttpSettings
defaultUrl="https://api.example.com"
dataSourceConfig={options}
onChange={onOptionsChange}
/>

<ManualOverrideExtensionConfig
onOptionsChange={onOptionsChange}
options={options}
/>
</>
)
}
Loading

0 comments on commit 15890ce

Please sign in to comment.