Skip to content

Commit

Permalink
Add data render mode and passing selected data frame (#246)
Browse files Browse the repository at this point in the history
* Replace everyRow option to renderMode

* Fix tests

* Implement all panel data templating

* Pass panel data to helpers

* Pass selected data frame to helpers

* Update tests

* Update CHANGELOG.md

---------

Co-authored-by: Mikhail Volkov <mikhail@volkovlabs.io>
  • Loading branch information
asimonok and mikhail-vl authored Dec 14, 2023
1 parent 40048c2 commit 6e99009
Show file tree
Hide file tree
Showing 14 changed files with 365 additions and 77 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- Update ESLint configuration and refactor (#239)
- Update Collapse from @volkovlabs/components (#239)
- Update Introduction video in README (#240)
- Add data render mode and passing selected data frame (#246)

### Bug fixes

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 @@ -65,6 +65,7 @@ export const Row: React.FC<Props> = ({ className, item, afterRender, replaceVari
unsubscribe = func({
element: ref.current,
data: item.data,
panelData: item.panelData,
grafana: {
replaceVariables,
eventBus,
Expand All @@ -78,7 +79,7 @@ export const Row: React.FC<Props> = ({ className, item, afterRender, replaceVari
unsubscribe();
}
};
}, [afterRender, eventBus, item.data, replaceVariables]);
}, [afterRender, eventBus, item.data, item.panelData, replaceVariables]);

return (
<div
Expand Down
135 changes: 122 additions & 13 deletions src/components/Text/Text.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,24 @@ import { render, screen } from '@testing-library/react';
import React from 'react';

import { DEFAULT_OPTIONS, TEST_IDS } from '../../constants';
import { RenderMode } from '../../types';
import { Props, Text } from './Text';

/**
* Text
*/
describe('<Text />', () => {
describe('Text', () => {
/**
* Default Content
*/
it('Should render default content when there is no dataframe', async () => {
const props: Props = {
data: {} as any,
options: {
...DEFAULT_OPTIONS,
content: 'Test content',
defaultContent: 'Test default content',
everyRow: true,
renderMode: RenderMode.ALL_ROWS,
},
timeRange: {} as any,
timeZone: '',
Expand All @@ -38,11 +40,12 @@ describe('<Text />', () => {
`;
const replaceVariables = jest.fn((str: string) => str);
const props: Props = {
data: {} as any,
options: {
...DEFAULT_OPTIONS,
content: 'Test content',
defaultContent: 'Test default content',
everyRow: true,
renderMode: RenderMode.EVERY_ROW,
styles,
},
timeRange: {} as any,
Expand All @@ -67,13 +70,14 @@ describe('<Text />', () => {
const replaceVariables = jest.fn((str: string) => str);

const props: Props = {
data: {} as any,
options: {
...DEFAULT_OPTIONS,
defaultContent: '<div id="element"></div>',
afterRender: `
context.grafana.eventBus.publish('ready', context.element.querySelector('#element'));
`,
everyRow: true,
renderMode: RenderMode.EVERY_ROW,
},
timeRange: {} as any,
timeZone: '',
Expand All @@ -93,13 +97,14 @@ describe('<Text />', () => {
const replaceVariables = jest.fn((str: string) => str);

const props: Props = {
data: {} as any,
options: {
...DEFAULT_OPTIONS,
defaultContent: '<div id="element"></div>',
afterRender: `
return () => context.grafana.eventBus.publish('destroy');
`,
everyRow: true,
renderMode: RenderMode.EVERY_ROW,
},
timeRange: {} as any,
timeZone: '',
Expand Down Expand Up @@ -131,13 +136,14 @@ describe('<Text />', () => {
],
});
const props: Props = {
data: {} as any,
frame: dataFrame,
options: {
...DEFAULT_OPTIONS,
status: 'value',
content: '<div style="background-color: {{statusColor}};" data-testid="status">{{status}}</div>',
defaultContent: 'Test default content',
everyRow: true,
renderMode: RenderMode.EVERY_ROW,
},
timeRange: {} as any,
timeZone: '',
Expand All @@ -153,12 +159,13 @@ describe('<Text />', () => {
});

/**
* Render content twice
* Render every row
*/
it('Should render content twice when there is a dataframe and everyRow is true', async () => {
it('Should render content twice when there is a dataframe and every row enabled', async () => {
const nameData: string[] = ['Erik', 'Natasha'];
const ageData: number[] = [42, 38];
const props: Props = {
data: {} as any,
frame: toDataFrame({
fields: [
{
Expand All @@ -179,7 +186,7 @@ describe('<Text />', () => {
...DEFAULT_OPTIONS,
content: 'Test content',
defaultContent: 'Test default content',
everyRow: true,
renderMode: RenderMode.EVERY_ROW,
},
timeRange: {} as any,
timeZone: '',
Expand All @@ -196,10 +203,11 @@ describe('<Text />', () => {
});

/**
* Render content once
* Render all rows
*/
it('Should render content once when there is a dataframe and everyRow is false', async () => {
it('Should render content once when there is a dataframe and all rows enabled', async () => {
const props: Props = {
data: {} as any,
frame: {
fields: [],
length: 2,
Expand All @@ -208,7 +216,46 @@ describe('<Text />', () => {
...DEFAULT_OPTIONS,
content: 'Test content',
defaultContent: 'Test default content',
everyRow: false,
renderMode: RenderMode.ALL_ROWS,
},
timeRange: {} as any,
timeZone: '',
replaceVariables: (str: string) => str,
eventBus: {} as any,
};

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

expect(screen.getAllByText('Test content')).toHaveLength(1);
});

/**
* Render all data
*/
it('Should render content once when there is a dataframe and all data enabled', async () => {
const props: Props = {
data: {
series: [
toDataFrame({
fields: [
{
type: FieldType.string,
name: 'text',
values: ['hello', 'hello2'],
},
],
}),
],
} as any,
frame: {
fields: [],
length: 2,
},
options: {
...DEFAULT_OPTIONS,
content: 'Test content',
defaultContent: 'Test default content',
renderMode: RenderMode.DATA,
},
timeRange: {} as any,
timeZone: '',
Expand Down Expand Up @@ -236,6 +283,7 @@ describe('<Text />', () => {
`;

const props: Props = {
data: {} as any,
frame: toDataFrame({
fields: [
{
Expand All @@ -257,7 +305,68 @@ describe('<Text />', () => {
...DEFAULT_OPTIONS,
content: template,
defaultContent: 'Test default content',
everyRow: false,
renderMode: RenderMode.ALL_ROWS,
},
timeRange: {} as any,
timeZone: '',
replaceVariables: (str: string) => str,
eventBus: {} as any,
};

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

expect(screen.getAllByRole('row')[1]).toHaveTextContent('Erik');
expect(screen.getAllByRole('row')[2]).toHaveTextContent('Natasha');
});

/**
* Render all data properties
*/
it('Should render properties of all panel data in template', async () => {
const nameData: string[] = ['Erik', 'Natasha'];
const ageData: number[] = [42, 38];

const template = `| Name | Age |
| ---- | --- |
{{#each data.[0]}}
{{name}} - {{#with (lookup ../data.[1] @index)}}{{age}}{{/with}}
{{/each}}
`;

const frames = [
toDataFrame({
fields: [
{
name: 'name',
type: FieldType.string,
config: {},
values: nameData,
},
],
length: 2,
}),
toDataFrame({
fields: [
{
name: 'age',
type: FieldType.number,
config: {},
values: ageData,
},
],
length: 2,
}),
];
const props: Props = {
data: {
series: frames,
} as any,
frame: frames[0],
options: {
...DEFAULT_OPTIONS,
content: template,
defaultContent: 'Test default content',
renderMode: RenderMode.DATA,
},
timeRange: {} as any,
timeZone: '',
Expand Down
Loading

0 comments on commit 6e99009

Please sign in to comment.