Skip to content
This repository has been archived by the owner on Nov 10, 2017. It is now read-only.

Commit

Permalink
Merge pull request #132 from Gongreg/master
Browse files Browse the repository at this point in the history
Add option to use storybook with more than one user
  • Loading branch information
Muhammed Thanish authored Mar 28, 2017
2 parents c9a1ff4 + 20eab47 commit b0275d5
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 25 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"shelljs": "^0.7.3",
"style-loader": "^0.13.1",
"url-loader": "^0.5.7",
"uuid": "^3.0.1",
"webpack": "^1.13.2",
"webpack-dev-middleware": "^1.8.3",
"webpack-hot-middleware": "^2.12.2"
Expand Down
30 changes: 23 additions & 7 deletions src/bin/storybook-start.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ import Server from '../server';
program
.option('-h, --host <host>', 'host to listen on')
.option('-p, --port <port>', 'port to listen on')
.option('-s, --secured', 'whether server is running on https')
.option('-c, --config-dir [dir-name]', 'storybook config directory')
.option('-e, --environment [environment]', 'DEVELOPMENT/PRODUCTION environment for webpack')
.option('-r, --reset-cache', 'reset react native packager')
.option('--skip-packager', 'run only storybook server')
.option('-i, --manual-id', 'allow multiple users to work with same storybook')
.parse(process.argv);

const projectDir = path.resolve();
Expand All @@ -18,7 +23,14 @@ if (program.host) {
listenAddr.push(program.host);
}

const server = new Server({projectDir, configDir});
const server = new Server({
projectDir,
configDir,
environment: program.environment,
manualId: program.manualId,
secured: program.secured
});

