Skip to content

Commit

Permalink
fix: properly display values in QueryBuilderTag (#383)
Browse files Browse the repository at this point in the history
  • Loading branch information
simPod authored Feb 4, 2023
1 parent e2ed098 commit 33a8724
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 13 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@
"dependencies": {
"lodash": "^4.17.21",
"react-virtualized-auto-sizer": "^1.0.7",
"rxjs": "7.5.7"
"rxjs": "7.5.7",
"ts-pattern": "^4.1.3"
},
"homepage": "https://github.com/simPod/GrafanaJsonDatasource",
"engineStrict": true,
Expand Down
13 changes: 9 additions & 4 deletions src/Component/QueryBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,20 @@ interface LastQuery {
metric: string;
}

type UnknownPayload = Array<{ name: string; value: unknown }>;

type EditorProps = QueryEditorProps<DataSource, GrafanaQuery, GenericOptions>;

interface Props extends EditorProps {
payload: { [key: string]: any };
payload: { [key: string]: unknown };
}

export const QueryBuilder: ComponentType<Props> = (props) => {
const { datasource, onChange, onRunQuery, query } = props;
const [metric, setMetric] = React.useState<SelectableValue<string | number>>();
const [payload, setPayload] = React.useState(props.payload ?? '');

const [unknownPayload, setUnknownPayload] = React.useState<Array<{ name: string; value: any }>>([]);
const [unknownPayload, setUnknownPayload] = React.useState<UnknownPayload>([]);

const [lastQuery, setLastQuery] = React.useState<LastQuery | null>(null);
const [payloadConfig, setPayloadConfig] = React.useState<MetricPayloadConfig[]>([]);
Expand Down Expand Up @@ -82,12 +84,13 @@ export const QueryBuilder: ComponentType<Props> = (props) => {
}, [payload, metric]);

React.useEffect(() => {
const newUnknownPayload: Array<{ name: string; value: any }> = [];
const newUnknownPayload: UnknownPayload = [];
for (const key in payload) {
const foundConfig = payloadConfig.find((item) => item.name === key);
if (foundConfig === undefined) {
newUnknownPayload.push({ name: key, value: payload[key] });
}

setUnknownPayload(newUnknownPayload);
}
}, [payload, payloadConfig]);
Expand Down Expand Up @@ -166,7 +169,8 @@ export const QueryBuilder: ComponentType<Props> = (props) => {
<QueryBuilderPayloadSelect
{...props}
config={opt}
value={payload[opt.name]}
// TODO: Handle types properly, possibly buggy
value={payload[opt.name] as string | number | string[] | number[]}
isMulti={opt.type === 'multi-select'}
onPayloadChange={(v) => {
changePayload(opt.name, opt.reloadMetric, v);
Expand All @@ -181,6 +185,7 @@ export const QueryBuilder: ComponentType<Props> = (props) => {
<label className="gf-form-label">{opt.label ?? opt.label}</label>
<QueryBuilderTextArea
config={opt}
// TODO: Handle types properly, possibly buggy
value={payload[opt.name] as string}
onValueChange={(v) => {
changePayload(opt.name, opt.reloadMetric, { value: v });
Expand Down
19 changes: 19 additions & 0 deletions src/Component/QueryBuilderTag.jest.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import { QueryBuilderTag } from './QueryBuilderTag';
import React from 'react';

test.each([
['key="text"', 'text'],
['key=true', true],
['key=1', 1],
['key=null', null],
['key="{"some":"object"}"', { some: 'object' }],
])('displays key-value as %s for %s', async (expectedContent, value) => {
render(<QueryBuilderTag name="key" value={value} onRemove={() => {}} />);

const element: HTMLSpanElement = screen.getByText(/key/);

expect(element).toBeInTheDocument();
expect(element).toHaveTextContent(expectedContent);
});
12 changes: 10 additions & 2 deletions src/Component/QueryBuilderTag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { css } from '@emotion/css';
import { GrafanaTheme } from '@grafana/data';
import { getTagColorsFromName, IconButton, stylesFactory, useTheme } from '@grafana/ui';
import React, { ComponentType } from 'react';
import { match } from 'ts-pattern';

type QueryBuilderTagProps = {
name: string;
value: string;
value: unknown;
onRemove: (name: string) => void;
};

Expand Down Expand Up @@ -48,10 +49,17 @@ export const QueryBuilderTag: ComponentType<QueryBuilderTagProps> = ({ name, val
const theme = useTheme();
const styles = getStyles({ theme, name });

const formattedValue = match(typeof value)
.with('string', () => `"${value}"`)
.with('number', () => value)
.with('boolean', () => (value as boolean).toString())
.with('object', () => (value === null ? 'null' : `"${JSON.stringify(value)}"`))
.otherwise(() => `"${JSON.stringify(value)}"`);

return (
<div className={styles.itemStyle}>
<span className={styles.nameStyle}>
{name}={value}
{name}={formattedValue}
</span>
<IconButton
name="times"
Expand Down
4 changes: 2 additions & 2 deletions src/Component/QueryEditorContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { CodeEditor, InlineField, InlineSwitch } from '@grafana/ui';

type Props = QueryEditorProps<DataSource, GrafanaQuery, GenericOptions>;

function convertPayloadToObject(payload: string | { [key: string]: any }): { [key: string]: any } {
function convertPayloadToObject(payload: string | { [key: string]: unknown }): { [key: string]: unknown } {
if (payload) {
if (typeof payload === 'string') {
try {
Expand All @@ -29,7 +29,7 @@ function convertPayloadToObject(payload: string | { [key: string]: any }): { [ke
}
}

const convertPayloadToString = (payload: string | { [key: string]: any }): string => {
const convertPayloadToString = (payload: string | { [key: string]: unknown }): string => {
if (typeof payload === 'string') {
return payload;
} else if (payload) {
Expand Down
6 changes: 3 additions & 3 deletions src/DataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ export class DataSource extends DataSourceApi<GrafanaQuery, GenericOptions> {
listMetricPayloadOptions(
name: string,
metric: string,
payload: string | { [key: string]: string }
payload: string | { [key: string]: unknown }
): Promise<Array<SelectableValue<string | number>>> {
return lastValueFrom<Array<SelectableValue<string | number>>>(
this.doFetch({
Expand Down Expand Up @@ -284,7 +284,7 @@ export class DataSource extends DataSourceApi<GrafanaQuery, GenericOptions> {
return getBackendSrv().fetch<T>(options);
}

processPayload(payload: string | { [key: string]: any }, editorMode?: QueryEditorMode, scopedVars?: ScopedVars) {
processPayload(payload: string | { [key: string]: unknown }, editorMode?: QueryEditorMode, scopedVars?: ScopedVars) {
try {
if (typeof payload === 'string' && editorMode !== 'builder') {
if (payload.trim() !== '') {
Expand All @@ -295,7 +295,7 @@ export class DataSource extends DataSourceApi<GrafanaQuery, GenericOptions> {
return {};
} else {
const newPayload: { [key: string]: any } =
typeof payload === 'string' ? (JSON.parse(payload) as { [key: string]: string }) : { ...payload };
typeof payload === 'string' ? (JSON.parse(payload) as { [key: string]: unknown }) : { ...payload };
for (const key in newPayload) {
if (Object.prototype.hasOwnProperty.call(newPayload, key)) {
const value = newPayload[key];
Expand Down
2 changes: 1 addition & 1 deletion src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export interface GrafanaQuery extends DataQuery {
editorMode?: QueryEditorMode;
alias?: string;
target?: string;
payload: string | { [key: string]: any };
payload: string | { [key: string]: unknown };
}

export interface GenericOptions extends DataSourceJsonData {
Expand Down
8 changes: 8 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8069,6 +8069,7 @@ __metadata:
react-dom: ^18.2.0
react-virtualized-auto-sizer: ^1.0.7
rxjs: 7.5.7
ts-pattern: ^4.1.3
languageName: unknown
linkType: soft

Expand Down Expand Up @@ -14085,6 +14086,13 @@ __metadata:
languageName: node
linkType: hard

"ts-pattern@npm:^4.1.3":
version: 4.1.3
resolution: "ts-pattern@npm:4.1.3"
checksum: a9462aa0e503dcf8fd1a8d648b02315276f644711bf1c7564a1185cd8b78a7b84fa9bc4f9ecdbb0fd88692c74a28f03e5af1898066d5f3b8744a87508d6a457b
languageName: node
linkType: hard

"tslib@npm:2.4.0":
version: 2.4.0
resolution: "tslib@npm:2.4.0"
Expand Down

0 comments on commit 33a8724

Please sign in to comment.