[APM] Storybook theme fixes (#69730)
* [APM] Storybook theme fixes The changes adding theme support in #69362 broke some of the Storybook stories. Add decorators to wrap some of the stories in the theme context. This should be done in a global decorator, but our current storybook setup doesn't support this. It also would be nice to be able to switch between light/dark mode, but that's something we can add in the future. * Remove unused import * Adds missing decorator to cytoscape examples + adds a new real-world example Co-authored-by: Oliver Gupte <olivergupte@gmail.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
78ebb6250a
commit
2e078dbab9
|
@ -10,60 +10,63 @@ import cytoscape from 'cytoscape';
|
|||
import React from 'react';
|
||||
import { Cytoscape } from '../Cytoscape';
|
||||
import { iconForNode } from '../icons';
|
||||
import { EuiThemeProvider } from '../../../../../../observability/public';
|
||||
|
||||
storiesOf('app/ServiceMap/Cytoscape', module).add(
|
||||
'example',
|
||||
() => {
|
||||
const elements: cytoscape.ElementDefinition[] = [
|
||||
{
|
||||
data: {
|
||||
id: 'opbeans-python',
|
||||
'service.name': 'opbeans-python',
|
||||
'agent.name': 'python',
|
||||
storiesOf('app/ServiceMap/Cytoscape', module)
|
||||
.addDecorator((storyFn) => <EuiThemeProvider>{storyFn()}</EuiThemeProvider>)
|
||||
.add(
|
||||
'example',
|
||||
() => {
|
||||
const elements: cytoscape.ElementDefinition[] = [
|
||||
{
|
||||
data: {
|
||||
id: 'opbeans-python',
|
||||
'service.name': 'opbeans-python',
|
||||
'agent.name': 'python',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
data: {
|
||||
id: 'opbeans-node',
|
||||
'service.name': 'opbeans-node',
|
||||
'agent.name': 'nodejs',
|
||||
{
|
||||
data: {
|
||||
id: 'opbeans-node',
|
||||
'service.name': 'opbeans-node',
|
||||
'agent.name': 'nodejs',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
data: {
|
||||
id: 'opbeans-ruby',
|
||||
'service.name': 'opbeans-ruby',
|
||||
'agent.name': 'ruby',
|
||||
{
|
||||
data: {
|
||||
id: 'opbeans-ruby',
|
||||
'service.name': 'opbeans-ruby',
|
||||
'agent.name': 'ruby',
|
||||
},
|
||||
},
|
||||
},
|
||||
{ data: { source: 'opbeans-python', target: 'opbeans-node' } },
|
||||
{
|
||||
data: {
|
||||
bidirectional: true,
|
||||
source: 'opbeans-python',
|
||||
target: 'opbeans-ruby',
|
||||
{ data: { source: 'opbeans-python', target: 'opbeans-node' } },
|
||||
{
|
||||
data: {
|
||||
bidirectional: true,
|
||||
source: 'opbeans-python',
|
||||
target: 'opbeans-ruby',
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
const height = 300;
|
||||
const width = 1340;
|
||||
const serviceName = 'opbeans-python';
|
||||
return (
|
||||
<Cytoscape
|
||||
elements={elements}
|
||||
height={height}
|
||||
width={width}
|
||||
serviceName={serviceName}
|
||||
/>
|
||||
);
|
||||
},
|
||||
{
|
||||
info: {
|
||||
propTables: false,
|
||||
source: false,
|
||||
];
|
||||
const height = 300;
|
||||
const width = 1340;
|
||||
const serviceName = 'opbeans-python';
|
||||
return (
|
||||
<Cytoscape
|
||||
elements={elements}
|
||||
height={height}
|
||||
width={width}
|
||||
serviceName={serviceName}
|
||||
/>
|
||||
);
|
||||
},
|
||||
}
|
||||
);
|
||||
{
|
||||
info: {
|
||||
propTables: false,
|
||||
source: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
storiesOf('app/ServiceMap/Cytoscape', module).add(
|
||||
'node icons',
|
||||
|
|
|
@ -6,23 +6,25 @@
|
|||
/* eslint-disable no-console */
|
||||
|
||||
import {
|
||||
EuiButton,
|
||||
EuiCodeEditor,
|
||||
EuiFieldNumber,
|
||||
EuiFilePicker,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiButton,
|
||||
EuiForm,
|
||||
EuiFieldNumber,
|
||||
EuiToolTip,
|
||||
EuiCodeEditor,
|
||||
EuiSpacer,
|
||||
EuiFilePicker,
|
||||
EuiToolTip,
|
||||
} from '@elastic/eui';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { EuiThemeProvider } from '../../../../../../observability/public';
|
||||
import { Cytoscape } from '../Cytoscape';
|
||||
import { generateServiceMapElements } from './generate_service_map_elements';
|
||||
import exampleResponseOpbeansBeats from './example_response_opbeans_beats.json';
|
||||
import exampleResponseHipsterStore from './example_response_hipster_store.json';
|
||||
import exampleResponseOpbeansBeats from './example_response_opbeans_beats.json';
|
||||
import exampleResponseTodo from './example_response_todo.json';
|
||||
import exampleResponseOneDomainManyIPs from './example_response_one_domain_many_ips.json';
|
||||
import { generateServiceMapElements } from './generate_service_map_elements';
|
||||
|
||||
const STORYBOOK_PATH = 'app/ServiceMap/Cytoscape/Example data';
|
||||
|
||||
|
@ -34,151 +36,155 @@ function setSessionJson(json: string) {
|
|||
window.sessionStorage.setItem(SESSION_STORAGE_KEY, json);
|
||||
}
|
||||
|
||||
storiesOf(STORYBOOK_PATH, module).add(
|
||||
'Generate map',
|
||||
() => {
|
||||
const [size, setSize] = useState<number>(10);
|
||||
const [json, setJson] = useState<string>('');
|
||||
const [elements, setElements] = useState<any[]>(
|
||||
generateServiceMapElements(size)
|
||||
);
|
||||
storiesOf(STORYBOOK_PATH, module)
|
||||
.addDecorator((storyFn) => <EuiThemeProvider>{storyFn()}</EuiThemeProvider>)
|
||||
.add(
|
||||
'Generate map',
|
||||
() => {
|
||||
const [size, setSize] = useState<number>(10);
|
||||
const [json, setJson] = useState<string>('');
|
||||
const [elements, setElements] = useState<any[]>(
|
||||
generateServiceMapElements(size)
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<EuiButton
|
||||
onClick={() => {
|
||||
setElements(generateServiceMapElements(size));
|
||||
setJson('');
|
||||
}}
|
||||
>
|
||||
Generate service map
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiToolTip position="right" content="Number of services">
|
||||
<EuiFieldNumber
|
||||
placeholder="Size"
|
||||
value={size}
|
||||
onChange={(e) => setSize(e.target.valueAsNumber)}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiButton
|
||||
onClick={() => {
|
||||
setJson(JSON.stringify({ elements }, null, 2));
|
||||
}}
|
||||
>
|
||||
Get JSON
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<Cytoscape elements={elements} height={600} width={1340} />
|
||||
|
||||
{json && (
|
||||
<EuiCodeEditor
|
||||
mode="json"
|
||||
theme="github"
|
||||
width="100%"
|
||||
value={json}
|
||||
setOptions={{ fontSize: '12px' }}
|
||||
isReadOnly
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
{
|
||||
info: { propTables: false, source: false },
|
||||
}
|
||||
);
|
||||
|
||||
storiesOf(STORYBOOK_PATH, module).add(
|
||||
'Map from JSON',
|
||||
() => {
|
||||
const [json, setJson] = useState<string>(
|
||||
getSessionJson() || JSON.stringify(exampleResponseTodo, null, 2)
|
||||
);
|
||||
const [error, setError] = useState<string | undefined>();
|
||||
|
||||
const [elements, setElements] = useState<any[]>([]);
|
||||
useEffect(() => {
|
||||
try {
|
||||
setElements(JSON.parse(json).elements);
|
||||
} catch (e) {
|
||||
setError(e.message);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Cytoscape elements={elements} height={600} width={1340} />
|
||||
<EuiForm isInvalid={error !== undefined} error={error}>
|
||||
return (
|
||||
<div>
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<EuiCodeEditor
|
||||
mode="json"
|
||||
theme="github"
|
||||
width="100%"
|
||||
value={json}
|
||||
setOptions={{ fontSize: '12px' }}
|
||||
onChange={(value) => {
|
||||
setJson(value);
|
||||
<EuiButton
|
||||
onClick={() => {
|
||||
setElements(generateServiceMapElements(size));
|
||||
setJson('');
|
||||
}}
|
||||
/>
|
||||
>
|
||||
Generate service map
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFlexGroup direction="column">
|
||||
<EuiFilePicker
|
||||
display={'large'}
|
||||
fullWidth={true}
|
||||
style={{ height: '100%' }}
|
||||
initialPromptText="Upload a JSON file"
|
||||
onChange={(event) => {
|
||||
const item = event?.item(0);
|
||||
|
||||
if (item) {
|
||||
const f = new FileReader();
|
||||
f.onload = (onloadEvent) => {
|
||||
const result = onloadEvent?.target?.result;
|
||||
if (typeof result === 'string') {
|
||||
setJson(result);
|
||||
}
|
||||
};
|
||||
f.readAsText(item);
|
||||
}
|
||||
}}
|
||||
<EuiToolTip position="right" content="Number of services">
|
||||
<EuiFieldNumber
|
||||
placeholder="Size"
|
||||
value={size}
|
||||
onChange={(e) => setSize(e.target.valueAsNumber)}
|
||||
/>
|
||||
<EuiSpacer />
|
||||
<EuiButton
|
||||
onClick={() => {
|
||||
try {
|
||||
setElements(JSON.parse(json).elements);
|
||||
setSessionJson(json);
|
||||
setError(undefined);
|
||||
} catch (e) {
|
||||
setError(e.message);
|
||||
}
|
||||
}}
|
||||
>
|
||||
Render JSON
|
||||
</EuiButton>
|
||||
</EuiFlexGroup>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiButton
|
||||
onClick={() => {
|
||||
setJson(JSON.stringify({ elements }, null, 2));
|
||||
}}
|
||||
>
|
||||
Get JSON
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiForm>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
{
|
||||
info: {
|
||||
propTables: false,
|
||||
source: false,
|
||||
text: `
|
||||
|
||||
<Cytoscape elements={elements} height={600} width={1340} />
|
||||
|
||||
{json && (
|
||||
<EuiCodeEditor
|
||||
mode="json"
|
||||
theme="github"
|
||||
width="100%"
|
||||
value={json}
|
||||
setOptions={{ fontSize: '12px' }}
|
||||
isReadOnly
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
{
|
||||
info: { propTables: false, source: false },
|
||||
}
|
||||
);
|
||||
|
||||
storiesOf(STORYBOOK_PATH, module)
|
||||
.addDecorator((storyFn) => <EuiThemeProvider>{storyFn()}</EuiThemeProvider>)
|
||||
.add(
|
||||
'Map from JSON',
|
||||
() => {
|
||||
const [json, setJson] = useState<string>(
|
||||
getSessionJson() || JSON.stringify(exampleResponseTodo, null, 2)
|
||||
);
|
||||
const [error, setError] = useState<string | undefined>();
|
||||
|
||||
const [elements, setElements] = useState<any[]>([]);
|
||||
useEffect(() => {
|
||||
try {
|
||||
setElements(JSON.parse(json).elements);
|
||||
} catch (e) {
|
||||
setError(e.message);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Cytoscape elements={elements} height={600} width={1340} />
|
||||
<EuiForm isInvalid={error !== undefined} error={error}>
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<EuiCodeEditor
|
||||
mode="json"
|
||||
theme="github"
|
||||
width="100%"
|
||||
value={json}
|
||||
setOptions={{ fontSize: '12px' }}
|
||||
onChange={(value) => {
|
||||
setJson(value);
|
||||
}}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFlexGroup direction="column">
|
||||
<EuiFilePicker
|
||||
display={'large'}
|
||||
fullWidth={true}
|
||||
style={{ height: '100%' }}
|
||||
initialPromptText="Upload a JSON file"
|
||||
onChange={(event) => {
|
||||
const item = event?.item(0);
|
||||
|
||||
if (item) {
|
||||
const f = new FileReader();
|
||||
f.onload = (onloadEvent) => {
|
||||
const result = onloadEvent?.target?.result;
|
||||
if (typeof result === 'string') {
|
||||
setJson(result);
|
||||
}
|
||||
};
|
||||
f.readAsText(item);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<EuiSpacer />
|
||||
<EuiButton
|
||||
onClick={() => {
|
||||
try {
|
||||
setElements(JSON.parse(json).elements);
|
||||
setSessionJson(json);
|
||||
setError(undefined);
|
||||
} catch (e) {
|
||||
setError(e.message);
|
||||
}
|
||||
}}
|
||||
>
|
||||
Render JSON
|
||||
</EuiButton>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiForm>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
{
|
||||
info: {
|
||||
propTables: false,
|
||||
source: false,
|
||||
text: `
|
||||
Enter JSON map data into the text box or upload a file and click "Render JSON" to see the results. You can enable a download button on the service map by putting
|
||||
|
||||
\`\`\`
|
||||
|
@ -186,60 +192,86 @@ storiesOf(STORYBOOK_PATH, module).add(
|
|||
\`\`\`
|
||||
|
||||
into the JavaScript console and reloading the page.`,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
storiesOf(STORYBOOK_PATH, module)
|
||||
.addDecorator((storyFn) => <EuiThemeProvider>{storyFn()}</EuiThemeProvider>)
|
||||
.add(
|
||||
'Todo app',
|
||||
() => {
|
||||
return (
|
||||
<div>
|
||||
<Cytoscape
|
||||
elements={exampleResponseTodo.elements}
|
||||
height={600}
|
||||
width={1340}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
}
|
||||
);
|
||||
{
|
||||
info: { propTables: false, source: false },
|
||||
}
|
||||
);
|
||||
|
||||
storiesOf(STORYBOOK_PATH, module).add(
|
||||
'Todo app',
|
||||
() => {
|
||||
return (
|
||||
<div>
|
||||
<Cytoscape
|
||||
elements={exampleResponseTodo.elements}
|
||||
height={600}
|
||||
width={1340}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
{
|
||||
info: { propTables: false, source: false },
|
||||
}
|
||||
);
|
||||
storiesOf(STORYBOOK_PATH, module)
|
||||
.addDecorator((storyFn) => <EuiThemeProvider>{storyFn()}</EuiThemeProvider>)
|
||||
.add(
|
||||
'Opbeans + beats',
|
||||
() => {
|
||||
return (
|
||||
<div>
|
||||
<Cytoscape
|
||||
elements={exampleResponseOpbeansBeats.elements}
|
||||
height={600}
|
||||
width={1340}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
{
|
||||
info: { propTables: false, source: false },
|
||||
}
|
||||
);
|
||||
|
||||
storiesOf(STORYBOOK_PATH, module).add(
|
||||
'Opbeans + beats',
|
||||
() => {
|
||||
return (
|
||||
<div>
|
||||
<Cytoscape
|
||||
elements={exampleResponseOpbeansBeats.elements}
|
||||
height={600}
|
||||
width={1340}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
{
|
||||
info: { propTables: false, source: false },
|
||||
}
|
||||
);
|
||||
storiesOf(STORYBOOK_PATH, module)
|
||||
.addDecorator((storyFn) => <EuiThemeProvider>{storyFn()}</EuiThemeProvider>)
|
||||
.add(
|
||||
'Hipster store',
|
||||
() => {
|
||||
return (
|
||||
<div>
|
||||
<Cytoscape
|
||||
elements={exampleResponseHipsterStore.elements}
|
||||
height={600}
|
||||
width={1340}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
{
|
||||
info: { propTables: false, source: false },
|
||||
}
|
||||
);
|
||||
|
||||
storiesOf(STORYBOOK_PATH, module).add(
|
||||
'Hipster store',
|
||||
() => {
|
||||
return (
|
||||
<div>
|
||||
<Cytoscape
|
||||
elements={exampleResponseHipsterStore.elements}
|
||||
height={600}
|
||||
width={1340}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
{
|
||||
info: { propTables: false, source: false },
|
||||
}
|
||||
);
|
||||
storiesOf(STORYBOOK_PATH, module)
|
||||
.addDecorator((storyFn) => <EuiThemeProvider>{storyFn()}</EuiThemeProvider>)
|
||||
.add(
|
||||
'Node resolves one domain name to many IPs',
|
||||
() => {
|
||||
return (
|
||||
<div>
|
||||
<Cytoscape
|
||||
elements={exampleResponseOneDomainManyIPs.elements}
|
||||
height={600}
|
||||
width={1340}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
{
|
||||
info: { propTables: false, source: false },
|
||||
}
|
||||
);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -21,13 +21,13 @@ import {
|
|||
ApmPluginContext,
|
||||
ApmPluginContextValue,
|
||||
} from '../../../../../context/ApmPluginContext';
|
||||
import { EuiThemeProvider } from '../../../../../../../observability/public';
|
||||
|
||||
storiesOf(
|
||||
'app/Settings/AgentConfigurations/AgentConfigurationCreateEdit',
|
||||
module
|
||||
).add(
|
||||
'with config',
|
||||
() => {
|
||||
)
|
||||
.addDecorator((storyFn) => {
|
||||
const httpMock = {};
|
||||
|
||||
// mock
|
||||
|
@ -40,10 +40,21 @@ storiesOf(
|
|||
},
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<ApmPluginContext.Provider
|
||||
value={(contextMock as unknown) as ApmPluginContextValue}
|
||||
>
|
||||
<EuiThemeProvider>
|
||||
<ApmPluginContext.Provider
|
||||
value={(contextMock as unknown) as ApmPluginContextValue}
|
||||
>
|
||||
{storyFn()}
|
||||
</ApmPluginContext.Provider>
|
||||
</EuiThemeProvider>
|
||||
);
|
||||
})
|
||||
.add(
|
||||
'with config',
|
||||
() => {
|
||||
return (
|
||||
<AgentConfigurationCreateEdit
|
||||
pageStep="choose-settings-step"
|
||||
existingConfigResult={{
|
||||
|
@ -54,12 +65,11 @@ storiesOf(
|
|||
} as AgentConfiguration,
|
||||
}}
|
||||
/>
|
||||
</ApmPluginContext.Provider>
|
||||
);
|
||||
},
|
||||
{
|
||||
info: {
|
||||
source: false,
|
||||
);
|
||||
},
|
||||
}
|
||||
);
|
||||
{
|
||||
info: {
|
||||
source: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue