Skip to content

Commit

Permalink
Add suggestions for helper and after render editors
Browse files Browse the repository at this point in the history
  • Loading branch information
asimonok committed Dec 15, 2023
1 parent e7209d0 commit 7892261
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 8 deletions.
24 changes: 22 additions & 2 deletions src/components/CustomEditor/CustomEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@ import { CodeEditor, CodeEditorSuggestionItem, CodeEditorSuggestionItemKind } fr
import type * as monacoType from 'monaco-editor/esm/vs/editor/editor.api';
import React, { useCallback, useMemo } from 'react';

import { CodeLanguage, EditorType, Format, HELPERS_EDITOR_SUGGESTIONS, TEST_IDS } from '../../constants';
import {
AFTER_RENDER_EDITOR_SUGGESTIONS,
CodeLanguage,
EditorType,
Format,
HELPERS_EDITOR_SUGGESTIONS,
TEST_IDS,
} from '../../constants';

/**
* Properties
Expand Down Expand Up @@ -64,6 +71,10 @@ export const CustomEditor: React.FC<Props> = ({ value, onChange, context, type =
return suggestions;
}

if (type === EditorType.AFTER_RENDER) {
return AFTER_RENDER_EDITOR_SUGGESTIONS.concat(suggestions);
}

return HELPERS_EDITOR_SUGGESTIONS.concat(suggestions);
}, [templateSrv, type]);

Expand All @@ -80,7 +91,7 @@ export const CustomEditor: React.FC<Props> = ({ value, onChange, context, type =
* Language
*/
const language = useMemo(() => {
if (type === EditorType.HELPERS) {
if (type === EditorType.HELPERS || type === EditorType.AFTER_RENDER) {
return CodeLanguage.JAVASCRIPT;
}

Expand Down Expand Up @@ -125,6 +136,15 @@ export const HelpersEditor: React.FC<StandardEditorProps> = (props) => (
<CustomEditor {...props} type={EditorType.HELPERS} />
);

/**
* After Render Editor
* @param props
* @constructor
*/
export const AfterRenderEditor: React.FC<StandardEditorProps> = (props) => (
<CustomEditor {...props} type={EditorType.AFTER_RENDER} />
);

/**
* Styles Editor
* @param props
Expand Down
68 changes: 66 additions & 2 deletions src/components/CustomEditor/CutomEditor.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,14 @@ import { CodeEditor, CodeEditorSuggestionItemKind } from '@grafana/ui';
import { render, screen } from '@testing-library/react';
import React from 'react';

import { CodeLanguage, Format, HELPERS_EDITOR_SUGGESTIONS, TEST_IDS } from '../../constants';
import { CustomEditor, HelpersEditor, StylesEditor, TextEditor } from './CustomEditor';
import {
AFTER_RENDER_EDITOR_SUGGESTIONS,
CodeLanguage,
Format,
HELPERS_EDITOR_SUGGESTIONS,
TEST_IDS,
} from '../../constants';
import { CustomEditor, HelpersEditor, StylesEditor, TextEditor, AfterRenderEditor } from './CustomEditor';

/**
* Mock @grafana/ui
Expand Down Expand Up @@ -271,6 +277,64 @@ describe('Custom Editor', () => {
});
});

describe('After Render Editor', () => {
/**
* Properties
*/
const props: any = { context: { options: { editor: {} } }, onChange };

it('Should use javascript language', () => {
render(<AfterRenderEditor {...props} />);

expect(CodeEditor).toHaveBeenCalledWith(
expect.objectContaining({
language: CodeLanguage.JAVASCRIPT,
}),
expect.anything()
);
});

it('Should make correct suggestions', () => {
let suggestionsResult;
const variableWithDescription = { name: 'var1', description: 'Var description', label: 'Var Label' };
const variableWithoutDescription = { name: 'var2', description: '', label: 'Var 2' };
const variables = [variableWithDescription, variableWithoutDescription];

jest.mocked(CodeEditor).mockImplementation(({ getSuggestions }: any) => {
suggestionsResult = getSuggestions();
return null;
});
jest.mocked(getTemplateSrv).mockImplementation(
() =>
({
getVariables: jest.fn().mockImplementation(() => variables),
}) as any
);

render(<AfterRenderEditor {...props} />);

expect(suggestionsResult).toEqual(expect.arrayContaining(AFTER_RENDER_EDITOR_SUGGESTIONS));
expect(suggestionsResult).toEqual(
expect.arrayContaining([
{
label: `\$\{${variableWithDescription.name}\}`,
kind: CodeEditorSuggestionItemKind.Property,
detail: variableWithDescription.description,
},
])
);
expect(suggestionsResult).toEqual(
expect.arrayContaining([
{
label: `\$\{${variableWithoutDescription.name}\}`,
kind: CodeEditorSuggestionItemKind.Property,
detail: variableWithoutDescription.label,
},
])
);
});
});

describe('Styles Editor', () => {
/**
* Properties
Expand Down
3 changes: 2 additions & 1 deletion src/components/Row/Row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export const Row: React.FC<Props> = ({ className, item, afterRender, replaceVari
element: ref.current,
data: item.data,
panelData: item.panelData,
dataFrame: item.dataFrame,
grafana: {
replaceVariables,
eventBus,
Expand All @@ -79,7 +80,7 @@ export const Row: React.FC<Props> = ({ className, item, afterRender, replaceVari
unsubscribe();
}
};
}, [afterRender, eventBus, item.data, item.panelData, replaceVariables]);
}, [afterRender, eventBus, item.data, item.dataFrame, item.panelData, replaceVariables]);

return (
<div
Expand Down
68 changes: 67 additions & 1 deletion src/constants/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,72 @@ export const HELPERS_EDITOR_SUGGESTIONS: CodeEditorSuggestionItem[] = [
{
label: 'eventBus',
kind: CodeEditorSuggestionItemKind.Property,
detail: 'Event bus for application events.',
detail: 'Panels events.',
},
{
label: 'dataFrame',
kind: CodeEditorSuggestionItemKind.Constant,
detail: 'Selected data frame.',
},
{
label: 'panelData',
kind: CodeEditorSuggestionItemKind.Constant,
detail: 'Panel data.',
},
];

/**
* After Render Editor Suggestions
*/
export const AFTER_RENDER_EDITOR_SUGGESTIONS: CodeEditorSuggestionItem[] = [
{
label: 'context',
kind: CodeEditorSuggestionItemKind.Constant,
detail: 'All passed possible properties and methods.',
},
{
label: 'context.element',
kind: CodeEditorSuggestionItemKind.Property,
detail: 'Row html element.',
},
{
label: 'context.data',
kind: CodeEditorSuggestionItemKind.Property,
detail: 'Row data.',
},
{
label: 'context.dataFrame',
kind: CodeEditorSuggestionItemKind.Property,
detail: 'Selected data frame.',
},
{
label: 'context.panelData',
kind: CodeEditorSuggestionItemKind.Property,
detail: 'Panel data.',
},

/**
* Grafana
*/
{
label: 'context.grafana',
kind: CodeEditorSuggestionItemKind.Property,
detail: 'Grafana properties and methods.',
},
{
label: 'context.grafana.eventBus',
kind: CodeEditorSuggestionItemKind.Property,
detail: 'Panels events.',
},
{
label: 'context.grafana.locationService',
kind: CodeEditorSuggestionItemKind.Property,
detail: 'Location service.',
},
{
label: 'context.grafana.replaceVariables',
kind: CodeEditorSuggestionItemKind.Method,
detail: 'Interpolate variables.',
},
];

Expand All @@ -87,6 +152,7 @@ export const HELPERS_EDITOR_SUGGESTIONS: CodeEditorSuggestionItem[] = [
*/
export enum EditorType {
HELPERS = 'helpers',
AFTER_RENDER = 'AFTER_RENDER',
STYLES = 'styles',
TEXT = 'text',
}
4 changes: 2 additions & 2 deletions src/module.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Field, FieldConfigProperty, FieldType, PanelPlugin } from '@grafana/data';
import { config } from '@grafana/runtime';

import { HelpersEditor, ResourcesEditor, StylesEditor, TextEditor, TextPanel } from './components';
import { AfterRenderEditor, HelpersEditor, ResourcesEditor, StylesEditor, TextEditor, TextPanel } from './components';
import {
CODE_LANGUAGE_OPTIONS,
DEFAULT_OPTIONS,
Expand Down Expand Up @@ -171,7 +171,7 @@ export const plugin = new PanelPlugin<PanelOptions>(TextPanel)
description:
'Allows to execute code after content is ready. E.g. use element for drawing chart or event listeners.',
defaultValue: DEFAULT_OPTIONS.afterRender,
editor: HelpersEditor,
editor: AfterRenderEditor,
category: ['JavaScript'],
showIf: (config) =>
config.editors.includes(EditorType.AFTER_RENDER) || config.afterRender !== DEFAULT_OPTIONS.afterRender,
Expand Down

0 comments on commit 7892261

Please sign in to comment.