├── .gitignore ├── config ├── env.js ├── jest │ ├── CSSStub.js │ └── FileStub.js ├── paths.js ├── polyfills.js ├── storybook │ ├── config.js │ ├── dummy-child_process.js │ ├── dummy-electron.js │ └── webpack.config.js ├── webpack.config.dev.js └── webpack.config.prod.js ├── electron.js ├── license.md ├── package.json ├── public ├── about.html ├── index.html ├── loader.css ├── logo.png └── spinner.svg ├── readme.md ├── resources ├── icon.icns └── icon.ico ├── scripts ├── build.js ├── start.js └── test.js ├── src ├── About.css ├── About.js ├── App.css ├── App.js ├── Button.css ├── Button.js ├── CreateModal.css ├── CreateModal.js ├── CreateModal │ ├── Config.js │ ├── Type.css │ └── Type.js ├── Form │ ├── FixedValue.css │ ├── FixedValue.js │ └── Table │ │ ├── index.css │ │ └── index.js ├── Header.css ├── Header.js ├── Icon.js ├── Installer.css ├── Installer.js ├── Installer.scss ├── Installer │ ├── DownloadStatus.js │ ├── Downloader.css │ ├── Downloader.js │ ├── Downloads.css │ ├── Downloads.js │ ├── ImportBoxes.css │ ├── ImportBoxes.js │ ├── Ready.css │ ├── Ready.js │ ├── Vagrant.png │ ├── VirtualBox.png │ └── Welcome.js ├── ItemList.css ├── ItemList.js ├── KeyHandler.css ├── KeyHandler.js ├── LoadingIndicator.css ├── LoadingIndicator.js ├── MachineActions.css ├── MachineActions.js ├── MachineDetails.js ├── MachineDetails.scss ├── MachineItem.css ├── MachineItem.js ├── MachineList.css ├── MachineList.js ├── MachineSettings.css ├── MachineSettings.js ├── Modal.css ├── Modal.js ├── Root.js ├── Settings.css ├── Settings.js ├── Splash.js ├── Step.js ├── Steps.js ├── Steps.scss ├── Terminal.js ├── Terminal.scss ├── Toolbar.js ├── about-entry.js ├── index.js ├── lib │ ├── actions.js │ ├── actions │ │ ├── cloneChassis.js │ │ ├── install.js │ │ ├── loadConfig.js │ │ ├── runCommand.js │ │ ├── updateBoxStatus.js │ │ ├── updateConfig.js │ │ └── updateGlobalStatus.js │ ├── configure.js │ ├── createStore.js │ ├── download.js │ ├── formatPath.js │ ├── keys.js │ ├── openBrowser.js │ ├── reducers.js │ ├── reducers │ │ ├── boxes.js │ │ ├── installer.js │ │ ├── preferences.js │ │ ├── terminal.js │ │ ├── ui.js │ │ └── vagrant.js │ ├── spawn-sync.js │ └── vagrant │ │ ├── Machine.js │ │ └── parser.js └── logo.svg └── stories ├── Button.js ├── Header.js ├── MachineActions.js ├── MachineItem.js ├── MachineSettings.js └── Terminal.js /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | 6 | # testing 7 | coverage 8 | 9 | # production 10 | build 11 | dist 12 | 13 | # misc 14 | .DS_Store 15 | .env 16 | npm-debug.log 17 | -------------------------------------------------------------------------------- /config/env.js: -------------------------------------------------------------------------------- 1 | // Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be 2 | // injected into the application via DefinePlugin in Webpack configuration. 3 | 4 | var REACT_APP = /^REACT_APP_/i; 5 | 6 | function getClientEnvironment(publicUrl) { 7 | return Object 8 | .keys(process.env) 9 | .filter(key => REACT_APP.test(key)) 10 | .reduce((env, key) => { 11 | env['process.env.' + key] = JSON.stringify(process.env[key]); 12 | return env; 13 | }, { 14 | // Useful for determining whether we’re running in production mode. 15 | // Most importantly, it switches React into the correct mode. 16 | 'process.env.NODE_ENV': JSON.stringify( 17 | process.env.NODE_ENV || 'development' 18 | ), 19 | // Useful for resolving the correct path to static assets in `public`. 20 | // For example, . 21 | // This should only be used as an escape hatch. Normally you would put 22 | // images into the `src` and `import` them in code to get their paths. 23 | 'process.env.PUBLIC_URL': JSON.stringify(publicUrl) 24 | }); 25 | } 26 | 27 | module.exports = getClientEnvironment; 28 | -------------------------------------------------------------------------------- /config/jest/CSSStub.js: -------------------------------------------------------------------------------- 1 | module.exports = {}; 2 | -------------------------------------------------------------------------------- /config/jest/FileStub.js: -------------------------------------------------------------------------------- 1 | module.exports = "test-file-stub"; 2 | -------------------------------------------------------------------------------- /config/paths.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var fs = require('fs'); 3 | 4 | // Make sure any symlinks in the project folder are resolved: 5 | // https://github.com/facebookincubator/create-react-app/issues/637 6 | var appDirectory = fs.realpathSync(process.cwd()); 7 | function resolveApp(relativePath) { 8 | return path.resolve(appDirectory, relativePath); 9 | } 10 | 11 | // We support resolving modules according to `NODE_PATH`. 12 | // This lets you use absolute paths in imports inside large monorepos: 13 | // https://github.com/facebookincubator/create-react-app/issues/253. 14 | 15 | // It works similar to `NODE_PATH` in Node itself: 16 | // https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders 17 | 18 | // We will export `nodePaths` as an array of absolute paths. 19 | // It will then be used by Webpack configs. 20 | // Jest doesn’t need this because it already handles `NODE_PATH` out of the box. 21 | 22 | var nodePaths = (process.env.NODE_PATH || '') 23 | .split(process.platform === 'win32' ? ';' : ':') 24 | .filter(Boolean) 25 | .map(resolveApp); 26 | 27 | // config after eject: we're in ./config/ 28 | module.exports = { 29 | appBuild: resolveApp('build'), 30 | appPublic: resolveApp('public'), 31 | appHtml: resolveApp('public/index.html'), 32 | appIndexJs: resolveApp('src/index.js'), 33 | appAboutHtml: resolveApp('public/about.html'), 34 | appAboutJs: resolveApp('src/about-entry.js'), 35 | appPackageJson: resolveApp('package.json'), 36 | appSrc: resolveApp('src'), 37 | testsSetup: resolveApp('src/setupTests.js'), 38 | appNodeModules: resolveApp('node_modules'), 39 | ownNodeModules: resolveApp('node_modules'), 40 | nodePaths: nodePaths 41 | }; 42 | -------------------------------------------------------------------------------- /config/polyfills.js: -------------------------------------------------------------------------------- 1 | if (typeof Promise === 'undefined') { 2 | // Rejection tracking prevents a common issue where React gets into an 3 | // inconsistent state due to an error, but it gets swallowed by a Promise, 4 | // and the user has no idea what causes React's erratic future behavior. 5 | require('promise/lib/rejection-tracking').enable(); 6 | window.Promise = require('promise/lib/es6-extensions.js'); 7 | } 8 | 9 | // fetch() polyfill for making API calls. 10 | require('whatwg-fetch'); 11 | 12 | // Object.assign() is commonly used with React. 13 | // It will use the native implementation if it's present and isn't buggy. 14 | Object.assign = require('object-assign'); 15 | -------------------------------------------------------------------------------- /config/storybook/config.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Provider } from 'react-redux'; 3 | import { createStore } from 'redux'; 4 | import { addDecorator, configure } from '@storybook/react'; 5 | 6 | // Load CSS 7 | import 'font-awesome/css/font-awesome.css'; 8 | import '../../public/loader.css'; 9 | 10 | const require_story = require.context( '../../stories', true, /\.js$/ ) 11 | 12 | function loadStories() { 13 | require_story.keys().forEach( filename => require_story( filename ) ); 14 | } 15 | 16 | // Add dummy store for KeyHandler 17 | const INITIAL_STATE = { 18 | preferences: {}, 19 | }; 20 | addDecorator( story => ( 21 | state, INITIAL_STATE ) }> 22 | { story() } 23 | 24 | )); 25 | 26 | // Add dummy handler. 27 | window.keyHandler = { 28 | register: () => {}, 29 | unregister: () => {}, 30 | }; 31 | 32 | configure( loadStories, module ); 33 | -------------------------------------------------------------------------------- /config/storybook/dummy-child_process.js: -------------------------------------------------------------------------------- 1 | export const spawn = () => { 2 | throw new Error( 'Not running in Electron context.' ) 3 | }; 4 | -------------------------------------------------------------------------------- /config/storybook/dummy-electron.js: -------------------------------------------------------------------------------- 1 | export const shell = { 2 | openExternal: url => console.log( url ), 3 | }; 4 | -------------------------------------------------------------------------------- /config/storybook/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require( 'path' ); 2 | const genDefaultConfig = require('@storybook/react/dist/server/config/defaults/webpack.config.js'); 3 | 4 | module.exports = (baseConfig, env) => { 5 | const config = genDefaultConfig(baseConfig, env); 6 | 7 | // Shim in our fake electron modules. 8 | config.resolve.alias.child_process = path.resolve( __dirname, 'dummy-child_process.js' ); 9 | config.resolve.alias.electron = path.resolve( __dirname, 'dummy-electron.js' ); 10 | 11 | // Add SCSS processing. 12 | // console.log( config ); 13 | config.module.rules.push({ 14 | test: /\.scss$/, 15 | use: [ 16 | { 17 | loader: "style-loader" // creates style nodes from JS strings 18 | }, 19 | { 20 | loader: "css-loader" // translates CSS into CommonJS 21 | }, 22 | { 23 | loader: "sass-loader" // compiles Sass to CSS 24 | }, 25 | ], 26 | // loader: ExtractTextPlugin.extract('style', 'css!sass') 27 | }); 28 | 29 | return config; 30 | }; 31 | -------------------------------------------------------------------------------- /config/webpack.config.dev.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var autoprefixer = require('autoprefixer'); 3 | var webpack = require('webpack'); 4 | var findCacheDir = require('find-cache-dir'); 5 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 6 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 7 | var CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin'); 8 | var InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin'); 9 | var WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin'); 10 | var getClientEnvironment = require('./env'); 11 | var paths = require('./paths'); 12 | 13 | // Webpack uses `publicPath` to determine where the app is being served from. 14 | // In development, we always serve from the root. This makes config easier. 15 | var publicPath = '/'; 16 | // `publicUrl` is just like `publicPath`, but we will provide it to our app 17 | // as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript. 18 | // Omit trailing shlash as %PUBLIC_PATH%/xyz looks better than %PUBLIC_PATH%xyz. 19 | var publicUrl = ''; 20 | // Get enrivonment variables to inject into our app. 21 | var env = getClientEnvironment(publicUrl); 22 | 23 | // This is the development configuration. 24 | // It is focused on developer experience and fast rebuilds. 25 | // The production configuration is different and lives in a separate file. 26 | module.exports = { 27 | // This makes the bundle appear split into separate modules in the devtools. 28 | // We don't use source maps here because they can be confusing: 29 | // https://github.com/facebookincubator/create-react-app/issues/343#issuecomment-237241875 30 | // You may want 'cheap-module-source-map' instead if you prefer source maps. 31 | devtool: 'eval', 32 | 33 | // Add Electron as the target. 34 | target: 'electron-renderer', 35 | 36 | // These are the "entry points" to our application. 37 | // This means they will be the "root" imports that are included in JS bundle. 38 | // The first two entry points enable "hot" CSS and auto-refreshes for JS. 39 | entry: { 40 | main: [ 41 | // Include an alternative client for WebpackDevServer. A client's job is to 42 | // connect to WebpackDevServer by a socket and get notified about changes. 43 | // When you save a file, the client will either apply hot updates (in case 44 | // of CSS changes), or refresh the page (in case of JS changes). When you 45 | // make a syntax error, this client will display a syntax error overlay. 46 | // Note: instead of the default WebpackDevServer client, we use a custom one 47 | // to bring better experience for Create React App users. You can replace 48 | // the line below with these two lines if you prefer the stock client: 49 | // require.resolve('webpack-dev-server/client') + '?/', 50 | // require.resolve('webpack/hot/dev-server'), 51 | require.resolve('react-dev-utils/webpackHotDevClient'), 52 | // We ship a few polyfills by default: 53 | require.resolve('./polyfills'), 54 | // Finally, this is your app's code: 55 | paths.appIndexJs 56 | // We include the app code last so that if there is a runtime error during 57 | // initialization, it doesn't blow up the WebpackDevServer client, and 58 | // changing JS code would still trigger a refresh. 59 | ], 60 | about: [ 61 | require.resolve('react-dev-utils/webpackHotDevClient'), 62 | require.resolve('./polyfills'), 63 | paths.appAboutJs, 64 | ] 65 | }, 66 | output: { 67 | // Next line is not used in dev but WebpackDevServer crashes without it: 68 | path: paths.appBuild, 69 | // Add /* filename */ comments to generated require()s in the output. 70 | pathinfo: true, 71 | // This does not produce a real file. It's just the virtual path that is 72 | // served by WebpackDevServer in development. This is the JS bundle 73 | // containing code from all our entry points, and the Webpack runtime. 74 | filename: 'static/js/[name].js', 75 | // This is the URL that app is served from. We use "/" in development. 76 | publicPath: publicPath 77 | }, 78 | resolve: { 79 | // This allows you to set a fallback for where Webpack should look for modules. 80 | // We read `NODE_PATH` environment variable in `paths.js` and pass paths here. 81 | // We use `fallback` instead of `root` because we want `node_modules` to "win" 82 | // if there any conflicts. This matches Node resolution mechanism. 83 | // https://github.com/facebookincubator/create-react-app/issues/253 84 | fallback: paths.nodePaths, 85 | // These are the reasonable defaults supported by the Node ecosystem. 86 | // We also include JSX as a common component filename extension to support 87 | // some tools, although we do not recommend using it, see: 88 | // https://github.com/facebookincubator/create-react-app/issues/290 89 | extensions: ['.js', '.json', '.jsx', ''], 90 | alias: { 91 | // Support React Native Web 92 | // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/ 93 | 'react-native': 'react-native-web', 94 | 'spawn-sync': path.join( paths.appSrc, 'lib', 'spawn-sync.js' ), 95 | } 96 | }, 97 | 98 | module: { 99 | // First, run the linter. 100 | // It's important to do this before Babel processes the JS. 101 | preLoaders: [ 102 | { 103 | test: /\.(js|jsx)$/, 104 | loader: 'eslint', 105 | include: paths.appSrc, 106 | } 107 | ], 108 | loaders: [ 109 | // Process JS with Babel. 110 | { 111 | test: /\.(js|jsx)$/, 112 | include: paths.appSrc, 113 | loader: 'babel', 114 | query: { 115 | 116 | // This is a feature of `babel-loader` for webpack (not Babel itself). 117 | // It enables caching results in ./node_modules/.cache/react-scripts/ 118 | // directory for faster rebuilds. We use findCacheDir() because of: 119 | // https://github.com/facebookincubator/create-react-app/issues/483 120 | cacheDirectory: findCacheDir({ 121 | name: 'react-scripts' 122 | }) 123 | } 124 | }, 125 | // "postcss" loader applies autoprefixer to our CSS. 126 | // "css" loader resolves paths in CSS and adds assets as dependencies. 127 | // "style" loader turns CSS into JS modules that inject