grafana-flamegraph: Add storybook stories for major components (#113375)
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { createDataFrame } from '@grafana/data';
|
||||
|
||||
import { ColorScheme, SelectedView } from '../types';
|
||||
|
||||
import FlameGraph from './FlameGraph';
|
||||
import { CollapsedMap, FlameGraphDataContainer } from './dataTransform';
|
||||
import { data } from './testData/dataBasic';
|
||||
|
||||
const meta: Meta<typeof FlameGraph> = {
|
||||
title: 'FlameGraph',
|
||||
component: FlameGraph,
|
||||
args: {
|
||||
rangeMin: 0,
|
||||
rangeMax: 1,
|
||||
textAlign: 'left',
|
||||
colorScheme: ColorScheme.PackageBased,
|
||||
selectedView: SelectedView.Both,
|
||||
search: '',
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
export const Basic: StoryObj<typeof meta> = {
|
||||
render: (args) => {
|
||||
const dataContainer = new FlameGraphDataContainer(createDataFrame(data), { collapsing: false });
|
||||
|
||||
return <FlameGraph {...args} data={dataContainer} collapsedMap={new CollapsedMap()} />;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
import { DataFrameDTO } from '@grafana/data';
|
||||
|
||||
export const data: DataFrameDTO = {
|
||||
name: 'response',
|
||||
refId: 'A',
|
||||
// @ts-ignore
|
||||
meta: { preferredVisualisationType: 'flamegraph' },
|
||||
fields: [
|
||||
{
|
||||
name: 'level',
|
||||
values: [0, 1, 2, 3, 2, 1],
|
||||
},
|
||||
{
|
||||
name: 'value',
|
||||
values: [10000, 5000, 4000, 3000, 500, 3000],
|
||||
config: {
|
||||
unit: 'ms',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'self',
|
||||
values: [10000, 500, 1000, 3000, 500, 3000],
|
||||
config: {
|
||||
unit: 'ms',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'label',
|
||||
values: ['total', 'fn_1', 'fn_2', 'fn_3', 'fn_4', 'fn_5'],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { createDataFrame } from '@grafana/data';
|
||||
import { useTheme2 } from '@grafana/ui';
|
||||
|
||||
import { data } from './FlameGraph/testData/dataNestedSet';
|
||||
import FlameGraphContainer, { Props } from './FlameGraphContainer';
|
||||
|
||||
const WrappedFlameGraph = (props: Omit<Props, 'getTheme'>) => {
|
||||
const theme = useTheme2();
|
||||
const df = createDataFrame(data);
|
||||
return <FlameGraphContainer {...props} data={df} getTheme={() => theme} />;
|
||||
};
|
||||
|
||||
const meta: Meta<typeof FlameGraphContainer> = {
|
||||
title: 'FlameGraphContainer',
|
||||
render: (args) => {
|
||||
return <WrappedFlameGraph {...args} />;
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
export const Basic: StoryObj<typeof meta> = {};
|
||||
@@ -0,0 +1,41 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { createDataFrame } from '@grafana/data';
|
||||
|
||||
import { FlameGraphDataContainer } from '../FlameGraph/dataTransform';
|
||||
import { data } from '../FlameGraph/testData/dataNestedSet';
|
||||
import { ColorScheme } from '../types';
|
||||
|
||||
import FlameGraphTopTableContainer from './FlameGraphTopTableContainer';
|
||||
|
||||
const meta: Meta<typeof FlameGraphTopTableContainer> = {
|
||||
title: 'TopTable',
|
||||
component: FlameGraphTopTableContainer,
|
||||
args: {
|
||||
colorScheme: ColorScheme.ValueBased,
|
||||
},
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div style={{ width: '100%', height: '600px' }}>
|
||||
<Story />
|
||||
</div>
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
export const Basic: StoryObj<typeof meta> = {
|
||||
render: (args) => {
|
||||
const dataContainer = new FlameGraphDataContainer(createDataFrame(data), { collapsing: true });
|
||||
|
||||
return (
|
||||
<FlameGraphTopTableContainer
|
||||
{...args}
|
||||
data={dataContainer}
|
||||
onSymbolClick={() => {}}
|
||||
onSearch={() => {}}
|
||||
onSandwich={() => {}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
};
|
||||
@@ -144,6 +144,7 @@ function buildFilteredTable(data: FlameGraphDataContainer, matchedLabels?: Set<s
|
||||
// Add current call to the stack
|
||||
callStack.push(label);
|
||||
}
|
||||
|
||||
return filteredTable;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Decorator } from '@storybook/react';
|
||||
import * as React from 'react';
|
||||
|
||||
import { getThemeById, ThemeContext } from '@grafana/data';
|
||||
import { GlobalStyles } from '@grafana/ui';
|
||||
|
||||
interface ThemeableStoryProps {
|
||||
themeId: string;
|
||||
}
|
||||
const ThemeableStory = ({ children, themeId }: React.PropsWithChildren<ThemeableStoryProps>) => {
|
||||
const theme = getThemeById(themeId);
|
||||
|
||||
const css = `
|
||||
#storybook-root {
|
||||
padding: ${theme.spacing(2)};
|
||||
}
|
||||
|
||||
body {
|
||||
background: ${theme.colors.background.primary};
|
||||
}
|
||||
`;
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={theme}>
|
||||
<GlobalStyles />
|
||||
|
||||
<style>{css}</style>
|
||||
{children}
|
||||
</ThemeContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const withTheme =
|
||||
(): Decorator =>
|
||||
// eslint-disable-next-line react/display-name
|
||||
(story, context) => <ThemeableStory themeId={context.globals.theme}>{story()}</ThemeableStory>;
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Decorator } from '@storybook/react';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { setTimeZoneResolver } from '@grafana/data';
|
||||
|
||||
export const withTimeZone = (): Decorator => (Story, context) => {
|
||||
useEffect(() => {
|
||||
setTimeZoneResolver(() => context.globals.timeZone ?? 'browser');
|
||||
}, [context.globals.timeZone]);
|
||||
|
||||
return Story();
|
||||
};
|
||||
Reference in New Issue
Block a user