server.listen(...listenAddr, function (err) {
if (err) {
throw err;
Expand All @@ -27,11 +39,15 @@ server.listen(...listenAddr, function (err) {
console.info(`\nReact Native Storybook started on => ${address}\n`);
});

const projectRoots = configDir === projectDir ? [configDir] : [configDir, projectDir];
if (!program.skipPackager) {
const projectRoots = configDir === projectDir ? [configDir] : [configDir, projectDir];

// RN packager
shelljs.exec([
'node node_modules/react-native/local-cli/cli.js start',
`--projectRoots ${projectRoots.join(',')}`,
`--root ${projectDir}`,
].join(' '), {async: true});
shelljs.exec([
'node node_modules/react-native/local-cli/cli.js start',
`--projectRoots ${projectRoots.join(',')}`,
`--root ${projectDir}`,
program.resetCache && '--reset-cache'
].filter(x => x).join(' '), {async: true});

}
2 changes: 1 addition & 1 deletion src/manager/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ import renderStorybookUI from '@kadira/storybook-ui';
import Provider from './provider';

const rootEl = document.getElementById('root');
renderStorybookUI(rootEl, new Provider({ url: `ws://${location.host}` }));
renderStorybookUI(rootEl, new Provider({ url: location.host, options: window.storybookOptions}));
30 changes: 26 additions & 4 deletions src/manager/provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,25 @@ import React from 'react';
import { Provider } from '@kadira/storybook-ui';
import createChannel from '@kadira/storybook-channel-websocket';
import addons from '@kadira/storybook-addons';
import uuid from 'uuid';

export default class ReactProvider extends Provider {
constructor({ url }) {
constructor({ url: domain, options }) {
super();
this.options = options;
this.selection = null;
this.channel = addons.getChannel();

const secured = options.secured;
const websocketType = secured ? 'wss' : 'ws';
let url = websocketType + '://' + domain;
if (options.manualId) {
const pairedId = uuid().substr(-6);

this.pairedId = pairedId;
url += '/pairedId=' + this.pairedId;
}

if (!this.channel) {
this.channel = createChannel({ url });
addons.setChannel(this.channel);
Expand All @@ -22,10 +35,19 @@ export default class ReactProvider extends Provider {
this.selection = { kind, story };
this.channel.emit('setCurrentStory', { kind, story });
const renderPreview = addons.getPreview();
if (renderPreview) {
return renderPreview(kind, story);

const innerPreview = renderPreview ? renderPreview(kind, story) : null;

if (this.options.manualId) {
return (
<div>
Your ID: { this.pairedId }
{ innerPreview }
</div>
);
}
return null;

return innerPreview;
}

handleAPI(api) {
Expand Down
9 changes: 8 additions & 1 deletion src/preview/components/StoryView/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@ export default class StoryView extends Component {
constructor(props, ...args) {
super(props, ...args);
this.state = {storyFn: null, selection: {}};
this.props.events.on('story', this.selectStory.bind(this));

this.storyHandler = this.selectStory.bind(this);

this.props.events.on('story', this.storyHandler);
}

componentWillUnmount() {
this.props.events.removeListener('story', this.storyHandler);
}

selectStory(storyFn, selection) {
Expand Down
17 changes: 13 additions & 4 deletions src/preview/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,20 @@ export default class Preview {
return () => {
let webUrl = null;
let channel = addons.getChannel();
if (!channel) {
if (params.resetStorybook || !channel) {
const host = params.host || 'localhost';
const port = params.port || 7007;
const url = `ws://${host}:${port}`;
webUrl = `http://${host}:${port}`;

const port = params.port !== false
? ':' + (params.port || 7007)
: '';

const query = params.query || '';
const secured = params.secured;
const websocketType = secured ? 'wss' : 'ws';
const httpType = secured ? 'https' : 'http';

const url = `${websocketType}://${host}${port}/${query}`;
webUrl = `${httpType}://${host}${port}`;
channel = createChannel({ url });
addons.setChannel(channel);
}
Expand Down
3 changes: 2 additions & 1 deletion src/server/config/webpack.config.prod.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ const config = {
devtool: '#cheap-module-source-map',
entry: entries,
output: {
path: path.join(__dirname, 'dist'),
filename: 'static/[name].bundle.js',
// Here we set the publicPath to ''.
// This allows us to deploy storybook into subpaths like GitHub pages.
// This works with css and image loaders too.
// This is working for storybook since, we don't use pushState urls and
// relative URLs works always.
publicPath: '',
publicPath: '/',
},
plugins: [
new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"production"' }),
Expand Down
5 changes: 4 additions & 1 deletion src/server/index.html.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import url from 'url';

export default function (publicPath, settings) {
export default function (publicPath, options) {
return `
<!DOCTYPE html>
<html>
Expand Down Expand Up @@ -40,6 +40,9 @@ export default function (publicPath, settings) {
</head>
<body style="margin: 0;">
<div id="root"></div>
<script>
window.storybookOptions = ${JSON.stringify(options)};
</script>
<script src="${url.resolve(publicPath, 'static/manager.bundle.js')}"></script>
</body>
</html>
Expand Down
20 changes: 18 additions & 2 deletions src/server/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import express from 'express';
import querystring from 'querystring';
import http from 'http';
import ws from 'ws';
import storybook from './middleware';
Expand All @@ -8,15 +9,30 @@ export default class Server {
this.options = options;
this.httpServer = http.createServer();
this.expressApp = express();
this.expressApp.use(storybook(options.projectDir, options.configDir));
this.expressApp.use(storybook(options));
this.httpServer.on('request', this.expressApp);
this.wsServer = ws.Server({server: this.httpServer});
this.wsServer.on('connection', s => this.handleWS(s));
}

handleWS(socket) {

if (this.options.manualId) {
const params = socket.upgradeReq && socket.upgradeReq.url
? querystring.parse(socket.upgradeReq.url.substr(1))
: {};

if (params.pairedId) {
socket.pairedId = params.pairedId;
}
}

socket.on('message', data => {
this.wsServer.clients.forEach(c => c.send(data));
this.wsServer.clients.forEach(c => {
if (!this.options.manualId || (socket.pairedId && socket.pairedId === c.pairedId)) {
return c.send(data);
}
});
});
}

Expand Down
18 changes: 14 additions & 4 deletions src/server/middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import webpack from 'webpack';
import webpackDevMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';
import baseConfig from './config/webpack.config';
import baseProductionConfig from './config/webpack.config.prod';
import loadConfig from './config';
import getIndexHtml from './index.html';

Expand All @@ -20,10 +21,13 @@ function getMiddleware(configDir) {
return function () {};
}

export default function (projectDir, configDir) {
export default function ({projectDir, configDir, ...options}) {
// Build the webpack configuration using the `baseConfig`
// custom `.babelrc` file and `webpack.config.js` files
const config = loadConfig('DEVELOPMENT', baseConfig, projectDir, configDir);
const environment = options.environment || 'DEVELOPMENT';
const isProd = environment === 'PRODUCTION';
const currentWebpackConfig = isProd ? baseProductionConfig : baseConfig;
const config = loadConfig(environment, currentWebpackConfig, projectDir, configDir);

// remove the leading '/'
let publicPath = config.output.publicPath;
Expand All @@ -43,10 +47,16 @@ export default function (projectDir, configDir) {
middlewareFn(router);

router.use(webpackDevMiddleware(compiler, devMiddlewareOptions));
router.use(webpackHotMiddleware(compiler));

if (!isProd) {
router.use(webpackHotMiddleware(compiler));
}

router.get('/', function (req, res) {
res.send(getIndexHtml(publicPath));
res.send(getIndexHtml(publicPath, {
manualId: options.manualId,
secured: options.secured,
}));
});

return router;
Expand Down

0 comments on commit b0275d5

Please sign in to comment.