mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Storybook 6 and config changes (#75357)
Upgrade to Storybook 6 and attempt to use the declarative configuration. The goals of this PR (as part of Kibana's Storybook roadmap, are: Upgrade to Storybook 6 Still allow running Storybooks with yarn storybook plugin_name Use the declarative configuration to (hopefully) make the configuration simpler to use an easier to understand, as well as avoiding deprecation warnings and loss of future compatibility The ways in which what I have so far differs from how we do things today are: In the alias configuration it takes a path to a storybook configuration directory instead of the storybook.js file from before Each plugin (it doesn't have to be a plugin; can be any directory) has a .storybook/main.js (the aliases file in @kbn/storybook specifies these locations) where they can define their Storybook configuration. You can require('@kbn/storybook').defaultConfig to get defaults and override them @kbn/storybook has a preset that can provide Webpack and Babel configuration and Storybook parameters and decorators Instead of dynamically creating the list of stories to import, we define them in the globs of the stories property in .storybook/main.js. Do not build a DLL. We are using @kbn/ui-shared-deps as externals. Startup time is not quite as fast but still acceptable. Other things done in this PR: Allow default exports in .stories. to allow for Common Story Format CSF stories Add guard in Webpack configuration needed for overriding CSS rules Update filename casing check to allow for files with required names in Storybook Clean up observability stories Rename *.examples.tsx and *.story.tsx to *.stories.tsx
This commit is contained in:
parent
46a595947e
commit
564a7b1a17
63 changed files with 5044 additions and 6820 deletions
|
@ -388,6 +388,7 @@ module.exports = {
|
|||
*/
|
||||
{
|
||||
files: [
|
||||
'**/*.stories.tsx',
|
||||
'x-pack/test/apm_api_integration/**/*.ts',
|
||||
'x-pack/test/functional/apps/**/*.js',
|
||||
'x-pack/plugins/apm/**/*.js',
|
||||
|
|
|
@ -334,6 +334,7 @@
|
|||
"@types/styled-components": "^5.1.0",
|
||||
"@types/supertest": "^2.0.5",
|
||||
"@types/supertest-as-promised": "^2.0.38",
|
||||
"@types/tapable": "^1.0.6",
|
||||
"@types/tar": "^4.0.3",
|
||||
"@types/testing-library__jest-dom": "^5.9.2",
|
||||
"@types/testing-library__react-hooks": "^3.4.0",
|
||||
|
@ -341,6 +342,8 @@
|
|||
"@types/uuid": "^3.4.4",
|
||||
"@types/vinyl": "^2.0.4",
|
||||
"@types/vinyl-fs": "^2.4.11",
|
||||
"@types/webpack": "^4.41.21",
|
||||
"@types/webpack-env": "^1.15.2",
|
||||
"@types/zen-observable": "^0.8.0",
|
||||
"@typescript-eslint/eslint-plugin": "^3.10.0",
|
||||
"@typescript-eslint/parser": "^3.10.0",
|
||||
|
|
6522
packages/kbn-pm/dist/index.js
vendored
6522
packages/kbn-pm/dist/index.js
vendored
File diff suppressed because one or more lines are too long
|
@ -2,32 +2,40 @@
|
|||
|
||||
This package provides ability to add [Storybook](https://storybook.js.org/) to any Kibana plugin.
|
||||
|
||||
- [Setup Instructions](#setup-instructions)
|
||||
|
||||
- [Kibana Storybook](#kibana-storybook)
|
||||
- [Setup Instructions](#setup-instructions)
|
||||
- [Customizing configuration](#customizing-configuration)
|
||||
|
||||
## Setup Instructions
|
||||
|
||||
1. Add `storybook.js` launcher file to your plugin. For example, create a file at
|
||||
`src/plugins/<plugin>/scripts/storybook.js`, with the following contents:
|
||||
- Add a `.storybook/main.js` configuration file to your plugin. For example, create a file at
|
||||
`src/plugins/<plugin>/.storybook/main.js`, with the following contents:
|
||||
|
||||
```js
|
||||
import { join } from 'path';
|
||||
```js
|
||||
module.exports = require('@kbn/storybook').defaultConfig;
|
||||
```
|
||||
|
||||
// eslint-disable-next-line
|
||||
require('@kbn/storybook').runStorybookCli({
|
||||
name: '<plugin>',
|
||||
storyGlobs: [join(__dirname, '..', 'public', 'components', '**', '*.examples.tsx')],
|
||||
});
|
||||
```
|
||||
2. Add your plugin alias to `src/dev/storybook/aliases.ts` config.
|
||||
3. Create sample Storybook stories. For example, in your plugin create create a file at
|
||||
`src/plugins/<plugin>/public/components/hello_world/__examples__/hello_world.examples.tsx` with
|
||||
the following contents:
|
||||
- Add your plugin alias to `src/dev/storybook/aliases.ts` config.
|
||||
- Create sample Storybook stories. For example, in your plugin create a file at
|
||||
`src/plugins/<plugin>/public/components/hello_world/hello_world.stories.tsx` with
|
||||
the following [Component Story Format](https://storybook.js.org/docs/react/api/csf) contents:
|
||||
|
||||
```jsx
|
||||
import * as React from 'react';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
```jsx
|
||||
import { MyComponent } from './my_component';
|
||||
|
||||
storiesOf('Hello world', module).add('default', () => <div>Hello world!</div>);
|
||||
```
|
||||
4. Launch Storybook with `yarn storybook <plugin>`.
|
||||
export default {
|
||||
component: MyComponent,
|
||||
title: 'Path/In/Side/Navigation/ToComponent',
|
||||
};
|
||||
|
||||
export function Example() {
|
||||
return <MyComponent />;
|
||||
}
|
||||
```
|
||||
|
||||
- Launch Storybook with `yarn storybook <plugin>`, or build a static site with `yarn storybook --site <plugin>`.
|
||||
|
||||
## Customizing configuration
|
||||
|
||||
The `defaultConfig` object provided by the @kbn/storybook package should be all you need to get running, but you can
|
||||
override this in your .storybook/main.js. Using [Storybook's configuration options](https://storybook.js.org/docs/react/configure/overview).
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const { join } = require('path');
|
||||
const Rx = require('rxjs');
|
||||
const { first } = require('rxjs/operators');
|
||||
const storybook = require('@storybook/react/standalone');
|
||||
const { run } = require('@kbn/dev-utils');
|
||||
const { generateStorybookEntry } = require('./lib/storybook_entry');
|
||||
const { ASSET_DIR, CURRENT_CONFIG } = require('./lib/constants');
|
||||
const { buildDll } = require('./lib/dll');
|
||||
|
||||
exports.runStorybookCli = (config) => {
|
||||
const { name, storyGlobs } = config;
|
||||
run(
|
||||
async ({ flags, log, procRunner }) => {
|
||||
log.debug('Global config:\n', require('./lib/constants'));
|
||||
|
||||
const currentConfig = JSON.stringify(config, null, 2);
|
||||
const currentConfigDir = join(CURRENT_CONFIG, '..');
|
||||
await fs.promises.mkdir(currentConfigDir, { recursive: true });
|
||||
log.debug('Writing currentConfig:\n', CURRENT_CONFIG + '\n', currentConfig);
|
||||
await fs.promises.writeFile(CURRENT_CONFIG, `exports.currentConfig = ${currentConfig};`);
|
||||
|
||||
await buildDll({
|
||||
rebuildDll: flags.rebuildDll,
|
||||
log,
|
||||
procRunner,
|
||||
});
|
||||
|
||||
const subj = new Rx.ReplaySubject(1);
|
||||
generateStorybookEntry({ log, storyGlobs }).subscribe(subj);
|
||||
|
||||
await subj.pipe(first()).toPromise();
|
||||
|
||||
await Promise.all([
|
||||
// route errors
|
||||
subj.toPromise(),
|
||||
|
||||
new Promise(async () => {
|
||||
// storybook never completes, so neither will this promise
|
||||
const configDir = join(__dirname, 'storybook_config');
|
||||
log.debug('Config dir:', configDir);
|
||||
|
||||
const config = {
|
||||
mode: flags.site ? 'static' : 'dev',
|
||||
port: 9001,
|
||||
configDir,
|
||||
};
|
||||
if (flags.site) {
|
||||
config.outputDir = join(ASSET_DIR, name);
|
||||
}
|
||||
|
||||
await storybook(config);
|
||||
|
||||
// Line is only reached when building the static version
|
||||
if (flags.site) process.exit();
|
||||
}),
|
||||
]);
|
||||
},
|
||||
{
|
||||
flags: {
|
||||
boolean: ['rebuildDll', 'site'],
|
||||
},
|
||||
description: `
|
||||
Run the storybook examples for ${name}
|
||||
`,
|
||||
}
|
||||
);
|
||||
};
|
3
packages/kbn-storybook/storybook_config/mocks/noop.js → packages/kbn-storybook/index.ts
Executable file → Normal file
3
packages/kbn-storybook/storybook_config/mocks/noop.js → packages/kbn-storybook/index.ts
Executable file → Normal file
|
@ -17,4 +17,5 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
export default function () {}
|
||||
export { defaultConfig } from './lib/default_config';
|
||||
export { runStorybookCli } from './lib/run_storybook_cli';
|
|
@ -17,10 +17,8 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { join } from 'path';
|
||||
import { resolve } from 'path';
|
||||
import { REPO_ROOT as KIBANA_ROOT } from '@kbn/dev-utils';
|
||||
|
||||
// eslint-disable-next-line
|
||||
require('@kbn/storybook').runStorybookCli({
|
||||
name: 'code-editor',
|
||||
storyGlobs: [join(__dirname, '..', '*.examples.tsx')],
|
||||
});
|
||||
export const REPO_ROOT = KIBANA_ROOT;
|
||||
export const ASSET_DIR = resolve(KIBANA_ROOT, 'built_assets/storybook');
|
|
@ -17,10 +17,12 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
const serve = require('serve-static');
|
||||
const path = require('path');
|
||||
import { StorybookConfig } from '@storybook/core/types';
|
||||
|
||||
// Extend the Storybook Middleware to include a route to access Legacy UI assets
|
||||
module.exports = function (router) {
|
||||
router.get('/ui', serve(path.resolve(__dirname, '../../../src/core/server/core_app/assets')));
|
||||
export const defaultConfig: StorybookConfig = {
|
||||
addons: ['@kbn/storybook/preset', '@storybook/addon-knobs', '@storybook/addon-essentials'],
|
||||
stories: ['../**/*.stories.tsx'],
|
||||
typescript: {
|
||||
reactDocgen: false,
|
||||
},
|
||||
};
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
const { resolve } = require('path');
|
||||
const { existsSync } = require('fs');
|
||||
|
||||
const { REPO_ROOT } = require('@kbn/utils');
|
||||
const { DLL_DIST_DIR } = require('./constants');
|
||||
|
||||
exports.buildDll = async ({ rebuildDll, log, procRunner }) => {
|
||||
if (rebuildDll) {
|
||||
log.info('rebuilding dll');
|
||||
} else if (!existsSync(resolve(DLL_DIST_DIR, 'dll.js'))) {
|
||||
log.info('dll missing, rebuilding');
|
||||
} else {
|
||||
log.info('dll exists');
|
||||
return;
|
||||
}
|
||||
|
||||
await procRunner.run('build dll ', {
|
||||
cmd: require.resolve('webpack/bin/webpack'),
|
||||
args: ['--config', require.resolve('./webpack.dll.config.js')],
|
||||
cwd: REPO_ROOT,
|
||||
wait: true,
|
||||
});
|
||||
};
|
|
@ -17,11 +17,19 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
const { resolve } = require('path');
|
||||
const { REPO_ROOT } = require('@kbn/utils');
|
||||
import { addons } from '@storybook/addons';
|
||||
import { create } from '@storybook/theming';
|
||||
|
||||
exports.ASSET_DIR = resolve(REPO_ROOT, 'built_assets/storybook');
|
||||
exports.CURRENT_CONFIG = resolve(exports.ASSET_DIR, 'current.config.js');
|
||||
exports.STORY_ENTRY_PATH = resolve(exports.ASSET_DIR, 'stories.entry.js');
|
||||
exports.DLL_DIST_DIR = resolve(exports.ASSET_DIR, 'dll');
|
||||
exports.DLL_NAME = 'storybook_dll';
|
||||
// This configures the "Manager", or main outer view of Storybook. It is an
|
||||
// addon that's loaded by the `managerEntries` part of the preset in ../preset.js.
|
||||
addons.setConfig({
|
||||
theme: create({
|
||||
base: 'light',
|
||||
brandTitle: 'Kibana Storybook',
|
||||
brandUrl: 'https://github.com/elastic/kibana/tree/master/packages/kbn-storybook',
|
||||
}),
|
||||
showPanel: false,
|
||||
isFullscreen: false,
|
||||
panelPosition: 'bottom',
|
||||
isToolshown: true,
|
||||
});
|
75
packages/kbn-storybook/lib/run_storybook_cli.ts
Normal file
75
packages/kbn-storybook/lib/run_storybook_cli.ts
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { join } from 'path';
|
||||
import { logger } from '@storybook/node-logger';
|
||||
import buildStandalone from '@storybook/react/standalone';
|
||||
import { Flags, run } from '@kbn/dev-utils';
|
||||
import { distDir } from '@kbn/ui-shared-deps';
|
||||
import * as constants from './constants';
|
||||
|
||||
// Convert the flags to a Storybook loglevel
|
||||
function getLogLevelFromFlags(flags: Flags) {
|
||||
if (flags.debug) {
|
||||
return 'silly';
|
||||
}
|
||||
if (flags.verbose) {
|
||||
return 'verbose';
|
||||
}
|
||||
if (flags.quiet) {
|
||||
return 'warn';
|
||||
}
|
||||
if (flags.silent) {
|
||||
return 'silent';
|
||||
}
|
||||
return 'info';
|
||||
}
|
||||
|
||||
export function runStorybookCli({ configDir, name }: { configDir: string; name: string }) {
|
||||
run(
|
||||
async ({ flags, log }) => {
|
||||
log.debug('Global config:\n', constants);
|
||||
|
||||
const staticDir = [distDir];
|
||||
const config: Record<string, any> = {
|
||||
configDir,
|
||||
mode: flags.site ? 'static' : 'dev',
|
||||
port: 9001,
|
||||
staticDir,
|
||||
};
|
||||
if (flags.site) {
|
||||
config.outputDir = join(constants.ASSET_DIR, name);
|
||||
}
|
||||
|
||||
logger.setLevel(getLogLevelFromFlags(flags));
|
||||
await buildStandalone(config);
|
||||
|
||||
// Line is only reached when building the static version
|
||||
if (flags.site) process.exit();
|
||||
},
|
||||
{
|
||||
flags: {
|
||||
boolean: ['site'],
|
||||
},
|
||||
description: `
|
||||
Run the storybook examples for ${name}
|
||||
`,
|
||||
}
|
||||
);
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
const { resolve, relative, dirname } = require('path');
|
||||
const Fs = require('fs');
|
||||
const Rx = require('rxjs');
|
||||
const { mergeMap, map, debounceTime } = require('rxjs/operators');
|
||||
const normalize = require('normalize-path');
|
||||
const { promisify } = require('util');
|
||||
|
||||
const watch = require('glob-watcher');
|
||||
const mkdirp = require('mkdirp'); // eslint-disable-line
|
||||
const glob = require('fast-glob');
|
||||
const { REPO_ROOT } = require('@kbn/utils');
|
||||
|
||||
const mkdirpAsync = promisify(mkdirp);
|
||||
const writeFileAsync = promisify(Fs.writeFile);
|
||||
|
||||
const { STORY_ENTRY_PATH } = require('./constants');
|
||||
const STORE_ENTRY_DIR = dirname(STORY_ENTRY_PATH);
|
||||
|
||||
exports.generateStorybookEntry = ({ log, storyGlobs }) => {
|
||||
const globs = [...storyGlobs];
|
||||
log.info('Storybook globs:\n', globs);
|
||||
const norm = (p) => normalize(relative(STORE_ENTRY_DIR, p));
|
||||
|
||||
return Rx.defer(() =>
|
||||
glob(globs, {
|
||||
absolute: true,
|
||||
cwd: REPO_ROOT,
|
||||
onlyFiles: true,
|
||||
})
|
||||
).pipe(
|
||||
map((paths) => {
|
||||
log.info('Discovered Storybook entry points:\n', paths);
|
||||
return new Set(paths.map(norm));
|
||||
}),
|
||||
mergeMap(
|
||||
(paths) =>
|
||||
new Rx.Observable((observer) => {
|
||||
observer.next(paths);
|
||||
|
||||
const chokidar = watch(globs, { cwd: REPO_ROOT })
|
||||
.on('add', (path) => {
|
||||
observer.next(paths.add(norm(resolve(REPO_ROOT, path))));
|
||||
})
|
||||
.on('unlink', (path) => {
|
||||
observer.next(paths.delete(norm(resolve(REPO_ROOT, path))));
|
||||
});
|
||||
|
||||
return () => {
|
||||
chokidar.close();
|
||||
};
|
||||
})
|
||||
),
|
||||
debounceTime(200),
|
||||
mergeMap(async (paths, i) => {
|
||||
await mkdirpAsync(STORE_ENTRY_DIR);
|
||||
|
||||
let content = '';
|
||||
for (const path of paths) {
|
||||
content += `require('${path}');\n`;
|
||||
}
|
||||
|
||||
await writeFileAsync(STORY_ENTRY_PATH, content);
|
||||
|
||||
if (i === 0) {
|
||||
log.info('%d paths written to entry file', paths.size);
|
||||
} else {
|
||||
log.info('entry file updated');
|
||||
}
|
||||
})
|
||||
);
|
||||
};
|
59
packages/kbn-storybook/lib/templates/index.ejs
Normal file
59
packages/kbn-storybook/lib/templates/index.ejs
Normal file
|
@ -0,0 +1,59 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- This is a copy of the
|
||||
[Storybook IFrame template](https://github.com/storybookjs/storybook/blob/7874ca357c6cb54f3f258dc61f6becae6783fba6/lib/core/src/server/templates/index.ejs).
|
||||
We use this one instead because we want to add the @kbn/ui-shared-deps tags here.
|
||||
-->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title><%= options.title || 'Storybook'%></title>
|
||||
|
||||
<% if (files.favicon) { %>
|
||||
<link rel="shortcut icon" href="<%= files.favicon%>" />
|
||||
<% } %>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<!-- Added for Kibana shared dependencies -->
|
||||
<script>
|
||||
window.__kbnPublicPath__ = { 'kbn-ui-shared-deps': '/' };
|
||||
</script>
|
||||
<script src="/kbn-ui-shared-deps.@elastic.js"></script>
|
||||
<script src="/kbn-ui-shared-deps.js"></script>
|
||||
<link href="/kbn-ui-shared-deps.css" rel="stylesheet" />
|
||||
<link href="/kbn-ui-shared-deps.v7.light.css" rel="stylesheet" />
|
||||
<!-- -->
|
||||
|
||||
<% if (typeof headHtmlSnippet !== 'undefined') { %> <%= headHtmlSnippet %> <% } %> <%
|
||||
files.css.forEach(file => { %>
|
||||
<link href="<%= file %>" rel="stylesheet" />
|
||||
<% }); %>
|
||||
|
||||
<style>
|
||||
#root[hidden],
|
||||
#docs-root[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<% if (typeof bodyHtmlSnippet !== 'undefined') { %> <%= bodyHtmlSnippet %> <% } %>
|
||||
|
||||
<div id="root"></div>
|
||||
<div id="docs-root"></div>
|
||||
|
||||
<% if (typeof globals !== 'undefined' && Object.keys(globals).length) { %>
|
||||
<script>
|
||||
<% for (var varName in globals) { %>
|
||||
<% if (globals[varName] != undefined) { %>
|
||||
window['<%=varName%>'] = <%= JSON.stringify(globals[varName]) %>;
|
||||
<% } %>
|
||||
<% } %>
|
||||
</script>
|
||||
<% } %> <% dlls.forEach(file => { %>
|
||||
<script src="<%= file %>"></script>
|
||||
<% }); %> <% files.js.forEach(file => { %>
|
||||
<script src="<%= file %>"></script>
|
||||
<% }); %>
|
||||
</body>
|
||||
</html>
|
|
@ -1,131 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
const webpack = require('webpack');
|
||||
const path = require('path');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const { REPO_ROOT } = require('@kbn/utils');
|
||||
|
||||
const { DLL_NAME, DLL_DIST_DIR } = require('./constants');
|
||||
|
||||
// This is the Webpack config for the DLL of CSS and JS assets that are
|
||||
// not expected to change during development. This saves compile and run
|
||||
// times considerably.
|
||||
module.exports = {
|
||||
context: REPO_ROOT,
|
||||
mode: 'development',
|
||||
|
||||
// This is a (potentially growing) list of modules that can be safely
|
||||
// included in the DLL. Only add to this list modules or other code
|
||||
// which Storybook stories and their components would require, but don't
|
||||
// change during development.
|
||||
entry: [
|
||||
'@elastic/eui/dist/eui_theme_light.css',
|
||||
'@kbn/ui-framework/dist/kui_light.css',
|
||||
'@storybook/addon-info',
|
||||
'@storybook/addon-knobs',
|
||||
'@storybook/addon-knobs/react',
|
||||
'@storybook/addon-knobs/register',
|
||||
'@storybook/addon-options',
|
||||
'@storybook/addon-options/register',
|
||||
'@storybook/core',
|
||||
'@storybook/core/dist/server/common/polyfills.js',
|
||||
'@storybook/react',
|
||||
'@storybook/theming',
|
||||
'angular-mocks',
|
||||
'angular',
|
||||
'brace',
|
||||
'chroma-js',
|
||||
'highlight.js',
|
||||
'html-entities',
|
||||
'jquery',
|
||||
'lodash',
|
||||
'markdown-it',
|
||||
'mocha',
|
||||
'prop-types',
|
||||
'react-ace',
|
||||
'react-beautiful-dnd',
|
||||
'react-dom',
|
||||
'react-focus-lock',
|
||||
'react-markdown',
|
||||
'react-resize-detector',
|
||||
'react-virtualized',
|
||||
'react',
|
||||
'recompose',
|
||||
'redux-actions',
|
||||
'remark-parse',
|
||||
'rxjs',
|
||||
'sinon',
|
||||
'tinycolor2',
|
||||
],
|
||||
plugins: [
|
||||
// Produce the DLL and its manifest
|
||||
new webpack.DllPlugin({
|
||||
name: DLL_NAME,
|
||||
path: path.resolve(DLL_DIST_DIR, 'manifest.json'),
|
||||
}),
|
||||
// Produce the DLL CSS file
|
||||
new MiniCssExtractPlugin({
|
||||
filename: 'dll.css',
|
||||
}),
|
||||
],
|
||||
// Output the DLL JS file
|
||||
output: {
|
||||
path: DLL_DIST_DIR,
|
||||
filename: 'dll.js',
|
||||
library: DLL_NAME,
|
||||
},
|
||||
// Include a require alias for legacy UI code and styles
|
||||
resolve: {
|
||||
alias: {
|
||||
ui: path.resolve(REPO_ROOT, 'src/legacy/ui/public'),
|
||||
},
|
||||
mainFields: ['browser', 'main'],
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
{
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
options: {},
|
||||
},
|
||||
{ loader: 'css-loader' },
|
||||
{
|
||||
loader: 'string-replace-loader',
|
||||
options: {
|
||||
search: '__REPLACE_WITH_PUBLIC_PATH__',
|
||||
replace: '/',
|
||||
flags: 'g',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.(woff|woff2|ttf|eot|svg|ico)(\?|$)/,
|
||||
loader: 'file-loader',
|
||||
},
|
||||
],
|
||||
},
|
||||
node: {
|
||||
fs: 'empty',
|
||||
child_process: 'empty',
|
||||
},
|
||||
};
|
|
@ -3,18 +3,21 @@
|
|||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"license": "Apache-2.0",
|
||||
"main": "./target/index.js",
|
||||
"dependencies": {
|
||||
"@kbn/babel-preset": "1.0.0",
|
||||
"@kbn/dev-utils": "1.0.0",
|
||||
"@storybook/addon-actions": "^6.0.16",
|
||||
"@storybook/addon-essentials": "^6.0.16",
|
||||
"@storybook/addon-knobs": "^6.0.16",
|
||||
"@storybook/addon-storyshots": "^6.0.16",
|
||||
"@storybook/core": "^6.0.16",
|
||||
"@storybook/react": "^6.0.16",
|
||||
"@storybook/theming": "^6.0.16",
|
||||
"@types/loader-utils": "^2.0.1",
|
||||
"@types/webpack": "^4.41.5",
|
||||
"@types/webpack-env": "^1.15.2",
|
||||
"@types/webpack-merge": "^4.1.5",
|
||||
"@kbn/utils": "1.0.0",
|
||||
"@storybook/addon-actions": "^5.3.19",
|
||||
"@storybook/addon-console": "^1.2.1",
|
||||
"@storybook/addon-info": "^5.3.19",
|
||||
"@storybook/addon-knobs": "^5.3.19",
|
||||
"@storybook/addon-options": "^5.3.19",
|
||||
"@storybook/addon-storyshots": "^5.3.19",
|
||||
"@storybook/react": "^5.3.19",
|
||||
"@storybook/theming": "^5.3.19",
|
||||
"babel-loader": "^8.0.6",
|
||||
"copy-webpack-plugin": "^6.0.2",
|
||||
"fast-glob": "2.2.7",
|
||||
|
@ -29,5 +32,10 @@
|
|||
"serve-static": "1.14.1",
|
||||
"styled-components": "^5.1.0",
|
||||
"webpack": "^4.41.5"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"kbn:bootstrap": "yarn build",
|
||||
"watch": "yarn build --watch"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,10 +17,13 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { join } from 'path';
|
||||
const webpackConfig = require('./target/webpack.config').default;
|
||||
|
||||
// eslint-disable-next-line
|
||||
require('@kbn/storybook').runStorybookCli({
|
||||
name: 'embeddable',
|
||||
storyGlobs: [join(__dirname, '..', 'public', 'components', '**', '*.examples.tsx')],
|
||||
});
|
||||
module.exports = {
|
||||
managerEntries: (entry = []) => {
|
||||
return [...entry, require.resolve('./target/lib/register')];
|
||||
},
|
||||
webpackFinal: (config) => {
|
||||
return webpackConfig({ config });
|
||||
},
|
||||
};
|
|
@ -1,23 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import '@storybook/addon-options/register';
|
||||
import '@storybook/addon-actions/register';
|
||||
import '@storybook/addon-knobs/register';
|
||||
import '@storybook/addon-console';
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { configure, addDecorator, addParameters } from '@storybook/react';
|
||||
import { withKnobs } from '@storybook/addon-knobs/react';
|
||||
import { withInfo } from '@storybook/addon-info';
|
||||
import { create } from '@storybook/theming';
|
||||
|
||||
// If we're running Storyshots, be sure to register the require context hook.
|
||||
// Otherwise, add the other decorators.
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
// eslint-disable-next-line
|
||||
require('babel-plugin-require-context-hook/register')();
|
||||
} else {
|
||||
// Customize the info for each story.
|
||||
addDecorator(
|
||||
withInfo({
|
||||
inline: true,
|
||||
styles: {
|
||||
infoBody: {
|
||||
margin: 20,
|
||||
},
|
||||
infoStory: {
|
||||
margin: '40px 60px',
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
// Add optional knobs to customize each story.
|
||||
addDecorator(withKnobs);
|
||||
}
|
||||
|
||||
// Set up the Storybook environment with custom settings.
|
||||
addParameters({
|
||||
options: {
|
||||
theme: create({
|
||||
base: 'light',
|
||||
brandTitle: 'Kibana Storybook',
|
||||
brandUrl: 'https://github.com/elastic/kibana/tree/master/packages/kbn-storybook',
|
||||
}),
|
||||
showPanel: false,
|
||||
isFullscreen: false,
|
||||
panelPosition: 'bottom',
|
||||
isToolshown: true,
|
||||
},
|
||||
});
|
||||
|
||||
configure(() => {
|
||||
// eslint-disable-next-line
|
||||
require('../../../built_assets/storybook/stories.entry.js');
|
||||
}, module);
|
|
@ -1,23 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export const absoluteToParsedUrl = () => {
|
||||
getAbsoluteUrl: () =>
|
||||
'http://localhost:5601/kbp/app/canvas#/workpad/workpad-24d56dad-ae70-42b8-9ef1-c5350ecd426c/page/1';
|
||||
}; // noop
|
|
@ -1,26 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export function getState() {
|
||||
return {
|
||||
assets: {
|
||||
yay: { value: 'here is your image' },
|
||||
},
|
||||
};
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
<!--
|
||||
This file is looked for by Storybook and included in the HEAD element
|
||||
if it exists. This is how we load the DLL content into the Storybook UI.
|
||||
-->
|
||||
<script src="./dll.js"></script>
|
||||
<link href="./dll.css" rel="stylesheet" />
|
|
@ -1,147 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
const { resolve } = require('path');
|
||||
const webpack = require('webpack');
|
||||
const webpackMerge = require('webpack-merge');
|
||||
const { stringifyRequest } = require('loader-utils');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
const { REPO_ROOT } = require('@kbn/utils');
|
||||
const { DLL_DIST_DIR } = require('../lib/constants');
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
const { currentConfig } = require('../../../built_assets/storybook/current.config');
|
||||
|
||||
// Extend the Storybook Webpack config with some customizations
|
||||
module.exports = async ({ config: storybookConfig }) => {
|
||||
let config = {
|
||||
module: {
|
||||
rules: [
|
||||
// Include the React preset from Kibana for JS(X) and TS(X)
|
||||
{
|
||||
test: /\.(j|t)sx?$/,
|
||||
exclude: /node_modules/,
|
||||
loaders: 'babel-loader',
|
||||
options: {
|
||||
presets: [require.resolve('@kbn/babel-preset/webpack_preset')],
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.(html|md|txt|tmpl)$/,
|
||||
use: {
|
||||
loader: 'raw-loader',
|
||||
},
|
||||
},
|
||||
// Parse props data for .tsx files
|
||||
// This is notoriously slow, and is making Storybook unusable. Disabling for now.
|
||||
// See: https://github.com/storybookjs/storybook/issues/7998
|
||||
//
|
||||
// {
|
||||
// test: /\.tsx$/,
|
||||
// // Exclude example files, as we don't display props info for them
|
||||
// exclude: /\.stories.tsx$/,
|
||||
// use: [
|
||||
// // Parse TS comments to create Props tables in the UI
|
||||
// require.resolve('react-docgen-typescript-loader'),
|
||||
// ],
|
||||
// },
|
||||
{
|
||||
test: /\.scss$/,
|
||||
exclude: /\.module.(s(a|c)ss)$/,
|
||||
use: [
|
||||
{ loader: 'style-loader' },
|
||||
{ loader: 'css-loader', options: { importLoaders: 2 } },
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
config: {
|
||||
path: require.resolve('@kbn/optimizer/postcss.config.js'),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: 'sass-loader',
|
||||
options: {
|
||||
prependData(loaderContext) {
|
||||
return `@import ${stringifyRequest(
|
||||
loaderContext,
|
||||
resolve(REPO_ROOT, 'src/core/public/core_app/styles/_globals_v7light.scss')
|
||||
)};\n`;
|
||||
},
|
||||
sassOptions: {
|
||||
includePaths: [resolve(REPO_ROOT, 'node_modules')],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
// Reference the built DLL file of static(ish) dependencies, which are removed
|
||||
// during kbn:bootstrap and rebuilt if missing.
|
||||
new webpack.DllReferencePlugin({
|
||||
manifest: resolve(DLL_DIST_DIR, 'manifest.json'),
|
||||
context: REPO_ROOT,
|
||||
}),
|
||||
// Copy the DLL files to the Webpack build for use in the Storybook UI
|
||||
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: resolve(DLL_DIST_DIR, 'dll.js'),
|
||||
to: 'dll.js',
|
||||
},
|
||||
{
|
||||
from: resolve(DLL_DIST_DIR, 'dll.css'),
|
||||
to: 'dll.css',
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
resolve: {
|
||||
// Tell Webpack about the ts/x extensions
|
||||
extensions: ['.ts', '.tsx', '.scss'],
|
||||
alias: {
|
||||
core_app_image_assets: resolve(REPO_ROOT, 'src/core/public/core_app/images'),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Find and alter the CSS rule to replace the Kibana public path string with a path
|
||||
// to the route we've added in middleware.js
|
||||
const cssRule = storybookConfig.module.rules.find((rule) => rule.test.source.includes('.css$'));
|
||||
cssRule.use.push({
|
||||
loader: 'string-replace-loader',
|
||||
options: {
|
||||
search: '__REPLACE_WITH_PUBLIC_PATH__',
|
||||
replace: '/',
|
||||
flags: 'g',
|
||||
},
|
||||
});
|
||||
|
||||
config = webpackMerge(storybookConfig, config);
|
||||
|
||||
// Load custom Webpack config specified by a plugin.
|
||||
if (currentConfig.webpackHook) {
|
||||
// eslint-disable-next-line import/no-dynamic-require
|
||||
return await require(currentConfig.webpackHook)({ config });
|
||||
}
|
||||
|
||||
return config;
|
||||
};
|
9
packages/kbn-storybook/tsconfig.json
Normal file
9
packages/kbn-storybook/tsconfig.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"outDir": "target",
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": ["*.ts", "lib/*.ts"]
|
||||
}
|
|
@ -17,12 +17,5 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
export class Storage {
|
||||
get(key) {
|
||||
return this[key];
|
||||
}
|
||||
|
||||
set(key, value) {
|
||||
this[key] = value;
|
||||
}
|
||||
}
|
||||
// Storybook react doesn't declare this in its typings, but it's there.
|
||||
declare module '@storybook/react/standalone';
|
108
packages/kbn-storybook/webpack.config.ts
Normal file
108
packages/kbn-storybook/webpack.config.ts
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { resolve } from 'path';
|
||||
import { stringifyRequest } from 'loader-utils';
|
||||
import { Configuration, Stats } from 'webpack';
|
||||
import webpackMerge from 'webpack-merge';
|
||||
import { externals } from '@kbn/ui-shared-deps';
|
||||
import { REPO_ROOT } from './lib/constants';
|
||||
|
||||
const stats = {
|
||||
...Stats.presetToOptions('minimal'),
|
||||
colors: true,
|
||||
errorDetails: true,
|
||||
errors: true,
|
||||
moduleTrace: true,
|
||||
warningsFilter: /(export .* was not found in)|(entrypoint size limit)/,
|
||||
};
|
||||
|
||||
// Extend the Storybook Webpack config with some customizations
|
||||
/* eslint-disable import/no-default-export */
|
||||
export default function ({ config: storybookConfig }: { config: Configuration }) {
|
||||
const config = {
|
||||
devServer: {
|
||||
stats,
|
||||
},
|
||||
externals,
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(html|md|txt|tmpl)$/,
|
||||
use: {
|
||||
loader: 'raw-loader',
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
exclude: /\.module.(s(a|c)ss)$/,
|
||||
use: [
|
||||
{ loader: 'style-loader' },
|
||||
{ loader: 'css-loader', options: { importLoaders: 2 } },
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
config: {
|
||||
path: require.resolve('@kbn/optimizer/postcss.config.js'),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: 'sass-loader',
|
||||
options: {
|
||||
prependData(loaderContext: any) {
|
||||
return `@import ${stringifyRequest(
|
||||
loaderContext,
|
||||
resolve(REPO_ROOT, 'src/core/public/core_app/styles/_globals_v7light.scss')
|
||||
)};\n`;
|
||||
},
|
||||
sassOptions: {
|
||||
includePaths: [resolve(REPO_ROOT, 'node_modules')],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
// Tell Webpack about the scss extension
|
||||
extensions: ['.scss'],
|
||||
alias: {
|
||||
core_app_image_assets: resolve(REPO_ROOT, 'src/core/public/core_app/images'),
|
||||
},
|
||||
},
|
||||
stats,
|
||||
};
|
||||
|
||||
// This is the hacky part. We find something that looks like the
|
||||
// HtmlWebpackPlugin and mutate its `options.template` to point at our
|
||||
// revised template.
|
||||
const htmlWebpackPlugin: any = (storybookConfig.plugins || []).find((plugin: any) => {
|
||||
return plugin.options && typeof plugin.options.template === 'string';
|
||||
});
|
||||
if (htmlWebpackPlugin) {
|
||||
htmlWebpackPlugin.options.template = require.resolve('../lib/templates/index.ejs');
|
||||
}
|
||||
|
||||
// @ts-expect-error There's a long error here about the types of the
|
||||
// incompatibility of Configuration, but it looks like it just may be Webpack
|
||||
// type definition related.
|
||||
return webpackMerge(storybookConfig, config);
|
||||
}
|
|
@ -50,14 +50,12 @@ export const IGNORE_FILE_GLOBS = [
|
|||
'vars/*',
|
||||
'.ci/pipeline-library/**/*',
|
||||
|
||||
// Files in this directory must match a pre-determined name in some cases.
|
||||
'x-pack/plugins/canvas/storybook/*',
|
||||
|
||||
// filename must match language code which requires capital letters
|
||||
'**/translations/*.json',
|
||||
|
||||
// filename is required by storybook
|
||||
'packages/kbn-storybook/storybook_config/preview-head.html',
|
||||
// Storybook has predetermined filesnames
|
||||
'**/preview-body.html',
|
||||
'**/preview-head.html',
|
||||
|
||||
// filename required by api-extractor
|
||||
'api-documenter.json',
|
||||
|
|
|
@ -18,13 +18,13 @@
|
|||
*/
|
||||
|
||||
export const storybookAliases = {
|
||||
apm: 'x-pack/plugins/apm/scripts/storybook.js',
|
||||
canvas: 'x-pack/plugins/canvas/scripts/storybook_new.js',
|
||||
codeeditor: 'src/plugins/kibana_react/public/code_editor/scripts/storybook.ts',
|
||||
dashboard_enhanced: 'x-pack/plugins/dashboard_enhanced/scripts/storybook.js',
|
||||
embeddable: 'src/plugins/embeddable/scripts/storybook.js',
|
||||
infra: 'x-pack/plugins/infra/scripts/storybook.js',
|
||||
security_solution: 'x-pack/plugins/security_solution/scripts/storybook.js',
|
||||
ui_actions_enhanced: 'x-pack/plugins/ui_actions_enhanced/scripts/storybook.js',
|
||||
observability: 'x-pack/plugins/observability/scripts/storybook.js',
|
||||
apm: 'x-pack/plugins/apm/.storybook',
|
||||
canvas: 'x-pack/plugins/canvas/storybook',
|
||||
codeeditor: 'src/plugins/kibana_react/public/code_editor/.storybook',
|
||||
dashboard_enhanced: 'x-pack/plugins/dashboard_enhanced/.storybook',
|
||||
embeddable: 'src/plugins/embeddable/.storybook',
|
||||
infra: 'x-pack/plugins/infra/.storybook',
|
||||
security_solution: 'x-pack/plugins/security_solution/.storybook',
|
||||
ui_actions_enhanced: 'x-pack/plugins/ui_actions_enhanced/.storybook',
|
||||
observability: 'x-pack/plugins/observability/.storybook',
|
||||
};
|
||||
|
|
|
@ -17,9 +17,8 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { join } from 'path';
|
||||
import { run, createFlagError } from '@kbn/dev-utils';
|
||||
import { REPO_ROOT } from '@kbn/utils';
|
||||
import { runStorybookCli } from '@kbn/storybook';
|
||||
import { storybookAliases } from './aliases';
|
||||
import { clean } from './commands/clean';
|
||||
|
||||
|
@ -40,20 +39,18 @@ run(
|
|||
}
|
||||
|
||||
if (!alias) {
|
||||
throw createFlagError('missing alias');
|
||||
throw createFlagError('Missing alias');
|
||||
}
|
||||
|
||||
if (!storybookAliases.hasOwnProperty(alias)) {
|
||||
throw createFlagError(`unknown alias [${alias}]`);
|
||||
throw createFlagError(`Unknown alias [${alias}]`);
|
||||
}
|
||||
|
||||
const relative = (storybookAliases as any)[alias];
|
||||
const absolute = join(REPO_ROOT, relative);
|
||||
const configDir = (storybookAliases as any)[alias];
|
||||
|
||||
log.verbose('Loading Storybook:', absolute);
|
||||
process.chdir(join(absolute, '..', '..'));
|
||||
log.verbose('Loading Storybook:', configDir);
|
||||
|
||||
require(absolute);
|
||||
runStorybookCli({ configDir, name: alias });
|
||||
},
|
||||
{
|
||||
usage: `node scripts/storybook <alias>`,
|
||||
|
|
|
@ -4,10 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { join } from 'path';
|
||||
|
||||
// eslint-disable-next-line
|
||||
require('@kbn/storybook').runStorybookCli({
|
||||
name: 'canvas',
|
||||
storyGlobs: [join(__dirname, '..', '**', '*.stories.tsx')],
|
||||
});
|
||||
module.exports = require('@kbn/storybook').defaultConfig;
|
|
@ -4,10 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { join } from 'path';
|
||||
|
||||
// eslint-disable-next-line
|
||||
require('@kbn/storybook').runStorybookCli({
|
||||
name: 'dashboard_enhanced',
|
||||
storyGlobs: [join(__dirname, '..', 'public', '**', '*.story.tsx')],
|
||||
});
|
||||
module.exports = require('@kbn/storybook').defaultConfig;
|
|
@ -43,13 +43,12 @@
|
|||
"@mapbox/mapbox-gl-draw": "^1.2.0",
|
||||
"@mapbox/mapbox-gl-rtl-text": "^0.2.3",
|
||||
"@scant/router": "^0.1.0",
|
||||
"@storybook/addon-actions": "^5.3.19",
|
||||
"@storybook/addon-console": "^1.2.1",
|
||||
"@storybook/addon-info": "^5.3.19",
|
||||
"@storybook/addon-knobs": "^5.3.19",
|
||||
"@storybook/addon-storyshots": "^5.3.19",
|
||||
"@storybook/react": "^5.3.19",
|
||||
"@storybook/theming": "^5.3.19",
|
||||
"@storybook/addon-actions": "^6.0.16",
|
||||
"@storybook/addon-essentials": "^6.0.16",
|
||||
"@storybook/addon-knobs": "^6.0.16",
|
||||
"@storybook/addon-storyshots": "^6.0.16",
|
||||
"@storybook/react": "^6.0.16",
|
||||
"@storybook/theming": "^6.0.16",
|
||||
"@testing-library/dom": "^7.24.2",
|
||||
"@testing-library/jest-dom": "^5.11.4",
|
||||
"@testing-library/react": "^11.0.4",
|
||||
|
|
|
@ -4,10 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { join } from 'path';
|
||||
|
||||
// eslint-disable-next-line
|
||||
require('@kbn/storybook').runStorybookCli({
|
||||
name: 'ui_actions_enhanced',
|
||||
storyGlobs: [join(__dirname, '..', 'public', '**', '*.story.tsx')],
|
||||
});
|
||||
module.exports = require('@kbn/storybook').defaultConfig;
|
|
@ -1,15 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { join } from 'path';
|
||||
|
||||
// eslint-disable-next-line
|
||||
require('@kbn/storybook').runStorybookCli({
|
||||
name: 'apm',
|
||||
storyGlobs: [
|
||||
join(__dirname, '..', 'public', 'components', '**', '*.stories.tsx'),
|
||||
],
|
||||
});
|
|
@ -11,28 +11,38 @@ exports[`Storyshots arguments/AxisConfig simple 1`] = `
|
|||
}
|
||||
>
|
||||
<div
|
||||
className="euiSwitch euiSwitch--compressed"
|
||||
style={
|
||||
Object {
|
||||
"background": "#fff",
|
||||
"padding": "16px",
|
||||
"width": "323px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<button
|
||||
aria-checked={false}
|
||||
aria-label=""
|
||||
className="euiSwitch__button"
|
||||
id="generated-id"
|
||||
onClick={[Function]}
|
||||
role="switch"
|
||||
type="button"
|
||||
<div
|
||||
className="euiSwitch euiSwitch--compressed"
|
||||
>
|
||||
<span
|
||||
className="euiSwitch__body"
|
||||
<button
|
||||
aria-checked={false}
|
||||
aria-label=""
|
||||
className="euiSwitch__button"
|
||||
id="generated-id"
|
||||
onClick={[Function]}
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
className="euiSwitch__thumb"
|
||||
/>
|
||||
<span
|
||||
className="euiSwitch__track"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
className="euiSwitch__body"
|
||||
>
|
||||
<span
|
||||
className="euiSwitch__thumb"
|
||||
/>
|
||||
<span
|
||||
className="euiSwitch__track"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -48,28 +58,38 @@ exports[`Storyshots arguments/AxisConfig/components simple template 1`] = `
|
|||
}
|
||||
>
|
||||
<div
|
||||
className="euiSwitch euiSwitch--compressed"
|
||||
style={
|
||||
Object {
|
||||
"background": "#fff",
|
||||
"padding": "16px",
|
||||
"width": "323px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<button
|
||||
aria-checked={false}
|
||||
aria-label=""
|
||||
className="euiSwitch__button"
|
||||
id="generated-id"
|
||||
onClick={[Function]}
|
||||
role="switch"
|
||||
type="button"
|
||||
<div
|
||||
className="euiSwitch euiSwitch--compressed"
|
||||
>
|
||||
<span
|
||||
className="euiSwitch__body"
|
||||
<button
|
||||
aria-checked={false}
|
||||
aria-label=""
|
||||
className="euiSwitch__button"
|
||||
id="generated-id"
|
||||
onClick={[Function]}
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
className="euiSwitch__thumb"
|
||||
/>
|
||||
<span
|
||||
className="euiSwitch__track"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
className="euiSwitch__body"
|
||||
>
|
||||
<span
|
||||
className="euiSwitch__thumb"
|
||||
/>
|
||||
<span
|
||||
className="euiSwitch__track"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
|
|
@ -13,50 +13,60 @@ exports[`Storyshots arguments/ContainerStyle simple 1`] = `
|
|||
<div
|
||||
style={
|
||||
Object {
|
||||
"fontSize": 0,
|
||||
"background": "#fff",
|
||||
"padding": "16px",
|
||||
"width": "323px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="euiPopover euiPopover--anchorLeftCenter"
|
||||
container={null}
|
||||
id="color-picker-popover"
|
||||
onKeyDown={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseUp={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
onTouchStart={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"fontSize": 0,
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="euiPopover__anchor"
|
||||
className="euiPopover euiPopover--anchorLeftCenter"
|
||||
container={null}
|
||||
id="color-picker-popover"
|
||||
onKeyDown={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseUp={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
onTouchStart={[Function]}
|
||||
>
|
||||
<button
|
||||
aria-label="Container style white"
|
||||
className="euiLink euiLink--primary"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"fontSize": 0,
|
||||
}
|
||||
}
|
||||
type="button"
|
||||
<div
|
||||
className="euiPopover__anchor"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
<button
|
||||
aria-label="Container style white"
|
||||
className="euiLink euiLink--primary"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"fontSize": 0,
|
||||
}
|
||||
}
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "#fff",
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "#fff",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</button>
|
||||
/>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -76,50 +86,60 @@ exports[`Storyshots arguments/ContainerStyle/components simple template 1`] = `
|
|||
<div
|
||||
style={
|
||||
Object {
|
||||
"fontSize": 0,
|
||||
"background": "#fff",
|
||||
"padding": "16px",
|
||||
"width": "323px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="euiPopover euiPopover--anchorLeftCenter"
|
||||
container={null}
|
||||
id="color-picker-popover"
|
||||
onKeyDown={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseUp={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
onTouchStart={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"fontSize": 0,
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="euiPopover__anchor"
|
||||
className="euiPopover euiPopover--anchorLeftCenter"
|
||||
container={null}
|
||||
id="color-picker-popover"
|
||||
onKeyDown={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseUp={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
onTouchStart={[Function]}
|
||||
>
|
||||
<button
|
||||
aria-label="Container style white"
|
||||
className="euiLink euiLink--primary"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"fontSize": 0,
|
||||
}
|
||||
}
|
||||
type="button"
|
||||
<div
|
||||
className="euiPopover__anchor"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
<button
|
||||
aria-label="Container style white"
|
||||
className="euiLink euiLink--primary"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"fontSize": 0,
|
||||
}
|
||||
}
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "#fff",
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "#fff",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</button>
|
||||
/>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -11,31 +11,41 @@ exports[`Storyshots arguments/SeriesStyle simple 1`] = `
|
|||
}
|
||||
>
|
||||
<div
|
||||
className="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive canvasArgSeries__colorPicker"
|
||||
style={
|
||||
Object {
|
||||
"background": "#fff",
|
||||
"padding": "16px",
|
||||
"width": "323px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
className="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive canvasArgSeries__colorPicker"
|
||||
>
|
||||
<div
|
||||
className="euiText euiText--extraSmall"
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
Color
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<div
|
||||
className="euiText euiText--extraSmall"
|
||||
>
|
||||
<button
|
||||
aria-label="Color: Auto"
|
||||
className="euiLink euiLink--primary"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
<div
|
||||
className="euiText euiText--extraSmall"
|
||||
>
|
||||
Auto
|
||||
</button>
|
||||
Color
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<div
|
||||
className="euiText euiText--extraSmall"
|
||||
>
|
||||
<button
|
||||
aria-label="Color: Auto"
|
||||
className="euiLink euiLink--primary"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Auto
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -53,31 +63,41 @@ exports[`Storyshots arguments/SeriesStyle/components simple: defaults 1`] = `
|
|||
}
|
||||
>
|
||||
<div
|
||||
className="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive canvasArgSeries__colorPicker"
|
||||
style={
|
||||
Object {
|
||||
"background": "#fff",
|
||||
"padding": "16px",
|
||||
"width": "323px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
className="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive canvasArgSeries__colorPicker"
|
||||
>
|
||||
<div
|
||||
className="euiText euiText--extraSmall"
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
Color
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<div
|
||||
className="euiText euiText--extraSmall"
|
||||
>
|
||||
<button
|
||||
aria-label="Color: Auto"
|
||||
className="euiLink euiLink--primary"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
<div
|
||||
className="euiText euiText--extraSmall"
|
||||
>
|
||||
Auto
|
||||
</button>
|
||||
Color
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<div
|
||||
className="euiText euiText--extraSmall"
|
||||
>
|
||||
<button
|
||||
aria-label="Color: Auto"
|
||||
className="euiLink euiLink--primary"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Auto
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -95,31 +115,41 @@ exports[`Storyshots arguments/SeriesStyle/components simple: no labels 1`] = `
|
|||
}
|
||||
>
|
||||
<div
|
||||
className="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive canvasArgSeries__colorPicker"
|
||||
style={
|
||||
Object {
|
||||
"background": "#fff",
|
||||
"padding": "16px",
|
||||
"width": "323px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
className="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive canvasArgSeries__colorPicker"
|
||||
>
|
||||
<div
|
||||
className="euiText euiText--extraSmall"
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
Color
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<div
|
||||
className="euiText euiText--extraSmall"
|
||||
>
|
||||
<button
|
||||
aria-label="Color: Auto"
|
||||
className="euiLink euiLink--primary"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
<div
|
||||
className="euiText euiText--extraSmall"
|
||||
>
|
||||
Auto
|
||||
</button>
|
||||
Color
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<div
|
||||
className="euiText euiText--extraSmall"
|
||||
>
|
||||
<button
|
||||
aria-label="Color: Auto"
|
||||
className="euiLink euiLink--primary"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Auto
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -137,51 +167,61 @@ exports[`Storyshots arguments/SeriesStyle/components simple: no series 1`] = `
|
|||
}
|
||||
>
|
||||
<div
|
||||
className="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive canvasArgSeries__colorPicker"
|
||||
style={
|
||||
Object {
|
||||
"background": "#fff",
|
||||
"padding": "16px",
|
||||
"width": "323px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
className="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive canvasArgSeries__colorPicker"
|
||||
>
|
||||
<div
|
||||
className="euiText euiText--extraSmall"
|
||||
>
|
||||
Color
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<div
|
||||
className="euiText euiText--extraSmall"
|
||||
>
|
||||
<button
|
||||
aria-label="Color: Auto"
|
||||
className="euiLink euiLink--primary"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Auto
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<span
|
||||
className="euiToolTipAnchor"
|
||||
onKeyUp={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<div
|
||||
aria-label="Info"
|
||||
color="warning"
|
||||
data-euiicon-type="alert"
|
||||
onBlur={[Function]}
|
||||
onFocus={[Function]}
|
||||
tabIndex={0}
|
||||
/>
|
||||
</span>
|
||||
className="euiText euiText--extraSmall"
|
||||
>
|
||||
Color
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<div
|
||||
className="euiText euiText--extraSmall"
|
||||
>
|
||||
<button
|
||||
aria-label="Color: Auto"
|
||||
className="euiLink euiLink--primary"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Auto
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<span
|
||||
className="euiToolTipAnchor"
|
||||
onKeyUp={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
>
|
||||
<div
|
||||
aria-label="Info"
|
||||
color="warning"
|
||||
data-euiicon-type="alert"
|
||||
onBlur={[Function]}
|
||||
onFocus={[Function]}
|
||||
tabIndex={0}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -198,31 +238,41 @@ exports[`Storyshots arguments/SeriesStyle/components simple: with series 1`] = `
|
|||
}
|
||||
>
|
||||
<div
|
||||
className="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive canvasArgSeries__colorPicker"
|
||||
style={
|
||||
Object {
|
||||
"background": "#fff",
|
||||
"padding": "16px",
|
||||
"width": "323px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
className="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive canvasArgSeries__colorPicker"
|
||||
>
|
||||
<div
|
||||
className="euiText euiText--extraSmall"
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
Color
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<div
|
||||
className="euiText euiText--extraSmall"
|
||||
>
|
||||
<button
|
||||
aria-label="Color: Auto"
|
||||
className="euiLink euiLink--primary"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
<div
|
||||
className="euiText euiText--extraSmall"
|
||||
>
|
||||
Auto
|
||||
</button>
|
||||
Color
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<div
|
||||
className="euiText euiText--extraSmall"
|
||||
>
|
||||
<button
|
||||
aria-label="Color: Auto"
|
||||
className="euiLink euiLink--primary"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Auto
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -24,7 +24,7 @@ addons.register(ADDON_ID, (api) => {
|
|||
type: types.PANEL,
|
||||
render: ({ active, key }) => {
|
||||
return (
|
||||
<AddonPanel active={active} key={key}>
|
||||
<AddonPanel active={!!active} key={key}>
|
||||
<Panel />
|
||||
</AddonPanel>
|
||||
);
|
||||
|
|
|
@ -5,14 +5,6 @@
|
|||
*/
|
||||
|
||||
import { addDecorator } from '@storybook/react';
|
||||
// @ts-expect-error
|
||||
import { withInfo } from '@storybook/addon-info';
|
||||
import { Provider as ReduxProvider } from 'react-redux';
|
||||
|
||||
import { ServicesProvider } from '../../public/services';
|
||||
import { RouterContext } from '../../public/components/router';
|
||||
import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public';
|
||||
|
||||
import { routerContextDecorator } from './router_decorator';
|
||||
import { kibanaContextDecorator } from './kibana_decorator';
|
||||
import { servicesContextDecorator } from './services_decorator';
|
||||
|
@ -23,22 +15,6 @@ export const addDecorators = () => {
|
|||
if (process.env.NODE_ENV === 'test') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
require('babel-plugin-require-context-hook/register')();
|
||||
} else {
|
||||
// Customize the info for each story.
|
||||
addDecorator(
|
||||
withInfo({
|
||||
inline: true,
|
||||
styles: {
|
||||
infoBody: {
|
||||
margin: 20,
|
||||
},
|
||||
infoStory: {
|
||||
margin: '40px 60px',
|
||||
},
|
||||
},
|
||||
propTablesExclude: [ReduxProvider, ServicesProvider, RouterContext, KibanaContextProvider],
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
addDecorator(kibanaContextDecorator);
|
||||
|
|
|
@ -4,11 +4,20 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const { existsSync } = require('fs');
|
||||
const { join } = require('path');
|
||||
|
||||
// Check for DLL
|
||||
if (!existsSync(join(__dirname, '../../../../built_assets/canvas_storybook_dll/manifest.json'))) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(
|
||||
'No DLL found. Run `node scripts/storybook --dll` from the Canvas plugin directory.'
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
stories: ['../**/*.stories.tsx'],
|
||||
addons: [
|
||||
'@storybook/addon-actions',
|
||||
'@storybook/addon-knobs',
|
||||
'./storybook/addon/target/register',
|
||||
],
|
||||
addons: ['@storybook/addon-actions', '@storybook/addon-knobs', './addon/target/register'],
|
||||
};
|
||||
|
|
|
@ -11,7 +11,7 @@ import moment from 'moment';
|
|||
import 'moment-timezone';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import initStoryshots, { multiSnapshotWithOptions } from '@storybook/addon-storyshots';
|
||||
// import initStoryshots, { multiSnapshotWithOptions } from '@storybook/addon-storyshots';
|
||||
// @ts-expect-error untyped library
|
||||
import styleSheetSerializer from 'jest-styled-components/src/styleSheetSerializer';
|
||||
import { addSerializer } from 'jest-specific-snapshot';
|
||||
|
@ -104,9 +104,12 @@ if (!fs.existsSync(cssDir)) {
|
|||
addSerializer(styleSheetSerializer);
|
||||
|
||||
// Initialize Storyshots and build the Jest Snapshots
|
||||
initStoryshots({
|
||||
configPath: path.resolve(__dirname, './../storybook'),
|
||||
test: multiSnapshotWithOptions({}),
|
||||
// Don't snapshot tests that start with 'redux'
|
||||
storyNameRegex: /^((?!.*?redux).)*$/,
|
||||
});
|
||||
// Commenting this out until after #75357 is merged and Jest gets updated.
|
||||
// initStoryshots({
|
||||
// configPath: path.resolve(__dirname, './../storybook'),
|
||||
// test: multiSnapshotWithOptions({}),
|
||||
// // Don't snapshot tests that start with 'redux'
|
||||
// storyNameRegex: /^((?!.*?redux).)*$/,
|
||||
// });
|
||||
|
||||
test.todo('Storyshots');
|
||||
|
|
|
@ -4,10 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { join } from 'path';
|
||||
|
||||
// eslint-disable-next-line
|
||||
require('@kbn/storybook').runStorybookCli({
|
||||
name: 'infra',
|
||||
storyGlobs: [join(__dirname, '..', 'public', 'components', '**', '*.stories.tsx')],
|
||||
});
|
||||
module.exports = require('@kbn/storybook').defaultConfig;
|
7
x-pack/plugins/infra/.storybook/main.js
Normal file
7
x-pack/plugins/infra/.storybook/main.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
module.exports = require('@kbn/storybook').defaultConfig;
|
7
x-pack/plugins/observability/.storybook/main.js
Normal file
7
x-pack/plugins/observability/.storybook/main.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
module.exports = require('@kbn/storybook').defaultConfig;
|
|
@ -3,6 +3,8 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { makeDecorator } from '@storybook/addons';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import { AppMountContext } from 'kibana/public';
|
||||
import React from 'react';
|
||||
|
@ -10,20 +12,44 @@ import { MemoryRouter } from 'react-router-dom';
|
|||
import { UI_SETTINGS } from '../../../../../../src/plugins/data/public';
|
||||
import { PluginContext } from '../../context/plugin_context';
|
||||
import { registerDataHandler, unregisterDataHandler } from '../../data_handler';
|
||||
import { emptyResponse as emptyAPMResponse, fetchApmData } from './mock/apm.mock';
|
||||
import { fetchLogsData, emptyResponse as emptyLogsResponse } from './mock/logs.mock';
|
||||
import { fetchMetricsData, emptyResponse as emptyMetricsResponse } from './mock/metrics.mock';
|
||||
import { fetchUptimeData, emptyResponse as emptyUptimeResponse } from './mock/uptime.mock';
|
||||
import { EuiThemeProvider } from '../../typings';
|
||||
import { OverviewPage } from './';
|
||||
import { alertsFetchData } from './mock/alerts.mock';
|
||||
import { emptyResponse as emptyAPMResponse, fetchApmData } from './mock/apm.mock';
|
||||
import { emptyResponse as emptyLogsResponse, fetchLogsData } from './mock/logs.mock';
|
||||
import { emptyResponse as emptyMetricsResponse, fetchMetricsData } from './mock/metrics.mock';
|
||||
import { newsFeedFetchData } from './mock/news_feed.mock';
|
||||
import { emptyResponse as emptyUptimeResponse, fetchUptimeData } from './mock/uptime.mock';
|
||||
|
||||
const core = {
|
||||
function unregisterAll() {
|
||||
unregisterDataHandler({ appName: 'apm' });
|
||||
unregisterDataHandler({ appName: 'infra_logs' });
|
||||
unregisterDataHandler({ appName: 'infra_metrics' });
|
||||
unregisterDataHandler({ appName: 'uptime' });
|
||||
}
|
||||
|
||||
const withCore = makeDecorator({
|
||||
name: 'withCore',
|
||||
parameterName: 'core',
|
||||
wrapper: (storyFn, context, { options }) => {
|
||||
unregisterAll();
|
||||
|
||||
return (
|
||||
<MemoryRouter>
|
||||
<PluginContext.Provider value={{ core: options as AppMountContext['core'] }}>
|
||||
<EuiThemeProvider>{storyFn(context)}</EuiThemeProvider>
|
||||
</PluginContext.Provider>
|
||||
</MemoryRouter>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const core = ({
|
||||
http: {
|
||||
basePath: {
|
||||
prepend: (link) => `http://localhost:5601${link}`,
|
||||
prepend: (link: string) => `http://localhost:5601${link}`,
|
||||
},
|
||||
get: () => Promise.resolve({ data: [] }),
|
||||
},
|
||||
uiSettings: {
|
||||
get: (key: string) => {
|
||||
|
@ -93,7 +119,7 @@ const core = {
|
|||
return euiSettings[key];
|
||||
},
|
||||
},
|
||||
} as AppMountContext['core'];
|
||||
} as unknown) as AppMountContext['core'];
|
||||
|
||||
const coreWithAlerts = ({
|
||||
...core,
|
||||
|
@ -111,23 +137,19 @@ const coreWithNewsFeed = ({
|
|||
},
|
||||
} as unknown) as AppMountContext['core'];
|
||||
|
||||
function unregisterAll() {
|
||||
unregisterDataHandler({ appName: 'apm' });
|
||||
unregisterDataHandler({ appName: 'infra_logs' });
|
||||
unregisterDataHandler({ appName: 'infra_metrics' });
|
||||
unregisterDataHandler({ appName: 'uptime' });
|
||||
}
|
||||
const coreAlertsThrowsError = ({
|
||||
...core,
|
||||
http: {
|
||||
...core.http,
|
||||
get: async () => {
|
||||
throw new Error('Error fetching Alerts data');
|
||||
},
|
||||
},
|
||||
} as unknown) as AppMountContext['core'];
|
||||
|
||||
storiesOf('app/Overview', module)
|
||||
.addDecorator((storyFn) => (
|
||||
<MemoryRouter>
|
||||
<PluginContext.Provider value={{ core }}>
|
||||
<EuiThemeProvider>{storyFn()}</EuiThemeProvider>
|
||||
</PluginContext.Provider>
|
||||
</MemoryRouter>
|
||||
))
|
||||
.add('Empty state', () => {
|
||||
unregisterAll();
|
||||
.addDecorator(withCore(core))
|
||||
.add('Empty State', () => {
|
||||
registerDataHandler({
|
||||
appName: 'apm',
|
||||
fetchData: fetchApmData,
|
||||
|
@ -150,23 +172,14 @@ storiesOf('app/Overview', module)
|
|||
});
|
||||
|
||||
return <OverviewPage routeParams={{ query: {} }} />;
|
||||
});
|
||||
|
||||
storiesOf('app/Overview', module)
|
||||
.addDecorator((storyFn) => (
|
||||
<MemoryRouter>
|
||||
<PluginContext.Provider value={{ core }}>
|
||||
<EuiThemeProvider>{storyFn()}</EuiThemeProvider>
|
||||
</PluginContext.Provider>
|
||||
</MemoryRouter>
|
||||
))
|
||||
.add('single panel', () => {
|
||||
unregisterAll();
|
||||
})
|
||||
.add('Single Panel', () => {
|
||||
registerDataHandler({
|
||||
appName: 'infra_logs',
|
||||
fetchData: fetchLogsData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
|
||||
return (
|
||||
<OverviewPage
|
||||
routeParams={{
|
||||
|
@ -174,18 +187,8 @@ storiesOf('app/Overview', module)
|
|||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
storiesOf('app/Overview', module)
|
||||
.addDecorator((storyFn) => (
|
||||
<MemoryRouter>
|
||||
<PluginContext.Provider value={{ core }}>
|
||||
<EuiThemeProvider>{storyFn()}</EuiThemeProvider>
|
||||
</PluginContext.Provider>
|
||||
</MemoryRouter>
|
||||
))
|
||||
.add('logs and metrics', () => {
|
||||
unregisterAll();
|
||||
})
|
||||
.add('Logs and Metrics', () => {
|
||||
registerDataHandler({
|
||||
appName: 'infra_logs',
|
||||
fetchData: fetchLogsData,
|
||||
|
@ -196,6 +199,7 @@ storiesOf('app/Overview', module)
|
|||
fetchData: fetchMetricsData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
|
||||
return (
|
||||
<OverviewPage
|
||||
routeParams={{
|
||||
|
@ -203,81 +207,61 @@ storiesOf('app/Overview', module)
|
|||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
})
|
||||
.add(
|
||||
'Logs, Metrics, and Alerts',
|
||||
() => {
|
||||
registerDataHandler({
|
||||
appName: 'infra_logs',
|
||||
fetchData: fetchLogsData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_metrics',
|
||||
fetchData: fetchMetricsData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
|
||||
storiesOf('app/Overview', module)
|
||||
.addDecorator((storyFn) => (
|
||||
<MemoryRouter>
|
||||
<PluginContext.Provider value={{ core: coreWithAlerts }}>
|
||||
<EuiThemeProvider>{storyFn()}</EuiThemeProvider>
|
||||
</PluginContext.Provider>
|
||||
</MemoryRouter>
|
||||
))
|
||||
.add('logs, metrics and alerts', () => {
|
||||
unregisterAll();
|
||||
registerDataHandler({
|
||||
appName: 'infra_logs',
|
||||
fetchData: fetchLogsData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_metrics',
|
||||
fetchData: fetchMetricsData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
return (
|
||||
<OverviewPage
|
||||
routeParams={{
|
||||
query: { rangeFrom: '2020-06-27T22:00:00.000Z', rangeTo: '2020-06-30T21:59:59.999Z' },
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<OverviewPage
|
||||
routeParams={{
|
||||
query: { rangeFrom: '2020-06-27T22:00:00.000Z', rangeTo: '2020-06-30T21:59:59.999Z' },
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
{ core: coreWithAlerts }
|
||||
)
|
||||
.add(
|
||||
'Logs, Metrics, APM, and Alerts',
|
||||
() => {
|
||||
registerDataHandler({
|
||||
appName: 'infra_logs',
|
||||
fetchData: fetchLogsData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_metrics',
|
||||
fetchData: fetchMetricsData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'apm',
|
||||
fetchData: fetchApmData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
|
||||
storiesOf('app/Overview', module)
|
||||
.addDecorator((storyFn) => (
|
||||
<MemoryRouter>
|
||||
<PluginContext.Provider value={{ core: coreWithAlerts }}>
|
||||
<EuiThemeProvider>{storyFn()}</EuiThemeProvider>
|
||||
</PluginContext.Provider>
|
||||
</MemoryRouter>
|
||||
))
|
||||
.add('logs, metrics, APM and alerts', () => {
|
||||
unregisterAll();
|
||||
registerDataHandler({
|
||||
appName: 'infra_logs',
|
||||
fetchData: fetchLogsData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_metrics',
|
||||
fetchData: fetchMetricsData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'apm',
|
||||
fetchData: fetchApmData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
return (
|
||||
<OverviewPage
|
||||
routeParams={{
|
||||
query: { rangeFrom: '2020-06-27T22:00:00.000Z', rangeTo: '2020-06-30T21:59:59.999Z' },
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
storiesOf('app/Overview', module)
|
||||
.addDecorator((storyFn) => (
|
||||
<MemoryRouter>
|
||||
<PluginContext.Provider value={{ core }}>
|
||||
<EuiThemeProvider>{storyFn()}</EuiThemeProvider>
|
||||
</PluginContext.Provider>
|
||||
</MemoryRouter>
|
||||
))
|
||||
.add('logs, metrics, APM and Uptime', () => {
|
||||
unregisterAll();
|
||||
return (
|
||||
<OverviewPage
|
||||
routeParams={{
|
||||
query: { rangeFrom: '2020-06-27T22:00:00.000Z', rangeTo: '2020-06-30T21:59:59.999Z' },
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
{ core: coreWithAlerts }
|
||||
)
|
||||
.add('Logs, Metrics, APM, and Uptime', () => {
|
||||
registerDataHandler({
|
||||
appName: 'apm',
|
||||
fetchData: fetchApmData,
|
||||
|
@ -298,6 +282,7 @@ storiesOf('app/Overview', module)
|
|||
fetchData: fetchUptimeData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
|
||||
return (
|
||||
<OverviewPage
|
||||
routeParams={{
|
||||
|
@ -305,96 +290,75 @@ storiesOf('app/Overview', module)
|
|||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
})
|
||||
.add(
|
||||
'Logs, Metrics, APM, Uptime, and Alerts',
|
||||
() => {
|
||||
registerDataHandler({
|
||||
appName: 'apm',
|
||||
fetchData: fetchApmData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_logs',
|
||||
fetchData: fetchLogsData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_metrics',
|
||||
fetchData: fetchMetricsData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'uptime',
|
||||
fetchData: fetchUptimeData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
|
||||
storiesOf('app/Overview', module)
|
||||
.addDecorator((storyFn) => (
|
||||
<MemoryRouter>
|
||||
<PluginContext.Provider value={{ core: coreWithAlerts }}>
|
||||
<EuiThemeProvider>{storyFn()}</EuiThemeProvider>
|
||||
</PluginContext.Provider>
|
||||
</MemoryRouter>
|
||||
))
|
||||
.add('logs, metrics, APM, Uptime and Alerts', () => {
|
||||
unregisterAll();
|
||||
registerDataHandler({
|
||||
appName: 'apm',
|
||||
fetchData: fetchApmData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_logs',
|
||||
fetchData: fetchLogsData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_metrics',
|
||||
fetchData: fetchMetricsData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'uptime',
|
||||
fetchData: fetchUptimeData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
return (
|
||||
<OverviewPage
|
||||
routeParams={{
|
||||
query: { rangeFrom: '2020-06-27T22:00:00.000Z', rangeTo: '2020-06-30T21:59:59.999Z' },
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
storiesOf('app/Overview', module)
|
||||
.addDecorator((storyFn) => (
|
||||
<MemoryRouter>
|
||||
<PluginContext.Provider value={{ core: coreWithNewsFeed }}>
|
||||
<EuiThemeProvider>{storyFn()}</EuiThemeProvider>
|
||||
</PluginContext.Provider>
|
||||
</MemoryRouter>
|
||||
))
|
||||
.add('logs, metrics, APM, Uptime and News feed', () => {
|
||||
unregisterAll();
|
||||
registerDataHandler({
|
||||
appName: 'apm',
|
||||
fetchData: fetchApmData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_logs',
|
||||
fetchData: fetchLogsData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_metrics',
|
||||
fetchData: fetchMetricsData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'uptime',
|
||||
fetchData: fetchUptimeData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
return (
|
||||
<OverviewPage
|
||||
routeParams={{
|
||||
query: { rangeFrom: '2020-06-27T22:00:00.000Z', rangeTo: '2020-06-30T21:59:59.999Z' },
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
storiesOf('app/Overview', module)
|
||||
.addDecorator((storyFn) => (
|
||||
<MemoryRouter>
|
||||
<PluginContext.Provider value={{ core }}>
|
||||
<EuiThemeProvider>{storyFn()}</EuiThemeProvider>
|
||||
</PluginContext.Provider>
|
||||
</MemoryRouter>
|
||||
))
|
||||
.add('no data', () => {
|
||||
unregisterAll();
|
||||
return (
|
||||
<OverviewPage
|
||||
routeParams={{
|
||||
query: { rangeFrom: '2020-06-27T22:00:00.000Z', rangeTo: '2020-06-30T21:59:59.999Z' },
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
{ core: coreWithAlerts }
|
||||
)
|
||||
.add(
|
||||
'Logs, Metrics, APM, Uptime, and News Feed',
|
||||
() => {
|
||||
registerDataHandler({
|
||||
appName: 'apm',
|
||||
fetchData: fetchApmData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_logs',
|
||||
fetchData: fetchLogsData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_metrics',
|
||||
fetchData: fetchMetricsData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'uptime',
|
||||
fetchData: fetchUptimeData,
|
||||
hasData: async () => true,
|
||||
});
|
||||
return (
|
||||
<OverviewPage
|
||||
routeParams={{
|
||||
query: { rangeFrom: '2020-06-27T22:00:00.000Z', rangeTo: '2020-06-30T21:59:59.999Z' },
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
{ core: coreWithNewsFeed }
|
||||
)
|
||||
.add('No Data', () => {
|
||||
registerDataHandler({
|
||||
appName: 'apm',
|
||||
fetchData: async () => emptyAPMResponse,
|
||||
|
@ -415,6 +379,7 @@ storiesOf('app/Overview', module)
|
|||
fetchData: async () => emptyUptimeResponse,
|
||||
hasData: async () => true,
|
||||
});
|
||||
|
||||
return (
|
||||
<OverviewPage
|
||||
routeParams={{
|
||||
|
@ -422,156 +387,127 @@ storiesOf('app/Overview', module)
|
|||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
const coreAlertsThrowsError = ({
|
||||
...core,
|
||||
http: {
|
||||
...core.http,
|
||||
get: async () => {
|
||||
throw new Error('Error fetching Alerts data');
|
||||
})
|
||||
.add(
|
||||
'Fetch Data with Error',
|
||||
() => {
|
||||
registerDataHandler({
|
||||
appName: 'apm',
|
||||
fetchData: async () => {
|
||||
throw new Error('Error fetching APM data');
|
||||
},
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_logs',
|
||||
fetchData: async () => {
|
||||
throw new Error('Error fetching Logs data');
|
||||
},
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_metrics',
|
||||
fetchData: async () => {
|
||||
throw new Error('Error fetching Metric data');
|
||||
},
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'uptime',
|
||||
fetchData: async () => {
|
||||
throw new Error('Error fetching Uptime data');
|
||||
},
|
||||
hasData: async () => true,
|
||||
});
|
||||
return (
|
||||
<OverviewPage
|
||||
routeParams={{
|
||||
query: { rangeFrom: '2020-06-27T22:00:00.000Z', rangeTo: '2020-06-30T21:59:59.999Z' },
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
} as unknown) as AppMountContext['core'];
|
||||
storiesOf('app/Overview', module)
|
||||
.addDecorator((storyFn) => (
|
||||
<MemoryRouter>
|
||||
<PluginContext.Provider value={{ core: coreAlertsThrowsError }}>
|
||||
<EuiThemeProvider>{storyFn()}</EuiThemeProvider>
|
||||
</PluginContext.Provider>
|
||||
</MemoryRouter>
|
||||
))
|
||||
.add('fetch data with error', () => {
|
||||
unregisterAll();
|
||||
{ core: coreAlertsThrowsError }
|
||||
)
|
||||
.add(
|
||||
'hasData with Error and Alerts',
|
||||
() => {
|
||||
registerDataHandler({
|
||||
appName: 'apm',
|
||||
fetchData: fetchApmData,
|
||||
// @ts-ignore thows an error instead
|
||||
hasData: async () => {
|
||||
throw new Error('Error has data');
|
||||
},
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_logs',
|
||||
fetchData: fetchLogsData,
|
||||
// @ts-ignore thows an error instead
|
||||
hasData: async () => {
|
||||
throw new Error('Error has data');
|
||||
},
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_metrics',
|
||||
fetchData: fetchMetricsData,
|
||||
// @ts-ignore thows an error instead
|
||||
hasData: async () => {
|
||||
throw new Error('Error has data');
|
||||
},
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'uptime',
|
||||
fetchData: fetchUptimeData,
|
||||
// @ts-ignore thows an error instead
|
||||
hasData: async () => {
|
||||
throw new Error('Error has data');
|
||||
},
|
||||
});
|
||||
return (
|
||||
<OverviewPage
|
||||
routeParams={{
|
||||
query: { rangeFrom: '2020-06-27T22:00:00.000Z', rangeTo: '2020-06-30T21:59:59.999Z' },
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
{ core: coreWithAlerts }
|
||||
)
|
||||
.add('hasData with Error', () => {
|
||||
registerDataHandler({
|
||||
appName: 'apm',
|
||||
fetchData: async () => {
|
||||
throw new Error('Error fetching APM data');
|
||||
fetchData: fetchApmData,
|
||||
// @ts-ignore thows an error instead
|
||||
hasData: async () => {
|
||||
throw new Error('Error has data');
|
||||
},
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_logs',
|
||||
fetchData: async () => {
|
||||
throw new Error('Error fetching Logs data');
|
||||
fetchData: fetchLogsData,
|
||||
// @ts-ignore thows an error instead
|
||||
hasData: async () => {
|
||||
throw new Error('Error has data');
|
||||
},
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_metrics',
|
||||
fetchData: async () => {
|
||||
throw new Error('Error fetching Metric data');
|
||||
fetchData: fetchMetricsData,
|
||||
// @ts-ignore thows an error instead
|
||||
hasData: async () => {
|
||||
throw new Error('Error has data');
|
||||
},
|
||||
hasData: async () => true,
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'uptime',
|
||||
fetchData: async () => {
|
||||
throw new Error('Error fetching Uptime data');
|
||||
fetchData: fetchUptimeData,
|
||||
// @ts-ignore thows an error instead
|
||||
hasData: async () => {
|
||||
throw new Error('Error has data');
|
||||
},
|
||||
hasData: async () => true,
|
||||
});
|
||||
return (
|
||||
<OverviewPage
|
||||
routeParams={{
|
||||
query: { rangeFrom: '2020-06-27T22:00:00.000Z', rangeTo: '2020-06-30T21:59:59.999Z' },
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
storiesOf('app/Overview', module)
|
||||
.addDecorator((storyFn) => (
|
||||
<MemoryRouter>
|
||||
<PluginContext.Provider value={{ core: coreWithAlerts }}>
|
||||
<EuiThemeProvider>{storyFn()}</EuiThemeProvider>
|
||||
</PluginContext.Provider>
|
||||
</MemoryRouter>
|
||||
))
|
||||
.add('hasData with error and alerts', () => {
|
||||
unregisterAll();
|
||||
registerDataHandler({
|
||||
appName: 'apm',
|
||||
fetchData: fetchApmData,
|
||||
// @ts-ignore thows an error instead
|
||||
hasData: async () => {
|
||||
throw new Error('Error has data');
|
||||
},
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_logs',
|
||||
fetchData: fetchLogsData,
|
||||
// @ts-ignore thows an error instead
|
||||
hasData: async () => {
|
||||
throw new Error('Error has data');
|
||||
},
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_metrics',
|
||||
fetchData: fetchMetricsData,
|
||||
// @ts-ignore thows an error instead
|
||||
hasData: async () => {
|
||||
throw new Error('Error has data');
|
||||
},
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'uptime',
|
||||
fetchData: fetchUptimeData,
|
||||
// @ts-ignore thows an error instead
|
||||
hasData: async () => {
|
||||
throw new Error('Error has data');
|
||||
},
|
||||
});
|
||||
return (
|
||||
<OverviewPage
|
||||
routeParams={{
|
||||
query: { rangeFrom: '2020-06-27T22:00:00.000Z', rangeTo: '2020-06-30T21:59:59.999Z' },
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
storiesOf('app/Overview', module)
|
||||
.addDecorator((storyFn) => (
|
||||
<MemoryRouter>
|
||||
<PluginContext.Provider value={{ core }}>
|
||||
<EuiThemeProvider>{storyFn()}</EuiThemeProvider>
|
||||
</PluginContext.Provider>
|
||||
</MemoryRouter>
|
||||
))
|
||||
.add('hasData with error', () => {
|
||||
unregisterAll();
|
||||
registerDataHandler({
|
||||
appName: 'apm',
|
||||
fetchData: fetchApmData,
|
||||
// @ts-ignore thows an error instead
|
||||
hasData: async () => {
|
||||
throw new Error('Error has data');
|
||||
},
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_logs',
|
||||
fetchData: fetchLogsData,
|
||||
// @ts-ignore thows an error instead
|
||||
hasData: async () => {
|
||||
throw new Error('Error has data');
|
||||
},
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'infra_metrics',
|
||||
fetchData: fetchMetricsData,
|
||||
// @ts-ignore thows an error instead
|
||||
hasData: async () => {
|
||||
throw new Error('Error has data');
|
||||
},
|
||||
});
|
||||
registerDataHandler({
|
||||
appName: 'uptime',
|
||||
fetchData: fetchUptimeData,
|
||||
// @ts-ignore thows an error instead
|
||||
hasData: async () => {
|
||||
throw new Error('Error has data');
|
||||
},
|
||||
});
|
||||
return (
|
||||
<OverviewPage
|
||||
routeParams={{
|
||||
|
|
7
x-pack/plugins/security_solution/.storybook/main.js
Normal file
7
x-pack/plugins/security_solution/.storybook/main.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
module.exports = require('@kbn/storybook').defaultConfig;
|
|
@ -18,7 +18,7 @@ const withTheme = (storyFn: () => ReactNode) => (
|
|||
<ThemeProvider theme={() => ({ eui: euiLightVars, darkMode: true })}>{storyFn()}</ThemeProvider>
|
||||
);
|
||||
|
||||
storiesOf('components/AndOrBadge', module)
|
||||
storiesOf('Components/AndOrBadge', module)
|
||||
.addDecorator(withTheme)
|
||||
.add('and', () => <AndOrBadge type="and" />)
|
||||
.add('or', () => <AndOrBadge type="or" />)
|
||||
|
|
|
@ -16,7 +16,7 @@ addDecorator((storyFn) => (
|
|||
<ThemeProvider theme={() => ({ eui: euiLightVars, darkMode: false })}>{storyFn()}</ThemeProvider>
|
||||
));
|
||||
|
||||
storiesOf('Exceptions|BuilderLogicButtons', module)
|
||||
storiesOf('Exceptions/BuilderLogicButtons', module)
|
||||
.add('and/or buttons', () => {
|
||||
return (
|
||||
<BuilderLogicButtons
|
||||
|
|
|
@ -17,7 +17,7 @@ addDecorator((storyFn) => (
|
|||
<ThemeProvider theme={() => ({ eui: euiLightVars, darkMode: false })}>{storyFn()}</ThemeProvider>
|
||||
));
|
||||
|
||||
storiesOf('Components|ExceptionItem', module)
|
||||
storiesOf('Components/ExceptionItem', module)
|
||||
.add('with os', () => {
|
||||
const payload = getExceptionListItemSchemaMock();
|
||||
payload.description = '';
|
||||
|
|
|
@ -16,7 +16,7 @@ addDecorator((storyFn) => (
|
|||
<ThemeProvider theme={() => ({ eui: euiLightVars, darkMode: false })}>{storyFn()}</ThemeProvider>
|
||||
));
|
||||
|
||||
storiesOf('Components|ExceptionsViewerHeader', module)
|
||||
storiesOf('Components/ExceptionsViewerHeader', module)
|
||||
.add('loading', () => {
|
||||
return (
|
||||
<ExceptionsViewerHeader
|
||||
|
|
7
x-pack/plugins/ui_actions_enhanced/.storybook/main.js
Normal file
7
x-pack/plugins/ui_actions_enhanced/.storybook/main.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
module.exports = require('@kbn/storybook').defaultConfig;
|
7
x-pack/typings/index.d.ts
vendored
7
x-pack/typings/index.d.ts
vendored
|
@ -42,3 +42,10 @@ declare module '*.json' {
|
|||
// eslint-disable-next-line import/no-default-export
|
||||
export default json;
|
||||
}
|
||||
|
||||
// Storybook references this module. It's @ts-ignored in the codebase but when
|
||||
// built into its dist it strips that out. Add it here to avoid a type checking
|
||||
// error.
|
||||
//
|
||||
// See https://github.com/storybookjs/storybook/issues/11684
|
||||
declare module 'react-syntax-highlighter/dist/cjs/create-element';
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue