Storybook: Fix broken stories (#22975)
* Rewrite to CSF and make it not crash * Move comments to be in generated docs * Fix broken ThresholdsEditor story * Fix breaking Select docs
This commit is contained in:
@@ -3,9 +3,18 @@ import { FormattedValue } from '../valueFormats';
|
|||||||
export type DisplayProcessor = (value: any) => DisplayValue;
|
export type DisplayProcessor = (value: any) => DisplayValue;
|
||||||
|
|
||||||
export interface DisplayValue extends FormattedValue {
|
export interface DisplayValue extends FormattedValue {
|
||||||
numeric: number; // Use isNaN to check if it is a real number
|
/**
|
||||||
percent?: number; // 0-1 between min & max
|
* Use isNaN to check if it is a real number
|
||||||
color?: string; // color based on configs or Threshold
|
*/
|
||||||
|
numeric: number;
|
||||||
|
/**
|
||||||
|
* 0-1 between min & max
|
||||||
|
*/
|
||||||
|
percent?: number;
|
||||||
|
/**
|
||||||
|
* Color based on configs or Threshold
|
||||||
|
*/
|
||||||
|
color?: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,31 @@
|
|||||||
export interface Threshold {
|
export interface Threshold {
|
||||||
value: number;
|
value: number;
|
||||||
color: string;
|
color: string;
|
||||||
state?: string; // Warning, Error, LowLow, Low, OK, High, HighHigh etc
|
/**
|
||||||
|
* Warning, Error, LowLow, Low, OK, High, HighHigh etc
|
||||||
|
*/
|
||||||
|
state?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display mode
|
||||||
|
*/
|
||||||
export enum ThresholdsMode {
|
export enum ThresholdsMode {
|
||||||
Absolute = 'absolute',
|
Absolute = 'absolute',
|
||||||
Percentage = 'percentage', // between 0 and 1 (based on min/max)
|
/**
|
||||||
|
* between 0 and 1 (based on min/max)
|
||||||
|
*/
|
||||||
|
Percentage = 'percentage',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Config that is passed to the ThresholdsEditor
|
||||||
|
*/
|
||||||
export interface ThresholdsConfig {
|
export interface ThresholdsConfig {
|
||||||
mode: ThresholdsMode;
|
mode: ThresholdsMode;
|
||||||
|
|
||||||
// Must be sorted by 'value', first value is always -Infinity
|
/**
|
||||||
|
* Must be sorted by 'value', first value is always -Infinity
|
||||||
|
*/
|
||||||
steps: Threshold[];
|
steps: Threshold[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { Button } from '../Button';
|
|||||||
import { ButtonSelect } from './ButtonSelect';
|
import { ButtonSelect } from './ButtonSelect';
|
||||||
import { getIconKnob } from '../../../utils/storybook/knobs';
|
import { getIconKnob } from '../../../utils/storybook/knobs';
|
||||||
import kebabCase from 'lodash/kebabCase';
|
import kebabCase from 'lodash/kebabCase';
|
||||||
|
import { generateOptions } from './mockOptions';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Forms/Select',
|
title: 'Forms/Select',
|
||||||
@@ -16,36 +17,6 @@ export default {
|
|||||||
decorators: [withCenteredStory, withHorizontallyCenteredStory],
|
decorators: [withCenteredStory, withHorizontallyCenteredStory],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const generateOptions = () => {
|
|
||||||
const values = [
|
|
||||||
'Sharilyn Markowitz',
|
|
||||||
'Naomi Striplin',
|
|
||||||
'Beau Bevel',
|
|
||||||
'Garrett Starkes',
|
|
||||||
'Hildegarde Pedro',
|
|
||||||
'Gudrun Seyler',
|
|
||||||
'Eboni Raines',
|
|
||||||
'Hye Felix',
|
|
||||||
'Chau Brito',
|
|
||||||
'Heidy Zook',
|
|
||||||
'Karima Husain',
|
|
||||||
'Virgil Mckinny',
|
|
||||||
'Kaley Dodrill',
|
|
||||||
'Sharan Ruf',
|
|
||||||
'Edgar Loveland',
|
|
||||||
'Judie Sanger',
|
|
||||||
'Season Bundrick',
|
|
||||||
'Ok Vicente',
|
|
||||||
'Garry Spitz',
|
|
||||||
'Han Harnish',
|
|
||||||
];
|
|
||||||
|
|
||||||
return values.map<SelectableValue<string>>(name => ({
|
|
||||||
value: kebabCase(name),
|
|
||||||
label: name,
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
const loadAsyncOptions = () => {
|
const loadAsyncOptions = () => {
|
||||||
return new Promise<Array<SelectableValue<string>>>(resolve => {
|
return new Promise<Array<SelectableValue<string>>>(resolve => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import { SelectableValue } from '@grafana/data';
|
||||||
|
import { kebabCase } from 'lodash';
|
||||||
|
|
||||||
|
export const generateOptions = () => {
|
||||||
|
const values = [
|
||||||
|
'Sharilyn Markowitz',
|
||||||
|
'Naomi Striplin',
|
||||||
|
'Beau Bevel',
|
||||||
|
'Garrett Starkes',
|
||||||
|
'Hildegarde Pedro',
|
||||||
|
'Gudrun Seyler',
|
||||||
|
'Eboni Raines',
|
||||||
|
'Hye Felix',
|
||||||
|
'Chau Brito',
|
||||||
|
'Heidy Zook',
|
||||||
|
'Karima Husain',
|
||||||
|
'Virgil Mckinny',
|
||||||
|
'Kaley Dodrill',
|
||||||
|
'Sharan Ruf',
|
||||||
|
'Edgar Loveland',
|
||||||
|
'Judie Sanger',
|
||||||
|
'Season Bundrick',
|
||||||
|
'Ok Vicente',
|
||||||
|
'Garry Spitz',
|
||||||
|
'Han Harnish',
|
||||||
|
];
|
||||||
|
|
||||||
|
return values.map<SelectableValue<string>>(name => ({
|
||||||
|
value: kebabCase(name),
|
||||||
|
label: name,
|
||||||
|
}));
|
||||||
|
};
|
||||||
@@ -1,42 +1,35 @@
|
|||||||
import { storiesOf } from '@storybook/react';
|
import React from 'react';
|
||||||
import { number, text, object } from '@storybook/addon-knobs';
|
import { number, object, select } from '@storybook/addon-knobs';
|
||||||
import { PieChart, PieChartType } from './PieChart';
|
import { PieChart, PieChartType } from './PieChart';
|
||||||
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
|
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
|
||||||
import { renderComponentWithTheme } from '../../utils/storybook/withTheme';
|
|
||||||
|
export default {
|
||||||
|
title: 'Visualizations/PieChart',
|
||||||
|
decorators: [withCenteredStory],
|
||||||
|
component: PieChart,
|
||||||
|
};
|
||||||
|
|
||||||
const getKnobs = () => {
|
const getKnobs = () => {
|
||||||
return {
|
return {
|
||||||
datapoints: object('datapoints', [
|
datapoints: object('datapoints', [
|
||||||
{
|
{
|
||||||
value: 100,
|
numeric: 100,
|
||||||
name: '100',
|
text: '100',
|
||||||
color: '#7EB26D',
|
color: '#7EB26D',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 200,
|
numeric: 200,
|
||||||
name: '200',
|
text: '200',
|
||||||
color: '#6ED0E0',
|
color: '#6ED0E0',
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
pieType: text('pieType', PieChartType.PIE),
|
pieType: select('pieType', [PieChartType.PIE, PieChartType.DONUT], PieChartType.PIE),
|
||||||
strokeWidth: number('strokeWidth', 1),
|
strokeWidth: number('strokeWidth', 1),
|
||||||
unit: text('unit', 'ms'),
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const PieChartStories = storiesOf('Visualizations/PieChart', module);
|
export const basic = () => {
|
||||||
|
const { datapoints, pieType, strokeWidth } = getKnobs();
|
||||||
|
|
||||||
PieChartStories.addDecorator(withCenteredStory);
|
return <PieChart width={200} height={400} values={datapoints} pieType={pieType} strokeWidth={strokeWidth} />;
|
||||||
|
};
|
||||||
PieChartStories.add('Pie type: pie', () => {
|
|
||||||
const { datapoints, pieType, strokeWidth, unit } = getKnobs();
|
|
||||||
|
|
||||||
return renderComponentWithTheme(PieChart, {
|
|
||||||
width: 200,
|
|
||||||
height: 400,
|
|
||||||
datapoints,
|
|
||||||
pieType,
|
|
||||||
strokeWidth,
|
|
||||||
unit,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,23 +1,29 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { storiesOf } from '@storybook/react';
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import { object } from '@storybook/addon-knobs';
|
||||||
|
|
||||||
import { ThresholdsEditor } from './ThresholdsEditor';
|
import { ThresholdsEditor } from './ThresholdsEditor';
|
||||||
import { ThresholdsMode, ThresholdsConfig } from '@grafana/data';
|
import { ThresholdsMode } from '@grafana/data';
|
||||||
|
|
||||||
const ThresholdsEditorStories = storiesOf('Panel/ThresholdsEditor', module);
|
export default {
|
||||||
const thresholds: ThresholdsConfig = {
|
title: 'Panel/ThresholdsEditor',
|
||||||
mode: ThresholdsMode.Absolute,
|
component: ThresholdsEditor,
|
||||||
steps: [
|
|
||||||
{ value: -Infinity, color: 'green' },
|
|
||||||
{ value: 50, color: 'red' },
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ThresholdsEditorStories.add('default', () => {
|
const getKnobs = () => {
|
||||||
return <ThresholdsEditor thresholds={{} as ThresholdsConfig} onChange={action('Thresholds changed')} />;
|
return {
|
||||||
});
|
initThresholds: object('Initial thresholds', {
|
||||||
|
mode: ThresholdsMode.Absolute,
|
||||||
|
steps: [
|
||||||
|
{ value: -Infinity, color: 'green' },
|
||||||
|
{ value: 50, color: 'red' },
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
ThresholdsEditorStories.add('with thresholds', () => {
|
export const basic = () => <ThresholdsEditor onChange={action('Thresholds changed')} />;
|
||||||
return <ThresholdsEditor thresholds={thresholds} onChange={action('Thresholds changed')} />;
|
|
||||||
});
|
export const withThresholds = () => (
|
||||||
|
<ThresholdsEditor thresholds={getKnobs().initThresholds} onChange={action('Thresholds changed')} />
|
||||||
|
);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { text } from '@storybook/addon-knobs';
|
|||||||
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
|
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
|
||||||
import { ValuePicker } from './ValuePicker';
|
import { ValuePicker } from './ValuePicker';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { generateOptions } from '../Forms/Select/Select.story';
|
import { generateOptions } from '../Forms/Select/mockOptions';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'General/ValuePicker',
|
title: 'General/ValuePicker',
|
||||||
|
|||||||
Reference in New Issue
Block a user