mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 18:09:57 -03:30
Merge pull request #49 from gconsidine/ui/clean-build
Update UI build system
This commit is contained in:
commit
ccbf7af7f2
@ -17,38 +17,4 @@ module.exports = function(grunt) {
|
||||
grunt.initConfig(configs);
|
||||
grunt.loadNpmTasks('grunt-newer');
|
||||
grunt.loadNpmTasks('grunt-angular-gettext');
|
||||
|
||||
// writes environment variables for development. current manages:
|
||||
// browser-sync + websocket proxy
|
||||
|
||||
grunt.registerTask('sync', [
|
||||
'browserSync:http',
|
||||
'concurrent:watch'
|
||||
]);
|
||||
|
||||
grunt.registerTask('dev', [
|
||||
'clean:tmp',
|
||||
'clean:static',
|
||||
'concurrent:dev',
|
||||
'concat:css',
|
||||
'webpack:dev',
|
||||
'sync'
|
||||
]);
|
||||
|
||||
grunt.registerTask('devNoSync', [
|
||||
'clean:tmp',
|
||||
'clean:static',
|
||||
'concurrent:devNoSync',
|
||||
'concat:css'
|
||||
]);
|
||||
|
||||
grunt.registerTask('release', [
|
||||
'clean:tmp',
|
||||
'clean:static',
|
||||
'concurrent:prod',
|
||||
'webpack:prod',
|
||||
'concat:css',
|
||||
'cssmin:vendor',
|
||||
'cssmin:source'
|
||||
]);
|
||||
};
|
||||
|
||||
198
awx/ui/build/webpack.base.js
Normal file
198
awx/ui/build/webpack.base.js
Normal file
@ -0,0 +1,198 @@
|
||||
const path = require('path');
|
||||
|
||||
const webpack = require('webpack');
|
||||
const CleanWebpackPlugin = require('clean-webpack-plugin');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
|
||||
const CLIENT_PATH = path.resolve(__dirname, '../client');
|
||||
const LIB_PATH = path.join(CLIENT_PATH, 'lib');
|
||||
const UI_PATH = path.resolve(__dirname, '..');
|
||||
|
||||
const ASSETS_PATH = path.join(CLIENT_PATH, 'assets');
|
||||
const COMPONENTS_PATH = path.join(LIB_PATH, 'components');
|
||||
const COVERAGE_PATH = path.join(UI_PATH, 'coverage');
|
||||
const FEATURES_PATH = path.join(CLIENT_PATH, 'features');
|
||||
const LANGUAGES_PATH = path.join(CLIENT_PATH, 'languages');
|
||||
const MODELS_PATH = path.join(LIB_PATH, 'models');
|
||||
const NODE_MODULES_PATH = path.join(UI_PATH, 'node_modules');
|
||||
const SERVICES_PATH = path.join(LIB_PATH, 'services');
|
||||
const SOURCE_PATH = path.join(CLIENT_PATH, 'src');
|
||||
const STATIC_PATH = path.join(UI_PATH, 'static');
|
||||
|
||||
const APP_ENTRY = path.join(SOURCE_PATH, 'app.js');
|
||||
const VENDOR_ENTRY = path.join(SOURCE_PATH, 'vendor.js');
|
||||
const INDEX_ENTRY = path.join(CLIENT_PATH, 'index.template.ejs');
|
||||
const INDEX_OUTPUT = path.join(UI_PATH, 'templates/ui/index.html');
|
||||
const THEME_ENTRY = path.join(LIB_PATH, 'theme', 'index.less');
|
||||
const OUTPUT = 'js/[name].[hash].js';
|
||||
const CHUNKS = ['vendor', 'app'];
|
||||
|
||||
const VENDOR = VENDOR_ENTRY;
|
||||
const APP = [THEME_ENTRY, APP_ENTRY];
|
||||
|
||||
let base = {
|
||||
entry: {
|
||||
vendor: VENDOR,
|
||||
app: APP
|
||||
},
|
||||
output: {
|
||||
path: STATIC_PATH,
|
||||
publicPath: '',
|
||||
filename: OUTPUT
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
exclude: /node_modules/
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: ExtractTextPlugin.extract({
|
||||
use: {
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
url: false
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
test: /\lib\/theme\/index.less$/,
|
||||
use: ExtractTextPlugin.extract({
|
||||
use: ['css-loader', 'less-loader']
|
||||
})
|
||||
},
|
||||
{
|
||||
test: require.resolve('jquery'),
|
||||
loader: 'expose-loader?$!expose-loader?jQuery!expose-loader?jquery'
|
||||
},
|
||||
{
|
||||
loader: 'script-loader',
|
||||
test: [
|
||||
/node_modules\/javascript-detect-element-resize\/jquery.resize\.js$/,
|
||||
/node_modules\/d3\/d3\.min.js$/
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
use: 'imports-loader?define=>false'
|
||||
},
|
||||
{
|
||||
test: /\.html$/,
|
||||
use: ['ngtemplate-loader', 'html-loader'],
|
||||
include: [
|
||||
/lib\/components\//,
|
||||
/features\//
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.json$/,
|
||||
loader: 'json-loader',
|
||||
exclude: /node_modules/
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new webpack.ProvidePlugin({
|
||||
jsyaml: 'js-yaml',
|
||||
CodeMirror: 'codemirror',
|
||||
jsonlint: 'codemirror.jsonlint',
|
||||
_: 'lodash'
|
||||
}),
|
||||
new ExtractTextPlugin('css/[name].[hash].css'),
|
||||
new CleanWebpackPlugin([STATIC_PATH, COVERAGE_PATH], {
|
||||
root: UI_PATH,
|
||||
}),
|
||||
new CopyWebpackPlugin([
|
||||
{
|
||||
from: path.join(ASSETS_PATH, 'fontcustom/**/*'),
|
||||
to: path.join(STATIC_PATH, 'fonts/'),
|
||||
flatten: true
|
||||
},
|
||||
{
|
||||
from: path.join(NODE_MODULES_PATH, 'components-font-awesome/fonts/*'),
|
||||
to: path.join(STATIC_PATH, 'fonts/'),
|
||||
flatten: true
|
||||
},
|
||||
{
|
||||
from: path.join(ASSETS_PATH, 'custom-theme/images.new/*'),
|
||||
to: path.join(STATIC_PATH, 'images/'),
|
||||
flatten: true
|
||||
},
|
||||
{
|
||||
from: path.join(LANGUAGES_PATH, '*'),
|
||||
to: path.join(STATIC_PATH, 'languages'),
|
||||
flatten: true
|
||||
},
|
||||
{
|
||||
from: ASSETS_PATH,
|
||||
to: path.join(STATIC_PATH, 'assets')
|
||||
},
|
||||
{
|
||||
from: path.join(NODE_MODULES_PATH, 'angular-scheduler/lib/*.html'),
|
||||
to: path.join(STATIC_PATH, 'lib'),
|
||||
context: NODE_MODULES_PATH
|
||||
},
|
||||
{
|
||||
from: path.join(NODE_MODULES_PATH, 'angular-tz-extensions/tz/data/*'),
|
||||
to: path.join(STATIC_PATH, 'lib/'),
|
||||
context: NODE_MODULES_PATH
|
||||
},
|
||||
{
|
||||
from: path.join(SOURCE_PATH, '**/*.partial.html'),
|
||||
to: path.join(STATIC_PATH, 'partials/'),
|
||||
context: SOURCE_PATH
|
||||
},
|
||||
{
|
||||
from: path.join(SOURCE_PATH, 'partials', '*.html'),
|
||||
to: STATIC_PATH,
|
||||
context: SOURCE_PATH
|
||||
},
|
||||
{
|
||||
from: path.join(SOURCE_PATH, '*config.js'),
|
||||
to: STATIC_PATH,
|
||||
flatten: true
|
||||
}
|
||||
]),
|
||||
new HtmlWebpackPlugin({
|
||||
alwaysWriteToDisk: true,
|
||||
template: INDEX_ENTRY,
|
||||
filename: INDEX_OUTPUT,
|
||||
inject: false,
|
||||
chunks: CHUNKS,
|
||||
chunksSortMode: (moduleA, moduleB) => {
|
||||
moduleA.files.sort((fileA, fileB) => fileA.includes('js') ? -1 : 1)
|
||||
moduleB.files.sort((fileA, fileB) => fileA.includes('js') ? -1 : 1)
|
||||
|
||||
return moduleA.names[0] === 'vendor' ? -1 : 1
|
||||
}
|
||||
})
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@features': FEATURES_PATH,
|
||||
'@models': MODELS_PATH,
|
||||
'@services': SERVICES_PATH,
|
||||
'@components': COMPONENTS_PATH,
|
||||
'@modules': NODE_MODULES_PATH,
|
||||
'@assets': ASSETS_PATH,
|
||||
'd3$': '@modules/d3/d3.min.js',
|
||||
'codemirror.jsonlint$': '@modules/codemirror/addon/lint/json-lint.js',
|
||||
'jquery-resize$': '@modules/javascript-detect-element-resize/jquery.resize.js',
|
||||
'select2$': '@modules/select2/dist/js/select2.full.min.js',
|
||||
'js-yaml$': '@modules/js-yaml/dist/js-yaml.min.js',
|
||||
'lr-infinite-scroll$': '@modules/lr-infinite-scroll/lrInfiniteScroll.js',
|
||||
'angular-ui-router$': '@modules/angular-ui-router/release/angular-ui-router.js',
|
||||
'angular-ui-router-state-events$': '@modules/angular-ui-router/release/stateEvents.js',
|
||||
'ng-toast-provider$': '@modules/ng-toast/src/scripts/provider.js',
|
||||
'ng-toast-directives$': '@modules/ng-toast/src/scripts/directives.js',
|
||||
'ng-toast$': '@modules/ng-toast/src/scripts/module.js'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = base;
|
||||
11
awx/ui/build/webpack.development.js
Normal file
11
awx/ui/build/webpack.development.js
Normal file
@ -0,0 +1,11 @@
|
||||
const path = require('path');
|
||||
|
||||
const _ = require('lodash');
|
||||
|
||||
let base = require('./webpack.base');
|
||||
|
||||
let development = {
|
||||
devtool: 'cheap-source-map'
|
||||
};
|
||||
|
||||
module.exports = _.merge(base, development);
|
||||
19
awx/ui/build/webpack.production.js
Normal file
19
awx/ui/build/webpack.production.js
Normal file
@ -0,0 +1,19 @@
|
||||
const _ = require('lodash');
|
||||
|
||||
const webpack = require('webpack');
|
||||
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
|
||||
|
||||
let base = require('./webpack.base');
|
||||
|
||||
let production = {
|
||||
plugins: [
|
||||
new UglifyJSPlugin({
|
||||
compress: true,
|
||||
mangle: false
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
production.plugins = base.plugins.concat(production.plugins)
|
||||
|
||||
module.exports = _.merge(base, production);
|
||||
21
awx/ui/build/webpack.test.js
Normal file
21
awx/ui/build/webpack.test.js
Normal file
@ -0,0 +1,21 @@
|
||||
const path = require('path');
|
||||
|
||||
const _ = require('lodash');
|
||||
const webpack = require('webpack');
|
||||
|
||||
const STATIC_URL = '/static/';
|
||||
|
||||
let development = require('./webpack.development');
|
||||
|
||||
let test = {
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
$basePath: STATIC_URL
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
test.plugins = development.plugins.concat(test.plugins)
|
||||
|
||||
module.exports = _.merge(development, test);
|
||||
|
||||
42
awx/ui/build/webpack.watch.js
Normal file
42
awx/ui/build/webpack.watch.js
Normal file
@ -0,0 +1,42 @@
|
||||
const path = require('path');
|
||||
|
||||
const _ = require('lodash');
|
||||
const webpack = require('webpack');
|
||||
const HtmlWebpackHarddiskPlugin = require('html-webpack-harddisk-plugin');
|
||||
|
||||
const TARGET_PORT = _.get(process.env, 'npm_package_config_django_port', 8043);
|
||||
const TARGET_HOST = _.get(process.env, 'npm_package_config_django_host', 'https://localhost');
|
||||
const TARGET = `https://${TARGET_HOST}:${TARGET_PORT}`;
|
||||
|
||||
let development = require('./webpack.development');
|
||||
|
||||
let watch = {
|
||||
plugins: [
|
||||
new HtmlWebpackHarddiskPlugin(),
|
||||
new webpack.HotModuleReplacementPlugin()
|
||||
],
|
||||
devServer: {
|
||||
contentBase: path.resolve(__dirname, '..', 'static'),
|
||||
clientLogLevel: 'info',
|
||||
publicPath: '/static/',
|
||||
host: '127.0.0.1',
|
||||
port: 3000,
|
||||
proxy: {
|
||||
'/': {
|
||||
target: TARGET,
|
||||
secure: false,
|
||||
ws: false
|
||||
},
|
||||
'/websocket': {
|
||||
target: TARGET,
|
||||
secure: false,
|
||||
ws: true
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
watch.plugins = development.plugins.concat(watch.plugins)
|
||||
|
||||
module.exports = _.merge(development, watch);
|
||||
|
||||
@ -3,6 +3,8 @@ import AddController from './add-credentials.controller';
|
||||
import EditController from './edit-credentials.controller';
|
||||
import CredentialsStrings from './credentials.strings'
|
||||
|
||||
const addEditTemplate = require('@features/credentials/add-edit-credentials.view.html');
|
||||
|
||||
function CredentialsResolve ($q, $stateParams, Me, Credential, CredentialType, Organization) {
|
||||
let id = $stateParams.credential_id;
|
||||
|
||||
@ -51,8 +53,7 @@ CredentialsResolve.$inject = [
|
||||
'OrganizationModel'
|
||||
];
|
||||
|
||||
function CredentialsConfig ($stateExtenderProvider, legacyProvider, pathProvider, stringProvider) {
|
||||
let path = pathProvider.$get();
|
||||
function CredentialsConfig ($stateExtenderProvider, legacyProvider, stringProvider) {
|
||||
let stateExtender = $stateExtenderProvider.$get();
|
||||
let legacy = legacyProvider.$get();
|
||||
let strings = stringProvider.$get();
|
||||
@ -69,7 +70,7 @@ function CredentialsConfig ($stateExtenderProvider, legacyProvider, pathProvider
|
||||
},
|
||||
views: {
|
||||
'add@credentials': {
|
||||
templateUrl: path.getViewPath('credentials/add-edit-credentials'),
|
||||
templateUrl: addEditTemplate,
|
||||
controller: AddController,
|
||||
controllerAs: 'vm'
|
||||
}
|
||||
@ -92,7 +93,7 @@ function CredentialsConfig ($stateExtenderProvider, legacyProvider, pathProvider
|
||||
},
|
||||
views: {
|
||||
'edit@credentials': {
|
||||
templateUrl: path.getViewPath('credentials/add-edit-credentials'),
|
||||
templateUrl: addEditTemplate,
|
||||
controller: EditController,
|
||||
controllerAs: 'vm'
|
||||
}
|
||||
@ -114,7 +115,6 @@ function CredentialsConfig ($stateExtenderProvider, legacyProvider, pathProvider
|
||||
CredentialsConfig.$inject = [
|
||||
'$stateExtenderProvider',
|
||||
'LegacyCredentialsServiceProvider',
|
||||
'PathServiceProvider',
|
||||
'CredentialsStringsProvider'
|
||||
];
|
||||
|
||||
|
||||
@ -5,7 +5,9 @@ import OrganizationList from '../../src/organizations/organizations.list';
|
||||
import ListController from '../../src/credentials/list/credentials-list.controller';
|
||||
import { N_ } from '../../src/i18n';
|
||||
|
||||
function LegacyCredentialsService (pathService) {
|
||||
const indexTemplate = require('@features/credentials/index.view.html');
|
||||
|
||||
function LegacyCredentialsService () {
|
||||
this.list = {
|
||||
name: 'credentials',
|
||||
route: '/credentials',
|
||||
@ -18,7 +20,7 @@ function LegacyCredentialsService (pathService) {
|
||||
},
|
||||
views: {
|
||||
'@': {
|
||||
templateUrl: pathService.getViewPath('credentials/index')
|
||||
templateUrl: indexTemplate
|
||||
},
|
||||
'list@credentials': {
|
||||
templateProvider: function(CredentialList, generateList) {
|
||||
@ -361,8 +363,4 @@ function LegacyCredentialsService (pathService) {
|
||||
};
|
||||
}
|
||||
|
||||
LegacyCredentialsService.$inject = [
|
||||
'PathService'
|
||||
];
|
||||
|
||||
export default LegacyCredentialsService;
|
||||
|
||||
159
awx/ui/client/index.template.ejs
Normal file
159
awx/ui/client/index.template.ejs
Normal file
@ -0,0 +1,159 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" ng-app="awApp">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="shortcut icon" href="{{ STATIC_URL }}assets/favicon.ico?v={{version}}" />
|
||||
<title ng-bind="tabTitle"></title>
|
||||
<script>var $basePath = '{{ STATIC_URL }}'</script>
|
||||
<% htmlWebpackPlugin.files.css.forEach(file => {%>
|
||||
<link href="{{ STATIC_URL }}<%= file %>" rel="stylesheet" />
|
||||
<% }) %>
|
||||
<% htmlWebpackPlugin.files.js.forEach(file => {%>
|
||||
<script src="{{ STATIC_URL }}<%= file %>"></script>
|
||||
<% }) %>
|
||||
</head>
|
||||
|
||||
<body data-user-agent="{{userAgent}}">
|
||||
<at-layout>
|
||||
<bread-crumb></bread-crumb>
|
||||
<toast></toast>
|
||||
<div class="container-fluid" id="content-container">
|
||||
<div class="row">
|
||||
<div class="col-lg-12" ui-view>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Password Dialog -->
|
||||
<div id="password-modal" style="display: none;"></div>
|
||||
<div id="idle-modal" style="display:none" translate>Your session will expire in <span id="remaining_seconds" class="IdleModal-remainingSeconds">60</span> seconds, would you like to continue?</div>
|
||||
<stream-detail-modal></stream-detail-modal>
|
||||
<!-- Confirmation Dialog -->
|
||||
<div id="prompt-modal" class="modal fade">
|
||||
<div class="modal-dialog">
|
||||
<div class="Modal-content modal-content">
|
||||
<div class="Modal-header">
|
||||
<div class="Modal-title" ng-bind="promptHeader" id="prompt-header"></div>
|
||||
<div class="Modal-exitHolder">
|
||||
<button class="close Modal-exit" data-target="#prompt-modal" data-dismiss="modal" aria-hidden="true"><i class="fa fa-times-circle"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="Modal-body" ng-bind-html="promptBody" id="prompt-body">
|
||||
</div>
|
||||
<div class="Modal-footer">
|
||||
<a href="#" data-target="#prompt-modal" data-dismiss="modal" id="prompt_cancel_btn" class="btn Modal-defaultButton Modal-footerButton" translate>CANCEL</a>
|
||||
<a href="" ng-class="promptActionBtnClass" ng-click="promptAction()" id="prompt_action_btn" class="btn Modal-footerButton" ng-bind="promptActionText"></a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- modal-content -->
|
||||
</div>
|
||||
<!-- modal-dialog -->
|
||||
</div>
|
||||
<!-- modal -->
|
||||
<!-- Alerts/error handling dialogs -->
|
||||
<div id="alert-modal" class="modal fade">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" ng-hide="disableButtons" data-target="#alert-modal" data-dismiss="modal" class="modal" aria-hidden="true"><i class="fa fa-times-circle"></i></button>
|
||||
<h3 id="alertHeader" ng-bind="alertHeader"></h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="alert-modal-msg" class="alert" ng-bind-html="alertBody"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#" ng-hide="disableButtons" data-target="#form-modal" data-dismiss="modal" id="alert_ok_btn" class="btn btn-default" translate>OK</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- modal-content -->
|
||||
</div>
|
||||
<!-- modal-dialog -->
|
||||
</div>
|
||||
<!-- modal -->
|
||||
<div id="alert-modal2" class="modal fade">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-target="#alert-modal2" data-dismiss="modal" ng-hide="disableButtons2" aria-hidden="true">×</button>
|
||||
<h3 id="alertHeader2" ng-bind="alertHeader2"></h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="alert2-modal-msg" class="alert" ng-bind-html="alertBody2"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#" ng-hide="disableButtons2" data-target="#form-modal2" data-dismiss="modal" id="alert2_ok_btn" class="btn btn-primary">OK</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- modal-content -->
|
||||
</div>
|
||||
<!-- modal-dialog -->
|
||||
</div>
|
||||
<!-- modal -->
|
||||
<div id="login-modal-dialog" style="display: none;"></div>
|
||||
<div id="help-modal-dialog" style="display: none;"></div>
|
||||
<div id="prompt-for-days" style="display:none">
|
||||
<form name="prompt_for_days_form" id="prompt_for_days_form" class="MgmtCards-promptText">
|
||||
<span translate>Set how many days of data should be retained.</span>
|
||||
<br>
|
||||
<input type="integer" id="days_to_keep" name="days_to_keep" ng-model="days_to_keep" ng-required="true" class="form-control Form-textInput" min=0 max=9999 style="margin-top:10px;" integer>
|
||||
<div class="error" ng-show="prompt_for_days_form.days_to_keep.$dirty && (prompt_for_days_form.days_to_keep.$error.number || prompt_for_days_form.days_to_keep.$error.integer ||
|
||||
prompt_for_days_form.days_to_keep.$error.required ||
|
||||
prompt_for_days_form.days_to_keep.$error.min ||
|
||||
prompt_for_days_form.days_to_keep.$error.max)" translate>Please enter an integer<span ng-show="prompt_for_days_form.days_to_keep.$dirty && prompt_for_days_form.days_to_keep.$error.min"> that is not negative</span><span ng-show="prompt_for_days_form.days_to_keep.$dirty && prompt_for_days_form.days_to_keep.$error.max"> that is lower than 9999</span>.</div>
|
||||
</form>
|
||||
</div>
|
||||
<div id="prompt-for-days-facts" style="display:none">
|
||||
<form name="prompt_for_days_facts_form" id="prompt_for_days_facts_form" class="MgmtCards-promptText">
|
||||
<div style="padding-bottom:15px;"><span translate>For facts collected older than the time period specified, save one fact scan (snapshot) per time window (frequency). For example, facts older than 30 days are purged, while one weekly fact scan is kept.</span>
|
||||
<br>
|
||||
<br>
|
||||
<span translate>CAUTION: Setting both numerical variables to "0" will delete all facts.</span>
|
||||
<br>
|
||||
<br>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description">
|
||||
<span class="label-text" translate>Select a time period after which to remove old facts</span>
|
||||
</label>
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<input type="integer" id="keep_amount" name="keep_amount" ng-model="keep_amount" ng-required="true" class="form-control Form-textInput MgmtCards-card--promptElements" min=0 max=9999 integer></input>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<select id="keep_unit" name="keep_unit" ng-model="keep_unit" ng-options="type.label for type in keep_unit_choices track by type.value" ng-required="true" class="form-control MgmtCards-card--promptElements"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="error" ng-show="prompt_for_days_facts_form.keep_amount.$dirty && (prompt_for_days_facts_form.keep_amount.$error.number || prompt_for_days_facts_form.keep_amount.$error.integer ||
|
||||
prompt_for_days_facts_form.keep_amount.$error.required ||
|
||||
prompt_for_days_facts_form.keep_amount.$error.min ||
|
||||
prompt_for_days_facts_form.keep_amount.$error.max)" translate>Please enter an integer<span ng-show="prompt_for_days_facts_form.keep_amount.$dirty && prompt_for_days_facts_form.keep_amount.$error.min"> that is not negative</span><span ng-show="prompt_for_days_facts_form.keep_amount.$dirty && prompt_for_days_facts_form.keep_amount.$error.max"> that is lower than 9999</span>.</div>
|
||||
</div>
|
||||
<div class="form-group ">
|
||||
<label for="description">
|
||||
<span class="label-text" translate>Select a frequency for snapshot retention</span>
|
||||
</label>
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<input type="integer" id="granularity_keep_amount" name="granularity_keep_amount" ng-model="granularity_keep_amount" ng-required="true" class="form-control Form-textInput MgmtCards-card--promptElements" min=0 max=9999 integer></input>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<select id="granularity_keep_unit" name="granularity_keep_unit" ng-model="granularity_keep_unit" ng-options="type.label for type in granularity_keep_unit_choices track by type.value" ng-required="true" class="form-control MgmtCards-card--promptElements"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="error" ng-show="prompt_for_days_facts_form.granularity_keep_amount.$dirty && (prompt_for_days_facts_form.granularity_keep_amount.$error.number || prompt_for_days_facts_form.granularity_keep_amount.$error.integer ||
|
||||
prompt_for_days_facts_form.granularity_keep_amount.$error.required ||
|
||||
prompt_for_days_facts_form.granularity_keep_amount.$error.min ||
|
||||
prompt_for_days_facts_form.granularity_keep_amount.$error.max)" translate>Please enter an integer<span ng-show="prompt_for_days_facts_form.granularity_keep_amount.$dirty && prompt_for_days_facts_form.granularity_keep_amount.$error.min"> that is not negative</span><span ng-show="prompt_for_days_facts_form.granularity_keep_amount.$dirty && prompt_for_days_facts_form.granularity_keep_amount.$error.max"> that is lower than 9999</span>.</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="overlay"></div>
|
||||
<div class="spinny"><i class="fa fa-cog fa-spin fa-2x"></i>
|
||||
<p translate>working...</p>
|
||||
</div>
|
||||
</div>
|
||||
</at-layout>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@ -1,9 +1,11 @@
|
||||
function atActionGroup (pathService) {
|
||||
const templateUrl = require('@components/action/action-group.partial.html');
|
||||
|
||||
function atActionGroup () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
transclude: true,
|
||||
templateUrl: pathService.getPartialPath('components/action/action-group'),
|
||||
templateUrl,
|
||||
scope: {
|
||||
col: '@',
|
||||
pos: '@'
|
||||
@ -11,6 +13,4 @@ function atActionGroup (pathService) {
|
||||
};
|
||||
}
|
||||
|
||||
atActionGroup.$inject = ['PathService'];
|
||||
|
||||
export default atActionGroup;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const templateUrl = require('@components/form/action.partial.html');
|
||||
|
||||
function link (scope, element, attrs, controllers) {
|
||||
let formController = controllers[0];
|
||||
let actionController = controllers[1];
|
||||
@ -52,13 +54,13 @@ function atFormActionController ($state, strings) {
|
||||
|
||||
atFormActionController.$inject = ['$state', 'ComponentsStrings'];
|
||||
|
||||
function atFormAction (pathService) {
|
||||
function atFormAction () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
replace: true,
|
||||
require: ['^^atForm', 'atFormAction'],
|
||||
templateUrl: pathService.getPartialPath('components/form/action'),
|
||||
templateUrl,
|
||||
controller: atFormActionController,
|
||||
controllerAs: 'vm',
|
||||
link,
|
||||
@ -70,6 +72,4 @@ function atFormAction (pathService) {
|
||||
};
|
||||
}
|
||||
|
||||
atFormAction.$inject = ['PathService'];
|
||||
|
||||
export default atFormAction;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const templateUrl = require('@components/form/form.partial.html');
|
||||
|
||||
function atFormLink (scope, el, attrs, controllers) {
|
||||
let formController = controllers[0];
|
||||
let form = el[0];
|
||||
@ -195,13 +197,13 @@ function AtFormController (eventService, strings) {
|
||||
|
||||
AtFormController.$inject = ['EventService', 'ComponentsStrings'];
|
||||
|
||||
function atForm (pathService) {
|
||||
function atForm () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
transclude: true,
|
||||
require: ['atForm'],
|
||||
templateUrl: pathService.getPartialPath('components/form/form'),
|
||||
templateUrl,
|
||||
controller: AtFormController,
|
||||
controllerAs: 'vm',
|
||||
link: atFormLink,
|
||||
@ -211,6 +213,4 @@ function atForm (pathService) {
|
||||
};
|
||||
}
|
||||
|
||||
atForm.$inject = ['PathService'];
|
||||
|
||||
export default atForm;
|
||||
|
||||
@ -1,39 +1,35 @@
|
||||
import layout from './layout/layout.directive';
|
||||
import topNavItem from './layout/top-nav-item.directive';
|
||||
import sideNav from './layout/side-nav.directive';
|
||||
import sideNavItem from './layout/side-nav-item.directive';
|
||||
import actionGroup from './action/action-group.directive';
|
||||
import divider from './utility/divider.directive';
|
||||
import form from './form/form.directive';
|
||||
import formAction from './form/action.directive';
|
||||
import inputCheckbox from './input/checkbox.directive';
|
||||
import inputGroup from './input/group.directive';
|
||||
import inputLabel from './input/label.directive';
|
||||
import inputLookup from './input/lookup.directive';
|
||||
import inputMessage from './input/message.directive';
|
||||
import inputSecret from './input/secret.directive';
|
||||
import inputSelect from './input/select.directive';
|
||||
import inputText from './input/text.directive';
|
||||
import inputTextarea from './input/textarea.directive';
|
||||
import inputTextareaSecret from './input/textarea-secret.directive';
|
||||
import modal from './modal/modal.directive';
|
||||
import panel from './panel/panel.directive';
|
||||
import panelHeading from './panel/heading.directive';
|
||||
import panelBody from './panel/body.directive';
|
||||
import popover from './popover/popover.directive';
|
||||
import tab from './tabs/tab.directive';
|
||||
import tabGroup from './tabs/group.directive';
|
||||
import truncate from './truncate/truncate.directive';
|
||||
import actionGroup from '@components/action/action-group.directive';
|
||||
import divider from '@components/utility/divider.directive';
|
||||
import form from '@components/form/form.directive';
|
||||
import formAction from '@components/form/action.directive';
|
||||
import inputCheckbox from '@components/input/checkbox.directive';
|
||||
import inputGroup from '@components/input/group.directive';
|
||||
import inputLabel from '@components/input/label.directive';
|
||||
import inputLookup from '@components/input/lookup.directive';
|
||||
import inputMessage from '@components/input/message.directive';
|
||||
import inputSecret from '@components/input/secret.directive';
|
||||
import inputSelect from '@components/input/select.directive';
|
||||
import inputText from '@components/input/text.directive';
|
||||
import inputTextarea from '@components/input/textarea.directive';
|
||||
import inputTextareaSecret from '@components/input/textarea-secret.directive';
|
||||
import layout from '@components/layout/layout.directive';
|
||||
import modal from '@components/modal/modal.directive';
|
||||
import panel from '@components/panel/panel.directive';
|
||||
import panelBody from '@components/panel/body.directive';
|
||||
import panelHeading from '@components/panel/heading.directive';
|
||||
import popover from '@components/popover/popover.directive';
|
||||
import sideNav from '@components/layout/side-nav.directive';
|
||||
import sideNavItem from '@components/layout/side-nav-item.directive';
|
||||
import tab from '@components/tabs/tab.directive';
|
||||
import tabGroup from '@components/tabs/group.directive';
|
||||
import topNavItem from '@components/layout/top-nav-item.directive';
|
||||
import truncate from '@components/truncate/truncate.directive';
|
||||
|
||||
import BaseInputController from './input/base.controller';
|
||||
import ComponentsStrings from './components.strings';
|
||||
import BaseInputController from '@components/input/base.controller';
|
||||
import ComponentsStrings from '@components/components.strings';
|
||||
|
||||
angular
|
||||
.module('at.lib.components', [])
|
||||
.directive('atLayout', layout)
|
||||
.directive('atTopNavItem', topNavItem)
|
||||
.directive('atSideNav', sideNav)
|
||||
.directive('atSideNavItem', sideNavItem)
|
||||
.directive('atActionGroup', actionGroup)
|
||||
.directive('atDivider', divider)
|
||||
.directive('atForm', form)
|
||||
@ -48,13 +44,17 @@ angular
|
||||
.directive('atInputText', inputText)
|
||||
.directive('atInputTextarea', inputTextarea)
|
||||
.directive('atInputTextareaSecret', inputTextareaSecret)
|
||||
.directive('atLayout', layout)
|
||||
.directive('atModal', modal)
|
||||
.directive('atPanel', panel)
|
||||
.directive('atPanelHeading', panelHeading)
|
||||
.directive('atPanelBody', panelBody)
|
||||
.directive('atPanelHeading', panelHeading)
|
||||
.directive('atPopover', popover)
|
||||
.directive('atSideNav', sideNav)
|
||||
.directive('atSideNavItem', sideNavItem)
|
||||
.directive('atTab', tab)
|
||||
.directive('atTabGroup', tabGroup)
|
||||
.directive('atTopNavItem', topNavItem)
|
||||
.directive('atTruncate', truncate)
|
||||
.service('ComponentsStrings', ComponentsStrings)
|
||||
.service('BaseInputController', BaseInputController);
|
||||
.service('BaseInputController', BaseInputController)
|
||||
.service('ComponentsStrings', ComponentsStrings);
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const templateUrl = require('@components/input/checkbox.partial.html');
|
||||
|
||||
function atInputCheckboxLink (scope, element, attrs, controllers) {
|
||||
let formController = controllers[0];
|
||||
let inputController = controllers[1];
|
||||
@ -23,13 +25,13 @@ function AtInputCheckboxController (baseInputController) {
|
||||
|
||||
AtInputCheckboxController.$inject = ['BaseInputController'];
|
||||
|
||||
function atInputCheckbox (pathService) {
|
||||
function atInputCheckbox () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
replace: true,
|
||||
require: ['^^atForm', 'atInputCheckbox'],
|
||||
templateUrl: pathService.getPartialPath('components/input/checkbox'),
|
||||
templateUrl,
|
||||
controller: AtInputCheckboxController,
|
||||
controllerAs: 'vm',
|
||||
link: atInputCheckboxLink,
|
||||
@ -41,6 +43,4 @@ function atInputCheckbox (pathService) {
|
||||
};
|
||||
}
|
||||
|
||||
atInputCheckbox.$inject = ['PathService'];
|
||||
|
||||
export default atInputCheckbox;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const templateUrl = require('@components/input/group.partial.html');
|
||||
|
||||
function atInputGroupLink (scope, el, attrs, controllers) {
|
||||
let groupController = controllers[0];
|
||||
let formController = controllers[1];
|
||||
@ -168,13 +170,13 @@ function AtInputGroupController ($scope, $compile) {
|
||||
|
||||
AtInputGroupController.$inject = ['$scope', '$compile'];
|
||||
|
||||
function atInputGroup (pathService) {
|
||||
function atInputGroup () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
transclude: true,
|
||||
require: ['atInputGroup', '^^atForm'],
|
||||
templateUrl: pathService.getPartialPath('components/input/group'),
|
||||
templateUrl,
|
||||
controller: AtInputGroupController,
|
||||
controllerAs: 'vm',
|
||||
link: atInputGroupLink,
|
||||
@ -186,6 +188,4 @@ function atInputGroup (pathService) {
|
||||
};
|
||||
}
|
||||
|
||||
atInputGroup.$inject = ['PathService'];
|
||||
|
||||
export default atInputGroup;
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
function atInputLabel (pathService) {
|
||||
const templateUrl = require('@components/input/label.partial.html');
|
||||
|
||||
function atInputLabel () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: pathService.getPartialPath('components/input/label')
|
||||
templateUrl
|
||||
};
|
||||
}
|
||||
|
||||
atInputLabel.$inject = ['PathService'];
|
||||
|
||||
export default atInputLabel;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const templateUrl = require('@components/input/lookup.partial.html');
|
||||
|
||||
const DEFAULT_DEBOUNCE = 250;
|
||||
const DEFAULT_KEY = 'name';
|
||||
|
||||
@ -120,13 +122,13 @@ AtInputLookupController.$inject = [
|
||||
'$stateParams'
|
||||
];
|
||||
|
||||
function atInputLookup (pathService) {
|
||||
function atInputLookup () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
replace: true,
|
||||
require: ['^^atForm', 'atInputLookup'],
|
||||
templateUrl: pathService.getPartialPath('components/input/lookup'),
|
||||
templateUrl,
|
||||
controller: AtInputLookupController,
|
||||
controllerAs: 'vm',
|
||||
link: atInputLookupLink,
|
||||
@ -138,6 +140,4 @@ function atInputLookup (pathService) {
|
||||
};
|
||||
}
|
||||
|
||||
atInputLookup.$inject = ['PathService'];
|
||||
|
||||
export default atInputLookup;
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
function atInputMessage (pathService) {
|
||||
const templateUrl = require('@components/input/message.partial.html');
|
||||
|
||||
function atInputMessage () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: pathService.getPartialPath('components/input/message'),
|
||||
templateUrl
|
||||
};
|
||||
}
|
||||
|
||||
atInputMessage.$inject = ['PathService'];
|
||||
|
||||
export default atInputMessage;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const templateUrl = require('@components/input/secret.partial.html');
|
||||
|
||||
function atInputSecretLink (scope, element, attrs, controllers) {
|
||||
let formController = controllers[0];
|
||||
let inputController = controllers[1];
|
||||
@ -48,13 +50,13 @@ function AtInputSecretController (baseInputController) {
|
||||
|
||||
AtInputSecretController.$inject = ['BaseInputController'];
|
||||
|
||||
function atInputSecret (pathService) {
|
||||
function atInputSecret () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
replace: true,
|
||||
require: ['^^atForm', 'atInputSecret'],
|
||||
templateUrl: pathService.getPartialPath('components/input/secret'),
|
||||
templateUrl,
|
||||
controller: AtInputSecretController,
|
||||
controllerAs: 'vm',
|
||||
link: atInputSecretLink,
|
||||
@ -66,6 +68,4 @@ function atInputSecret (pathService) {
|
||||
};
|
||||
}
|
||||
|
||||
atInputSecret.$inject = ['PathService'];
|
||||
|
||||
export default atInputSecret;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const templateUrl = require('@components/input/select.partial.html');
|
||||
|
||||
function atInputSelectLink (scope, element, attrs, controllers) {
|
||||
let formController = controllers[0];
|
||||
let inputController = controllers[1];
|
||||
@ -72,13 +74,13 @@ function AtInputSelectController (baseInputController, eventService) {
|
||||
|
||||
AtInputSelectController.$inject = ['BaseInputController', 'EventService'];
|
||||
|
||||
function atInputSelect (pathService) {
|
||||
function atInputSelect () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
replace: true,
|
||||
require: ['^^at-form', 'atInputSelect'],
|
||||
templateUrl: pathService.getPartialPath('components/input/select'),
|
||||
templateUrl,
|
||||
controller: AtInputSelectController,
|
||||
controllerAs: 'vm',
|
||||
link: atInputSelectLink,
|
||||
@ -90,6 +92,4 @@ function atInputSelect (pathService) {
|
||||
};
|
||||
}
|
||||
|
||||
atInputSelect.$inject = ['PathService'];
|
||||
|
||||
export default atInputSelect;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const templateUrl = require('@components/input/text.partial.html');
|
||||
|
||||
function atInputTextLink (scope, element, attrs, controllers) {
|
||||
let formController = controllers[0];
|
||||
let inputController = controllers[1];
|
||||
@ -21,13 +23,13 @@ function AtInputTextController (baseInputController) {
|
||||
|
||||
AtInputTextController.$inject = ['BaseInputController'];
|
||||
|
||||
function atInputText (pathService) {
|
||||
function atInputText () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
replace: true,
|
||||
require: ['^^atForm', 'atInputText'],
|
||||
templateUrl: pathService.getPartialPath('components/input/text'),
|
||||
templateUrl,
|
||||
controller: AtInputTextController,
|
||||
controllerAs: 'vm',
|
||||
link: atInputTextLink,
|
||||
@ -39,6 +41,4 @@ function atInputText (pathService) {
|
||||
};
|
||||
}
|
||||
|
||||
atInputText.$inject = ['PathService'];
|
||||
|
||||
export default atInputText;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const templateUrl = require('@components/input/textarea-secret.partial.html');
|
||||
|
||||
function atInputTextareaSecretLink (scope, element, attrs, controllers) {
|
||||
let formController = controllers[0];
|
||||
let inputController = controllers[1];
|
||||
@ -96,13 +98,13 @@ AtInputTextareaSecretController.$inject = [
|
||||
'ComponentsStrings'
|
||||
];
|
||||
|
||||
function atInputTextareaSecret (pathService) {
|
||||
function atInputTextareaSecret () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
replace: true,
|
||||
require: ['^^atForm', 'atInputTextareaSecret'],
|
||||
templateUrl: pathService.getPartialPath('components/input/textarea-secret'),
|
||||
templateUrl,
|
||||
controller: AtInputTextareaSecretController,
|
||||
controllerAs: 'vm',
|
||||
link: atInputTextareaSecretLink,
|
||||
@ -114,6 +116,4 @@ function atInputTextareaSecret (pathService) {
|
||||
};
|
||||
}
|
||||
|
||||
atInputTextareaSecret.$inject = ['PathService'];
|
||||
|
||||
export default atInputTextareaSecret;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const templateUrl = require('@components/input/textarea.partial.html');
|
||||
|
||||
function atInputTextareaLink (scope, element, attrs, controllers) {
|
||||
let formController = controllers[0];
|
||||
let inputController = controllers[1];
|
||||
@ -21,13 +23,13 @@ function AtInputTextareaController (baseInputController) {
|
||||
|
||||
AtInputTextareaController.$inject = ['BaseInputController'];
|
||||
|
||||
function atInputTextarea (pathService) {
|
||||
function atInputTextarea () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
replace: true,
|
||||
require: ['^^atForm', 'atInputTextarea'],
|
||||
templateUrl: pathService.getPartialPath('components/input/textarea'),
|
||||
templateUrl,
|
||||
controller: AtInputTextareaController,
|
||||
controllerAs: 'vm',
|
||||
link: atInputTextareaLink,
|
||||
@ -39,6 +41,4 @@ function atInputTextarea (pathService) {
|
||||
};
|
||||
}
|
||||
|
||||
atInputTextarea.$inject = ['PathService'];
|
||||
|
||||
export default atInputTextarea;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const templateUrl = require('@components/layout/layout.partial.html');
|
||||
|
||||
function AtLayoutController ($scope, strings) {
|
||||
let vm = this || {};
|
||||
|
||||
@ -34,12 +36,12 @@ function AtLayoutController ($scope, strings) {
|
||||
|
||||
AtLayoutController.$inject = ['$scope', 'ComponentsStrings'];
|
||||
|
||||
function atLayout (pathService) {
|
||||
function atLayout () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
transclude: true,
|
||||
templateUrl: pathService.getPartialPath('components/layout/layout'),
|
||||
templateUrl,
|
||||
controller: AtLayoutController,
|
||||
controllerAs: 'vm',
|
||||
scope: {
|
||||
@ -47,6 +49,4 @@ function atLayout (pathService) {
|
||||
};
|
||||
}
|
||||
|
||||
atLayout.$inject = ['PathService'];
|
||||
|
||||
export default atLayout;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const templateUrl = require('@components/layout/side-nav-item.partial.html');
|
||||
|
||||
function atSideNavItemLink (scope, element, attrs, ctrl) {
|
||||
scope.navVm = ctrl[0];
|
||||
scope.layoutVm = ctrl[1];
|
||||
@ -29,10 +31,10 @@ function AtSideNavItemController ($state, $scope) {
|
||||
|
||||
AtSideNavItemController.$inject = ['$state', '$scope'];
|
||||
|
||||
function atSideNavItem (pathService) {
|
||||
function atSideNavItem () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
templateUrl: pathService.getPartialPath('components/layout/side-nav-item'),
|
||||
templateUrl,
|
||||
require: ['^^atSideNav', '^^atLayout'],
|
||||
controller: AtSideNavItemController,
|
||||
controllerAs: 'vm',
|
||||
@ -46,6 +48,4 @@ function atSideNavItem (pathService) {
|
||||
};
|
||||
}
|
||||
|
||||
atSideNavItem.$inject = ['PathService'];
|
||||
|
||||
export default atSideNavItem;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const templateUrl = require('@components/layout/side-nav.partial.html');
|
||||
|
||||
function atSideNavLink (scope, element, attrs, ctrl) {
|
||||
scope.layoutVm = ctrl;
|
||||
}
|
||||
@ -12,7 +14,7 @@ function AtSideNavController () {
|
||||
}
|
||||
}
|
||||
|
||||
function atSideNav (pathService) {
|
||||
function atSideNav () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
@ -21,12 +23,10 @@ function atSideNav (pathService) {
|
||||
controllerAs: 'vm',
|
||||
link: atSideNavLink,
|
||||
transclude: true,
|
||||
templateUrl: pathService.getPartialPath('components/layout/side-nav'),
|
||||
templateUrl,
|
||||
scope: {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
atSideNav.$inject = ['PathService'];
|
||||
|
||||
export default atSideNav;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const templateUrl = require('@components/layout/top-nav-item.partial.html');
|
||||
|
||||
function atTopNavItemLink (scope, element, attrs, ctrl) {
|
||||
scope.layoutVm = ctrl;
|
||||
|
||||
@ -12,12 +14,12 @@ function atTopNavItemLink (scope, element, attrs, ctrl) {
|
||||
}
|
||||
}
|
||||
|
||||
function atTopNavItem (pathService) {
|
||||
function atTopNavItem () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
transclude: true,
|
||||
templateUrl: pathService.getPartialPath('components/layout/top-nav-item'),
|
||||
templateUrl,
|
||||
require: '^^atLayout',
|
||||
link: atTopNavItemLink,
|
||||
scope: {
|
||||
@ -25,6 +27,4 @@ function atTopNavItem (pathService) {
|
||||
};
|
||||
}
|
||||
|
||||
atTopNavItem.$inject = ['PathService'];
|
||||
|
||||
export default atTopNavItem;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const templateUrl = require('@components/modal/modal.partial.html');
|
||||
|
||||
const DEFAULT_ANIMATION_DURATION = 150;
|
||||
|
||||
function atModalLink (scope, el, attrs, controllers) {
|
||||
@ -74,13 +76,13 @@ AtModalController.$inject = [
|
||||
'ComponentsStrings'
|
||||
]
|
||||
|
||||
function atModal (pathService) {
|
||||
function atModal () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
transclude: true,
|
||||
require: ['atModal'],
|
||||
templateUrl: pathService.getPartialPath('components/modal/modal'),
|
||||
templateUrl,
|
||||
controller: AtModalController,
|
||||
controllerAs: 'vm',
|
||||
link: atModalLink,
|
||||
@ -88,8 +90,4 @@ function atModal (pathService) {
|
||||
};
|
||||
}
|
||||
|
||||
atModal.$inject = [
|
||||
'PathService'
|
||||
];
|
||||
|
||||
export default atModal;
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
function atPanelBody (pathService) {
|
||||
const templateUrl = require('@components/panel/body.partial.html');
|
||||
|
||||
function atPanelBody () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
transclude: true,
|
||||
templateUrl: pathService.getPartialPath('components/panel/body'),
|
||||
templateUrl,
|
||||
scope: {
|
||||
state: '='
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
atPanelBody.$inject = ['PathService'];
|
||||
|
||||
export default atPanelBody;
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
const templateUrl = require('@components/panel/heading.partial.html');
|
||||
|
||||
function link (scope, el, attrs, panel) {
|
||||
panel.use(scope);
|
||||
}
|
||||
|
||||
function atPanelHeading (pathService) {
|
||||
function atPanelHeading () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
require: '^^atPanel',
|
||||
replace: true,
|
||||
transclude: true,
|
||||
templateUrl: pathService.getPartialPath('components/panel/heading'),
|
||||
templateUrl,
|
||||
link
|
||||
};
|
||||
}
|
||||
|
||||
atPanelHeading.$inject = ['PathService'];
|
||||
|
||||
export default atPanelHeading;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const templateUrl = require('@components/panel/panel.partial.html');
|
||||
|
||||
function atPanelLink (scope, el, attrs, controllers) {
|
||||
let panelController = controllers[0];
|
||||
|
||||
@ -26,13 +28,13 @@ function AtPanelController ($state) {
|
||||
|
||||
AtPanelController.$inject = ['$state'];
|
||||
|
||||
function atPanel (pathService, _$animate_) {
|
||||
function atPanel () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
require: ['atPanel'],
|
||||
transclude: true,
|
||||
templateUrl: pathService.getPartialPath('components/panel/panel'),
|
||||
templateUrl,
|
||||
controller: AtPanelController,
|
||||
controllerAs: 'vm',
|
||||
link: atPanelLink,
|
||||
@ -43,6 +45,4 @@ function atPanel (pathService, _$animate_) {
|
||||
};
|
||||
}
|
||||
|
||||
atPanel.$inject = ['PathService'];
|
||||
|
||||
export default atPanel;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const templateUrl = require('@components/popover/popover.partial.html');
|
||||
|
||||
const DEFAULT_POSITION = 'right';
|
||||
const DEFAULT_ACTION = 'click';
|
||||
const DEFAULT_ICON = 'fa fa-question-circle';
|
||||
@ -201,13 +203,13 @@ function AtPopoverController () {
|
||||
};
|
||||
}
|
||||
|
||||
function atPopover (pathService) {
|
||||
function atPopover () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
transclude: true,
|
||||
require: ['atPopover'],
|
||||
templateUrl: pathService.getPartialPath('components/popover/popover'),
|
||||
templateUrl,
|
||||
controller: AtPopoverController,
|
||||
controllerAs: 'vm',
|
||||
link: atPopoverLink,
|
||||
@ -217,8 +219,4 @@ function atPopover (pathService) {
|
||||
};
|
||||
}
|
||||
|
||||
atPopover.$inject = [
|
||||
'PathService'
|
||||
];
|
||||
|
||||
export default atPopover;
|
||||
export default atPopover;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const templateUrl = require('@components/tabs/group.partial.html');
|
||||
|
||||
function atTabGroupLink (scope, el, attrs, controllers) {
|
||||
let groupController = controllers[0];
|
||||
|
||||
@ -26,13 +28,13 @@ function AtTabGroupController ($state) {
|
||||
|
||||
AtTabGroupController.$inject = ['$state'];
|
||||
|
||||
function atTabGroup (pathService, _$animate_) {
|
||||
function atTabGroup () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
require: ['atTabGroup'],
|
||||
transclude: true,
|
||||
templateUrl: pathService.getPartialPath('components/tabs/group'),
|
||||
templateUrl,
|
||||
controller: AtTabGroupController,
|
||||
controllerAs: 'vm',
|
||||
link: atTabGroupLink,
|
||||
@ -42,6 +44,4 @@ function atTabGroup (pathService, _$animate_) {
|
||||
};
|
||||
}
|
||||
|
||||
atTabGroup.$inject = ['PathService'];
|
||||
|
||||
export default atTabGroup;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const templateUrl = require('@components/tabs/tab.partial.html');
|
||||
|
||||
function atTabLink (scope, el, attrs, controllers) {
|
||||
let groupController = controllers[0];
|
||||
let tabController = controllers[1];
|
||||
@ -31,13 +33,13 @@ function AtTabController ($state) {
|
||||
|
||||
AtTabController.$inject = ['$state'];
|
||||
|
||||
function atTab (pathService, _$animate_) {
|
||||
function atTab () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
transclude: true,
|
||||
require: ['^^atTabGroup', 'atTab'],
|
||||
templateUrl: pathService.getPartialPath('components/tabs/tab'),
|
||||
templateUrl,
|
||||
controller: AtTabController,
|
||||
controllerAs: 'vm',
|
||||
link: atTabLink,
|
||||
@ -47,6 +49,4 @@ function atTab (pathService, _$animate_) {
|
||||
};
|
||||
}
|
||||
|
||||
atTab.$inject = ['PathService'];
|
||||
|
||||
export default atTab;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const templateUrl = require('@components/truncate/truncate.partial.html');
|
||||
|
||||
function atTruncateLink (scope, el, attr, ctrl) {
|
||||
let truncateController = ctrl;
|
||||
let string = attr.string;
|
||||
@ -44,12 +46,12 @@ function AtTruncateController (strings) {
|
||||
|
||||
AtTruncateController.$inject = ['ComponentsStrings'];
|
||||
|
||||
function atTruncate(pathService) {
|
||||
function atTruncate() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
transclude: true,
|
||||
templateUrl: pathService.getPartialPath('components/truncate/truncate'),
|
||||
templateUrl,
|
||||
controller: AtTruncateController,
|
||||
controllerAs: 'vm',
|
||||
link: atTruncateLink,
|
||||
@ -61,8 +63,4 @@ function atTruncate(pathService) {
|
||||
}
|
||||
}
|
||||
|
||||
atTruncate.$inject = [
|
||||
'PathService'
|
||||
];
|
||||
|
||||
export default atTruncate;
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
function atPanelBody (pathService) {
|
||||
const templateUrl = require('@components/utility/divider.partial.html');
|
||||
|
||||
function atPanelBody () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: pathService.getPartialPath('components/utility/divider'),
|
||||
templateUrl,
|
||||
scope: false
|
||||
};
|
||||
}
|
||||
|
||||
atPanelBody.$inject = ['PathService'];
|
||||
|
||||
export default atPanelBody;
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import Base from './Base';
|
||||
import Config from './Config';
|
||||
import Credential from './Credential';
|
||||
import CredentialType from './CredentialType';
|
||||
import Me from './Me';
|
||||
import Organization from './Organization';
|
||||
import Base from '@models/Base';
|
||||
import Config from '@models/Config';
|
||||
import Credential from '@models/Credential';
|
||||
import CredentialType from '@models/CredentialType';
|
||||
import Me from '@models/Me';
|
||||
import Organization from '@models/Organization';
|
||||
|
||||
angular
|
||||
.module('at.lib.models', [])
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import defaults from '../../assets/default.strings.json';
|
||||
import defaults from '@assets/default.strings.json';
|
||||
|
||||
let i18n;
|
||||
|
||||
|
||||
@ -1,13 +1,11 @@
|
||||
import CacheService from './cache.service';
|
||||
import EventService from './event.service';
|
||||
import PathService from './path.service';
|
||||
import BaseStringService from './base-string.service';
|
||||
import AppStrings from './app.strings';
|
||||
import CacheService from '@services/cache.service';
|
||||
import EventService from '@services/event.service';
|
||||
import BaseStringService from '@services/base-string.service';
|
||||
import AppStrings from '@services/app.strings';
|
||||
|
||||
angular
|
||||
.module('at.lib.services', [])
|
||||
.service('AppStrings', AppStrings)
|
||||
.service('BaseStringService', BaseStringService)
|
||||
.service('CacheService', CacheService)
|
||||
.service('EventService', EventService)
|
||||
.service('PathService', PathService);
|
||||
.service('EventService', EventService);
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
function PathService () {
|
||||
this.getPartialPath = path => {
|
||||
return `/static/partials/${path}.partial.html`;
|
||||
};
|
||||
|
||||
this.getViewPath = path => {
|
||||
return `/static/views/${path}.view.html`;
|
||||
}
|
||||
}
|
||||
|
||||
export default PathService;
|
||||
@ -18,24 +18,24 @@
|
||||
* NOTE: Styles below are a mix of 3rd-party dependencies and in-house code. For the 3rd-party
|
||||
* stuff, we'd be better off managing them via npm where possible.
|
||||
*/
|
||||
@import '../../legacy-styles/fonts';
|
||||
@import '../../legacy-styles/animations';
|
||||
@import '../../legacy-styles/jquery-ui-overrides';
|
||||
@import '../../legacy-styles/codemirror';
|
||||
@import '../../legacy-styles/angular-scheduler';
|
||||
@import '../../legacy-styles/log-viewer';
|
||||
@import '../../legacy-styles/event-viewer';
|
||||
@import '../../legacy-styles/job-details';
|
||||
@import '../../legacy-styles/jobs';
|
||||
@import '../../legacy-styles/inventory-edit';
|
||||
@import '../../legacy-styles/stdout';
|
||||
@import '../../legacy-styles/lists';
|
||||
@import '../../legacy-styles/forms';
|
||||
@import '../../legacy-styles/dashboard';
|
||||
@import '../../legacy-styles/survey-maker';
|
||||
@import '../../legacy-styles/text-label';
|
||||
@import '../../legacy-styles/bootstrap-datepicker';
|
||||
@import '../../legacy-styles/ansible-ui';
|
||||
@import '../../legacy/styles/fonts';
|
||||
@import '../../legacy/styles/animations';
|
||||
@import '../../legacy/styles/jquery-ui-overrides';
|
||||
@import '../../legacy/styles/codemirror';
|
||||
@import '../../legacy/styles/angular-scheduler';
|
||||
@import '../../legacy/styles/log-viewer';
|
||||
@import '../../legacy/styles/event-viewer';
|
||||
@import '../../legacy/styles/job-details';
|
||||
@import '../../legacy/styles/jobs';
|
||||
@import '../../legacy/styles/inventory-edit';
|
||||
@import '../../legacy/styles/stdout';
|
||||
@import '../../legacy/styles/lists';
|
||||
@import '../../legacy/styles/forms';
|
||||
@import '../../legacy/styles/dashboard';
|
||||
@import '../../legacy/styles/survey-maker';
|
||||
@import '../../legacy/styles/text-label';
|
||||
@import '../../legacy/styles/bootstrap-datepicker';
|
||||
@import '../../legacy/styles/ansible-ui';
|
||||
|
||||
// Dependency Style Overrides
|
||||
@import '../../src/shared/bootstrap-settings';
|
||||
|
||||
@ -1,39 +1,17 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2016 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
// Vendor dependencies
|
||||
import 'jquery';
|
||||
import 'angular';
|
||||
import 'angular-gettext';
|
||||
import 'bootstrap';
|
||||
import 'jquery-ui';
|
||||
import 'bootstrap-datepicker';
|
||||
import 'jquery.resize';
|
||||
import 'codemirror';
|
||||
import 'js-yaml';
|
||||
import 'select2';
|
||||
import uiRouter from 'angular-ui-router';
|
||||
// backwards compatibility for $stateChange* events
|
||||
import 'angular-ui-router/release/stateEvents';
|
||||
|
||||
|
||||
// Configuration dependencies
|
||||
global.$AnsibleConfig = null;
|
||||
// Provided via Webpack DefinePlugin in webpack.config.js
|
||||
global.$ENV = {} ;
|
||||
// ui-router debugging
|
||||
if ($ENV['route-debug']){
|
||||
let trace = require('angular-ui-router').trace;
|
||||
let trace = angular.module('ui.router').trace;
|
||||
trace.enable();
|
||||
}
|
||||
|
||||
var urlPrefix;
|
||||
|
||||
if ($basePath) {
|
||||
urlPrefix = $basePath;
|
||||
urlPrefix = `${$basePath}`;
|
||||
}
|
||||
|
||||
// Modules
|
||||
@ -73,22 +51,21 @@ import '../lib/models';
|
||||
import '../lib/services';
|
||||
import '../features';
|
||||
|
||||
var awApp = angular.module('awApp', [
|
||||
// how to add CommonJS / AMD third-party dependencies:
|
||||
// 1. npm install --save package-name
|
||||
// 2. add package name to ./grunt-tasks/webpack.vendorFiles
|
||||
require('angular-breadcrumb'),
|
||||
require('angular-codemirror'),
|
||||
require('angular-drag-and-drop-lists'),
|
||||
require('angular-sanitize'),
|
||||
require('angular-scheduler').name,
|
||||
require('angular-tz-extensions'),
|
||||
require('angular-md5'),
|
||||
require('lr-infinite-scroll'),
|
||||
require('ng-toast'),
|
||||
'gettext',
|
||||
angular.module('awApp', [
|
||||
'I18N',
|
||||
uiRouter,
|
||||
'AngularCodeMirrorModule',
|
||||
'angular-duration-format',
|
||||
'angularMoment',
|
||||
'AngularScheduler',
|
||||
'angular-md5',
|
||||
'dndLists',
|
||||
'ncy-angular-breadcrumb',
|
||||
'ngSanitize',
|
||||
'ngCookies',
|
||||
'ngToast',
|
||||
'gettext',
|
||||
'Timezones',
|
||||
'ui.router',
|
||||
'ui.router.state.events',
|
||||
'lrInfiniteScroll',
|
||||
|
||||
@ -134,7 +111,6 @@ var awApp = angular.module('awApp', [
|
||||
'at.lib.services',
|
||||
'at.features',
|
||||
])
|
||||
|
||||
.constant('AngularScheduler.partials', urlPrefix + 'lib/angular-scheduler/lib/')
|
||||
.constant('AngularScheduler.useTimezone', true)
|
||||
.constant('AngularScheduler.showUTCField', true)
|
||||
@ -465,5 +441,3 @@ var awApp = angular.module('awApp', [
|
||||
LoadConfig();
|
||||
}
|
||||
]);
|
||||
|
||||
export default awApp;
|
||||
|
||||
@ -4,9 +4,6 @@
|
||||
* Options: static height, custom breakpoint
|
||||
*/
|
||||
|
||||
@import "./client/src/shared/branding/colors.default.less";
|
||||
|
||||
|
||||
.OnePlusOne-container(@height: 100%; @breakpoint: 900px){
|
||||
height: ~"calc(100vh - 150px)";
|
||||
display: flex;
|
||||
|
||||
@ -6,8 +6,6 @@
|
||||
* Style conventions
|
||||
* .ModuleName-component--subComponent
|
||||
*/
|
||||
@import "./client/src/shared/branding/colors.default.less";
|
||||
|
||||
|
||||
.OnePlusTwo-container(@height: 100%; @breakpoint: 900px){
|
||||
height: @height;
|
||||
|
||||
@ -34,10 +34,10 @@ import orgAdminLookup from './org-admin-lookup/main';
|
||||
import limitPanels from './limit-panels/main';
|
||||
import multiSelectPreview from './multi-select-preview/main';
|
||||
import credentialTypesLookup from './credentialTypesLookup.factory';
|
||||
import 'angular-duration-format';
|
||||
|
||||
export default
|
||||
angular.module('shared', [listGenerator.name,
|
||||
angular.module('shared', [
|
||||
listGenerator.name,
|
||||
formGenerator.name,
|
||||
lookupModal.name,
|
||||
smartSearch.name,
|
||||
@ -64,7 +64,7 @@ angular.module('shared', [listGenerator.name,
|
||||
orgAdminLookup.name,
|
||||
limitPanels.name,
|
||||
multiSelectPreview.name,
|
||||
require('angular-cookies'),
|
||||
'ngCookies',
|
||||
'angular-duration-format'
|
||||
])
|
||||
.factory('stateDefinitions', stateDefinitions)
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import newMoment from './moment';
|
||||
|
||||
export default
|
||||
angular.module('moment', [require('angular-moment').name])
|
||||
angular.module('moment', ['angularMoment'])
|
||||
.config(function() {
|
||||
// Remove the global variable for moment
|
||||
delete window.moment;
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
@import "./client/src/shared/branding/colors.default.less";
|
||||
|
||||
.position-center {
|
||||
left: 0;
|
||||
right: 0;
|
||||
@ -255,4 +253,4 @@
|
||||
max-width: ~"calc(100vw - 50px)";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
39
awx/ui/client/src/vendor.js
Normal file
39
awx/ui/client/src/vendor.js
Normal file
@ -0,0 +1,39 @@
|
||||
require('@assets/custom-theme/jquery-ui-1.10.3.custom.min.css');
|
||||
require('@assets/ansible-bootstrap.min.css');
|
||||
require('@assets/fontcustom/fontcustom.css');
|
||||
require('@modules/components-font-awesome/css/font-awesome.min.css');
|
||||
require('@modules/select2/dist/css/select2.css');
|
||||
require('@modules/codemirror/lib/codemirror.css');
|
||||
require('@modules/codemirror/theme/elegant.css');
|
||||
require('@modules/codemirror/addon/lint/lint.css');
|
||||
require('@modules/nvd3/build/nv.d3.css');
|
||||
require('@modules/ng-toast/dist/ngToast.min.css');
|
||||
require('jquery');
|
||||
require('jquery-resize');
|
||||
require('jquery-ui');
|
||||
require('bootstrap');
|
||||
require('bootstrap-datepicker');
|
||||
require('moment');
|
||||
require('select2');
|
||||
require('sprintf-js');
|
||||
require('reconnectingwebsocket');
|
||||
require('d3');
|
||||
require('nvd3');
|
||||
require('angular');
|
||||
require('angular-cookies');
|
||||
require('angular-sanitize');
|
||||
require('angular-breadcrumb');
|
||||
require('angular-codemirror');
|
||||
require('angular-drag-and-drop-lists');
|
||||
require('angular-duration-format');
|
||||
require('angular-gettext');
|
||||
require('angular-md5');
|
||||
require('angular-moment');
|
||||
require('angular-scheduler');
|
||||
require('angular-tz-extensions');
|
||||
require('angular-ui-router');
|
||||
require('angular-ui-router-state-events');
|
||||
require('ng-toast-provider');
|
||||
require('ng-toast-directives');
|
||||
require('ng-toast');
|
||||
require('lr-infinite-scroll');
|
||||
@ -1,30 +0,0 @@
|
||||
var django_port = process.env.npm_package_config_django_port,
|
||||
django_host = process.env.npm_package_config_django_host;
|
||||
|
||||
module.exports = {
|
||||
http: {
|
||||
bsFiles: {
|
||||
src: [
|
||||
'static/**/*',
|
||||
'!static/tower.vendor.js',
|
||||
'!static/tower.vendor.map.js',
|
||||
'!static/tower.js.map'
|
||||
]
|
||||
},
|
||||
options: {
|
||||
proxy: {
|
||||
target: `https://${django_host}:${django_port}`,
|
||||
ws: true
|
||||
},
|
||||
keepalive: false,
|
||||
watchTask: true,
|
||||
reloadDebounce: 1000,
|
||||
// The browser-sync-client lib will write your current scroll position to window.name
|
||||
// https://github.com/BrowserSync/browser-sync-client/blob/a2718faa91e11553feca7a3962313bf1ec6ba3e5/dist/index.js#L500
|
||||
// This strategy is enabled in the core browser-sync lib, and not externally documented as an option. Yay!
|
||||
// https://github.com/BrowserSync/browser-sync/blob/a522aaf12b6167d5591ed285eb3086f43a4d9ac2/lib/default-config.js#L312
|
||||
scrollRestoreTechnique: null,
|
||||
injectChanges: true
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -1,7 +0,0 @@
|
||||
module.exports = {
|
||||
options: { force: true },
|
||||
static: 'static/*',
|
||||
coverage: 'coverage/*',
|
||||
tmp: '../../tmp',
|
||||
jshint: 'coverage/jshint.xml'
|
||||
};
|
||||
@ -1,17 +0,0 @@
|
||||
module.exports = {
|
||||
css: {
|
||||
src: [
|
||||
'static/assets/custom-theme/jquery-ui-1.10.3.custom.min.css',
|
||||
'static/assets/ansible-bootstrap.min.css',
|
||||
'static/assets/fontcustom/fontcustom.css',
|
||||
'static/lib/components-font-awesome/css/font-awesome.min.css',
|
||||
'static/lib/select2/dist/css/select2.css',
|
||||
'static/lib/codemirror/lib/codemirror.css',
|
||||
'static/lib/codemirror/theme/elegant.css',
|
||||
'static/lib/codemirror/addon/lint/lint.css',
|
||||
'static/lib/nvd3/build/nv.d3.css',
|
||||
'static/lib/ng-toast/dist/ngToast.min.css'
|
||||
],
|
||||
dest: 'static/css/app.vendor.css'
|
||||
}
|
||||
};
|
||||
@ -1,61 +0,0 @@
|
||||
module.exports = {
|
||||
dev: {
|
||||
tasks: [
|
||||
'copy:vendor',
|
||||
'copy:assets',
|
||||
'copy:icons',
|
||||
'copy:fonts',
|
||||
'copy:images',
|
||||
'copy:partials',
|
||||
'copy:views',
|
||||
'copy:languages',
|
||||
'copy:config',
|
||||
'less:dev'
|
||||
]
|
||||
},
|
||||
// This concurrent target is intended for development ui builds that do not require raising browser-sync or filesystem polling
|
||||
devNoSync: {
|
||||
tasks: [
|
||||
'copy:vendor',
|
||||
'copy:assets',
|
||||
'copy:icons',
|
||||
'copy:fonts',
|
||||
'copy:images',
|
||||
'copy:partials',
|
||||
'copy:views',
|
||||
'copy:languages',
|
||||
'copy:config',
|
||||
'less:dev',
|
||||
'webpack:dev'
|
||||
]
|
||||
},
|
||||
prod: {
|
||||
tasks: [
|
||||
'newer:copy:vendor',
|
||||
'newer:copy:assets',
|
||||
'newer:copy:icons',
|
||||
'newer:copy:fonts',
|
||||
'newer:copy:images',
|
||||
'newer:copy:partials',
|
||||
'newer:copy:views',
|
||||
'newer:copy:languages',
|
||||
'newer:copy:config',
|
||||
'newer:less:prod'
|
||||
]
|
||||
},
|
||||
watch: {
|
||||
tasks: [
|
||||
'watch:css',
|
||||
'watch:partials',
|
||||
'watch:views',
|
||||
'watch:assets',
|
||||
[
|
||||
'watch:config'
|
||||
]
|
||||
],
|
||||
options: {
|
||||
logConcurrentOutput: true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,100 +0,0 @@
|
||||
var staticFiles = ['angular-tz-extensions/tz/data/*',
|
||||
'angular-scheduler/lib/angular-scheduler-detail.html',
|
||||
'angular-scheduler/lib/angular-scheduler.html',
|
||||
'nvd3/build/nv.d3.css',
|
||||
'ng-toast/dist/ngToast.min.css',
|
||||
'codemirror/addon/lint/lint.css',
|
||||
'codemirror/theme/elegant.css',
|
||||
'codemirror/lib/codemirror.css',
|
||||
'select2/dist/css/select2.css',
|
||||
'components-font-awesome/css/font-awesome.min.css',
|
||||
'components-font-awesome/fonts/fontawesome-webfont.ttf',
|
||||
'components-font-awesome/fonts/fontawesome-webfont.woff',
|
||||
'components-font-awesome/fonts/fontawesome-webfont.woff2'
|
||||
];
|
||||
|
||||
module.exports = {
|
||||
fonts: {
|
||||
files: [{
|
||||
cwd: 'client/',
|
||||
expand: true,
|
||||
flatten: true,
|
||||
filter: 'isFile',
|
||||
src: 'assets/fontcustom/**/*',
|
||||
dest: 'static/fonts/'
|
||||
}]
|
||||
},
|
||||
icons: {
|
||||
files: [{
|
||||
cwd: 'node_modules/',
|
||||
expand: true,
|
||||
flatten: true,
|
||||
filter: 'isFile',
|
||||
src: 'components-font-awesome/fonts/*',
|
||||
dest: 'static/fonts/'
|
||||
}]
|
||||
},
|
||||
images: {
|
||||
files: [{
|
||||
cwd: 'client/',
|
||||
expand: true,
|
||||
flatten: true,
|
||||
filter: 'isFile',
|
||||
src: 'assets/custom-theme/images.new/*',
|
||||
dest: 'static/images/'
|
||||
}]
|
||||
},
|
||||
assets: {
|
||||
files: [{
|
||||
cwd: 'client/',
|
||||
expand: true,
|
||||
src: 'assets/**/*',
|
||||
dest: 'static/'
|
||||
}]
|
||||
},
|
||||
vendor: {
|
||||
files: [{
|
||||
expand: true,
|
||||
cwd: 'node_modules/',
|
||||
src: staticFiles,
|
||||
dest: 'static/lib/'
|
||||
}]
|
||||
},
|
||||
views: {
|
||||
files: [{
|
||||
cwd: 'client/features',
|
||||
expand: true,
|
||||
src: ['**/*.view.html'],
|
||||
dest: 'static/views/'
|
||||
}]
|
||||
},
|
||||
partials: {
|
||||
files: [{
|
||||
cwd: 'client/src',
|
||||
expand: true,
|
||||
src: ['**/*.partial.html'],
|
||||
dest: 'static/partials'
|
||||
}, {
|
||||
cwd: 'client/src/partials',
|
||||
expand: true,
|
||||
src: ['*.html'],
|
||||
dest: 'static/partials/'
|
||||
}, {
|
||||
cwd: 'client/lib/components',
|
||||
expand: true,
|
||||
src: ['**/*.partial.html'],
|
||||
dest: 'static/partials/components/'
|
||||
}]
|
||||
},
|
||||
languages: {
|
||||
files: [{
|
||||
cwd: 'client/',
|
||||
expand: true,
|
||||
src: 'languages/*.json',
|
||||
dest: 'static/'
|
||||
}]
|
||||
},
|
||||
config: {
|
||||
files: { 'static/config.js': ['client/src/config.js'] }
|
||||
}
|
||||
};
|
||||
@ -1,22 +0,0 @@
|
||||
module.exports = {
|
||||
vendor: {
|
||||
files: [
|
||||
{
|
||||
expand: true,
|
||||
src: 'static/css/app.vendor.css',
|
||||
dest: '.',
|
||||
ext: '.vendor.css'
|
||||
}
|
||||
]
|
||||
},
|
||||
source: {
|
||||
files: [
|
||||
{
|
||||
expand: true,
|
||||
src: 'static/css/app.css',
|
||||
dest: '.',
|
||||
ext: '.css'
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
@ -1,27 +0,0 @@
|
||||
var AutoPrefixer = require('less-plugin-autoprefix');
|
||||
|
||||
var autoPrefixer = new AutoPrefixer({
|
||||
browsers: [ 'last 2 versions' ]
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
dev: {
|
||||
files: {
|
||||
'static/css/app.css': 'client/lib/theme/index.less'
|
||||
},
|
||||
options: {
|
||||
sourceMap: true,
|
||||
plugins: [ autoPrefixer ]
|
||||
}
|
||||
},
|
||||
prod: {
|
||||
files: {
|
||||
'static/css/app.css': 'client/lib/theme/index.less'
|
||||
},
|
||||
options: {
|
||||
compress: true,
|
||||
sourceMap: false,
|
||||
plugins: [ autoPrefixer ]
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -3,13 +3,14 @@ module.exports = {
|
||||
options: {
|
||||
format: 'json'
|
||||
},
|
||||
files: [ {
|
||||
files: [{
|
||||
expand: true,
|
||||
dot: true,
|
||||
dest: 'client/languages',
|
||||
cwd: 'po',
|
||||
ext: '.json',
|
||||
src: ['*.po']
|
||||
} ]
|
||||
dot: true,
|
||||
dest: 'client/languages',
|
||||
cwd: 'po',
|
||||
ext: '.json',
|
||||
src: ['*.po']
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
module.exports = {
|
||||
css: {
|
||||
files: 'client/**/*.less',
|
||||
tasks: ['less:dev']
|
||||
},
|
||||
partials: {
|
||||
files: [
|
||||
'client/lib/components/**/*.partial.html',
|
||||
'client/src/**/*.partial.html',
|
||||
'client/src/partials/*.html'
|
||||
],
|
||||
tasks: ['newer:copy:partials']
|
||||
},
|
||||
views: {
|
||||
files: 'client/features/**/*.view.html',
|
||||
tasks: ['newer:copy:views']
|
||||
},
|
||||
assets: {
|
||||
files: 'client/assets',
|
||||
tasks: ['newer:copy:assets']
|
||||
},
|
||||
config: {
|
||||
files: 'client/src/config.js',
|
||||
tasks: ['newer:copy:config']
|
||||
}
|
||||
};
|
||||
@ -1,5 +0,0 @@
|
||||
var config = require('../webpack.config.js');
|
||||
module.exports = {
|
||||
dev: config.dev,
|
||||
prod: config.release
|
||||
};
|
||||
@ -1,5 +1,4 @@
|
||||
var path = require('path'),
|
||||
webpack = require('webpack');
|
||||
const webpackTestConfig = require('./build/webpack.test.js');
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
@ -16,80 +15,20 @@ module.exports = function(config) {
|
||||
'jasmine',
|
||||
],
|
||||
reporters: ['progress', 'coverage', 'junit'],
|
||||
files: [
|
||||
files:[
|
||||
'./client/src/vendor.js',
|
||||
'./client/src/app.js',
|
||||
'./node_modules/angular-mocks/angular-mocks.js',
|
||||
{ pattern: './tests/**/*-test.js' },
|
||||
'client/src/**/*.html'
|
||||
],
|
||||
preprocessors: {
|
||||
'./client/src/vendor.js': ['webpack', 'sourcemap'],
|
||||
'./client/src/app.js': ['webpack', 'sourcemap'],
|
||||
'./tests/**/*-test.js': ['webpack', 'sourcemap'],
|
||||
'client/src/**/*.html': ['html2js']
|
||||
},
|
||||
webpack: {
|
||||
plugins: [
|
||||
// Django-provided definitions
|
||||
new webpack.DefinePlugin({
|
||||
$basePath: '/static/'
|
||||
}),
|
||||
// vendor shims:
|
||||
// [{expected_local_var : dependency}, ...]
|
||||
new webpack.ProvidePlugin({
|
||||
$: 'jquery',
|
||||
jQuery: 'jquery',
|
||||
'window.jQuery': 'jquery',
|
||||
_: 'lodash',
|
||||
'CodeMirror': 'codemirror',
|
||||
'$.fn.datepicker': 'bootstrap-datepicker'
|
||||
})
|
||||
],
|
||||
module: {
|
||||
loaders: [{
|
||||
test: /\.angular.js$/,
|
||||
loader: 'expose?angular'
|
||||
},
|
||||
{
|
||||
test: /\.json$/,
|
||||
loader: 'json-loader',
|
||||
exclude: '/(node_modules)/'
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
include: [path.resolve() + '/tests/'],
|
||||
exclude: '/(node_modules)/',
|
||||
query: {
|
||||
presets: ['es2015']
|
||||
}
|
||||
}, {
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
include: [
|
||||
path.resolve() + '/client/src/',
|
||||
path.resolve() + '/client/lib/',
|
||||
path.resolve() + '/client/features/'
|
||||
],
|
||||
exclude: '/(node_modules)/',
|
||||
query: {
|
||||
presets: ['es2015'],
|
||||
plugins: ['istanbul']
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
resolve: {
|
||||
root: [],
|
||||
modulesDirectory: ['node_modules'],
|
||||
alias: {
|
||||
'jquery.resize': path.resolve() + '/node_modules/javascript-detect-element-resize/jquery.resize.js',
|
||||
'select2': path.resolve() + '/node_modules/select2/dist/js/select2.full.js'
|
||||
}
|
||||
},
|
||||
devtool: 'inline-source-map',
|
||||
debug: true,
|
||||
cache: true
|
||||
},
|
||||
webpack: webpackTestConfig,
|
||||
webpackMiddleware: {
|
||||
stats: {
|
||||
colors: true
|
||||
|
||||
6187
awx/ui/npm-shrinkwrap.json
generated
6187
awx/ui/npm-shrinkwrap.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,65 +1,61 @@
|
||||
{
|
||||
"name": "ansible-tower",
|
||||
"version": "3.1.0",
|
||||
"name": "awx",
|
||||
"version": "1.0.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": ""
|
||||
"url": "https://github.com/ansible/awx"
|
||||
},
|
||||
"config": {
|
||||
"django_port": "8043",
|
||||
"django_host": "localhost"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^6.3.1",
|
||||
"npm": "^3.10.3"
|
||||
"node": "^6.11.3",
|
||||
"npm": "^3.10.10"
|
||||
},
|
||||
"scripts": {
|
||||
"ui-docker-machine": "ip=$(docker-machine ip $DOCKER_MACHINE_NAME); npm set ansible-tower:django_host ${ip}; grunt dev;",
|
||||
"ui-docker": "grunt dev;",
|
||||
"build-devel": "grunt devNoSync",
|
||||
"ui-docker": "npm run watch;",
|
||||
"build-devel": "npm run dev",
|
||||
"pot": "grunt nggettext_extract",
|
||||
"languages": "grunt nggettext_compile",
|
||||
"build-release": "grunt release",
|
||||
"pretest": "grunt clean:coverage",
|
||||
"build-release": "npm run production",
|
||||
"pretest": "",
|
||||
"test": "karma start karma.conf.js",
|
||||
"jshint": "grunt clean:jshint jshint:source --no-color",
|
||||
"jshint": "grunt jshint:source --no-color",
|
||||
"test:ci": "npm run test -- --single-run --reporter junit,dots --browsers=PhantomJS",
|
||||
"lint": "./node_modules/.bin/eslint -c .eslintrc.js .",
|
||||
"component-test": "./node_modules/.bin/karma start client/test/karma.conf.js",
|
||||
"lint-dev": "./node_modules/.bin/nodemon --exec \"./node_modules/.bin/eslint -c .eslintrc.js .\" --watch \"client/components/**/*.js\"",
|
||||
"component-dev": "./node_modules/.bin/karma start client/test/karma.conf.js --auto-watch --no-single-run"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"browser-sync": "^2.14.0",
|
||||
"grunt-browser-sync": "^2.2.0",
|
||||
"grunt-contrib-watch": "^1.0.0",
|
||||
"webpack-dev-server": "^1.14.1"
|
||||
"dev": "./node_modules/.bin/webpack --config build/webpack.development.js --progress",
|
||||
"watch": "./node_modules/.bin/webpack-dev-server --config build/webpack.watch.js --progress",
|
||||
"production": "./node_modules/.bin/webpack --config build/webpack.production.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"angular-mocks": "~1.4.14",
|
||||
"babel-core": "^6.11.4",
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-istanbul": "^0.11.0",
|
||||
"babel-loader": "^6.2.4",
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-plugin-istanbul": "^2.0.0",
|
||||
"babel-preset-es2015": "^6.9.0",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"clean-webpack-plugin": "^0.1.16",
|
||||
"copy-webpack-plugin": "^4.0.1",
|
||||
"css-loader": "^0.28.5",
|
||||
"eslint": "^3.18.0",
|
||||
"eslint-config-airbnb-base": "^11.1.1",
|
||||
"eslint-plugin-import": "^2.2.0",
|
||||
"expose-loader": "^0.7.1",
|
||||
"expose-loader": "^0.7.3",
|
||||
"extract-text-webpack-plugin": "^3.0.0",
|
||||
"grunt": "^1.0.1",
|
||||
"grunt-angular-gettext": "^2.2.3",
|
||||
"grunt-cli": "^1.2.0",
|
||||
"grunt-concurrent": "^2.3.0",
|
||||
"grunt-contrib-clean": "^1.0.0",
|
||||
"grunt-contrib-concat": "^1.0.1",
|
||||
"grunt-contrib-copy": "^1.0.0",
|
||||
"grunt-contrib-cssmin": "^2.2.0",
|
||||
"grunt-contrib-jshint": "^1.0.0",
|
||||
"grunt-contrib-less": "^1.3.0",
|
||||
"grunt-extract-sourcemap": "^0.1.18",
|
||||
"grunt-newer": "^1.2.0",
|
||||
"grunt-webpack": "^1.0.11",
|
||||
"imports-loader": "^0.6.5",
|
||||
"html-loader": "^0.5.1",
|
||||
"html-webpack-harddisk-plugin": "^0.1.0",
|
||||
"html-webpack-plugin": "^2.30.1",
|
||||
"imports-loader": "^0.7.1",
|
||||
"jasmine-core": "^2.5.2",
|
||||
"jshint": "^2.9.4",
|
||||
"jshint-loader": "^0.8.3",
|
||||
@ -77,31 +73,38 @@
|
||||
"karma-sauce-launcher": "^1.0.0",
|
||||
"karma-sourcemap-loader": "^0.3.7",
|
||||
"karma-webpack": "^1.8.0",
|
||||
"less": "^2.7.2",
|
||||
"less-loader": "^4.0.5",
|
||||
"less-plugin-autoprefix": "^1.4.2",
|
||||
"load-grunt-configs": "^1.0.0",
|
||||
"load-grunt-tasks": "^3.5.0",
|
||||
"minimist": "^1.2.0",
|
||||
"ngtemplate-loader": "^2.0.1",
|
||||
"phantomjs-prebuilt": "^2.1.12",
|
||||
"script-loader": "^0.7.0",
|
||||
"style-loader": "^0.18.2",
|
||||
"time-grunt": "^1.4.0",
|
||||
"webpack": "^1.13.1"
|
||||
"uglifyjs-webpack-plugin": "^0.4.6",
|
||||
"webpack": "^3.0.0",
|
||||
"webpack-dev-server": "^2.7.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"angular": "~1.4.14",
|
||||
"angular-breadcrumb": "github:ansible/angular-breadcrumb#0.4.1",
|
||||
"angular-codemirror": "github:ansible/angular-codemirror#1.0.4",
|
||||
"angular-breadcrumb": "git+https://git@github.com/ansible/angular-breadcrumb#0.4.1",
|
||||
"angular-codemirror": "git+https://git@github.com/ansible/angular-codemirror#1.0.4",
|
||||
"angular-cookies": "~1.4.14",
|
||||
"angular-drag-and-drop-lists": "github:ansible/angular-drag-and-drop-lists#1.4.0",
|
||||
"angular-drag-and-drop-lists": "git+https://git@github.com/ansible/angular-drag-and-drop-lists#1.4.0",
|
||||
"angular-duration-format": "^1.0.1",
|
||||
"angular-gettext": "^2.3.5",
|
||||
"angular-md5": "^0.1.8",
|
||||
"angular-moment": "^0.10.1",
|
||||
"angular-resource": "~1.4.14",
|
||||
"angular-sanitize": "~1.4.14",
|
||||
"angular-scheduler": "github:ansible/angular-scheduler#0.1.1",
|
||||
"angular-tz-extensions": "github:ansible/angular-tz-extensions#0.3.13",
|
||||
"angular-scheduler": "git+https://git@github.com/ansible/angular-scheduler#0.1.1",
|
||||
"angular-tz-extensions": "git+https://git@github.com/ansible/angular-tz-extensions#0.3.13",
|
||||
"angular-ui-router": "1.0.0-beta.3",
|
||||
"bootstrap": "^3.1.1",
|
||||
"bootstrap-datepicker": "^1.4.0",
|
||||
"bootstrap": "^3.3.7",
|
||||
"bootstrap-datepicker": "^1.7.1",
|
||||
"codemirror": "^5.17.0",
|
||||
"components-font-awesome": "^4.6.1",
|
||||
"d3": "~3.3.13",
|
||||
@ -111,12 +114,12 @@
|
||||
"js-yaml": "^3.2.7",
|
||||
"legacy-loader": "0.0.2",
|
||||
"lodash": "~3.8.0",
|
||||
"lr-infinite-scroll": "github:lorenzofox3/lrInfiniteScroll",
|
||||
"lr-infinite-scroll": "git+https://git@github.com/lorenzofox3/lrInfiniteScroll",
|
||||
"moment": "~2.10.0",
|
||||
"ng-toast": "github:ansible/ngToast#2.0.1",
|
||||
"nvd3": "github:ansible/nvd3#1.7.1",
|
||||
"ng-toast": "git+https://git@github.com/ansible/ngToast#2.0.1",
|
||||
"nvd3": "git+https://git@github.com/ansible/nvd3#1.7.1",
|
||||
"reconnectingwebsocket": "^1.0.0",
|
||||
"rrule": "github:jkbrzt/rrule#4ff63b2f8524fd6d5ba6e80db770953b5cd08a0c",
|
||||
"rrule": "git+https://git@github.com/jkbrzt/rrule#4ff63b2f8524fd6d5ba6e80db770953b5cd08a0c",
|
||||
"select2": "^4.0.2",
|
||||
"sprintf-js": "^1.0.3"
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,20 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
{% load i18n %}
|
||||
<html lang="en" ng-app="awApp">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title ng-bind="tabTitle"></title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="{{ STATIC_URL }}css/app.vendor.css?v={{version}}" type="text/css">
|
||||
<link rel="stylesheet" href="{{ STATIC_URL }}css/app.css?v={{version}}" type="text/css">
|
||||
<link rel="shortcut icon" href="{{ STATIC_URL }}assets/favicon.ico?v={{version}}" />
|
||||
<script>
|
||||
var $basePath = "{{ STATIC_URL }}";
|
||||
</script>
|
||||
<script src="{{ STATIC_URL }}app.vendor.js?v={{version}}"></script>
|
||||
<script src="{{ STATIC_URL }}app.js?v={{version}}"></script>
|
||||
<title ng-bind="tabTitle"></title>
|
||||
<script>var $basePath = '{{ STATIC_URL }}'</script>
|
||||
|
||||
<link href="{{ STATIC_URL }}css/vendor.f283b4795bc6921b48e5.css" rel="stylesheet" />
|
||||
|
||||
<link href="{{ STATIC_URL }}css/app.f283b4795bc6921b48e5.css" rel="stylesheet" />
|
||||
|
||||
|
||||
<script src="{{ STATIC_URL }}js/vendor.f283b4795bc6921b48e5.js"></script>
|
||||
|
||||
<script src="{{ STATIC_URL }}js/app.f283b4795bc6921b48e5.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body data-user-agent="{{userAgent}}">
|
||||
@ -28,7 +31,7 @@
|
||||
</div>
|
||||
<!-- Password Dialog -->
|
||||
<div id="password-modal" style="display: none;"></div>
|
||||
<div id="idle-modal" style="display:none">{% blocktrans %}Your session will expire in <span id="remaining_seconds" class="IdleModal-remainingSeconds">60</span> seconds, would you like to continue?{% endblocktrans %}</div>
|
||||
<div id="idle-modal" style="display:none" translate>Your session will expire in <span id="remaining_seconds" class="IdleModal-remainingSeconds">60</span> seconds, would you like to continue?</div>
|
||||
<stream-detail-modal></stream-detail-modal>
|
||||
<!-- Confirmation Dialog -->
|
||||
<div id="prompt-modal" class="modal fade">
|
||||
@ -43,7 +46,7 @@
|
||||
<div class="Modal-body" ng-bind-html="promptBody" id="prompt-body">
|
||||
</div>
|
||||
<div class="Modal-footer">
|
||||
<a href="#" data-target="#prompt-modal" data-dismiss="modal" id="prompt_cancel_btn" class="btn Modal-defaultButton Modal-footerButton">{% trans 'CANCEL' %}</a>
|
||||
<a href="#" data-target="#prompt-modal" data-dismiss="modal" id="prompt_cancel_btn" class="btn Modal-defaultButton Modal-footerButton" translate>CANCEL</a>
|
||||
<a href="" ng-class="promptActionBtnClass" ng-click="promptAction()" id="prompt_action_btn" class="btn Modal-footerButton" ng-bind="promptActionText"></a>
|
||||
</div>
|
||||
</div>
|
||||
@ -64,7 +67,7 @@
|
||||
<div id="alert-modal-msg" class="alert" ng-bind-html="alertBody"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#" ng-hide="disableButtons" data-target="#form-modal" data-dismiss="modal" id="alert_ok_btn" class="btn btn-default">{% trans 'OK' %}</a>
|
||||
<a href="#" ng-hide="disableButtons" data-target="#form-modal" data-dismiss="modal" id="alert_ok_btn" class="btn btn-default" translate>OK</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- modal-content -->
|
||||
@ -83,7 +86,7 @@
|
||||
<div id="alert2-modal-msg" class="alert" ng-bind-html="alertBody2"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#" ng-hide="disableButtons2" data-target="#form-modal2" data-dismiss="modal" id="alert2_ok_btn" class="btn btn-primary">{% trans 'OK' %}</a>
|
||||
<a href="#" ng-hide="disableButtons2" data-target="#form-modal2" data-dismiss="modal" id="alert2_ok_btn" class="btn btn-primary">OK</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- modal-content -->
|
||||
@ -95,28 +98,27 @@
|
||||
<div id="help-modal-dialog" style="display: none;"></div>
|
||||
<div id="prompt-for-days" style="display:none">
|
||||
<form name="prompt_for_days_form" id="prompt_for_days_form" class="MgmtCards-promptText">
|
||||
{% trans 'Set how many days of data should be retained.' %}
|
||||
<span translate>Set how many days of data should be retained.</span>
|
||||
<br>
|
||||
<input type="integer" id="days_to_keep" name="days_to_keep" ng-model="days_to_keep" ng-required="true" class="form-control Form-textInput" min=0 max=9999 style="margin-top:10px;" integer>
|
||||
<div class="error" ng-show="prompt_for_days_form.days_to_keep.$dirty && (prompt_for_days_form.days_to_keep.$error.number || prompt_for_days_form.days_to_keep.$error.integer ||
|
||||
prompt_for_days_form.days_to_keep.$error.required ||
|
||||
prompt_for_days_form.days_to_keep.$error.min ||
|
||||
prompt_for_days_form.days_to_keep.$error.max)">{% blocktrans %}Please enter an integer<span ng-show="prompt_for_days_form.days_to_keep.$dirty && prompt_for_days_form.days_to_keep.$error.min"> that is not negative</span><span ng-show="prompt_for_days_form.days_to_keep.$dirty && prompt_for_days_form.days_to_keep.$error.max"> that is lower than 9999</span>.{% endblocktrans %}</div>
|
||||
prompt_for_days_form.days_to_keep.$error.max)" translate>Please enter an integer<span ng-show="prompt_for_days_form.days_to_keep.$dirty && prompt_for_days_form.days_to_keep.$error.min"> that is not negative</span><span ng-show="prompt_for_days_form.days_to_keep.$dirty && prompt_for_days_form.days_to_keep.$error.max"> that is lower than 9999</span>.</div>
|
||||
</form>
|
||||
</div>
|
||||
<div id="prompt-for-days-facts" style="display:none">
|
||||
<form name="prompt_for_days_facts_form" id="prompt_for_days_facts_form" class="MgmtCards-promptText">
|
||||
<div style="padding-bottom:15px;">{% blocktrans %}For facts collected older than the time period specified, save one fact scan (snapshot) per time window (frequency). For example, facts older than 30 days are purged, while one weekly fact scan is kept.
|
||||
<div style="padding-bottom:15px;"><span translate>For facts collected older than the time period specified, save one fact scan (snapshot) per time window (frequency). For example, facts older than 30 days are purged, while one weekly fact scan is kept.</span>
|
||||
<br>
|
||||
<br>
|
||||
<span translate>CAUTION: Setting both numerical variables to "0" will delete all facts.</span>
|
||||
<br>
|
||||
<br> CAUTION: Setting both numerical variables to "0" will delete all facts.
|
||||
<br>
|
||||
<br>{% endblocktrans %}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description">
|
||||
<span class="label-text">
|
||||
{% trans 'Select a time period after which to remove old facts' %}
|
||||
</span>
|
||||
<span class="label-text" translate>Select a time period after which to remove old facts</span>
|
||||
</label>
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
@ -129,13 +131,11 @@
|
||||
<div class="error" ng-show="prompt_for_days_facts_form.keep_amount.$dirty && (prompt_for_days_facts_form.keep_amount.$error.number || prompt_for_days_facts_form.keep_amount.$error.integer ||
|
||||
prompt_for_days_facts_form.keep_amount.$error.required ||
|
||||
prompt_for_days_facts_form.keep_amount.$error.min ||
|
||||
prompt_for_days_facts_form.keep_amount.$error.max)">{% blocktrans %}Please enter an integer<span ng-show="prompt_for_days_facts_form.keep_amount.$dirty && prompt_for_days_facts_form.keep_amount.$error.min"> that is not negative</span><span ng-show="prompt_for_days_facts_form.keep_amount.$dirty && prompt_for_days_facts_form.keep_amount.$error.max"> that is lower than 9999</span>.{% endblocktrans %}</div>
|
||||
prompt_for_days_facts_form.keep_amount.$error.max)" translate>Please enter an integer<span ng-show="prompt_for_days_facts_form.keep_amount.$dirty && prompt_for_days_facts_form.keep_amount.$error.min"> that is not negative</span><span ng-show="prompt_for_days_facts_form.keep_amount.$dirty && prompt_for_days_facts_form.keep_amount.$error.max"> that is lower than 9999</span>.</div>
|
||||
</div>
|
||||
<div class="form-group ">
|
||||
<label for="description">
|
||||
<span class="label-text">
|
||||
{% trans 'Select a frequency for snapshot retention' %}
|
||||
</span>
|
||||
<span class="label-text" translate>Select a frequency for snapshot retention</span>
|
||||
</label>
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
@ -148,13 +148,13 @@
|
||||
<div class="error" ng-show="prompt_for_days_facts_form.granularity_keep_amount.$dirty && (prompt_for_days_facts_form.granularity_keep_amount.$error.number || prompt_for_days_facts_form.granularity_keep_amount.$error.integer ||
|
||||
prompt_for_days_facts_form.granularity_keep_amount.$error.required ||
|
||||
prompt_for_days_facts_form.granularity_keep_amount.$error.min ||
|
||||
prompt_for_days_facts_form.granularity_keep_amount.$error.max)">{% blocktrans %}Please enter an integer<span ng-show="prompt_for_days_facts_form.granularity_keep_amount.$dirty && prompt_for_days_facts_form.granularity_keep_amount.$error.min"> that is not negative</span><span ng-show="prompt_for_days_facts_form.granularity_keep_amount.$dirty && prompt_for_days_facts_form.granularity_keep_amount.$error.max"> that is lower than 9999</span>.{% endblocktrans %}</div>
|
||||
prompt_for_days_facts_form.granularity_keep_amount.$error.max)" translate>Please enter an integer<span ng-show="prompt_for_days_facts_form.granularity_keep_amount.$dirty && prompt_for_days_facts_form.granularity_keep_amount.$error.min"> that is not negative</span><span ng-show="prompt_for_days_facts_form.granularity_keep_amount.$dirty && prompt_for_days_facts_form.granularity_keep_amount.$error.max"> that is lower than 9999</span>.</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="overlay"></div>
|
||||
<div class="spinny"><i class="fa fa-cog fa-spin fa-2x"></i>
|
||||
<p>{% trans 'working...' %}</p>
|
||||
<p translate>working...</p>
|
||||
</div>
|
||||
</div>
|
||||
</at-layout>
|
||||
|
||||
@ -1,126 +0,0 @@
|
||||
var awx_env,
|
||||
path = require('path'),
|
||||
webpack = require('webpack'),
|
||||
options = require('minimist')(JSON.parse(process.env.npm_config_argv).remain),
|
||||
merge = require('lodash').merge;
|
||||
|
||||
awx_env = {
|
||||
'proxy': {
|
||||
'django_host': process.env.npm_package_config_django_host,
|
||||
'django_port': process.env.npm_package_config_django_port
|
||||
}
|
||||
};
|
||||
merge(awx_env, options);
|
||||
|
||||
var vendorPkgs = [
|
||||
'angular',
|
||||
'angular-breadcrumb',
|
||||
'angular-codemirror',
|
||||
'angular-cookies',
|
||||
'angular-drag-and-drop-lists',
|
||||
'angular-duration-format',
|
||||
'angular-gettext',
|
||||
'angular-md5',
|
||||
'angular-moment',
|
||||
'angular-sanitize',
|
||||
'angular-scheduler',
|
||||
'angular-tz-extensions',
|
||||
'angular-ui-router',
|
||||
'bootstrap',
|
||||
'bootstrap-datepicker',
|
||||
'codemirror',
|
||||
'd3',
|
||||
//'javascript-detect-element-resize', // jquery-flavored dist is alias'd below
|
||||
'jquery',
|
||||
'jquery-ui',
|
||||
'js-yaml',
|
||||
'lodash',
|
||||
'lr-infinite-scroll',
|
||||
'moment',
|
||||
'ng-toast',
|
||||
'nvd3',
|
||||
'select2',
|
||||
'sprintf-js',
|
||||
'reconnectingwebsocket'
|
||||
];
|
||||
|
||||
var baseConfig = function() {
|
||||
return {
|
||||
entry: {
|
||||
app: './client/src/app.js',
|
||||
vendor: vendorPkgs
|
||||
},
|
||||
output: {
|
||||
path: './static/',
|
||||
filename: 'app.js'
|
||||
},
|
||||
plugins: [
|
||||
// vendor shims:
|
||||
// [{expected_local_var : dependency}, ...]
|
||||
new webpack.ProvidePlugin({
|
||||
'$': 'jquery',
|
||||
'jQuery': 'jquery',
|
||||
'window.jQuery': 'jquery',
|
||||
'_': 'lodash',
|
||||
'CodeMirror': 'codemirror',
|
||||
'jsyaml': 'js-yaml',
|
||||
'jsonlint': 'codemirror.jsonlint'
|
||||
}),
|
||||
new webpack.optimize.CommonsChunkPlugin('vendor', 'app.vendor.js')
|
||||
],
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
// disable AMD loading (broken in this lib) and default to CommonJS (not broken)
|
||||
test: /\.angular-tz-extensions.js$/,
|
||||
loader: 'imports?define=>false'
|
||||
},
|
||||
{
|
||||
// es6 -> es5
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
exclude: /(node_modules)/,
|
||||
query: {
|
||||
presets: ['es2015']
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.json$/,
|
||||
loader: 'json-loader',
|
||||
exclude: /(node_modules)/
|
||||
}
|
||||
]
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'codemirror.jsonlint': path.resolve() + '/node_modules/codemirror/addon/lint/json-lint.js',
|
||||
'jquery.resize': path.resolve() + '/node_modules/javascript-detect-element-resize/jquery.resize.js',
|
||||
'select2': path.resolve() + '/node_modules/select2/dist/js/select2.full.js'
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
var dev = baseConfig();
|
||||
|
||||
dev.devtool = 'inline-source-map';
|
||||
dev.watch = true;
|
||||
dev.plugins.push(new webpack.DefinePlugin({ $ENV: JSON.stringify(awx_env) }));
|
||||
dev.module.preLoaders = [
|
||||
{
|
||||
test: /\.js?$/,
|
||||
loader: 'jshint-loader',
|
||||
exclude: ['/(node_modules)/'],
|
||||
include: [path.resolve() + '/client/src/'],
|
||||
jshint: {
|
||||
emitErrors: true
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
var release = baseConfig();
|
||||
|
||||
release.plugins.push(new webpack.DefinePlugin({ $ENV: {} }));
|
||||
release.plugins.push(new webpack.optimize.UglifyJsPlugin({ mangle: false }));
|
||||
|
||||
module.exports = { dev: dev, release: release };
|
||||
@ -1,237 +0,0 @@
|
||||
# UI BUILD SYSTEM
|
||||
|
||||
### Table of Contents
|
||||
|
||||
1. [Care and Keeping of NodeJS + NPM](#nodejs-and-npm)
|
||||
1. [Pin NodeJS & NPM versions](#pin-nodejs-npm-versions)
|
||||
2. [Use NVM to manage multple Node/NPM installations](#use-nvm)
|
||||
3.. [Add, incremenet, remove a package](#add-upgrade-remove-npm-package)
|
||||
4. [dependency, devDependency, or optionalDependency?](#npm-dependency-types)
|
||||
|
||||
2. [Webpack](#webpack)
|
||||
1. [What does Webpack handle?](#webpack-what-do)
|
||||
2. [Add / remove a vendor module](#add-upgrade-remove-vendor-module)
|
||||
3. [Strategies: loading a module](#loading-modules)
|
||||
4. [Strategies: exposing a module to application code](#exposing-modules)
|
||||
|
||||
|
||||
3. [Grunt](#grunt)
|
||||
1. [What does Grunt handle?](#grunt-what-do)
|
||||
2. [Add / remove a Grunt task](#add-remove-upgrade-grunt-task)
|
||||
3. [Task concurrency & process lifecycles](#grunt-task-concurrency)
|
||||
|
||||
4. [Karma](#karma)
|
||||
1. [Developer configuration](#karma-developer-config)
|
||||
2. [CI configuration](#karma-ci-config)
|
||||
|
||||
5. [Interfaces & Environments](#interfaces-and-environments)
|
||||
1. [NPM script targets](#npm-scripts)
|
||||
2. [Makefile targets](#make-targets)
|
||||
3. [NPM config variables](#npm-config-variables)
|
||||
4. [Other environment variables](#environment-variables)
|
||||
|
||||
6. References / Resources
|
||||
|
||||
|
||||
# <a name="nodejs-and-npm">Care and Keeping of NodeJS + NPM</a>
|
||||
## <a name="pin-nodejs-npm-versions">Pin NodeJS & NPM versions</a>
|
||||
|
||||
NodeJS began packaging their releases with a bundled version of NPM. Occasionally, the version of NPM that ships with a given NodeJS release can be unstable. For example, the v6 LTS of Node shipped with a version of NPM that introduced a regression that broke module installation for any package with platform-specific dependencies.
|
||||
|
||||
For this reason, it's strongly advised to pin development environments, CI, and release pipelines to vetted releases of NodeJS + NPM.
|
||||
|
||||
Pinned versions are best expressed through the engine field in `package.json`.
|
||||
|
||||
```json
|
||||
"engines": {
|
||||
"node": "^6.3.1",
|
||||
"npm": "=3.10.3"
|
||||
}
|
||||
```
|
||||
|
||||
## <a name="use-nvm">Use NVM to manage multiple NodeJS + NPM installations</a>
|
||||
|
||||
A system installation of Node raises *many* challenges on a development or shared system: user permissions, shared (global) modules, and installation paths for multiple versions. `nvm` is a light executable that addresses all of these issues. In the context of Tower, we use nvm to quickly switch between versions of NodeJS + NPM.
|
||||
|
||||
Version support per Tower release
|
||||
3.0.* - NodeJS v0.12.17 & NPM v2.15.1
|
||||
3.1.* - NodeJS 6.3.1 * & NPM 3.10.3
|
||||
|
||||
* [nvm installation guide](https://github.com/creationix/nvm#installation)
|
||||
* [additional shell integrations](https://github.com/creationix/nvm#deeper-shell-integration)
|
||||
|
||||
```bash
|
||||
$ nvm install 6.3
|
||||
$ nvm use 6.3
|
||||
|
||||
```
|
||||
|
||||
## <a name="add-upgrade-remove-npm-package">Adding, incrementing, removing packages via NPM</a>
|
||||
|
||||
The Tower package utilizes an `npm-shrinkwrap.json` file to freeze dependency resolution. When `npm install` runs, it will prefer to resolve dependencies as frozen in the shrinkwrap file before it ingests versions in `package.json`. To update the shrinkwrap file with a new dependency, pass the `--save` argument e.g. `npm install fooify@1.2.3 --save`.
|
||||
|
||||
*Do not run `npm shrinkwrap` when add/updating dependencies*. This will re-generate the entire conflict resolution tree, which will churn over time. Instead, depend on `--save`, `--save-dev` and `--save-optional` to create/update the shrinkwrapped package.
|
||||
|
||||
## <a name="npm-dependency-types">What's a dependency, devDependency, or optionalDependency</a>
|
||||
|
||||
`dependency` - Bundled in the Tower product. Customer-facing.
|
||||
`devDependency` - Used in the development, build, and release pipelines
|
||||
`optionalDependency` - Platform-specific dependencies, or dependencies which should not cause `npm install` to exit with an error if these modules fail to install.
|
||||
|
||||
# <a name="webpack">Webpack</a>
|
||||
|
||||
## <a name="webpack-what-do">What does Webpack handle?</a>
|
||||
|
||||
Webpack ingests our vendor and application modules, and outputs bundled code optimized for development or production. Configuration lives in `webpack.config.js`.
|
||||
|
||||
Webpack is a highly pluggable framework ([list of vetted plugins](https://webpack.github.io/docs/list-of-plugins.html)) We make use of the following plugins:
|
||||
|
||||
* [ProvidePlugin](https://webpack.github.io/docs/list-of-plugins.html#provideplugin) - automatically loads and exports a module into specified namespace. A modular approach to loading modules that you would otherwise have to load into global namespace. Example:
|
||||
|
||||
```javascript
|
||||
// webpack.config.js
|
||||
plugins: {
|
||||
new webpack.ProvidePlugin({
|
||||
'$': 'jquery',
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
```javascript
|
||||
// some-application-module.js
|
||||
// the following code:
|
||||
$('.my-thingy').click();
|
||||
|
||||
// is transformed into:
|
||||
var $ = require('jquery');
|
||||
$('.my-thingy').click();
|
||||
```
|
||||
|
||||
* [CommonChunksPlugin](https://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin) - a [chunk](https://webpack.github.io/docs/code-splitting.html#chunk-content) is Webpack's unit of code-splitting. This plugin' chunk consolidation strategy helps us split our bundled vendor code from our bundled application code, which *dramatically reduces* rebuild and browser loading time in development.
|
||||
|
||||
Currently, Tower is split into two output bundles: `tower.vendor.js` and `tower.js`. This would be the plugin configuration to update to additionally split application code into more portable components (example: for usage in the Insights UI).
|
||||
|
||||
* [DefinePlugin](https://webpack.github.io/docs/list-of-plugins.html#defineplugin) - injects a module that behaves like a global constant, which can be defined/configured as compile time. Tower uses this plugin to allow command-line arguments passed in at build time to be consumed by application code.
|
||||
|
||||
* [UglifyJSPlugin](https://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin) (production-only) - removes whitespace and minifies output. The mangle option can be used for an addiction layer of obfuscation, but it can also cause namespace issues.
|
||||
|
||||
## <a name="add-upgrade-remove-vendor-module">Add / remove a vendor module</a>
|
||||
|
||||
First, [install the package via npm](#add-upgrade-remove-npm-package). If the package doesn't export its contents as a CommonJS, AMD, or SystemJS module you will need to [write a module loader](https://webpack.github.io/docs/how-to-write-a-loader.html).
|
||||
|
||||
Not all packages correctly import their own dependencies. Some packages (notable: most jquery plugins) assume a certain dependency will already be in the global namespace. You will need to shim dependencies into these modules using Webpack's [export loader](https://webpack.github.io/docs/shimming-modules.html#exporting).
|
||||
|
||||
To bundle a new dependency in `tower.vendor.js`, add it to the `vendorPkgs` array in `webpack.config.js`.
|
||||
|
||||
## <a name="loading-modules">Strategies: loading a module</a>
|
||||
|
||||
Webpack ingests code through a concept called a `loader`. [What is a loader?, exactly?](http://webpack.github.io/docs/using-loaders.html#what-are-loaders)
|
||||
|
||||
Loaders can be chained together to perform a complex series of transformations and exports, or used in isolation to target a specific module.
|
||||
|
||||
The Webpack loaders used by Tower:
|
||||
|
||||
[Babel loader](https://github.com/babel/babel-loader) - loads files matching a pattern
|
||||
[imports loader](https://github.com/webpack/imports-loader) - shims dependency namespace, or constrains our own module loading strategies for this package (e.g. prefer to use CJS because AMD strategy is broken in package)
|
||||
|
||||
|
||||
|
||||
# <a name="grunt">Grunt</a>
|
||||
|
||||
[Grunt](http://gruntjs.com/) is a modular task runner. Functionally, it serves the same purpose as a Makefile or set of bash scripts. Grunt helps normalize the interfaces between disparate pieces of tooling. For purposes of Tower, Grunt also simplifies managing the lifecycle of concurrent child processes.
|
||||
|
||||
## <a name="grunt-what-do">What does Grunt handle?</a>a>
|
||||
|
||||
Grunt cleans up build artifacts, copies source files, lints, runs 18n text extraction & compilation, and transforms LESS to CSS.
|
||||
|
||||
Other development-only Grunt tasks will poll for file changes, run tasks when a subset of files changes, and raise an instance of BrowserSync (reloads browser on built changes) proxied to an instance of the Django API, running in a native Docker container or container inside of a Docker Machine.
|
||||
|
||||
Grunt internally uses minimatch [file globbing patterns](http://gruntjs.com/configuring-tasks#globbing-patterns)
|
||||
|
||||
## <a name="add-remove-upgrade-grunt-tasks"> Add / change / remove a Grunt task</a>
|
||||
|
||||
Grunt tasks live in `awx/ui/grunt-tasks/` and are organized in a file-per-plugin pattern.
|
||||
|
||||
The plugin `load-grunt-configs` will automatically load and register tasks read from the configuration files in `awx/ui/grunt-tasks`. This reduces the amount of boilerplate required to write, load, register, each task configuration.
|
||||
|
||||
|
||||
FEach task may be configured with a set of default option, plus additional targets that inherit or override defaults. For example, all tasks in `grunt-tasks/clean.js` run with `-f` or `--force` flag. `grunt-contrib-clean`
|
||||
|
||||
```javascript
|
||||
module.exports = {
|
||||
options: { force: true },
|
||||
static: 'static/*',
|
||||
coverage: 'coverage/*',
|
||||
tmp: '../../tmp',
|
||||
jshint: 'coverage/jshint.xml'
|
||||
};
|
||||
```
|
||||
|
||||
## <a name="grunt-task-concurrency">Grunt task concurrency</a>
|
||||
|
||||
By default, Grunt tasks are run in a series. [grunt-concurrent] is a plugin that allows us to parallelize certain tasks, to speed up the overall build process.
|
||||
|
||||
Note: certain polling tasks *must always be run on a thread that remains alive*. For example, the `webpack` tasks interact with Webpack's API. Therefor when Webpack's `livereload` option is on, Grunt `webpack` tasks should be spawned in series prior to Grunt `watch` tasks.
|
||||
|
||||
# <a name="karma"> Karma </a>
|
||||
|
||||
`karma.conf.js` is a generic configuration shared between developer and CI unit test runs.
|
||||
|
||||
The base configuration is suitable for live development. Additional command-line arguments supplement this general config to suit CI systems.
|
||||
|
||||
An [npm script](#npm-scripts) interface is provided to run either of these configurations: `npm test` (base) `npm test:ci`
|
||||
|
||||
# <a name="Interfaces & Environments">Interfaces & Environments</a>
|
||||
|
||||
The UI build system is intended for use through [NPM scripts](https://docs.npmjs.com/misc/scripts). NPM scripts are preferable to just running `grunt sometask` because `npm run` will look for `node_modules/.bin` executables, allowing us to manage CI/release executable versions through `package.json`. You would otherwise have to append these to the executor's $PATH.
|
||||
|
||||
`npm run` targets are run in a shell, which makes them a flexible way of mixing together Python, Ruby, Node, or other CLI tooling in a project.
|
||||
|
||||
## <a name="npm-scripts">Tower's NPM script targets</a>
|
||||
|
||||
Below is a reference of what each script target does in human language, and then what you can expect the script to execute.
|
||||
|
||||
-------
|
||||
|
||||
Builds a development version of the UI with a BrowserSync instance proxied to a Docker Machine
|
||||
```bash
|
||||
$ DOCKER_MACHINE_NAME=default npm run build-docker-machine
|
||||
$ ip=$(docker-machine ip $DOCKER_MACHINE_NAME); npm set ansible-tower:django_host ${ip}; grunt dev;
|
||||
```
|
||||
|
||||
Builds a development version of the UI with a BrowserSync instance proxied to a native Docker container
|
||||
```bash
|
||||
$ DOCKER_CID=1a2b3c4d5e npm run build-docker
|
||||
$ ip=`docker inspect --format '{{ .NetworkSettings.IPAddress }}' $DOCkER_CID` | npm set config ansible-tower:django_host ${ip}; grunt dev;
|
||||
```
|
||||
|
||||
Builds a development version of the UI. No filesystem polling. Re-run after each new revision.
|
||||
```bash
|
||||
$ npm run build-devel
|
||||
```
|
||||
|
||||
Builds a production version of the UI.
|
||||
```bash
|
||||
$ npm run build-release
|
||||
```
|
||||
|
||||
Launches unit test runners in assorted browsers. Alias for `npm run test`
|
||||
```bash
|
||||
$ npm test
|
||||
```
|
||||
|
||||
Launches unit test runners headless in PhantomJS. Alias for `npm run test:ci`
|
||||
```bash
|
||||
$ npm test:ci
|
||||
```
|
||||
|
||||
Extracts i18n string markers to a .pot template.
|
||||
```bash
|
||||
$ npm run pot
|
||||
```
|
||||
|
||||
Builds i18n language files with regard to .pot.
|
||||
```bash
|
||||
$ npm run languages
|
||||
```
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user