Replace require.js loader/r.js builder with webpack

Webpack is much more powerful than r.js and opens path
to further improvements in testing, build speed,
developer convenience, ES2015, etc.

Implements blueprint webpack

Change-Id: I18a3b74db243f29e5dacb004569d66463f4ab16d
This commit is contained in:
Vitaly Kramskikh 2015-08-29 13:49:19 -05:00
parent aa6e317fb1
commit ac33818194
59 changed files with 6919 additions and 2295 deletions

View File

@ -98,10 +98,12 @@
"env": {
"browser": true,
"node": true,
"mocha": true,
"amd": true
},
"globals": {
"app": false,
"requirejs": false
"assert": false,
"sinon": false
}
}

View File

@ -21,77 +21,19 @@ var argv = require('minimist')(process.argv.slice(2));
var fs = require('fs');
var path = require('path');
var glob = require('glob');
var spawn = require('child_process').spawn;
var rimraf = require('rimraf');
var es = require('event-stream');
var _ = require('lodash');
var webpack = require('webpack');
var gulp = require('gulp');
var gutil = require('gulp-util');
var shell = require('gulp-shell');
var runSequence = require('run-sequence');
var filter = require('gulp-filter');
var react = require('gulp-react');
var less = require('gulp-less');
var autoprefixer = require('gulp-autoprefixer');
var replace = require('gulp-replace');
var jison = require('gulp-jison');
var lintspaces = require('gulp-lintspaces');
var jscs = require('gulp-jscs');
var jscsConfig = JSON.parse(fs.readFileSync('./.jscsrc'));
var intermediate = require('gulp-intermediate');
var rjs = require('requirejs');
var rjsConfig = _.merge(rjs('static/config.js'), {
baseUrl: '.',
appDir: 'static',
optimize: 'uglify2',
optimizeCss: 'standard',
generateSourceMaps: true,
preserveLicenseComments: false, // required for generateSourceMaps
wrapShim: true,
pragmas: {
compressed: true
},
map: {
'*': {
JSXTransformer: 'empty:'
}
},
paths: {
react: 'vendor/npm/react/dist/react-with-addons.min'
},
stubModules: ['jsx'],
modules: [
{
name: 'main',
exclude: ['require-css/normalize']
}
]
});
var jsFilter = filter('**/*.js');
var jsxFilter = filter('**/*.jsx');
var lessFilter = filter('**/*.less');
var indexFilter = filter('index.html');
var buildSourceFilter = filter([
'**',
'!tests/**'
]);
var buildResultFilter = filter([
'index.html',
'main.js',
'main.js.map',
'vendor/npm/requirejs/require.js',
'vendor/npm/requirejs/require.js.map',
'styles/*.css',
'favicon.ico',
'img/**',
'**/*.+(ttf|eot|svg|woff|woff2)',
'plugins/**'
]);
var validateTranslations = require('./gulp/i18n').validate;
gulp.task('i18n:validate', function() {
@ -100,20 +42,6 @@ gulp.task('i18n:validate', function() {
validateTranslations(tranlations, locales);
});
gulp.task('copy-main', function() {
var config = JSON.parse(fs.readFileSync('package.json'));
var streams = _.map(config.mainFiles, function(files, package) {
if (!(package in config.dependencies) && !(package in config.devDependencies)) {
throw new Error(package + ' is not a dependency');
}
return _.map(_.isArray(files) ? files : [files], function(file) {
return gulp.src('node_modules/' + package + '/' + file, {base: 'node_modules'})
.pipe(gulp.dest('static/vendor/npm/'));
});
});
return es.merge(_.flatten(streams));
});
var selenium = require('selenium-standalone');
var seleniumProcess = null;
function shutdownSelenium() {
@ -148,6 +76,14 @@ gulp.task('selenium', ['selenium:fetch'], function(cb) {
);
});
gulp.task('karma', function(cb) {
var Server = require('karma').Server;
new Server({
configFile: __dirname + '/karma.config.js',
browsers: [argv.browser || 'firefox']
}, cb).start();
});
function runIntern(params) {
return function() {
var baseDir = 'static';
@ -175,11 +111,10 @@ function runIntern(params) {
};
}
gulp.task('intern:unit', runIntern({suites: argv.suites || 'static/tests/unit/**/*.js'}));
gulp.task('intern:functional', runIntern({functionalSuites: argv.suites || 'static/tests/functional/**/test_*.js'}));
gulp.task('unit-tests', function(cb) {
runSequence('selenium', 'intern:unit', function(err) {
runSequence('selenium', 'karma', function(err) {
shutdownSelenium();
cb(err);
});
@ -201,6 +136,7 @@ gulp.task('jison', function() {
var jsFiles = [
'static/**/*.js',
'static/**/*.jsx',
'!static/build/**',
'!static/vendor/**',
'!static/expression/parser.js',
'static/tests/**/*.js'
@ -208,22 +144,26 @@ var jsFiles = [
var styleFiles = [
'static/**/*.less',
'static/**/*.css',
'!static/build/**',
'!static/vendor/**'
];
gulp.task('jscs:fix', function() {
var jscs = require('gulp-jscs');
var jscsConfig = JSON.parse(fs.readFileSync('./.jscsrc'));
return gulp.src(jsFiles, {base: '.'})
.pipe(jscs(_.extend({fix: true}, jscsConfig)))
.pipe(gulp.dest('.'));
});
gulp.task('jscs', function() {
var jscs = require('gulp-jscs');
var jscsConfig = JSON.parse(fs.readFileSync('./.jscsrc'));
return gulp.src(jsFiles)
.pipe(jscs(jscsConfig));
});
gulp.task('eslint', function() {
// FIXME(vkramskikh): move to top after fixing packaging issues
var eslint = require('gulp-eslint');
var eslintConfig = JSON.parse(fs.readFileSync('./.eslintrc'));
return gulp.src(jsFiles)
@ -240,6 +180,7 @@ var lintspacesConfig = {
};
gulp.task('lintspaces:js', function() {
var lintspaces = require('gulp-lintspaces');
return gulp.src(jsFiles)
.pipe(lintspaces(_.extend({}, lintspacesConfig, {
ignores: ['js-comments'],
@ -249,6 +190,7 @@ gulp.task('lintspaces:js', function() {
});
gulp.task('lintspaces:styles', function() {
var lintspaces = require('gulp-lintspaces');
return gulp.src(styleFiles)
.pipe(lintspaces(_.extend({}, lintspacesConfig, {
ignores: ['js-comments'],
@ -265,46 +207,95 @@ gulp.task('lint', [
'lintspaces:styles'
]);
gulp.task('rjs', function() {
var targetDir = argv['static-dir'] || '/tmp/static_compressed';
rimraf.sync(targetDir);
var WEBPACK_STATS_OPTIONS = {
colors: true,
hash: false,
version: false,
assets: false,
chunks: false
};
return gulp.src(['static/**'])
.pipe(jsxFilter)
.pipe(react())
.pipe(jsxFilter.restore())
.pipe(lessFilter)
.pipe(less())
.pipe(autoprefixer())
.pipe(lessFilter.restore())
.pipe(jsFilter)
// use CSS loader instead LESS loader - styles are precompiled
.pipe(replace(/less!/g, 'require-css/css!'))
// remove explicit calls to JSX loader plugin
.pipe(replace(/jsx!/g, ''))
.pipe(jsFilter.restore())
.pipe(indexFilter)
.pipe(replace('__CACHE_BUST__', Date.now()))
.pipe(indexFilter.restore())
.pipe(buildSourceFilter)
.pipe(intermediate({output: '_build'}, function(tempDir, cb) {
var configFile = path.join(tempDir, 'build.json');
rjsConfig.appDir = tempDir;
rjsConfig.dir = path.join(tempDir, '_build');
fs.createWriteStream(configFile).write(JSON.stringify(rjsConfig));
gulp.task('dev-server', function() {
var devServerHost = argv['dev-server-host'] || '127.0.0.1';
var devServerPort = argv['dev-server-port'] || 8080;
var devServerUrl = 'http://' + devServerHost + ':' + devServerPort;
var nailgunHost = argv['nailgun-host'] || '127.0.0.1';
var nailgunPort = argv['nailgun-port'] || 8000;
var nailgunUrl = 'http://' + nailgunHost + ':' + nailgunPort;
var hotReload = !argv['no-hot'];
var rjs = spawn('./node_modules/.bin/r.js', ['-o', configFile]);
rjs.stdout.on('data', function(data) {
_(data.toString().split('\n')).compact().each(_.ary(gutil.log, 1)).value();
});
rjs.on('close', cb);
}))
.pipe(buildResultFilter)
.pipe(gulp.dest(targetDir));
var config = require('./webpack.config');
config.entry.push('webpack-dev-server/client?' + devServerUrl);
if (hotReload) {
config.entry.push('webpack/hot/dev-server');
config.plugins.push(new webpack.HotModuleReplacementPlugin());
config.plugins.push(new webpack.NoErrorsPlugin());
}
var WebpackDevServer = require('webpack-dev-server');
var options = {
hot: hotReload,
stats: WEBPACK_STATS_OPTIONS,
proxy: [
{path: '/', target: devServerUrl, rewrite: function(req) {
req.url = '/static/index.html';
}},
{path: /^\/(?!static\/).+/, target: nailgunUrl}
]
};
_.extend(options, config.output);
new WebpackDevServer(webpack(config), options).listen(devServerPort, devServerHost, function(err) {
if (err) throw err;
gutil.log('Development server started at ' + devServerUrl);
});
});
gulp.task('build', function(cb) {
runSequence('copy-main', 'rjs', cb);
var sourceDir = path.resolve('static');
var targetDir = argv['static-dir'] ? path.resolve(argv['static-dir']) : sourceDir;
var config = require('./webpack.config');
config.output.path = path.join(targetDir, 'build');
if (!argv.dev) {
config.plugins.push(
new webpack.DefinePlugin({'process.env': {NODE_ENV: '"production"'}}),
new webpack.optimize.DedupePlugin()
);
}
if (argv.uglify) {
config.plugins.push(
new webpack.optimize.UglifyJsPlugin({compress: {warnings: false}})
);
}
rimraf.sync(config.output.path);
webpack(config).run(function(err, stats) {
if (err) return cb(err);
gutil.log(stats.toString(WEBPACK_STATS_OPTIONS));
if (stats.hasErrors()) return cb('Build failed');
if (targetDir != sourceDir) {
var indexFilter = filter('index.html');
gulp
.src([
'index.html',
'favicon.ico',
'img/loader-bg.svg',
'img/loader-logo.svg',
'styles/layout.css'
], {cwd: sourceDir, base: sourceDir})
.pipe(indexFilter)
.pipe(replace('__CACHE_BUST__', Date.now()))
.pipe(indexFilter.restore())
.pipe(gulp.dest(targetDir))
.on('end', cb);
} else {
cb();
}
});
});
gulp.task('default', ['build']);

52
karma.config.js Normal file
View File

@ -0,0 +1,52 @@
/*eslint-disable strict*/
var webpackConfig = require('./webpack.config');
module.exports = function(config) {
config.set({
browsers: ['firefox'],
files: [
'static/tests/unit/**/*.js'
],
frameworks: [
'chai',
'mocha',
'sinon'
],
plugins: [
'karma-webdriver-launcher',
'karma-chai',
'karma-mocha',
'karma-sinon',
'karma-webpack'
],
preprocessors: {
'static/tests/unit/**/*.js': ['webpack']
},
reporters: ['dots'],
singleRun: true,
client: {
mocha: {
ui: 'tdd'
}
},
customLaunchers: {
chrome: {
base: 'WebDriver',
browserName: 'chrome'
},
firefox: {
base: 'WebDriver',
browserName: 'firefox'
},
phantomjs: {
base: 'WebDriver',
browserName: 'phantomjs'
}
},
webpack: webpackConfig,
webpackMiddleware: {
noInfo: true
}
});
};

8148
npm-shrinkwrap.json generated

File diff suppressed because it is too large Load Diff

View File

@ -5,93 +5,63 @@
"type": "git",
"url": "https://github.com/openstack/fuel-web.git"
},
"scripts": {
"install": "./node_modules/.bin/gulp copy-main"
},
"dependencies": {
"autoprefixer": "5.2.0",
"babel-core": "5.8.23",
"babel-loader": "5.3.2",
"backbone": "1.2.1",
"backbone.stickit": "0.9.2",
"bootstrap": "3.3.4",
"classnames": "1.1.4",
"css-loader": "0.17.0",
"exports-loader": "0.6.2",
"expose-loader": "0.7.0",
"file-loader": "0.8.4",
"gulp": "3.8.11",
"gulp-filter": "2.0.1",
"gulp-jison": "1.2.0",
"gulp-replace": "0.5.3",
"gulp-util": "3.0.4",
"i18next": "1.7.1",
"imports-loader": "0.6.4",
"jquery": "1.11.3",
"js-cookie": "1.5.1",
"json-loader": "0.5.3",
"less": "2.4.0",
"less-loader": "2.2.1",
"lodash": "3.9.3",
"minimist": "1.1.1",
"open-sans-fontface": "1.4.0",
"postcss-loader": "0.5.1",
"raw-loader": "0.5.1",
"react": "0.13.3",
"react-dnd": "1.1.3",
"require-css": "0.1.8",
"requirejs": "2.1.20",
"requirejs-plugins": "1.0.2"
"rimraf": "2.2.8",
"run-sequence": "1.0.2",
"style-loader": "0.12.4",
"webpack": "1.12.0",
"uglify-js": "2.4.21"
},
"devDependencies": {
"es5-shim": "~4.1.11",
"eslint-plugin-react": "~3.1.0",
"chai": "~3.2.0",
"es5-shim": "4.1.11",
"eslint-plugin-react": "3.1.0",
"esprima-fb": "13001.1001.0-dev-harmony-fb",
"event-stream": "~3.3.1",
"glob": "~5.0.5",
"gulp": "~3.8.11",
"gulp-autoprefixer": "~2.1.0",
"gulp-eslint": "~1.0.0",
"gulp-filter": "~2.0.1",
"gulp-intermediate": "~3.0.1",
"gulp-jison": "~1.2.0",
"gulp-jscs": "~1.6.0",
"gulp-less": "~3.0.2",
"gulp-lintspaces": "~0.3.1",
"gulp-react": "~3.0.1",
"gulp-replace": "~0.5.3",
"gulp-shell": "~0.4.1",
"gulp-util": "~3.0.4",
"intern": "~2.2.2",
"minimist": "~1.1.1",
"rimraf": "~2.2.8",
"run-sequence": "~1.0.2",
"gulp-eslint": "1.0.0",
"gulp-jscs": "1.6.0",
"gulp-lintspaces": "0.3.1",
"gulp-shell": "0.4.1",
"intern": "2.2.2",
"karma": "~0.13.9",
"karma-chai": "~0.1.0",
"karma-mocha": "~0.2.0",
"karma-sinon": "~1.0.4",
"karma-webdriver-launcher": "1.0.0",
"karma-webpack": "~1.7.0",
"mocha": "~2.3.2",
"selenium-standalone": "~4.4.0",
"sinon": "~1.15.3",
"uglify-js": "~2.4.21"
},
"mainFiles": {
"backbone": "backbone.js",
"backbone.stickit": "backbone.stickit.js",
"bootstrap": [
"dist/js/bootstrap.js",
"dist/css/bootstrap.css",
"dist/css/bootstrap.css.map",
"dist/fonts/*"
],
"classnames": "index.js",
"es5-shim": "es5-shim.js",
"i18next": "lib/dep/i18next-1.7.1.js",
"jquery": "dist/jquery.js",
"js-cookie": "src/js.cookie.js",
"less": "dist/less.js",
"lodash": "index.js",
"open-sans-fontface": [
"./open-sans.css",
"./fonts/**/*"
],
"react": [
"dist/JSXTransformer.js",
"dist/react-with-addons.js",
"dist/react-with-addons.min.js"
],
"react-dnd": "dist/ReactDnD.min.js",
"require-css": [
"css.js",
"css-builder.js",
"normalize.js"
],
"requirejs": "require.js",
"requirejs-plugins": [
"lib/text.js",
"src/json.js"
],
"sinon": [
"lib/sinon.js",
"lib/sinon/*",
"lib/sinon/util/*"
]
"webpack-dev-server": "1.11.0"
}
}

View File

@ -22,26 +22,25 @@ define(
'backbone',
'react',
'utils',
'jsx!views/layout',
'views/layout',
'coccyx',
'models',
'keystone_client',
'jsx!views/root',
'jsx!views/login_page',
'jsx!views/welcome_page',
'jsx!views/cluster_page',
'jsx!views/clusters_page',
'jsx!views/releases_page',
'jsx!views/plugins_page',
'jsx!views/notifications_page',
'jsx!views/support_page',
'jsx!views/capacity_page',
'views/root',
'views/login_page',
'views/welcome_page',
'views/cluster_page',
'views/clusters_page',
'views/releases_page',
'views/plugins_page',
'views/notifications_page',
'views/support_page',
'views/capacity_page',
'react.backbone',
'stickit',
'routefilter',
'backbone.routefilter',
'bootstrap',
'less!/static/styles/main'
'./styles/main.less'
],
function($, _, i18n, Backbone, React, utils, layoutComponents, Coccyx, models, KeystoneClient, RootComponent, LoginPage, WelcomePage, ClusterPage, ClustersPage, ReleasesPage, PluginsPage, NotificationsPage, SupportPage, CapacityPage) {
'use strict';

View File

@ -46,7 +46,7 @@ define(['jquery', 'underscore', 'backbone', 'utils', 'i18n', 'dispatcher', 'reac
if (Backbone.history.getHash() != href.substr(1) && _.result(this, 'hasChanges')) {
e.preventDefault();
var dialogs = require('jsx!views/dialogs');
var dialogs = require('views/dialogs');
dialogs.DiscardSettingsChangesDialog
.show({
reasonToStay: _.result(this, 'getStayMessage'),

View File

@ -1,87 +0,0 @@
/*
* Copyright 2014 Mirantis, Inc.
*
* Licensed 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.
**/
define(function() {
'use strict';
return {
baseUrl: 'static',
waitSeconds: 60,
paths: {
jquery: 'vendor/npm/jquery/dist/jquery',
'js-cookie': 'vendor/npm/js-cookie/src/js.cookie',
lodash: 'vendor/npm/lodash/index',
underscore: 'vendor/npm/lodash/index',
backbone: 'vendor/npm/backbone/backbone',
classnames: 'vendor/npm/classnames/index',
react: 'vendor/npm/react/dist/react-with-addons',
JSXTransformer: 'vendor/npm/react/dist/JSXTransformer',
jsx: 'vendor/custom/jsx',
'react.backbone': 'vendor/custom/react.backbone',
'react-dnd': 'vendor/npm/react-dnd/dist/ReactDnD.min',
stickit: 'vendor/npm/backbone.stickit/backbone.stickit',
coccyx: 'vendor/custom/coccyx',
routefilter: 'vendor/custom/backbone.routefilter',
bootstrap: 'vendor/npm/bootstrap/dist/js/bootstrap',
text: 'vendor/npm/requirejs-plugins/lib/text',
json: 'vendor/npm/requirejs-plugins/src/json',
i18next: 'vendor/npm/i18next/lib/dep/i18next-1.7.1',
deepModel: 'vendor/custom/deep-model',
lessLibrary: 'vendor/npm/less/dist/less',
'require-css': 'vendor/npm/require-css'
},
shim: {
'expression/parser': {
// non-AMD module; gulp-jison supports generation of AMD
// modules, but they have broken stacktrace
exports: 'parser'
},
coccyx: {
// non-AMD module
deps: ['backbone', 'underscore'],
exports: 'Coccyx'
},
classnames: {
// non-AMD module
exports: 'classNames'
},
bootstrap: {
// non-AMD module, relies on global jQuery
deps: ['jquery']
},
i18next: {
// non-AMD module, relies on global jQuery; there is AMD
// version, but we still use i18n var in lodash templates,
// so we should use non-AMD version until we get rid of
// Backbone.View's completely
deps: ['jquery'],
exports: 'i18n'
},
deepModel: {
// even though deepmodel uses AMD format, it uses _.mixin
// before define() call
deps: ['underscore']
}
},
map: {
'*': {
less: 'require-less'
}
},
jsx: {
fileExtension: '.jsx'
}
};
});

View File

@ -20,7 +20,7 @@ define([
'jquery',
'underscore',
'i18next',
'json!translations/core.json'
'./translations/core.json'
], function($, _, i18next, translations) {
'use strict';

View File

@ -11,9 +11,8 @@
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="pragma" content="no-cache" />
<link rel="shortcut icon" href="/static/favicon.ico" type="image/x-icon">
<link rel="stylesheet" type="text/css" href="/static/styles/layout.css">
<script src="/static/vendor/npm/requirejs/require.js"></script>
<link rel="shortcut icon" href="static/favicon.ico" type="image/x-icon">
<link rel="stylesheet" type="text/css" href="static/styles/layout.css">
<script type="text/javascript">
(function() {
'use strict';
@ -24,6 +23,14 @@
if (mainContainer && loadingErrors.length) mainContainer.textContent = loadingErrors.join('; ');
}
function loadScript(src, errorMessage) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = src;
script.onerror = showError.bind(null, errorMessage);
document.head.appendChild(script);
}
document.addEventListener('DOMContentLoaded', function() {
mainContainer = document.getElementById('main-container');
mainContainer.style.display = 'block';
@ -53,9 +60,12 @@
}());
if (hasCookies && hasStorage) {
requirejs.config({baseUrl: '/static', urlArgs: '_=__CACHE_BUST__'});
requirejs.onError = showError;
requirejs(['main']);
loadScript(
'static/build/bundle.js?__CACHE_BUST__',
'Failed to load compressed Fuel UI bundle. ' +
'If you are using development environment, ' +
'please run "gulp build" to compile Fuel UI.'
);
} else {
showError('Fuel UI requires Cookies and LocalStorage to work');
}

View File

@ -1,31 +0,0 @@
/*
* Copyright 2013 Mirantis, Inc.
*
* Licensed 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.
**/
//>>excludeStart("compressed", pragmas.compressed);
requirejs.config({
urlArgs: '_=' + (new Date()).getTime()
});
require(['./config'], function(config) {
'use strict';
//>>excludeEnd("compressed");
requirejs.config({baseUrl: 'static'});
//>>excludeStart("compressed", pragmas.compressed);
requirejs.config(config);
//>>excludeEnd("compressed");
require(['app']);
//>>excludeStart("compressed", pragmas.compressed);
});
//>>excludeEnd("compressed");

View File

@ -21,8 +21,8 @@ define([
'utils',
'expression',
'expression/objects',
'jsx!views/custom_controls',
'deepModel'
'views/custom_controls',
'deep-model'
], function($, _, i18n, Backbone, utils, Expression, expressionObjects, customControls) {
'use strict';

View File

@ -16,17 +16,18 @@
define(
[
'jsx!./vmware_tab',
'./vmware_tab',
'./vmware_models',
'json!./translations.json',
'less!./styles',
'./translations.json',
'./styles.less',
'jquery',
'underscore'
'underscore',
'i18next'
],
function(VmWareTab, vmWareModels, translations, styles, $, _) {
function(VmWareTab, vmWareModels, translations, styles, $, _, i18next) {
'use strict';
_.merge($.i18n.options.resStore, translations);
_.merge(i18next.options.resStore, translations);
return {
VmWareTab: VmWareTab,

View File

@ -22,8 +22,8 @@ define(
'underscore',
'dispatcher',
'utils',
'jsx!views/controls',
'jsx!component_mixins',
'views/controls',
'component_mixins',
'plugins/vmware/vmware_models'
], function(React, $, i18n, _, dispatcher, utils, controls, componentMixins, vmwareModels) {
'use strict';

View File

@ -1,30 +0,0 @@
/*
* Copyright 2014 Mirantis, Inc.
*
* Licensed 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.
**/
define(['jquery', 'lessLibrary'], function($, less) {
'use strict';
return {
load: function(name, req, onLoad) {
var url = req.toUrl(name + '.less');
var link = $('<link/>', {href: url, rel: 'stylesheet/less'});
link.appendTo('head');
less.sheets.push(link[0]);
less.refresh();
onLoad();
}
};
});

View File

@ -1,4 +1,4 @@
@import "../vendor/npm/bootstrap/dist/css/bootstrap.css";
@import "../../node_modules/bootstrap/dist/css/bootstrap.css";
// COLOR SETTINGS
@ -100,7 +100,7 @@
@slider-color: @tab-color + 20%;
// Fonts and Weight
@import "../vendor/npm/open-sans-fontface/open-sans.css";
@import "../../node_modules/open-sans-fontface/open-sans.css";
@open-sans-font: 'Open Sans', helvetica, arial, tahoma, verdana, sans-serif;
@ -116,7 +116,7 @@
// Bebas Bold
@font-face {
font-family: 'bebas bold';
src: url('../fonts/bebas-bold.eot');
src: url('../fonts/bebas_bold.eot');
src: url('../fonts/bebas_bold.eot?#iefix') format('embedded-opentype'), url('../fonts/bebas_bold.woff2') format('woff2'), url('../fonts/bebas_bold.woff') format('woff'), url('../fonts/bebas_bold.ttf') format('truetype'), url('../fonts/bebas_bold.svg#bebas_bold') format('svg');
font-weight: normal;
font-style: normal;

View File

@ -15,7 +15,7 @@
**/
define([
'underscore',
'intern/dojo/node!lodash',
'tests/functional/pages/modal',
'intern/dojo/node!leadfoot/helpers/pollUntil',
'../../helpers'

View File

@ -15,7 +15,7 @@
**/
define([
'underscore',
'intern/dojo/node!lodash',
'tests/functional/pages/modal',
'../../helpers'
], function(_, ModalWindow) {

View File

@ -15,7 +15,7 @@
**/
define([
'underscore',
'intern/dojo/node!lodash',
'intern/chai!assert',
'../../helpers',
'tests/functional/pages/login',

View File

@ -15,7 +15,7 @@
**/
define([
'underscore',
'intern/dojo/node!lodash',
'intern/chai!assert'
], function(_, assert) {
'use strict';

View File

@ -15,7 +15,7 @@
**/
define([
'underscore',
'intern/dojo/node!lodash',
'intern!object',
'intern/chai!assert',
'tests/helpers',

View File

@ -15,7 +15,7 @@
**/
define([
'underscore',
'intern/dojo/node!lodash',
'intern!object',
'intern/chai!assert',
'tests/functional/pages/common',

View File

@ -15,7 +15,7 @@
**/
define([
'underscore',
'intern/dojo/node!lodash',
'intern!object',
'intern/chai!assert',
'tests/helpers',

View File

@ -15,7 +15,7 @@
**/
define([
'underscore',
'intern/dojo/node!lodash',
'intern/chai!assert',
'intern/dojo/node!fs',
'intern/dojo/node!leadfoot/Command'

View File

@ -14,17 +14,9 @@
* under the License.
**/
define(['config'], function(config) {
define(function() {
'use strict';
config.baseUrl = '';
config.waitSeconds = 7;
config.paths.sinon = 'vendor/npm/sinon/lib/sinon';
// FIXME(vkramskikh): workaround for https://github.com/theintern/intern/issues/348
delete config.map['*'];
return {
proxyPort: 9057,
proxyUrl: 'http://localhost:9057/',
@ -38,7 +30,6 @@ define(['config'], function(config) {
},
grep: /^/,
excludeInstrumentation: /^/,
loader: config,
reporters: ['console', 'tests/screenshot_on_fail']
};
});

View File

@ -1,16 +1,29 @@
/*
* Copyright 2015 Mirantis, Inc.
*
* Licensed 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.
**/
define([
'intern!object',
'intern/chai!assert',
'underscore',
'lodash',
'models',
'expression',
'expression/objects'
], function(registerSuite, assert, _, models, Expression, expressionObjects) {
], function(_, models, Expression, expressionObjects) {
'use strict';
registerSuite({
name: 'Expression',
'Expression parser test': function() {
suite('Expression', function() {
test('Expression parser test', function() {
var hypervisor = 'kvm';
var testModels = {
cluster: new models.Cluster({mode: 'ha_compact'}),
@ -82,6 +95,6 @@ define([
assert.strictEqual(evaluate(expression, options), result, expression + ' evaluates correctly');
}
}));
}
});
});
});

View File

@ -1,17 +1,26 @@
define([
'intern!object',
'intern/chai!assert',
'underscore',
'sinon'
], function(registerSuite, assert, _, sinon) {
/*
* Copyright 2015 Mirantis, Inc.
*
* Licensed 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.
**/
define(function() {
'use strict';
var input;
registerSuite({
name: 'File Control',
beforeEach: function() {
suite('File Control', function() {
setup(function() {
var controls = require('views/controls');
input = new controls.Input({
@ -26,17 +35,17 @@ define([
content: 'CERTIFICATE'
}
});
},
});
Initialization: function() {
test('Initialization', function() {
var initialState = input.getInitialState();
assert.equal(input.props.type, 'file', 'Input type should be equal to file');
assert.equal(initialState.fileName, 'certificate.crt', 'Default file name must correspond to provided one');
assert.equal(initialState.content, 'CERTIFICATE', 'Content should be equal to the default');
},
});
'File selection': function() {
test('File selection', function() {
var clickSpy = sinon.spy();
sinon.stub(input, 'getInputDOMNode').returns({
@ -45,9 +54,9 @@ define([
input.pickFile();
assert.ok(clickSpy.calledOnce, 'When icon clicked input control should be clicked too to open select file dialog');
},
});
'File fetching': function() {
test('File fetching', function() {
var readMethod = sinon.mock(),
readerObject = {
readAsBinaryString: readMethod,
@ -70,9 +79,9 @@ define([
readerObject.onload();
assert.ok(saveMethod.calledOnce, 'saveFile handler called once');
sinon.assert.calledWith(saveMethod, 'somefile.ext', 'File contents');
},
});
'File saving': function() {
test('File saving', function() {
var setState = sinon.spy(input, 'setState'),
dummyName = 'dummy.ext',
dummyContent = 'Lorem ipsum dolores';
@ -87,6 +96,6 @@ define([
name: dummyName,
content: dummyContent
}, 'Control sends updated data upon changes');
}
});
});
});

View File

@ -1,10 +1,20 @@
define([
'intern!object',
'intern/chai!assert',
'underscore',
'sinon',
'jsx!views/cluster_page_tabs/nodes_tab_screens/offloading_modes_control'
], function(registerSuite, assert, _, sinon, OffloadingModes) {
/*
* Copyright 2015 Mirantis, Inc.
*
* Licensed 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.
**/
define(['views/cluster_page_tabs/nodes_tab_screens/offloading_modes_control'], function(OffloadingModes) {
'use strict';
var offloadingModesConrol,
@ -23,10 +33,8 @@ define([
}
};
registerSuite({
name: 'Offloadning Modes control',
beforeEach: function() {
suite('Offloadning Modes control', function() {
setup(function() {
TestMode22 = {name: 'TestName22', state: false, sub: []};
TestMode31 = {name: 'TestName31', state: null, sub: []};
fakeOffloadingModes = [
@ -54,25 +62,26 @@ define([
offloadingModesConrol = new OffloadingModes({
interface: fakeInterface
});
},
'Finding mode by name': function() {
});
test('Finding mode by name', function() {
var mode = offloadingModesConrol.findMode(TestMode22.name, fakeOffloadingModes);
assert.deepEqual(mode, TestMode22, 'Mode can be found by name');
},
'Set mode state logic': function() {
});
test('Set mode state logic', function() {
offloadingModesConrol.setModeState(TestMode31, true);
assert.strictEqual(TestMode31.state, true, 'Mode state is changing');
},
'Set submodes states logic': function() {
});
test('Set submodes states logic', function() {
var mode = offloadingModesConrol.findMode('TestName1', fakeOffloadingModes);
offloadingModesConrol.setModeState(mode, false);
assert.strictEqual(TestMode31.state, false, 'Parent state changing leads to all child modes states changing');
},
'Disabled reversed logic': function() {
});
test('Disabled reversed logic', function() {
var mode = offloadingModesConrol.findMode('TestName2', fakeOffloadingModes);
offloadingModesConrol.setModeState(TestMode22, true);
offloadingModesConrol.checkModes(null, fakeOffloadingModes);
assert.strictEqual(mode.state, null, 'Parent state changing leads to all child modes states changing');
}
});
});
});

View File

@ -15,18 +15,15 @@
**/
define([
'intern!object',
'intern/chai!assert',
'underscore',
'utils',
'i18n',
'backbone'
], function(registerSuite, assert, _, utils, i18n, Backbone) {
], function(_, utils, i18n, Backbone) {
'use strict';
registerSuite({
name: 'Test utils',
'Test getResponseText': function() {
suite('Test utils', function() {
test('Test getResponseText', function() {
var response;
var getResponseText = utils.getResponseText;
var serverErrorMessage = i18n('dialog.error_dialog.server_error');
@ -46,8 +43,9 @@ define([
response = {status: 400, responseText: JSON.stringify({message: '123'})};
assert.equal(getResponseText(response), '123', 'HTTP 400 with JSON response is treated correctly');
},
'Test comparison': function() {
});
test('Test comparison', function() {
var compare = utils.compare;
var model1 = new Backbone.Model({
string: 'bond2',
@ -83,8 +81,9 @@ define([
assert.equal(compare(model2, model2, {attr: 'boolean'}), 0, 'Boolean comparison false and false');
assert.equal(compare(model1, model2, {attr: 'booleanFlagWithNull'}), 0, 'Comparison null and false');
},
'Test highlightTestStep': function() {
});
test('Test highlightTestStep', function() {
var text;
var highlight = utils.highlightTestStep;
@ -135,6 +134,6 @@ define([
text,
'Attempting to highlight non-existent step keeps text as it is'
);
}
});
});
});

View File

@ -123,7 +123,7 @@ define([
}
},
showErrorDialog: function(options) {
var dialogs = require('jsx!views/dialogs'); // avoid circular dependencies
var dialogs = require('views/dialogs'); // avoid circular dependencies
options.message = options.response ? utils.getResponseText(options.response) :
options.message || i18n('dialog.error_dialog.warning');
dialogs.ErrorDialog.show(options);

View File

@ -1,76 +0,0 @@
/**
* @license The MIT License (MIT)
*
* Copyright (c) 2014 Felipe O. Carvalho
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
define(['JSXTransformer', 'text'], function (JSXTransformer, text) {
'use strict';
var buildMap = {};
var jsx = {
version: '0.6.2',
load: function (name, req, onLoadNative, config) {
var jsxOptions = config.jsx || {};
var fileExtension = jsxOptions.fileExtension || '.js';
var transformOptions = {
harmony: !!jsxOptions.harmony,
stripTypes: !!jsxOptions.stripTypes
};
var onLoad = function(content) {
try {
content = JSXTransformer.transform(content, transformOptions).code;
} catch (err) {
onLoadNative.error(err);
}
if (config.isBuild) {
buildMap[name] = content;
} else if (typeof location !== 'undefined') { // Do not create sourcemap when loaded in Node
content += '\n//# sourceURL=' + location.protocol + '//' + location.hostname +
config.baseUrl + name + fileExtension;
}
onLoadNative.fromText(content);
};
onLoad.error = function(err) {
onLoadNative.error(err);
};
text.load(name + fileExtension, req, onLoad, config);
},
write: function (pluginName, moduleName, write) {
if (buildMap.hasOwnProperty(moduleName)) {
var content = buildMap[moduleName];
write.asModule(pluginName + '!' + moduleName, content);
}
}
};
return jsx;
});

View File

@ -19,8 +19,8 @@ define(
'i18n',
'react',
'models',
'jsx!component_mixins',
'jsx!views/controls'
'component_mixins',
'views/controls'
],
function(_, i18n, React, models, componentMixins, controls) {
'use strict';

View File

@ -23,14 +23,14 @@ define(
'utils',
'models',
'dispatcher',
'jsx!component_mixins',
'jsx!views/dialogs',
'jsx!views/cluster_page_tabs/dashboard_tab',
'jsx!views/cluster_page_tabs/nodes_tab',
'jsx!views/cluster_page_tabs/network_tab',
'jsx!views/cluster_page_tabs/settings_tab',
'jsx!views/cluster_page_tabs/logs_tab',
'jsx!views/cluster_page_tabs/healthcheck_tab',
'component_mixins',
'views/dialogs',
'views/cluster_page_tabs/dashboard_tab',
'views/cluster_page_tabs/nodes_tab',
'views/cluster_page_tabs/network_tab',
'views/cluster_page_tabs/settings_tab',
'views/cluster_page_tabs/logs_tab',
'views/cluster_page_tabs/healthcheck_tab',
'plugins/vmware/vmware'
],
function($, _, i18n, Backbone, React, utils, models, dispatcher, componentMixins, dialogs, DashboardTab, NodesTab, NetworkTab, SettingsTab, LogsTab, HealthCheckTab, vmWare) {

View File

@ -22,9 +22,9 @@ define(
'utils',
'models',
'dispatcher',
'jsx!views/dialogs',
'jsx!component_mixins',
'jsx!views/controls'
'views/dialogs',
'component_mixins',
'views/controls'
],
function(_, i18n, $, React, utils, models, dispatcher, dialogs, componentMixins, controls) {
'use strict';

View File

@ -22,8 +22,8 @@ define(
'react',
'models',
'utils',
'jsx!component_mixins',
'jsx!views/controls'
'component_mixins',
'views/controls'
],
function($, _, i18n, Backbone, React, models, utils, componentMixins, controls) {
'use strict';

View File

@ -21,8 +21,8 @@ define(
'react',
'utils',
'models',
'jsx!component_mixins',
'jsx!views/controls'
'component_mixins',
'views/controls'
],
function($, _, i18n, React, utils, models, componentMixins, controls) {
'use strict';

View File

@ -23,8 +23,8 @@ define(
'models',
'dispatcher',
'utils',
'jsx!component_mixins',
'jsx!views/controls'
'component_mixins',
'views/controls'
],
function($, _, i18n, Backbone, React, models, dispatcher, utils, componentMixins, controls) {
'use strict';

View File

@ -18,12 +18,12 @@ define(
'jquery',
'underscore',
'react',
'jsx!views/controls',
'jsx!views/cluster_page_tabs/nodes_tab_screens/cluster_nodes_screen',
'jsx!views/cluster_page_tabs/nodes_tab_screens/add_nodes_screen',
'jsx!views/cluster_page_tabs/nodes_tab_screens/edit_nodes_screen',
'jsx!views/cluster_page_tabs/nodes_tab_screens/edit_node_disks_screen',
'jsx!views/cluster_page_tabs/nodes_tab_screens/edit_node_interfaces_screen'
'views/controls',
'views/cluster_page_tabs/nodes_tab_screens/cluster_nodes_screen',
'views/cluster_page_tabs/nodes_tab_screens/add_nodes_screen',
'views/cluster_page_tabs/nodes_tab_screens/edit_nodes_screen',
'views/cluster_page_tabs/nodes_tab_screens/edit_node_disks_screen',
'views/cluster_page_tabs/nodes_tab_screens/edit_node_interfaces_screen'
],
function($, _, React, controls, ClusterNodesScreen, AddNodesScreen, EditNodesScreen, EditNodeDisksScreen, EditNodeInterfacesScreen) {
'use strict';

View File

@ -19,7 +19,7 @@ define(
'underscore',
'react',
'models',
'jsx!views/cluster_page_tabs/nodes_tab_screens/node_list_screen'
'views/cluster_page_tabs/nodes_tab_screens/node_list_screen'
],
function($, _, React, models, NodeListScreen) {
'use strict';

View File

@ -17,7 +17,7 @@ define(
[
'underscore',
'react',
'jsx!views/cluster_page_tabs/nodes_tab_screens/node_list_screen'
'views/cluster_page_tabs/nodes_tab_screens/node_list_screen'
],
function(_, React, NodeListScreen) {
'use strict';

View File

@ -22,8 +22,8 @@ define(
'react',
'utils',
'models',
'jsx!component_mixins',
'jsx!views/controls'
'component_mixins',
'views/controls'
],
function($, _, i18n, Backbone, React, utils, models, ComponentMixins, controls) {
'use strict';

View File

@ -23,11 +23,11 @@ define(
'utils',
'models',
'dispatcher',
'jsx!views/dialogs',
'jsx!views/controls',
'jsx!component_mixins',
'views/dialogs',
'views/controls',
'component_mixins',
'react-dnd',
'jsx!views/cluster_page_tabs/nodes_tab_screens/offloading_modes_control'
'views/cluster_page_tabs/nodes_tab_screens/offloading_modes_control'
],
function($, _, Backbone, React, i18n, utils, models, dispatcher, dialogs, controls, ComponentMixins, DND, OffloadingModes) {
'use strict';

View File

@ -20,8 +20,8 @@ define(
'react',
'models',
'utils',
'jsx!component_mixins',
'jsx!views/cluster_page_tabs/nodes_tab_screens/node_list_screen'
'component_mixins',
'views/cluster_page_tabs/nodes_tab_screens/node_list_screen'
],
function($, _, React, models, utils, ComponentMixins, NodeListScreen) {
'use strict';

View File

@ -23,9 +23,9 @@ define(
'utils',
'models',
'dispatcher',
'jsx!views/controls',
'jsx!views/dialogs',
'jsx!component_mixins'
'views/controls',
'views/dialogs',
'component_mixins'
],
function($, _, i18n, Backbone, React, utils, models, dispatcher, controls, dialogs, componentMixins) {
'use strict';

View File

@ -23,10 +23,10 @@ define(
'utils',
'models',
'dispatcher',
'jsx!views/controls',
'jsx!views/dialogs',
'jsx!component_mixins',
'jsx!views/cluster_page_tabs/nodes_tab_screens/node'
'views/controls',
'views/dialogs',
'component_mixins',
'views/cluster_page_tabs/nodes_tab_screens/node'
],
function($, _, i18n, Backbone, React, utils, models, dispatcher, controls, dialogs, componentMixins, Node) {
'use strict';

View File

@ -22,9 +22,9 @@ define(
'utils',
'models',
'expression',
'jsx!component_mixins',
'jsx!views/controls',
'jsx!views/custom_controls'
'component_mixins',
'views/controls',
'views/custom_controls'
],
function($, _, i18n, React, utils, models, Expression, componentMixins, controls, customControls) {
'use strict';

View File

@ -22,7 +22,7 @@ define(
'models',
'utils',
'dispatcher',
'jsx!component_mixins',
'component_mixins',
'views/wizard'
],
function($, _, i18n, React, models, utils, dispatcher, componentMixins, wizard) {

View File

@ -20,7 +20,7 @@
* Based on https://github.com/react-bootstrap/react-bootstrap/blob/master/src/Input.jsx
**/
define(['i18n', 'jquery', 'underscore', 'react', 'utils', 'jsx!component_mixins'],
define(['i18n', 'jquery', 'underscore', 'react', 'utils', 'component_mixins'],
function(i18n, $, _, React, utils, componentMixins) {
'use strict';

View File

@ -20,7 +20,7 @@ define([
'i18n',
'react',
'utils',
'jsx!views/controls'
'views/controls'
], function($, _, i18n, React, utils, controls) {
'use strict';

View File

@ -23,8 +23,8 @@ define(
'utils',
'models',
'dispatcher',
'jsx!views/controls',
'jsx!component_mixins'
'views/controls',
'component_mixins'
],
function($, _, i18n, Backbone, React, utils, models, dispatcher, controls, componentMixins) {
'use strict';

View File

@ -22,9 +22,9 @@ define(
'react',
'utils',
'models',
'jsx!views/controls',
'jsx!component_mixins',
'jsx!views/dialogs'
'views/controls',
'component_mixins',
'views/dialogs'
],
function($, _, i18n, Backbone, React, utils, models, controls, componentMixins, dialogs) {
'use strict';

View File

@ -19,8 +19,8 @@ define(
'react',
'utils',
'models',
'jsx!views/dialogs',
'jsx!component_mixins'
'views/dialogs',
'component_mixins'
],
function(i18n, React, utils, models, dialogs, componentMixins) {
'use strict';

View File

@ -19,8 +19,8 @@ define(
'i18n',
'react',
'models',
'jsx!views/controls',
'jsx!component_mixins'
'views/controls',
'component_mixins'
],
function(_, i18n, React, models, controls, componentMixins) {
'use strict';

View File

@ -18,11 +18,12 @@ define([
'i18n',
'react',
'utils',
'jsx!views/layout',
'views/layout',
'dispatcher',
'jsx!component_mixins',
'react-dnd'
], function(_, i18n, React, utils, layoutComponents, dispatcher, componentMixins, DND) {
'component_mixins',
'react-dnd',
'react-dnd/modules/backends/HTML5'
], function(_, i18n, React, utils, layoutComponents, dispatcher, componentMixins, DND, HTML5Backend) {
'use strict';
var RootComponent = React.createClass({
@ -81,5 +82,5 @@ define([
}
});
return DND.DragDropContext(DND.HTML5)(RootComponent);
return DND.DragDropContext(HTML5Backend)(RootComponent);
});

View File

@ -20,8 +20,8 @@ define([
'react',
'utils',
'models',
'jsx!views/dialogs',
'jsx!views/controls'
'views/dialogs',
'views/controls'
], function($, _, i18n, React, utils, models, dialogs, controls) {
'use strict';

View File

@ -20,10 +20,10 @@ define(
'i18n',
'backbone',
'react',
'jsx!views/dialogs',
'jsx!component_mixins',
'views/dialogs',
'component_mixins',
'models',
'jsx!views/statistics_mixin'
'views/statistics_mixin'
],
function($, _, i18n, Backbone, React, dialogs, componentMixins, models, statisticsMixin) {
'use strict';

View File

@ -19,8 +19,8 @@ define(
'i18n',
'react',
'models',
'jsx!component_mixins',
'jsx!views/statistics_mixin'
'component_mixins',
'views/statistics_mixin'
],
function(_, i18n, React, models, componentMixins, statisticsMixin) {
'use strict';

View File

@ -20,20 +20,21 @@ define(
'underscore',
'i18n',
'backbone',
'backbone.stickit',
'utils',
'models',
'text!templates/wizard/create_cluster_wizard.html',
'text!templates/wizard/name_and_release.html',
'text!templates/wizard/common_wizard_panel.html',
'text!templates/wizard/mode.html',
'text!templates/wizard/network.html',
'text!templates/wizard/storage.html',
'text!templates/wizard/ready.html',
'text!templates/wizard/control_template.html',
'text!templates/wizard/warning.html',
'text!templates/wizard/text_input.html'
'templates/wizard/create_cluster_wizard.html',
'templates/wizard/name_and_release.html',
'templates/wizard/common_wizard_panel.html',
'templates/wizard/mode.html',
'templates/wizard/network.html',
'templates/wizard/storage.html',
'templates/wizard/ready.html',
'templates/wizard/control_template.html',
'templates/wizard/warning.html',
'templates/wizard/text_input.html'
],
function(require, $, _, i18n, Backbone, utils, models, createClusterWizardTemplate, clusterNameAndReleasePaneTemplate, commonWizardTemplate, modePaneTemplate, networkPaneTemplate, storagePaneTemplate, clusterReadyPaneTemplate, controlTemplate, warningTemplate, textInputTemplate) {
function(require, $, _, i18n, Backbone, stickit, utils, models, createClusterWizardTemplate, clusterNameAndReleasePaneTemplate, commonWizardTemplate, modePaneTemplate, networkPaneTemplate, storagePaneTemplate, clusterReadyPaneTemplate, controlTemplate, warningTemplate, textInputTemplate) {
'use strict';
var views = {},

46
webpack.config.js Normal file
View File

@ -0,0 +1,46 @@
/*eslint-disable strict*/
module.exports = {
entry: ['./static/app.js'],
output: {
path: __dirname + '/static/build/',
publicPath: '/static/build/',
filename: 'bundle.js',
chunkFilename: null,
sourceMapFilename: 'bundle.js.map'
},
module: {
loaders: [
{test: /\/expression\/parser\.js$/, loader: 'exports?parser'},
{test: require.resolve('jquery'), loader: 'expose?jQuery!expose?$'},
{test: /\.css$/, loader: 'style!css!postcss'},
{test: /\.less$/, loader: 'style!css!postcss!less'},
{test: /\.html$/, loader: 'raw'},
{test: /\.json$/, loader: 'json'},
{test: /\.jison$/, loader: 'jison'},
{test: /\.jsx$/, loader: 'babel', exclude: /(node_modules|bower_components)/},
{test: /\.(woff|woff2|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/, loader: 'file'},
{test: /\.(gif|png)$/, loader: 'file'}
]
},
resolve: {
modulesDirectories: ['static', 'node_modules', 'vendor/custom'],
extensions: ['', '.js', '.jsx'],
alias: {
underscore: 'lodash',
react: 'react/addons',
// FIXME(vkramskikh): node.js version depends on express
// and causes warnings
i18next: 'i18next/lib/dep/i18next-1.7.1.js'
}
},
node: {},
plugins: [],
postcss: function() {
return [require('autoprefixer')];
},
devtool: 'cheap-source-map',
watchOptions: {
aggregateTimeout: 300,
poll: 1000
}
};