diff --git a/awx/ui/.babelrc b/awx/ui/.babelrc deleted file mode 100644 index c13c5f627f..0000000000 --- a/awx/ui/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["es2015"] -} diff --git a/awx/ui/.eslintignore b/awx/ui/.eslintignore index 44869da7c0..1de8506d67 100644 --- a/awx/ui/.eslintignore +++ b/awx/ui/.eslintignore @@ -13,5 +13,7 @@ tests client/**/*.js test -!client/component/**/*.js -!client/model/**/*.js +!client/lib/components/**/*.js +!client/lib/models/**/*.js +!client/lib/services/**/*.js +!client/features/**/*.js diff --git a/awx/ui/.eslintrc.js b/awx/ui/.eslintrc.js index 6d1174fa55..5cb4504be4 100644 --- a/awx/ui/.eslintrc.js +++ b/awx/ui/.eslintrc.js @@ -1,8 +1,20 @@ +const path = require('path'); + module.exports = { - extends: 'airbnb-base', + root: true, + extends: [ + 'airbnb-base' + ], plugins: [ 'import' ], + settings: { + 'import/resolver': { + webpack: { + config: path.join(__dirname, 'build/webpack.development.js') + } + } + }, env: { browser: true, node: true @@ -11,13 +23,27 @@ module.exports = { angular: true, d3: true, $: true, + _: true, codemirror: true, jsyaml: true }, rules: { - indent: [0, 4], - 'comma-dangle': 0, - 'prefer-const': 0, - 'space-before-function-paren': [2, 'always'] + 'arrow-parens': 'off', + 'comma-dangle': 'off', + indent: ['error', 4, { + SwitchCase: 1 + }], + 'max-len': ['error', { + code: 100, + ignoreStrings: true, + ignoreTemplateLiterals: true, + }], + 'no-continue': 'off', + 'no-mixed-operators': 'off', + 'no-param-reassign': 'off', + 'no-plusplus': 'off', + 'no-underscore-dangle': 'off', + 'object-curly-newline': 'off', + 'space-before-function-paren': ['error', 'always'] } }; diff --git a/awx/ui/build/webpack.base.js b/awx/ui/build/webpack.base.js index e56cd0810d..dbdec3eafb 100644 --- a/awx/ui/build/webpack.base.js +++ b/awx/ui/build/webpack.base.js @@ -3,8 +3,8 @@ 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 ExtractTextPlugin = require('extract-text-webpack-plugin'); const CLIENT_PATH = path.resolve(__dirname, '../client'); const LIB_PATH = path.join(CLIENT_PATH, 'lib'); @@ -20,6 +20,7 @@ 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 THEME_PATH = path.join(LIB_PATH, 'theme'); const APP_ENTRY = path.join(SOURCE_PATH, 'app.js'); const VENDOR_ENTRY = path.join(SOURCE_PATH, 'vendor.js'); @@ -32,7 +33,7 @@ const CHUNKS = ['vendor', 'app']; const VENDOR = VENDOR_ENTRY; const APP = [THEME_ENTRY, APP_ENTRY]; -let base = { +const base = { entry: { vendor: VENDOR, app: APP @@ -42,12 +43,32 @@ let base = { publicPath: '', filename: OUTPUT }, + stats: { + children: false, + modules: false, + chunks: false, + excludeAssets: name => { + const chunkNames = `(${CHUNKS.join('|')})`; + const outputPattern = new RegExp(`${chunkNames}\.[a-f0-9]+\.(js|css)$`, 'i'); + + return !outputPattern.test(name); + } + }, module: { rules: [ { test: /\.js$/, loader: 'babel-loader', - exclude: /node_modules/ + exclude: /node_modules/, + options: { + presets: [ + ['env', { + targets: { + browsers: ['last 2 versions'] + } + }] + ] + } }, { test: /\.css$/, @@ -77,10 +98,6 @@ let base = { /node_modules\/d3\/d3\.min.js$/ ] }, - { - test: /\.js$/, - use: 'imports-loader?define=>false' - }, { test: /\.html$/, use: ['ngtemplate-loader', 'html-loader'], @@ -104,8 +121,9 @@ let base = { _: 'lodash' }), new ExtractTextPlugin('css/[name].[hash].css'), - new CleanWebpackPlugin([STATIC_PATH, COVERAGE_PATH], { + new CleanWebpackPlugin([STATIC_PATH, COVERAGE_PATH, LANGUAGES_PATH], { root: UI_PATH, + verbose: false }), new CopyWebpackPlugin([ { @@ -164,33 +182,35 @@ let base = { 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) + chunksSortMode: (chunk) => { + if (chunk.names[0] === 'polyfill' || chunk.names[0] === 'vendor') { + return -1; + } - return moduleA.names[0] === 'vendor' ? -1 : 1 + return 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' + '~features': FEATURES_PATH, + '~models': MODELS_PATH, + '~services': SERVICES_PATH, + '~components': COMPONENTS_PATH, + '~theme': THEME_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' } } }; diff --git a/awx/ui/build/webpack.development.js b/awx/ui/build/webpack.development.js index c89123c5ac..2d85a4bd7a 100644 --- a/awx/ui/build/webpack.development.js +++ b/awx/ui/build/webpack.development.js @@ -2,9 +2,9 @@ const path = require('path'); const _ = require('lodash'); -let base = require('./webpack.base'); +const base = require('./webpack.base'); -let development = { +const development = { devtool: 'cheap-source-map' }; diff --git a/awx/ui/build/webpack.production.js b/awx/ui/build/webpack.production.js index 80955f7fe0..e709962765 100644 --- a/awx/ui/build/webpack.production.js +++ b/awx/ui/build/webpack.production.js @@ -5,15 +5,15 @@ const webpack = require('webpack'); const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); -let base = require('./webpack.base'); +const base = require('./webpack.base'); const CLIENT_PATH = path.resolve(__dirname, '../client'); const UI_PATH = path.resolve(__dirname, '..'); -const INSTALL_RUNNING_ENTRY = path.join(CLIENT_PATH, 'installing.template.ejs') +const INSTALL_RUNNING_ENTRY = path.join(CLIENT_PATH, 'installing.template.ejs'); const INSTALL_RUNNING_OUTPUT = path.join(UI_PATH, 'templates/ui/installing.html'); const CHUNKS = ['vendor', 'app']; -let production = { +const production = { plugins: [ new UglifyJSPlugin({ compress: true, @@ -25,16 +25,17 @@ let production = { filename: INSTALL_RUNNING_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); + chunksSortMode: (chunk) => { + if (chunk.names[0] === 'polyfill' || chunk.names[0] === 'vendor') { + return -1; + } - return moduleA.names[0] === 'vendor' ? -1 : 1; + return 1; } }) ] }; -production.plugins = base.plugins.concat(production.plugins) +production.plugins = base.plugins.concat(production.plugins); module.exports = _.merge(base, production); diff --git a/awx/ui/build/webpack.test.js b/awx/ui/build/webpack.test.js index e23b2a957a..0ebcac286b 100644 --- a/awx/ui/build/webpack.test.js +++ b/awx/ui/build/webpack.test.js @@ -5,9 +5,9 @@ const webpack = require('webpack'); const STATIC_URL = '/static/'; -let development = require('./webpack.development'); +const development = require('./webpack.development'); -let test = { +const test = { plugins: [ new webpack.DefinePlugin({ $basePath: STATIC_URL @@ -15,7 +15,7 @@ let test = { ] }; -test.plugins = development.plugins.concat(test.plugins) +test.plugins = development.plugins.concat(test.plugins); module.exports = _.merge(development, test); diff --git a/awx/ui/build/webpack.watch.js b/awx/ui/build/webpack.watch.js index b858dddede..85431adddc 100644 --- a/awx/ui/build/webpack.watch.js +++ b/awx/ui/build/webpack.watch.js @@ -8,16 +8,26 @@ 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'); +const development = require('./webpack.development'); -let watch = { +const watch = { + module: { + rules: [ + { + test: /\.js$/, + enforce: 'pre', + exclude: /node_modules/, + loader: 'eslint-loader' + } + ] + }, plugins: [ new HtmlWebpackHarddiskPlugin(), new webpack.HotModuleReplacementPlugin() ], devServer: { contentBase: path.resolve(__dirname, '..', 'static'), - clientLogLevel: 'info', + stats: 'minimal', publicPath: '/static/', host: '127.0.0.1', port: 3000, @@ -36,7 +46,8 @@ let watch = { } }; -watch.plugins = development.plugins.concat(watch.plugins) +watch.module.rules = development.module.rules.concat(watch.module.rules); +watch.plugins = development.plugins.concat(watch.plugins); module.exports = _.merge(development, watch); diff --git a/awx/ui/client/features/credentials/add-credentials.controller.js b/awx/ui/client/features/credentials/add-credentials.controller.js index 193c2cbb5b..560968c918 100644 --- a/awx/ui/client/features/credentials/add-credentials.controller.js +++ b/awx/ui/client/features/credentials/add-credentials.controller.js @@ -1,10 +1,7 @@ function AddCredentialsController (models, $state, strings) { - let vm = this || {}; + const vm = this || {}; - let me = models.me; - let credential = models.credential; - let credentialType = models.credentialType; - let organization = models.organization; + const { me, credential, credentialType, organization } = models; vm.mode = 'add'; vm.strings = strings; @@ -12,7 +9,7 @@ function AddCredentialsController (models, $state, strings) { vm.tab = { details: { _active: true }, - permissions:{ _disabled: true } + permissions: { _disabled: true } }; vm.form = credential.createFormSchema('post', { @@ -25,14 +22,14 @@ function AddCredentialsController (models, $state, strings) { vm.form.organization._route = 'credentials.add.organization'; vm.form.organization._model = organization; vm.form.organization._placeholder = strings.get('inputs.ORGANIZATION_PLACEHOLDER'); - + vm.form.credential_type._resource = 'credential_type'; vm.form.credential_type._route = 'credentials.add.credentialType'; vm.form.credential_type._model = credentialType; vm.form.credential_type._placeholder = strings.get('inputs.CREDENTIAL_TYPE_PLACEHOLDER'); vm.form.inputs = { - _get: id => { + _get: () => { credentialType.mergeInputProperties(); return credentialType.get('inputs.fields'); diff --git a/awx/ui/client/features/credentials/credentials.strings.js b/awx/ui/client/features/credentials/credentials.strings.js index d8c031f743..958282aa09 100644 --- a/awx/ui/client/features/credentials/credentials.strings.js +++ b/awx/ui/client/features/credentials/credentials.strings.js @@ -1,8 +1,8 @@ function CredentialsStrings (BaseString) { BaseString.call(this, 'credentials'); - - let t = this.t; - let ns = this.credentials; + + const { t } = this; + const ns = this.credentials; ns.state = { ADD_BREADCRUMB_LABEL: t.s('CREATE CREDENTIAL'), diff --git a/awx/ui/client/features/credentials/edit-credentials.controller.js b/awx/ui/client/features/credentials/edit-credentials.controller.js index 177dab5239..6fe3845266 100644 --- a/awx/ui/client/features/credentials/edit-credentials.controller.js +++ b/awx/ui/client/features/credentials/edit-credentials.controller.js @@ -1,25 +1,22 @@ function EditCredentialsController (models, $state, $scope, strings) { - let vm = this || {}; + const vm = this || {}; - let me = models.me; - let credential = models.credential; - let credentialType = models.credentialType; - let organization = models.organization; + const { me, credential, credentialType, organization } = models; - let omit = ['user', 'team', 'inputs']; - let isEditable = credential.isEditable(); + const omit = ['user', 'team', 'inputs']; + const isEditable = credential.isEditable(); vm.mode = 'edit'; vm.strings = strings; vm.panelTitle = credential.get('name'); vm.tab = { - details: { + details: { _active: true, _go: 'credentials.edit', _params: { credential_id: credential.get('id') } }, - permissions:{ + permissions: { _go: 'credentials.edit.permissions', _params: { credential_id: credential.get('id') } } @@ -45,11 +42,11 @@ function EditCredentialsController (models, $state, $scope, strings) { vm.form.disabled = !isEditable; } - let isOrgAdmin = _.some(me.get('related.admin_of_organizations.results'), (org) => {return org.id === organization.get('id');}); - let isSuperuser = me.get('is_superuser'); - let isCurrentAuthor = Boolean(credential.get('summary_fields.created_by.id') === me.get('id')); + const isOrgAdmin = _.some(me.get('related.admin_of_organizations.results'), (org) => org.id === organization.get('id')); + const isSuperuser = me.get('is_superuser'); + const isCurrentAuthor = Boolean(credential.get('summary_fields.created_by.id') === me.get('id')); vm.form.organization._disabled = true; - if(isSuperuser || isOrgAdmin || (credential.get('organization') === null && isCurrentAuthor)){ + if (isSuperuser || isOrgAdmin || (credential.get('organization') === null && isCurrentAuthor)) { vm.form.organization._disabled = false; } @@ -66,11 +63,11 @@ function EditCredentialsController (models, $state, $scope, strings) { vm.form.credential_type._value = credentialType.get('id'); vm.form.credential_type._displayValue = credentialType.get('name'); vm.form.credential_type._placeholder = strings.get('inputs.CREDENTIAL_TYPE_PLACEHOLDER'); - + vm.form.inputs = { - _get (id) { + _get () { credentialType.mergeInputProperties(); - + if (credentialType.get('id') === credential.get('credential_type')) { return credential.assignInputGroupValues(credentialType.get('inputs.fields')); } @@ -94,7 +91,7 @@ function EditCredentialsController (models, $state, $scope, strings) { return credential.request('put', data); }; - vm.form.onSaveSuccess = res => { + vm.form.onSaveSuccess = () => { $state.go('credentials.edit', { credential_id: credential.get('id') }, { reload: true }); }; } diff --git a/awx/ui/client/features/credentials/index.js b/awx/ui/client/features/credentials/index.js index 28266b8b82..5800793287 100644 --- a/awx/ui/client/features/credentials/index.js +++ b/awx/ui/client/features/credentials/index.js @@ -1,35 +1,33 @@ import LegacyCredentials from './legacy.credentials'; import AddController from './add-credentials.controller'; import EditController from './edit-credentials.controller'; -import CredentialsStrings from './credentials.strings' +import CredentialsStrings from './credentials.strings'; -const addEditTemplate = require('@features/credentials/add-edit-credentials.view.html'); +const addEditTemplate = require('~features/credentials/add-edit-credentials.view.html'); function CredentialsResolve ($q, $stateParams, Me, Credential, CredentialType, Organization) { - let id = $stateParams.credential_id; + const id = $stateParams.credential_id; - let promises = { - me: new Me('get').then((me) => { - return me.extend('get', 'admin_of_organizations'); - }) + const promises = { + me: new Me('get').then((me) => me.extend('get', 'admin_of_organizations')) }; if (!id) { promises.credential = new Credential('options'); - promises.credentialType = new CredentialType(); - promises.organization = new Organization(); + promises.credentialType = new CredentialType(); + promises.organization = new Organization(); - return $q.all(promises) + return $q.all(promises); } promises.credential = new Credential(['get', 'options'], [id, id]); return $q.all(promises) .then(models => { - let typeId = models.credential.get('credential_type'); - let orgId = models.credential.get('organization'); + const typeId = models.credential.get('credential_type'); + const orgId = models.credential.get('organization'); - let dependents = { + const dependents = { credentialType: new CredentialType('get', typeId), organization: new Organization('get', orgId) }; @@ -54,9 +52,9 @@ CredentialsResolve.$inject = [ ]; function CredentialsConfig ($stateExtenderProvider, legacyProvider, stringProvider) { - let stateExtender = $stateExtenderProvider.$get(); - let legacy = legacyProvider.$get(); - let strings = stringProvider.$get(); + const stateExtender = $stateExtenderProvider.$get(); + const legacy = legacyProvider.$get(); + const strings = stringProvider.$get(); stateExtender.addState({ name: 'credentials.add', diff --git a/awx/ui/client/features/credentials/legacy.credentials.js b/awx/ui/client/features/credentials/legacy.credentials.js index 762ed96b88..c294207dea 100644 --- a/awx/ui/client/features/credentials/legacy.credentials.js +++ b/awx/ui/client/features/credentials/legacy.credentials.js @@ -1,11 +1,7 @@ -import PermissionsList from '../../src/access/permissions-list.controller'; -import CredentialForm from '../../src/credentials/credentials.form'; -import CredentialList from '../../src/credentials/credentials.list'; -import OrganizationList from '../../src/organizations/organizations.list'; import ListController from '../../src/credentials/list/credentials-list.controller'; import { N_ } from '../../src/i18n'; -const indexTemplate = require('@features/credentials/index.view.html'); +const indexTemplate = require('~features/credentials/index.view.html'); function LegacyCredentialsService () { this.list = { @@ -23,8 +19,8 @@ function LegacyCredentialsService () { templateUrl: indexTemplate }, 'list@credentials': { - templateProvider: function(CredentialList, generateList) { - let html = generateList.build({ + templateProvider (CredentialList, generateList) { + const html = generateList.build({ list: CredentialList, mode: 'edit' }); @@ -37,15 +33,13 @@ function LegacyCredentialsService () { searchPrefix: 'credential', resolve: { Dataset: ['CredentialList', 'QuerySet', '$stateParams', 'GetBasePath', - function(list, qs, $stateParams, GetBasePath) { - let path = GetBasePath(list.basePath) || GetBasePath(list.name); + (list, qs, $stateParams, GetBasePath) => { + const path = GetBasePath(list.basePath) || GetBasePath(list.name); return qs.search(path, $stateParams[`${list.iterator}_search`]); } ], - credentialType: ['CredentialTypeModel', CredentialType => { - return new CredentialType('get'); - }] + credentialType: ['CredentialTypeModel', CredentialType => new CredentialType('get')] } }; @@ -53,63 +47,60 @@ function LegacyCredentialsService () { name: 'credentials.edit.permissions', url: '/permissions?{permission_search:queryset}', resolve: { - ListDefinition: () => { - return { - name: 'permissions', - disabled: 'organization === undefined', - ngClick: `organization === undefined || $state.go('credentials.edit.permissions')`, - awToolTip: '{{permissionsTooltip}}', - dataTipWatch: 'permissionsTooltip', - awToolTipTabEnabledInEditMode: true, - dataPlacement: 'right', - basePath: 'api/v2/credentials/{{$stateParams.id}}/access_list/', - search: { - order_by: 'username' - }, - type: 'collection', - title: N_('Permissions'), - iterator: 'permission', - index: false, - open: false, - actions: { - add: { - ngClick: `$state.go('.add')`, - label: 'Add', - awToolTip: N_('Add a permission'), - actionClass: 'btn List-buttonSubmit', - buttonContent: '+ ' + N_('ADD'), - ngShow: '(credential_obj.summary_fields.user_capabilities.edit || canAdd)' - } - }, - fields: { - username: { - key: true, - label: N_('User'), - linkBase: 'users', - class: 'col-lg-3 col-md-3 col-sm-3 col-xs-4' - }, - role: { - label: N_('Role'), - type: 'role', - nosort: true, - class: 'col-lg-4 col-md-4 col-sm-4 col-xs-4' - }, - team_roles: { - label: N_('Team Roles'), - type: 'team_roles', - nosort: true, - class: 'col-lg-5 col-md-5 col-sm-5 col-xs-4' - } + ListDefinition: () => ({ + name: 'permissions', + disabled: 'organization === undefined', + ngClick: 'organization === undefined || $state.go(\'credentials.edit.permissions\')', + awToolTip: '{{permissionsTooltip}}', + dataTipWatch: 'permissionsTooltip', + awToolTipTabEnabledInEditMode: true, + dataPlacement: 'right', + basePath: 'api/v2/credentials/{{$stateParams.id}}/access_list/', + search: { + order_by: 'username' + }, + type: 'collection', + title: N_('Permissions'), + iterator: 'permission', + index: false, + open: false, + actions: { + add: { + ngClick: '$state.go(\'.add\')', + label: 'Add', + awToolTip: N_('Add a permission'), + actionClass: 'btn List-buttonSubmit', + buttonContent: `+ ${N_('ADD')}`, + ngShow: '(credential_obj.summary_fields.user_capabilities.edit || canAdd)' + } + }, + fields: { + username: { + key: true, + label: N_('User'), + linkBase: 'users', + class: 'col-lg-3 col-md-3 col-sm-3 col-xs-4' + }, + role: { + label: N_('Role'), + type: 'role', + nosort: true, + class: 'col-lg-4 col-md-4 col-sm-4 col-xs-4' + }, + team_roles: { + label: N_('Team Roles'), + type: 'team_roles', + nosort: true, + class: 'col-lg-5 col-md-5 col-sm-5 col-xs-4' } - }; - }, - Dataset: ['QuerySet', '$stateParams', (qs, $stateParams) => { - let id = $stateParams.credential_id; - let path = `api/v2/credentials/${id}/access_list/`; - - return qs.search(path, $stateParams[`permission_search`]); } - ] + }), + Dataset: ['QuerySet', '$stateParams', (qs, $stateParams) => { + const id = $stateParams.credential_id; + const path = `api/v2/credentials/${id}/access_list/`; + + return qs.search(path, $stateParams.permission_search); + }] }, params: { permission_search: { @@ -117,8 +108,8 @@ function LegacyCredentialsService () { page_size: '20', order_by: 'username' }, - dynamic:true, - squash:'' + dynamic: true, + squash: '' } }, ncyBreadcrumb: { @@ -126,12 +117,12 @@ function LegacyCredentialsService () { label: N_('PERMISSIONS') }, views: { - 'related': { - templateProvider: function(CredentialForm, GenerateForm) { - let html = GenerateForm.buildCollection({ + related: { + templateProvider (CredentialForm, GenerateForm) { + const html = GenerateForm.buildCollection({ mode: 'edit', - related: `permissions`, - form: typeof(CredentialForm) === 'function' ? + related: 'permissions', + form: typeof (CredentialForm) === 'function' ? CredentialForm() : CredentialForm }); return html; @@ -152,7 +143,14 @@ function LegacyCredentialsService () { 'GetBasePath', 'resourceData', (list, qs, $stateParams, GetBasePath, resourceData) => { - let path = resourceData.data.organization ? GetBasePath('organizations') + `${resourceData.data.organization}/users` : ((list.basePath) || GetBasePath(list.name)); + let path; + + if (resourceData.data.organization) { + path = `${GetBasePath('organizations')}${resourceData.data.organization}/users`; + } else { + path = list.basePath || GetBasePath(list.name); + } + return qs.search(path, $stateParams.user_search); } ], @@ -163,23 +161,22 @@ function LegacyCredentialsService () { 'GetBasePath', 'resourceData', (list, qs, $stateParams, GetBasePath, resourceData) => { - let path = GetBasePath(list.basePath) || GetBasePath(list.name); + const path = GetBasePath(list.basePath) || GetBasePath(list.name); + const org = resourceData.data.organization; - if(!resourceData.data.organization) { + if (!org) { return null; } - else { - $stateParams[`${list.iterator}_search`].organization = resourceData.data.organization; - return qs.search(path, $stateParams.team_search); - } + $stateParams[`${list.iterator}_search`].organization = org; + return qs.search(path, $stateParams.team_search); } ], - resourceData: ['CredentialModel', '$stateParams', (Credential, $stateParams) => { - return new Credential('get', $stateParams.credential_id) - .then(credential => ({ data: credential.get() })); - }], + resourceData: ['CredentialModel', '$stateParams', (Credential, $stateParams) => + new Credential('get', $stateParams.credential_id) + .then(credential => ({ data: credential.get() })) + ] }, params: { user_search: { @@ -224,7 +221,7 @@ function LegacyCredentialsService () { }; this.lookupTemplateProvider = (ListDefinition, generateList) => { - let html = generateList.build({ + const html = generateList.build({ mode: 'lookup', list: ListDefinition, input_type: 'radio' @@ -256,19 +253,15 @@ function LegacyCredentialsService () { }, views: {}, resolve: { - ListDefinition: ['OrganizationList', list => { - return list; - }], + ListDefinition: ['OrganizationList', list => list], Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath', - (list, qs, $stateParams, GetBasePath) => { - return qs.search( - GetBasePath('organizations'), - $stateParams[`${list.iterator}_search`] - ); - } + (list, qs, $stateParams, GetBasePath) => qs.search( + GetBasePath('organizations'), + $stateParams[`${list.iterator}_search`] + ) ] }, - onExit: function($state) { + onExit ($state) { if ($state.transition) { $('#form-modal').modal('hide'); $('.modal-backdrop').remove(); @@ -299,19 +292,15 @@ function LegacyCredentialsService () { }, views: {}, resolve: { - ListDefinition: ['CredentialTypesList', list => { - return list; - }], + ListDefinition: ['CredentialTypesList', list => list], Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath', - (list, qs, $stateParams, GetBasePath) => { - return qs.search( - GetBasePath('credential_types'), - $stateParams[`${list.iterator}_search`] - ); - } + (list, qs, $stateParams, GetBasePath) => qs.search( + GetBasePath('credential_types'), + $stateParams[`${list.iterator}_search`] + ) ] }, - onExit: function($state) { + onExit ($state) { if ($state.transition) { $('#form-modal').modal('hide'); $('.modal-backdrop').remove(); @@ -359,7 +348,7 @@ function LegacyCredentialsService () { default: throw new Error(N_(`Legacy state configuration for ${name} does not exist`)); - }; + } }; } diff --git a/awx/ui/client/features/index.js b/awx/ui/client/features/index.js index 30ce87123d..f5756de731 100644 --- a/awx/ui/client/features/index.js +++ b/awx/ui/client/features/index.js @@ -1,4 +1,4 @@ -import './credentials'; +import '~features/credentials'; angular.module('at.features', [ 'at.features.credentials' diff --git a/awx/ui/client/lib/components/action/action-group.directive.js b/awx/ui/client/lib/components/action/action-group.directive.js index a9bd073d7e..1974ab1d43 100644 --- a/awx/ui/client/lib/components/action/action-group.directive.js +++ b/awx/ui/client/lib/components/action/action-group.directive.js @@ -1,4 +1,4 @@ -const templateUrl = require('@components/action/action-group.partial.html'); +const templateUrl = require('~components/action/action-group.partial.html'); function atActionGroup () { return { diff --git a/awx/ui/client/lib/components/components.strings.js b/awx/ui/client/lib/components/components.strings.js index 296ab70b4e..0cb8017edb 100644 --- a/awx/ui/client/lib/components/components.strings.js +++ b/awx/ui/client/lib/components/components.strings.js @@ -1,8 +1,8 @@ function ComponentsStrings (BaseString) { BaseString.call(this, 'components'); - let t = this.t; - let ns = this.components; + const { t } = this; + const ns = this.components; ns.REPLACE = t.s('REPLACE'); ns.REVERT = t.s('REVERT'); @@ -18,7 +18,7 @@ function ComponentsStrings (BaseString) { ns.form = { SUBMISSION_ERROR_TITLE: t.s('Unable to Submit'), - SUBMISSION_ERROR_MESSAGE:t.s('Unexpected server error. View the console for more information'), + SUBMISSION_ERROR_MESSAGE: t.s('Unexpected server error. View the console for more information'), SUBMISSION_ERROR_PREFACE: t.s('Unexpected Error') }; @@ -46,7 +46,7 @@ function ComponentsStrings (BaseString) { ns.truncate = { DEFAULT: t.s('Copy full revision to clipboard.'), COPIED: t.s('Copied to clipboard.') - } + }; ns.layout = { CURRENT_USER_LABEL: t.s('Logged in as'), @@ -71,7 +71,7 @@ function ComponentsStrings (BaseString) { SETTINGS: t.s('Settings'), FOOTER_ABOUT: t.s('About'), FOOTER_COPYRIGHT: t.s('Copyright © 2017 Red Hat, Inc.') - } + }; } ComponentsStrings.$inject = ['BaseStringService']; diff --git a/awx/ui/client/lib/components/form/action.directive.js b/awx/ui/client/lib/components/form/action.directive.js index d034d99b79..4ba3c7d67a 100644 --- a/awx/ui/client/lib/components/form/action.directive.js +++ b/awx/ui/client/lib/components/form/action.directive.js @@ -1,25 +1,22 @@ -const templateUrl = require('@components/form/action.partial.html'); +const templateUrl = require('~components/form/action.partial.html'); function link (scope, element, attrs, controllers) { - let formController = controllers[0]; - let actionController = controllers[1]; + const [formController, actionController] = controllers; - actionController.init(formController, element, scope); + actionController.init(formController, scope); } function atFormActionController ($state, strings) { - let vm = this || {}; + const vm = this || {}; - let element; let form; let scope; - vm.init = (_form_, _element_, _scope_) => { + vm.init = (_form_, _scope_) => { form = _form_; - element = _element_; scope = _scope_; - switch(scope.type) { + switch (scope.type) { case 'cancel': vm.setCancelDefaults(); break; @@ -33,22 +30,18 @@ function atFormActionController ($state, strings) { form.register('action', scope); }; - vm.setCustomDefaults = () => { - - }; - vm.setCancelDefaults = () => { - scope.text = strings.get('CANCEL'), + scope.text = strings.get('CANCEL'); scope.fill = 'Hollow'; scope.color = 'default'; - scope.action = () => $state.go(scope.to || '^'); + scope.action = () => { $state.go(scope.to || '^'); }; }; vm.setSaveDefaults = () => { - scope.text = strings.get('SAVE'), + scope.text = strings.get('SAVE'); scope.fill = ''; scope.color = 'success'; - scope.action = () => form.submit(); + scope.action = () => { form.submit(); }; }; } diff --git a/awx/ui/client/lib/components/form/form.directive.js b/awx/ui/client/lib/components/form/form.directive.js index 04cdc913bb..018ca393e7 100644 --- a/awx/ui/client/lib/components/form/form.directive.js +++ b/awx/ui/client/lib/components/form/form.directive.js @@ -1,8 +1,8 @@ -const templateUrl = require('@components/form/form.partial.html'); +const templateUrl = require('~components/form/form.partial.html'); function atFormLink (scope, el, attrs, controllers) { - let formController = controllers[0]; - let form = el[0]; + const formController = controllers[0]; + const form = el[0]; scope.ns = 'form'; scope[scope.ns] = { modal: {} }; @@ -11,7 +11,7 @@ function atFormLink (scope, el, attrs, controllers) { } function AtFormController (eventService, strings) { - let vm = this || {}; + const vm = this || {}; let scope; let modal; @@ -27,22 +27,22 @@ function AtFormController (eventService, strings) { vm.init = (_scope_, _form_) => { scope = _scope_; form = _form_; - modal = scope[scope.ns].modal; + ({ modal } = scope[scope.ns]); vm.state.disabled = scope.state.disabled; vm.setListeners(); }; - vm.register = (category, component, el) => { + vm.register = (category, component) => { component.category = category; component.form = vm.state; - vm.components.push(component) + vm.components.push(component); }; vm.setListeners = () => { - let listeners = eventService.addListeners([ + const listeners = eventService.addListeners([ [form, 'keypress', vm.submitOnEnter] ]); @@ -58,14 +58,14 @@ function AtFormController (eventService, strings) { scope.$apply(vm.submit); }; - vm.submit = event => { + vm.submit = () => { if (!vm.state.isValid) { return; } vm.state.disabled = true; - let data = vm.components + const data = vm.components .filter(component => component.category === 'input') .reduce((values, component) => { if (!component.state._value) { @@ -87,7 +87,7 @@ function AtFormController (eventService, strings) { scope.state.save(data) .then(scope.state.onSaveSuccess) .catch(err => vm.onSaveError(err)) - .finally(() => vm.state.disabled = false); + .finally(() => { vm.state.disabled = false; }); }; vm.onSaveError = err => { @@ -103,22 +103,22 @@ function AtFormController (eventService, strings) { if (!handled) { let message; - let title = strings.get('form.SUBMISSION_ERROR_TITLE'); - let preface = strings.get('form.SUBMISSION_ERROR_PREFACE'); + const title = strings.get('form.SUBMISSION_ERROR_TITLE'); + const preface = strings.get('form.SUBMISSION_ERROR_PREFACE'); if (typeof err.data === 'object') { - message = JSON.stringify(err.data); + message = JSON.stringify(err.data); } else { message = err.data; } - modal.show(title, `${preface}: ${message}`) + modal.show(title, `${preface}: ${message}`); } }; - vm.handleUnexpectedError = err => { - let title = strings.get('form.SUBMISSION_ERROR_TITLE'); - let message = strings.get('form.SUBMISSION_ERROR_MESSAGE'); + vm.handleUnexpectedError = () => { + const title = strings.get('form.SUBMISSION_ERROR_TITLE'); + const message = strings.get('form.SUBMISSION_ERROR_MESSAGE'); modal.show(title, message); @@ -126,7 +126,7 @@ function AtFormController (eventService, strings) { }; vm.handleValidationError = errors => { - let errorMessageSet = vm.setValidationMessages(errors); + const errorMessageSet = vm.setValidationMessages(errors); if (errorMessageSet) { vm.check(); @@ -138,10 +138,11 @@ function AtFormController (eventService, strings) { vm.setValidationMessages = (errors, errorSet) => { let errorMessageSet = errorSet || false; - for (let id in errors) { + Object.keys(errors).forEach(id => { if (!Array.isArray(errors[id]) && typeof errors[id] === 'object') { errorMessageSet = vm.setValidationMessages(errors[id], errorMessageSet); - continue; + + return; } vm.components @@ -153,7 +154,7 @@ function AtFormController (eventService, strings) { component.state._rejected = true; component.state._message = errors[component.state.id].join(' '); }); - } + }); return errorMessageSet; }; @@ -176,7 +177,7 @@ function AtFormController (eventService, strings) { }; vm.check = () => { - let isValid = vm.validate(); + const isValid = vm.validate(); if (isValid !== vm.state.isValid) { vm.state.isValid = isValid; diff --git a/awx/ui/client/lib/components/index.js b/awx/ui/client/lib/components/index.js index 3f78229f5f..9d6a2a1ac2 100644 --- a/awx/ui/client/lib/components/index.js +++ b/awx/ui/client/lib/components/index.js @@ -1,32 +1,32 @@ -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 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 '@components/input/base.controller'; -import ComponentsStrings from '@components/components.strings'; +import BaseInputController from '~components/input/base.controller'; +import ComponentsStrings from '~components/components.strings'; angular .module('at.lib.components', []) diff --git a/awx/ui/client/lib/components/input/base.controller.js b/awx/ui/client/lib/components/input/base.controller.js index 8d92711660..13fa825a5d 100644 --- a/awx/ui/client/lib/components/input/base.controller.js +++ b/awx/ui/client/lib/components/input/base.controller.js @@ -4,7 +4,7 @@ function BaseInputController (strings) { const ENCRYPTED_VALUE = '$encrypted$'; return function extend (type, scope, element, form) { - let vm = this; + const vm = this; vm.strings = strings; @@ -50,10 +50,10 @@ function BaseInputController (strings) { } if (scope.state._required && !scope.state._value && !scope.state._displayValue) { - isValid = false; + isValid = false; message = vm.strings.get('message.REQUIRED_INPUT_MISSING'); } else if (scope.state._validate) { - let result = scope.state._validate(scope.state._value); + const result = scope.state._validate(scope.state._value); if (!result.isValid) { isValid = false; @@ -111,18 +111,16 @@ function BaseInputController (strings) { scope.state._activeModel = '_displayValue'; scope.state._disabled = true; scope.state._enableToggle = false; + } else if (scope.state._isBeingReplaced === false) { + scope.state._disabled = true; + scope.state._enableToggle = true; + scope.state._value = scope.state._preEditValue; } else { - if (scope.state._isBeingReplaced === false) { - scope.state._disabled = true; - scope.state._enableToggle = true; - scope.state._value = scope.state._preEditValue; - } else { - scope.state._activeModel = '_value'; - scope.state._disabled = false; - scope.state._value = ''; - } + scope.state._activeModel = '_value'; + scope.state._disabled = false; + scope.state._value = ''; } - + vm.check(); }; }; diff --git a/awx/ui/client/lib/components/input/checkbox.directive.js b/awx/ui/client/lib/components/input/checkbox.directive.js index 90bb268e53..00fcdcf05c 100644 --- a/awx/ui/client/lib/components/input/checkbox.directive.js +++ b/awx/ui/client/lib/components/input/checkbox.directive.js @@ -1,8 +1,8 @@ -const templateUrl = require('@components/input/checkbox.partial.html'); +const templateUrl = require('~components/input/checkbox.partial.html'); function atInputCheckboxLink (scope, element, attrs, controllers) { - let formController = controllers[0]; - let inputController = controllers[1]; + const formController = controllers[0]; + const inputController = controllers[1]; if (scope.tab === '1') { element.find('input')[0].focus(); @@ -12,7 +12,7 @@ function atInputCheckboxLink (scope, element, attrs, controllers) { } function AtInputCheckboxController (baseInputController) { - let vm = this || {}; + const vm = this || {}; vm.init = (scope, element, form) => { baseInputController.call(vm, 'input', scope, element, form); diff --git a/awx/ui/client/lib/components/input/group.directive.js b/awx/ui/client/lib/components/input/group.directive.js index e8a2a05466..c94dd99f04 100644 --- a/awx/ui/client/lib/components/input/group.directive.js +++ b/awx/ui/client/lib/components/input/group.directive.js @@ -1,15 +1,15 @@ -const templateUrl = require('@components/input/group.partial.html'); +const templateUrl = require('~components/input/group.partial.html'); function atInputGroupLink (scope, el, attrs, controllers) { - let groupController = controllers[0]; - let formController = controllers[1]; - let element = el[0].getElementsByClassName('at-InputGroup-container')[0]; - + const groupController = controllers[0]; + const formController = controllers[1]; + const element = el[0].getElementsByClassName('at-InputGroup-container')[0]; + groupController.init(scope, formController, element); } function AtInputGroupController ($scope, $compile) { - let vm = this || {}; + const vm = this || {}; let form; let scope; @@ -31,7 +31,7 @@ function AtInputGroupController ($scope, $compile) { if (!source._value || source._value === state._value) { return false; } - + return true; }; @@ -46,15 +46,15 @@ function AtInputGroupController ($scope, $compile) { state._value = source._value; - let inputs = state._get(source._value); - let group = vm.createComponentConfigs(inputs); + const inputs = state._get(source._value); + const group = vm.createComponentConfigs(inputs); vm.insert(group); state._group = group; }; vm.createComponentConfigs = inputs => { - let group = []; + const group = []; if (inputs) { inputs.forEach((input, i) => { @@ -73,7 +73,7 @@ function AtInputGroupController ($scope, $compile) { }; vm.getComponentType = input => { - let config = {}; + const config = {}; if (input.type === 'string') { if (!input.multiline) { @@ -105,17 +105,17 @@ function AtInputGroupController ($scope, $compile) { config._data = input.choices; config._exp = 'choice for (index, choice) in state._data'; } else { - let preface = vm.strings.get('group.UNSUPPORTED_ERROR_PREFACE'); - throw new Error(`${preface}: ${input.type}`) + const preface = vm.strings.get('group.UNSUPPORTED_ERROR_PREFACE'); + throw new Error(`${preface}: ${input.type}`); } return config; }; vm.insert = group => { - let container = document.createElement('div'); + const container = document.createElement('div'); let col = 1; - let colPerRow = 12 / scope.col; + const colPerRow = 12 / scope.col; let isDivided = true; group.forEach((input, i) => { @@ -125,7 +125,7 @@ function AtInputGroupController ($scope, $compile) { container.appendChild(input._element[0]); - if ((input._expand || col % colPerRow === 0) && i !== group.length -1) { + if ((input._expand || col % colPerRow === 0) && i !== group.length - 1) { container.appendChild(vm.createDivider()[0]); isDivided = true; col = 0; @@ -140,21 +140,19 @@ function AtInputGroupController ($scope, $compile) { }; vm.createComponent = (input, index) => { - let tabindex = Number(scope.tab) + index; - let col = input._expand ? 12 : scope.col; - let component = angular.element( - `<${input._component} col="${col}" tab="${tabindex}" + const tabindex = Number(scope.tab) + index; + const col = input._expand ? 12 : scope.col; + const component = angular.element(`<${input._component} col="${col}" tab="${tabindex}" state="${state._reference}._group[${index}]"> - ` - ); + `); - $compile(component)(scope.$parent) + $compile(component)(scope.$parent); return component; }; vm.createDivider = () => { - let divider = angular.element(''); + const divider = angular.element(''); $compile(divider[0])(scope.$parent); return divider; diff --git a/awx/ui/client/lib/components/input/label.directive.js b/awx/ui/client/lib/components/input/label.directive.js index 9fc896b398..ea1fafd23a 100644 --- a/awx/ui/client/lib/components/input/label.directive.js +++ b/awx/ui/client/lib/components/input/label.directive.js @@ -1,4 +1,4 @@ -const templateUrl = require('@components/input/label.partial.html'); +const templateUrl = require('~components/input/label.partial.html'); function atInputLabel () { return { diff --git a/awx/ui/client/lib/components/input/lookup.directive.js b/awx/ui/client/lib/components/input/lookup.directive.js index b5a7945dc8..1ab6e941e7 100644 --- a/awx/ui/client/lib/components/input/lookup.directive.js +++ b/awx/ui/client/lib/components/input/lookup.directive.js @@ -1,11 +1,11 @@ -const templateUrl = require('@components/input/lookup.partial.html'); +const templateUrl = require('~components/input/lookup.partial.html'); const DEFAULT_DEBOUNCE = 250; const DEFAULT_KEY = 'name'; function atInputLookupLink (scope, element, attrs, controllers) { - let formController = controllers[0]; - let inputController = controllers[1]; + const formController = controllers[0]; + const inputController = controllers[1]; if (scope.tab === '1') { element.find('input')[0].focus(); @@ -14,8 +14,8 @@ function atInputLookupLink (scope, element, attrs, controllers) { inputController.init(scope, element, formController); } -function AtInputLookupController (baseInputController, $q, $state, $stateParams) { - let vm = this || {}; +function AtInputLookupController (baseInputController, $q, $state) { + const vm = this || {}; let scope; let model; @@ -52,7 +52,7 @@ function AtInputLookupController (baseInputController, $q, $state, $stateParams) }; vm.lookup = () => { - let params = {}; + const params = {}; if (scope.state._value && scope.state._isValid) { params.selected = scope.state._value; @@ -77,7 +77,7 @@ function AtInputLookupController (baseInputController, $q, $state, $stateParams) vm.resetDebounce = () => { clearTimeout(vm.debounce); - vm.searchAfterDebounce(); + vm.searchAfterDebounce(); }; vm.search = () => { @@ -90,7 +90,9 @@ function AtInputLookupController (baseInputController, $q, $state, $stateParams) return model.search({ [search.key]: scope.state._displayValue }, search.config) .then(found => { if (!found) { - return vm.reset(); + vm.reset(); + + return; } scope[scope.state._resource] = model.get('id'); @@ -99,8 +101,8 @@ function AtInputLookupController (baseInputController, $q, $state, $stateParams) }) .catch(() => vm.reset()) .finally(() => { - let isValid = scope.state._value !== undefined; - let message = isValid ? '' : vm.strings.get('lookup.NOT_FOUND'); + const isValid = scope.state._value !== undefined; + const message = isValid ? '' : vm.strings.get('lookup.NOT_FOUND'); vm.check({ isValid, message }); }); @@ -108,7 +110,9 @@ function AtInputLookupController (baseInputController, $q, $state, $stateParams) vm.searchOnInput = () => { if (vm.isDebouncing) { - return vm.resetDebounce(); + vm.resetDebounce(); + + return; } vm.searchAfterDebounce(); @@ -118,8 +122,7 @@ function AtInputLookupController (baseInputController, $q, $state, $stateParams) AtInputLookupController.$inject = [ 'BaseInputController', '$q', - '$state', - '$stateParams' + '$state' ]; function atInputLookup () { diff --git a/awx/ui/client/lib/components/input/message.directive.js b/awx/ui/client/lib/components/input/message.directive.js index 0637382e6d..6e4dba6da3 100644 --- a/awx/ui/client/lib/components/input/message.directive.js +++ b/awx/ui/client/lib/components/input/message.directive.js @@ -1,4 +1,4 @@ -const templateUrl = require('@components/input/message.partial.html'); +const templateUrl = require('~components/input/message.partial.html'); function atInputMessage () { return { diff --git a/awx/ui/client/lib/components/input/secret.directive.js b/awx/ui/client/lib/components/input/secret.directive.js index 52a11a60a2..542103eba3 100644 --- a/awx/ui/client/lib/components/input/secret.directive.js +++ b/awx/ui/client/lib/components/input/secret.directive.js @@ -1,8 +1,8 @@ -const templateUrl = require('@components/input/secret.partial.html'); +const templateUrl = require('~components/input/secret.partial.html'); function atInputSecretLink (scope, element, attrs, controllers) { - let formController = controllers[0]; - let inputController = controllers[1]; + const formController = controllers[0]; + const inputController = controllers[1]; if (scope.tab === '1') { element.find('input')[0].focus(); @@ -12,7 +12,7 @@ function atInputSecretLink (scope, element, attrs, controllers) { } function AtInputSecretController (baseInputController) { - let vm = this || {}; + const vm = this || {}; let scope; diff --git a/awx/ui/client/lib/components/input/select.directive.js b/awx/ui/client/lib/components/input/select.directive.js index 9d4c6a0347..8507573a61 100644 --- a/awx/ui/client/lib/components/input/select.directive.js +++ b/awx/ui/client/lib/components/input/select.directive.js @@ -1,18 +1,13 @@ -const templateUrl = require('@components/input/select.partial.html'); +const templateUrl = require('~components/input/select.partial.html'); function atInputSelectLink (scope, element, attrs, controllers) { - let formController = controllers[0]; - let inputController = controllers[1]; - - if (scope.tab === '1') { - elements.select.focus(); - } + const [formController, inputController] = controllers; inputController.init(scope, element, formController); } function AtInputSelectController (baseInputController, eventService) { - let vm = this || {}; + const vm = this || {}; let scope; let element; @@ -24,8 +19,12 @@ function AtInputSelectController (baseInputController, eventService) { scope = _scope_; element = _element_; - input = element.find('input')[0]; - select = element.find('select')[0]; + [input] = element.find('input'); + [select] = element.find('select'); + + if (scope.tab === '1') { + select.focus(); + } if (!scope.state._data || scope.state._data.length === 0) { scope.state._disabled = true; @@ -36,14 +35,14 @@ function AtInputSelectController (baseInputController, eventService) { vm.check(); if (scope.state._value) { - vm.updateDisplayModel(); + vm.updateDisplayModel(); } }; vm.setListeners = () => { - let listeners = eventService.addListeners([ + const listeners = eventService.addListeners([ [input, 'focus', () => select.focus], - [select, 'mousedown', () => scope.$apply(() => scope.open = !scope.open)], + [select, 'mousedown', () => scope.$apply(() => { scope.open = !scope.open; })], [select, 'focus', () => input.classList.add('at-Input--focus')], [select, 'change', () => scope.$apply(() => { scope.open = false; diff --git a/awx/ui/client/lib/components/input/text.directive.js b/awx/ui/client/lib/components/input/text.directive.js index 384faa25f2..e8d514fc7e 100644 --- a/awx/ui/client/lib/components/input/text.directive.js +++ b/awx/ui/client/lib/components/input/text.directive.js @@ -1,8 +1,8 @@ -const templateUrl = require('@components/input/text.partial.html'); +const templateUrl = require('~components/input/text.partial.html'); function atInputTextLink (scope, element, attrs, controllers) { - let formController = controllers[0]; - let inputController = controllers[1]; + const formController = controllers[0]; + const inputController = controllers[1]; if (scope.tab === '1') { element.find('input')[0].focus(); @@ -12,7 +12,7 @@ function atInputTextLink (scope, element, attrs, controllers) { } function AtInputTextController (baseInputController) { - let vm = this || {}; + const vm = this || {}; vm.init = (scope, element, form) => { baseInputController.call(vm, 'input', scope, element, form); diff --git a/awx/ui/client/lib/components/input/textarea-secret.directive.js b/awx/ui/client/lib/components/input/textarea-secret.directive.js index 48b97382f0..7e4cd964d6 100644 --- a/awx/ui/client/lib/components/input/textarea-secret.directive.js +++ b/awx/ui/client/lib/components/input/textarea-secret.directive.js @@ -1,8 +1,7 @@ -const templateUrl = require('@components/input/textarea-secret.partial.html'); +const templateUrl = require('~components/input/textarea-secret.partial.html'); function atInputTextareaSecretLink (scope, element, attrs, controllers) { - let formController = controllers[0]; - let inputController = controllers[1]; + const [formController, inputController] = controllers; if (scope.tab === '1') { element.find('textarea')[0].focus(); @@ -12,34 +11,30 @@ function atInputTextareaSecretLink (scope, element, attrs, controllers) { } function AtInputTextareaSecretController (baseInputController, eventService) { - let vm = this || {}; + const vm = this || {}; let scope; let textarea; - let container; let input; vm.init = (_scope_, element, form) => { baseInputController.call(vm, 'input', _scope_, element, form); scope = _scope_; - textarea = element.find('textarea')[0]; - container = element[0]; + [textarea] = element.find('textarea'); if (scope.state.format === 'ssh_private_key') { scope.ssh = true; scope.state._hint = scope.state._hint || vm.strings.get('textarea.SSH_KEY_HINT'); - input = element.find('input')[0]; + [input] = element.find('input'); } if (scope.state._value) { scope.state._buttonText = vm.strings.get('REPLACE'); scope.state._placeholder = vm.strings.get('ENCRYPTED'); - } else { - if (scope.state.format === 'ssh_private_key') { - vm.listeners = vm.setFileListeners(textarea, input); - scope.state._displayHint = true; - } + } else if (scope.state.format === 'ssh_private_key') { + vm.listeners = vm.setFileListeners(textarea, input); + scope.state._displayHint = true; } vm.check(); @@ -59,34 +54,32 @@ function AtInputTextareaSecretController (baseInputController, eventService) { } }; - vm.setFileListeners = (textarea, input) => { - return eventService.addListeners([ - [textarea, 'dragenter', event => { - event.stopPropagation(); - event.preventDefault(); - scope.$apply(() => scope.drag = true); - }], + vm.setFileListeners = (textareaEl, inputEl) => eventService.addListeners([ + [textareaEl, 'dragenter', event => { + event.stopPropagation(); + event.preventDefault(); + scope.$apply(() => { scope.drag = true; }); + }], - [input, 'dragleave', event => { - event.stopPropagation(); - event.preventDefault(); - scope.$apply(() => scope.drag = false); - }], + [inputEl, 'dragleave', event => { + event.stopPropagation(); + event.preventDefault(); + scope.$apply(() => { scope.drag = false; }); + }], - [input, 'change', event => { - let reader = new FileReader(); + [inputEl, 'change', event => { + const reader = new FileReader(); - reader.onload = () => vm.readFile(reader, event); - reader.readAsText(input.files[0]); - }] - ]); - }; + reader.onload = () => vm.readFile(reader, event); + reader.readAsText(inputEl.files[0]); + }] + ]); - vm.readFile = (reader, event) => { + vm.readFile = (reader) => { scope.$apply(() => { scope.state._value = reader.result; vm.check(); - scope.drag = false + scope.drag = false; input.value = ''; }); }; diff --git a/awx/ui/client/lib/components/input/textarea.directive.js b/awx/ui/client/lib/components/input/textarea.directive.js index af5b4e2bcc..d5ac607c51 100644 --- a/awx/ui/client/lib/components/input/textarea.directive.js +++ b/awx/ui/client/lib/components/input/textarea.directive.js @@ -1,8 +1,8 @@ -const templateUrl = require('@components/input/textarea.partial.html'); +const templateUrl = require('~components/input/textarea.partial.html'); function atInputTextareaLink (scope, element, attrs, controllers) { - let formController = controllers[0]; - let inputController = controllers[1]; + const formController = controllers[0]; + const inputController = controllers[1]; if (scope.tab === '1') { element.find('input')[0].focus(); @@ -12,7 +12,7 @@ function atInputTextareaLink (scope, element, attrs, controllers) { } function AtInputTextareaController (baseInputController) { - let vm = this || {}; + const vm = this || {}; vm.init = (scope, element, form) => { baseInputController.call(vm, 'input', scope, element, form); diff --git a/awx/ui/client/lib/components/layout/layout.directive.js b/awx/ui/client/lib/components/layout/layout.directive.js index 396c290cec..0f40ce7868 100644 --- a/awx/ui/client/lib/components/layout/layout.directive.js +++ b/awx/ui/client/lib/components/layout/layout.directive.js @@ -1,13 +1,13 @@ -const templateUrl = require('@components/layout/layout.partial.html'); +const templateUrl = require('~components/layout/layout.partial.html'); function AtLayoutController ($scope, strings) { - let vm = this || {}; + const vm = this || {}; - $scope.$on('$stateChangeSuccess', function(event, next) { + $scope.$on('$stateChangeSuccess', (event, next) => { vm.currentState = next.name; }); - $scope.$watch('$root.current_user', function(val) { + $scope.$watch('$root.current_user', (val) => { vm.isLoggedIn = val && val.username; if (val) { vm.isSuperUser = $scope.$root.user_is_superuser || $scope.$root.user_is_system_auditor; @@ -16,19 +16,19 @@ function AtLayoutController ($scope, strings) { } }); - $scope.$watch('$root.socketStatus', function(newStatus) { + $scope.$watch('$root.socketStatus', (newStatus) => { vm.socketState = newStatus; - vm.socketIconClass = "icon-socket-" + $scope.socketStatus; + vm.socketIconClass = `icon-socket-${$scope.socketStatus}`; }); - $scope.$watch('$root.licenseMissing', function(licenseMissing) { + $scope.$watch('$root.licenseMissing', (licenseMissing) => { vm.licenseIsMissing = licenseMissing; }); - vm.getString = function(string) { + vm.getString = string => { try { return strings.get(`layout.${string}`); - } catch(err) { + } catch (err) { return strings.get(string); } }; @@ -44,8 +44,7 @@ function atLayout () { templateUrl, controller: AtLayoutController, controllerAs: 'vm', - scope: { - } + scope: {} }; } diff --git a/awx/ui/client/lib/components/layout/side-nav-item.directive.js b/awx/ui/client/lib/components/layout/side-nav-item.directive.js index 6a0f6c1624..ab52d74964 100644 --- a/awx/ui/client/lib/components/layout/side-nav-item.directive.js +++ b/awx/ui/client/lib/components/layout/side-nav-item.directive.js @@ -1,32 +1,29 @@ -const templateUrl = require('@components/layout/side-nav-item.partial.html'); +const templateUrl = require('~components/layout/side-nav-item.partial.html'); function atSideNavItemLink (scope, element, attrs, ctrl) { - scope.navVm = ctrl[0]; - scope.layoutVm = ctrl[1]; + [scope.navVm, scope.layoutVm] = ctrl; } function AtSideNavItemController ($state, $scope, strings) { - let vm = this || {}; + const vm = this || {}; - $scope.$watch('layoutVm.currentState', function(current) { + $scope.$watch('layoutVm.currentState', current => { if ($scope.name === 'portal mode') { vm.isRoute = (current && current.indexOf('portalMode') === 0); - } else { - if (current && current.indexOf($scope.route) === 0) { - if (current.indexOf('jobs.schedules') === 0 && $scope.route === 'jobs') { - vm.isRoute = false; - } else { - vm.isRoute = true; - } - } else { + } else if (current && current.indexOf($scope.route) === 0) { + if (current.indexOf('jobs.schedules') === 0 && $scope.route === 'jobs') { vm.isRoute = false; + } else { + vm.isRoute = true; } + } else { + vm.isRoute = false; } }); - vm.go = function() { - $state.go($scope.route, {}, {reload: true}); - } + vm.go = () => { + $state.go($scope.route, {}, { reload: true }); + }; vm.tooltip = { popover: { @@ -36,7 +33,7 @@ function AtSideNavItemController ($state, $scope, strings) { position: 'right', arrowHeight: 18 } - } + }; } AtSideNavItemController.$inject = ['$state', '$scope', 'ComponentsStrings']; diff --git a/awx/ui/client/lib/components/layout/side-nav.directive.js b/awx/ui/client/lib/components/layout/side-nav.directive.js index daeb334b3f..2b47d7a7da 100644 --- a/awx/ui/client/lib/components/layout/side-nav.directive.js +++ b/awx/ui/client/lib/components/layout/side-nav.directive.js @@ -1,17 +1,17 @@ -const templateUrl = require('@components/layout/side-nav.partial.html'); +const templateUrl = require('~components/layout/side-nav.partial.html'); function atSideNavLink (scope, element, attrs, ctrl) { scope.layoutVm = ctrl; } function AtSideNavController () { - let vm = this || {}; + const vm = this || {}; vm.isExpanded = false; vm.toggleExpansion = () => { vm.isExpanded = !vm.isExpanded; - } + }; } function atSideNav () { diff --git a/awx/ui/client/lib/components/layout/top-nav-item.directive.js b/awx/ui/client/lib/components/layout/top-nav-item.directive.js index d6c30d9b2a..8851565a3f 100644 --- a/awx/ui/client/lib/components/layout/top-nav-item.directive.js +++ b/awx/ui/client/lib/components/layout/top-nav-item.directive.js @@ -1,14 +1,14 @@ -const templateUrl = require('@components/layout/top-nav-item.partial.html'); +const templateUrl = require('~components/layout/top-nav-item.partial.html'); function atTopNavItemLink (scope, element, attrs, ctrl) { scope.layoutVm = ctrl; scope.isHidden = false; - var shownWhen = attrs.isShown; + const shownWhen = attrs.isShown; if (shownWhen !== 'missingLicense') { - scope.$watch('layoutVm.licenseIsMissing', function(val) { + scope.$watch('layoutVm.licenseIsMissing', (val) => { scope.isHidden = val; }); } diff --git a/awx/ui/client/lib/components/modal/modal.directive.js b/awx/ui/client/lib/components/modal/modal.directive.js index ecb67001b6..f6e5510ce5 100644 --- a/awx/ui/client/lib/components/modal/modal.directive.js +++ b/awx/ui/client/lib/components/modal/modal.directive.js @@ -1,19 +1,19 @@ -const templateUrl = require('@components/modal/modal.partial.html'); +const templateUrl = require('~components/modal/modal.partial.html'); const DEFAULT_ANIMATION_DURATION = 150; function atModalLink (scope, el, attrs, controllers) { - let modalController = controllers[0]; - let property = `scope.${scope.ns}.modal`; + const modalController = controllers[0]; + const property = `scope.${scope.ns}.modal`; - let done = scope.$watch(property, () => { + const done = scope.$watch(property, () => { modalController.init(scope, el); done(); }); } function AtModalController (eventService, strings) { - let vm = this; + const vm = this; let overlay; let modal; @@ -22,8 +22,8 @@ function AtModalController (eventService, strings) { vm.strings = strings; vm.init = (scope, el) => { - overlay = el[0]; - modal = el.find('.at-Modal-window')[0]; + [overlay] = el; + [modal] = el.find('.at-Modal-window'); vm.modal = scope[scope.ns].modal; vm.modal.show = vm.show; @@ -34,8 +34,6 @@ function AtModalController (eventService, strings) { vm.modal.title = title; vm.modal.message = message; - event.stopPropagation(); - listeners = eventService.addListeners([ [window, 'click', vm.clickToHide] ]); @@ -49,7 +47,9 @@ function AtModalController (eventService, strings) { eventService.remove(listeners); - setTimeout(() => overlay.style.display = 'none', DEFAULT_ANIMATION_DURATION); + setTimeout(() => { + overlay.style.display = 'none'; + }, DEFAULT_ANIMATION_DURATION); }; vm.clickToHide = event => { @@ -59,10 +59,10 @@ function AtModalController (eventService, strings) { }; vm.clickIsOutsideModal = e => { - let m = modal.getBoundingClientRect(); - let cx = e.clientX; - let cy = e.clientY; - + const m = modal.getBoundingClientRect(); + const cx = e.clientX; + const cy = e.clientY; + if (cx < m.left || cx > m.right || cy > m.bottom || cy < m.top) { return true; } @@ -74,7 +74,7 @@ function AtModalController (eventService, strings) { AtModalController.$inject = [ 'EventService', 'ComponentsStrings' -] +]; function atModal () { return { diff --git a/awx/ui/client/lib/components/panel/body.directive.js b/awx/ui/client/lib/components/panel/body.directive.js index b9c0c07b6a..1cf795596a 100644 --- a/awx/ui/client/lib/components/panel/body.directive.js +++ b/awx/ui/client/lib/components/panel/body.directive.js @@ -1,4 +1,4 @@ -const templateUrl = require('@components/panel/body.partial.html'); +const templateUrl = require('~components/panel/body.partial.html'); function atPanelBody () { return { diff --git a/awx/ui/client/lib/components/panel/heading.directive.js b/awx/ui/client/lib/components/panel/heading.directive.js index fd5da054c1..7850f1c354 100644 --- a/awx/ui/client/lib/components/panel/heading.directive.js +++ b/awx/ui/client/lib/components/panel/heading.directive.js @@ -1,4 +1,4 @@ -const templateUrl = require('@components/panel/heading.partial.html'); +const templateUrl = require('~components/panel/heading.partial.html'); function link (scope, el, attrs, panel) { panel.use(scope); diff --git a/awx/ui/client/lib/components/panel/panel.directive.js b/awx/ui/client/lib/components/panel/panel.directive.js index e6f9c7b59b..a58b386acf 100644 --- a/awx/ui/client/lib/components/panel/panel.directive.js +++ b/awx/ui/client/lib/components/panel/panel.directive.js @@ -1,20 +1,18 @@ -const templateUrl = require('@components/panel/panel.partial.html'); +const templateUrl = require('~components/panel/panel.partial.html'); -function atPanelLink (scope, el, attrs, controllers) { - let panelController = controllers[0]; +function atPanelLink (scope, el, attrs, controller) { + const panelController = controller; - panelController.init(scope, el); + panelController.init(scope); } function AtPanelController ($state) { - let vm = this; + const vm = this; let scope; - let el; - vm.init = (_scope_, _el_) => { + vm.init = (_scope_) => { scope = _scope_; - el = _el_; }; vm.dismiss = () => { @@ -32,7 +30,7 @@ function atPanel () { return { restrict: 'E', replace: true, - require: ['atPanel'], + require: 'atPanel', transclude: true, templateUrl, controller: AtPanelController, diff --git a/awx/ui/client/lib/components/popover/popover.directive.js b/awx/ui/client/lib/components/popover/popover.directive.js index c9eb13c368..ae23f06209 100644 --- a/awx/ui/client/lib/components/popover/popover.directive.js +++ b/awx/ui/client/lib/components/popover/popover.directive.js @@ -1,4 +1,4 @@ -const templateUrl = require('@components/popover/popover.partial.html'); +const templateUrl = require('~components/popover/popover.partial.html'); const DEFAULT_POSITION = 'right'; const DEFAULT_ACTION = 'click'; @@ -10,21 +10,20 @@ const DEFAULT_REFRESH_DELAY = 50; const DEFAULT_RESET_ON_EXIT = false; function atPopoverLink (scope, el, attr, controllers) { - let popoverController = controllers[0]; - let container = el[0]; - let popover = container.getElementsByClassName('at-Popover-container')[0]; - let icon = container.getElementsByTagName('i')[0]; + const popoverController = controllers[0]; + const container = el[0]; + const popover = container.getElementsByClassName('at-Popover-container')[0]; + const icon = container.getElementsByTagName('i')[0]; - let done = scope.$watch('state', () => { + const done = scope.$watch('state', () => { popoverController.init(scope, container, icon, popover); done(); }); } function AtPopoverController () { - let vm = this; + const vm = this; - let container; let icon; let popover; let scope; @@ -59,24 +58,22 @@ function AtPopoverController () { } }; - vm.createDismissListener = (createEvent) => { - return event => { - event.stopPropagation(); + vm.createDismissListener = () => event => { + event.stopPropagation(); - if (vm.isClickWithinPopover(event, popover)) { - return; - } + if (vm.isClickWithinPopover(event, popover)) { + return; + } - vm.dismiss(); + vm.dismiss(); - if (scope.popover.on === 'mouseenter') { - icon.removeEventListener('mouseleave', vm.dismissListener); - } else { - window.addEventListener(scope.popover.on, vm.dismissListener); - } + if (scope.popover.on === 'mouseenter') { + icon.removeEventListener('mouseleave', vm.dismissListener); + } else { + window.addEventListener(scope.popover.on, vm.dismissListener); + } - window.removeEventListener('resize', vm.dismissListener); - }; + window.removeEventListener('resize', vm.dismissListener); }; vm.dismiss = (refresh) => { @@ -91,11 +88,11 @@ function AtPopoverController () { popover.style.opacity = 0; }; - vm.isClickWithinPopover = (event, popover) => { - let box = popover.getBoundingClientRect(); + vm.isClickWithinPopover = (event, popoverEl) => { + const box = popoverEl.getBoundingClientRect(); - let x = event.clientX; - let y = event.clientY; + const x = event.clientX; + const y = event.clientY; if ((x <= box.right && x >= box.left) && (y >= box.top && y <= box.bottom)) { return true; @@ -104,26 +101,24 @@ function AtPopoverController () { return false; }; - vm.createDisplayListener = () => { - return event => { - if (vm.open) { - return; - } + vm.createDisplayListener = () => event => { + if (vm.open) { + return; + } - event.stopPropagation(); + event.stopPropagation(); - vm.display(); + vm.display(); - vm.dismissListener = vm.createDismissListener(event); + vm.dismissListener = vm.createDismissListener(event); - if (scope.popover.on === 'mouseenter') { - icon.addEventListener('mouseleave', vm.dismissListener); - } else { - window.addEventListener(scope.popover.on, vm.dismissListener); - } + if (scope.popover.on === 'mouseenter') { + icon.addEventListener('mouseleave', vm.dismissListener); + } else { + window.addEventListener(scope.popover.on, vm.dismissListener); + } - window.addEventListener('resize', vm.dismissListener); - }; + window.addEventListener('resize', vm.dismissListener); }; vm.refresh = () => { @@ -136,12 +131,12 @@ function AtPopoverController () { }; vm.getPositions = () => { - let arrow = popover.getElementsByClassName('at-Popover-arrow')[0]; + const arrow = popover.getElementsByClassName('at-Popover-arrow')[0]; arrow.style.lineHeight = `${DEFAULT_ARROW_HEIGHT}px`; arrow.children[0].style.lineHeight = `${scope.popover.arrowHeight}px`; - let data = { + const data = { arrow, icon: icon.getBoundingClientRect(), popover: popover.getBoundingClientRect(), @@ -158,12 +153,12 @@ function AtPopoverController () { vm.display = () => { vm.open = true; - let positions = vm.getPositions(); + const positions = vm.getPositions(); popover.style.visibility = 'visible'; popover.style.opacity = 1; - if (scope.popover.position === 'right') { + if (scope.popover.position === 'right') { vm.displayRight(positions); } else if (scope.popover.position === 'top') { vm.displayTop(positions); @@ -171,19 +166,18 @@ function AtPopoverController () { }; vm.displayRight = (pos) => { - let arrowHeight = pos.arrow.offsetHeight; - let arrowLeft = pos.rightBoundary + DEFAULT_PADDING; + const arrowHeight = pos.arrow.offsetHeight; + const arrowLeft = pos.rightBoundary + DEFAULT_PADDING; + const popoverLeft = arrowLeft + DEFAULT_PADDING - 1; let popoverTop; - let popoverLeft = arrowLeft + DEFAULT_PADDING - 1; - if (pos.cy < (pos.popover.height / 2)) { popoverTop = DEFAULT_PADDING; } else { popoverTop = Math.floor((pos.cy - pos.popover.height / 2)); } - let arrowTop = Math.floor(popoverTop + (pos.popover.height / 2) - (arrowHeight / 2)); + const arrowTop = Math.floor(popoverTop + (pos.popover.height / 2) - (arrowHeight / 2)); pos.arrow.style.top = `${arrowTop}px`; pos.arrow.style.left = `${arrowLeft}px`; @@ -193,11 +187,11 @@ function AtPopoverController () { }; vm.displayTop = (pos) => { - let arrowTop = pos.icon.top - pos.icon.height - DEFAULT_PADDING; - let arrowLeft = Math.floor(pos.icon.right - pos.icon.width - (pos.arrow.style.width / 2)); + const arrowTop = pos.icon.top - pos.icon.height - DEFAULT_PADDING; + const arrowLeft = Math.floor(pos.icon.right - pos.icon.width - (pos.arrow.style.width / 2)); - let popoverTop = pos.icon.top - pos.popover.height - pos.icon.height - 5; - let popoverLeft = Math.floor(pos.cx - (pos.popover.width / 2)); + const popoverTop = pos.icon.top - pos.popover.height - pos.icon.height - 5; + const popoverLeft = Math.floor(pos.cx - (pos.popover.width / 2)); pos.arrow.style.top = `${arrowTop}px`; pos.arrow.style.left = `${arrowLeft}px`; diff --git a/awx/ui/client/lib/components/tabs/group.directive.js b/awx/ui/client/lib/components/tabs/group.directive.js index 771956aa21..4d27d2e03d 100644 --- a/awx/ui/client/lib/components/tabs/group.directive.js +++ b/awx/ui/client/lib/components/tabs/group.directive.js @@ -1,24 +1,10 @@ -const templateUrl = require('@components/tabs/group.partial.html'); +const templateUrl = require('~components/tabs/group.partial.html'); -function atTabGroupLink (scope, el, attrs, controllers) { - let groupController = controllers[0]; - - groupController.init(scope, el); -} - -function AtTabGroupController ($state) { - let vm = this; +function AtTabGroupController () { + const vm = this; vm.tabs = []; - let scope; - let el; - - vm.init = (_scope_, _el_) => { - scope = _scope_; - el = _el_; - }; - vm.register = tab => { tab.active = true; @@ -26,18 +12,15 @@ function AtTabGroupController ($state) { }; } -AtTabGroupController.$inject = ['$state']; - function atTabGroup () { return { restrict: 'E', replace: true, - require: ['atTabGroup'], + require: 'atTabGroup', transclude: true, templateUrl, controller: AtTabGroupController, controllerAs: 'vm', - link: atTabGroupLink, scope: { state: '=' } diff --git a/awx/ui/client/lib/components/tabs/tab.directive.js b/awx/ui/client/lib/components/tabs/tab.directive.js index e9b9f93eab..c70448c43c 100644 --- a/awx/ui/client/lib/components/tabs/tab.directive.js +++ b/awx/ui/client/lib/components/tabs/tab.directive.js @@ -1,22 +1,20 @@ -const templateUrl = require('@components/tabs/tab.partial.html'); +const templateUrl = require('~components/tabs/tab.partial.html'); function atTabLink (scope, el, attrs, controllers) { - let groupController = controllers[0]; - let tabController = controllers[1]; + const groupController = controllers[0]; + const tabController = controllers[1]; - tabController.init(scope, el, groupController); + tabController.init(scope, groupController); } function AtTabController ($state) { - let vm = this; + const vm = this; let scope; - let el; let group; - vm.init = (_scope_, _el_, _group_) => { + vm.init = (_scope_, _group_) => { scope = _scope_; - el = _el_; group = _group_; group.register(scope); diff --git a/awx/ui/client/lib/components/truncate/truncate.directive.js b/awx/ui/client/lib/components/truncate/truncate.directive.js index 39f3f3455c..a2aa6b14ab 100644 --- a/awx/ui/client/lib/components/truncate/truncate.directive.js +++ b/awx/ui/client/lib/components/truncate/truncate.directive.js @@ -1,15 +1,15 @@ -const templateUrl = require('@components/truncate/truncate.partial.html'); +const templateUrl = require('~components/truncate/truncate.partial.html'); function atTruncateLink (scope, el, attr, ctrl) { - let truncateController = ctrl; - let string = attr.string; - let maxlength = attr.maxlength; + const truncateController = ctrl; + const { string } = attr; + const { maxlength } = attr; truncateController.init(el, string, maxlength); } function AtTruncateController (strings) { - let vm = this; + const vm = this; let el; let string; let maxlength; @@ -29,14 +29,14 @@ function AtTruncateController (strings) { position: 'top', icon: 'fa fa-clone', resetOnExit: true, - click: copyToClipboard + click: vm.copyToClipboard } }; - function copyToClipboard() { + vm.copyToClipboard = () => { vm.tooltip.popover.text = vm.strings.get('truncate.COPIED'); - let textarea = el[0].getElementsByClassName('at-Truncate-textarea')[0]; + const textarea = el[0].getElementsByClassName('at-Truncate-textarea')[0]; textarea.value = string; textarea.select(); @@ -46,7 +46,7 @@ function AtTruncateController (strings) { AtTruncateController.$inject = ['ComponentsStrings']; -function atTruncate() { +function atTruncate () { return { restrict: 'E', replace: true, @@ -60,7 +60,7 @@ function atTruncate() { maxLength: '@', string: '@' } - } + }; } export default atTruncate; diff --git a/awx/ui/client/lib/components/utility/divider.directive.js b/awx/ui/client/lib/components/utility/divider.directive.js index 6ce50a512a..8aa71fad50 100644 --- a/awx/ui/client/lib/components/utility/divider.directive.js +++ b/awx/ui/client/lib/components/utility/divider.directive.js @@ -1,4 +1,4 @@ -const templateUrl = require('@components/utility/divider.partial.html'); +const templateUrl = require('~components/utility/divider.partial.html'); function atPanelBody () { return { diff --git a/awx/ui/client/lib/models/Base.js b/awx/ui/client/lib/models/Base.js index a1c60e1bd9..72434e7d8d 100644 --- a/awx/ui/client/lib/models/Base.js +++ b/awx/ui/client/lib/models/Base.js @@ -4,9 +4,8 @@ let cache; function request (method, resource) { if (Array.isArray(method)) { - let promises = method.map((_method_, i) => { - return this.request(_method_, Array.isArray(resource) ? resource[i] : resource); - }); + const promises = method.map((_method_, i) => + this.request(_method_, Array.isArray(resource) ? resource[i] : resource)); return $q.all(promises); } @@ -14,12 +13,12 @@ function request (method, resource) { if (this.isCacheable(method, resource)) { return this.requestWithCache(method, resource); } - + return this.http[method](resource); } function requestWithCache (method, resource) { - let key = cache.createKey(method, this.path, resource); + const key = cache.createKey(method, this.path, resource); return cache.get(key) .then(data => { @@ -43,16 +42,16 @@ function requestWithCache (method, resource) { * supported by the API. * * @arg {Object} params - An object of keys and values to to format and - * to the URL as a query string. Refer to the API documentation for the + * to the URL as a query string. Refer to the API documentation for the * resource in use for specifics. * @arg {Object} config - Configuration specific to the UI to accommodate * common use cases. * - * @yields {boolean} - Indicating a match has been found. If so, the results + * @yields {boolean} - Indicating a match has been found. If so, the results * are set on the model. */ function search (params, config) { - let req = { + const req = { method: 'GET', url: this.path, params @@ -69,7 +68,7 @@ function search (params, config) { return false; } - this.model.GET = data.results[0]; + [this.model.GET] = data.results; } else { this.model.GET = data; } @@ -79,7 +78,7 @@ function search (params, config) { } function httpGet (resource) { - let req = { + const req = { method: 'GET', url: this.path }; @@ -101,7 +100,7 @@ function httpGet (resource) { } function httpPost (data) { - let req = { + const req = { method: 'POST', url: this.path, data @@ -115,9 +114,9 @@ function httpPost (data) { } function httpPut (changes) { - let model = Object.assign(this.get(), changes); + const model = Object.assign(this.get(), changes); - let req = { + const req = { method: 'PUT', url: `${this.path}${model.id}/`, data: model @@ -127,7 +126,7 @@ function httpPut (changes) { } function httpOptions (resource) { - let req = { + const req = { method: 'OPTIONS', url: this.path }; @@ -157,7 +156,7 @@ function unset (method, keys) { keys = method; method = 'GET'; } - + method = method.toUpperCase(); keys = keys.split('.'); @@ -166,10 +165,10 @@ function unset (method, keys) { } else if (keys.length === 1) { delete this.model[method][keys[0]]; } else { - let property = keys.splice(-1); + const property = keys.splice(-1); keys = keys.join('.'); - let model = this.find(method, keys) + const model = this.find(method, keys); delete model[property]; } } @@ -180,29 +179,29 @@ function set (method, keys, value) { keys = method; method = 'GET'; } - + keys = keys.split('.'); if (keys.length === 1) { - model[keys[0]] = value; + this.model[keys[0]] = value; } else { - let property = keys.splice(-1); + const property = keys.splice(-1); keys = keys.join('.'); - let model = this.find(method, keys) + const model = this.find(method, keys); model[property] = value; } } function match (method, key, value) { - if(!value) { + if (!value) { value = key; key = method; method = 'GET'; } - let model = this.model[method.toUpperCase()]; + const model = this.model[method.toUpperCase()]; if (!model) { return null; @@ -216,7 +215,7 @@ function match (method, key, value) { return null; } - let result = model.results.filter(result => result[key] === value); + const result = model.results.filter(object => object[key] === value); return result.length === 0 ? null : result[0]; } @@ -232,8 +231,8 @@ function find (method, keys) { keys = keys.split('.'); keys.forEach(key => { - let bracketIndex = key.indexOf('['); - let hasArray = bracketIndex !== -1; + const bracketIndex = key.indexOf('['); + const hasArray = bracketIndex !== -1; if (!hasArray) { value = value[key]; @@ -245,8 +244,8 @@ function find (method, keys) { return; } - let prop = key.substring(0, bracketIndex); - let index = Number(key.substring(bracketIndex + 1, key.length - 1)); + const prop = key.substring(0, bracketIndex); + const index = Number(key.substring(bracketIndex + 1, key.length - 1)); value = value[prop][index]; }); @@ -279,38 +278,37 @@ function has (method, keys) { function extend (method, related) { if (!related) { - related = method - method = 'GET' + related = method; + method = 'GET'; } else { - method = method.toUpperCase() + method = method.toUpperCase(); } if (this.has(method, `related.${related}`)) { - let id = this.get('id') - - let req = { + const req = { method, url: this.get(`related.${related}`) }; return $http(req) - .then(({data}) => { + .then(({ data }) => { this.set(method, `related.${related}`, data); + return this; - }) + }); } return Promise.reject(new Error(`No related property, ${related}, exists`)); } function normalizePath (resource) { - let version = '/api/v2/'; + const version = '/api/v2/'; return `${version}${resource}/`; } function isEditable () { - let canEdit = this.get('summary_fields.user_capabilities.edit'); + const canEdit = this.get('summary_fields.user_capabilities.edit'); if (canEdit) { return true; @@ -321,7 +319,6 @@ function isEditable () { } return false; - } function isCreatable () { @@ -361,20 +358,20 @@ function graft (id) { * @arg {string=} method - Populate the model with `GET` or `OPTIONS` data. * @arg {(string|Object)=} resource - An `id` reference to a particular * resource or an existing model's data. - * @arg {boolean=} graft - Create a new instance from existing model data. + * @arg {boolean=} isGraft - Create a new instance from existing model data. * * @returns {(Object|Promise)} - Returns a reference to the model instance * if an empty instance or graft is created. Otherwise, a promise yielding * a model instance is returned. */ -function create (method, resource, graft, config) { +function create (method, resource, isGraft, config) { if (!method) { return this; } this.promise = this.request(method, resource, config); - if (graft) { + if (isGraft) { return this; } @@ -421,7 +418,7 @@ function BaseModel (path, settings) { this.model = {}; this.path = this.normalizePath(path); this.settings = settings || {}; -}; +} function BaseModelLoader (_$http_, _$q_, _cache_) { $http = _$http_; diff --git a/awx/ui/client/lib/models/Config.js b/awx/ui/client/lib/models/Config.js index 17dd1f8901..85be6ef147 100644 --- a/awx/ui/client/lib/models/Config.js +++ b/awx/ui/client/lib/models/Config.js @@ -1,12 +1,13 @@ +let $log; let BaseModel; function getTruncatedVersion () { let version; try { - version = this.get('version').split('-')[0]; + [version] = this.get('version').split('-'); } catch (err) { - console.error(err); + $log.error(err); } return version; @@ -15,7 +16,7 @@ function getTruncatedVersion () { function isOpen () { return this.get('license_info.license_type') === 'open'; } - + function ConfigModel (method, resource, graft) { BaseModel.call(this, 'config', { cache: true }); @@ -26,12 +27,13 @@ function ConfigModel (method, resource, graft) { return this.create(method, resource, graft); } -function ConfigModelLoader (_BaseModel_) { +function ConfigModelLoader (_BaseModel_, _$log_) { BaseModel = _BaseModel_; + $log = _$log_; return ConfigModel; } -ConfigModelLoader.$inject = ['BaseModel']; +ConfigModelLoader.$inject = ['BaseModel', '$log']; export default ConfigModelLoader; diff --git a/awx/ui/client/lib/models/Credential.js b/awx/ui/client/lib/models/Credential.js index 93a5bacfd9..3b0aafcf3d 100644 --- a/awx/ui/client/lib/models/Credential.js +++ b/awx/ui/client/lib/models/Credential.js @@ -8,19 +8,19 @@ function createFormSchema (method, config) { method = 'GET'; } - let schema = Object.assign({}, this.options(`actions.${method.toUpperCase()}`)); + const schema = Object.assign({}, this.options(`actions.${method.toUpperCase()}`)); if (config && config.omit) { config.omit.forEach(key => delete schema[key]); } - for (let key in schema) { + Object.keys(schema).forEach(key => { schema[key].id = key; if (this.has(key)) { schema[key]._value = this.get(key); } - } + }); return schema; } @@ -31,7 +31,7 @@ function assignInputGroupValues (inputs) { } return inputs.map(input => { - let value = this.get(`inputs.${input.id}`); + const value = this.get(`inputs.${input.id}`); input._value = value; input._encrypted = value === ENCRYPTED_VALUE; @@ -50,7 +50,7 @@ function CredentialModel (method, resource, graft) { return this.create(method, resource, graft); } -function CredentialModelLoader (_BaseModel_ ) { +function CredentialModelLoader (_BaseModel_) { BaseModel = _BaseModel_; return CredentialModel; diff --git a/awx/ui/client/lib/models/CredentialType.js b/awx/ui/client/lib/models/CredentialType.js index 548bcbca9a..334ba234ce 100644 --- a/awx/ui/client/lib/models/CredentialType.js +++ b/awx/ui/client/lib/models/CredentialType.js @@ -1,7 +1,7 @@ let BaseModel; function categorizeByKind () { - let group = {}; + const group = {}; this.get('results').forEach(result => { group[result.kind] = group[result.kind] || []; @@ -16,12 +16,12 @@ function categorizeByKind () { function mergeInputProperties () { if (!this.has('inputs.fields')) { - return; + return undefined; } - let required = this.get('inputs.required'); + const required = this.get('inputs.required'); - return this.get('inputs.fields').map((field, i) => { + return this.get('inputs.fields').forEach((field, i) => { if (!required || required.indexOf(field.id) === -1) { this.set(`inputs.fields[${i}].required`, false); } else { diff --git a/awx/ui/client/lib/models/Me.js b/awx/ui/client/lib/models/Me.js index a606db9731..c2ee95d46e 100644 --- a/awx/ui/client/lib/models/Me.js +++ b/awx/ui/client/lib/models/Me.js @@ -12,7 +12,7 @@ function MeModel (method, resource, graft) { this.unset('results'); } - return this; + return this; }); } diff --git a/awx/ui/client/lib/models/index.js b/awx/ui/client/lib/models/index.js index eac47ce4c3..e56782441a 100644 --- a/awx/ui/client/lib/models/index.js +++ b/awx/ui/client/lib/models/index.js @@ -1,9 +1,9 @@ -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'; +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', []) diff --git a/awx/ui/client/lib/services/app.strings.js b/awx/ui/client/lib/services/app.strings.js index 6be3ece3f1..a844897308 100644 --- a/awx/ui/client/lib/services/app.strings.js +++ b/awx/ui/client/lib/services/app.strings.js @@ -1,5 +1,6 @@ -// The purpose of this file is to instantiate the BaseStringService -// for app-wide usage. +/** + * This service is used to access the app-wide strings defined in BaseStringService. + */ function AppStrings (BaseString) { BaseString.call(this, 'app'); } diff --git a/awx/ui/client/lib/services/base-string.service.js b/awx/ui/client/lib/services/base-string.service.js index 1ca71993a1..4f0df6b545 100644 --- a/awx/ui/client/lib/services/base-string.service.js +++ b/awx/ui/client/lib/services/base-string.service.js @@ -1,4 +1,4 @@ -import defaults from '@assets/default.strings.json'; +import defaults from '~assets/default.strings.json'; let i18n; @@ -45,7 +45,7 @@ function BaseStringService (namespace) { */ this.t.p = i18n.translatePlural; - let t = this.t; + const { t } = this; /* * These strings are globally relevant and configured to give priority to values in @@ -79,7 +79,7 @@ function BaseStringService (namespace) { * @arg {object=} context - An object containing data to use in the interpolation of the string */ this.get = (name, ...args) => { - let keys = name.split('.'); + const keys = name.split('.'); let value; keys.forEach(key => { @@ -90,7 +90,7 @@ function BaseStringService (namespace) { } if (!value) { - throw new Error(ERROR_NO_STRING + `: ${name}`); + throw new Error(`${ERROR_NO_STRING}: ${name}`); } }); diff --git a/awx/ui/client/lib/services/cache.service.js b/awx/ui/client/lib/services/cache.service.js index 9cc526f907..783b0e0d4c 100644 --- a/awx/ui/client/lib/services/cache.service.js +++ b/awx/ui/client/lib/services/cache.service.js @@ -1,16 +1,11 @@ function CacheService ($cacheFactory, $q) { - let cache = $cacheFactory('api'); + const cache = $cacheFactory('api'); - this.put = (key, data) => { - return cache.put(key, data); - }; - - this.get = (key) => { - return $q.resolve(cache.get(key)); - }; + this.put = (key, data) => cache.put(key, data); + this.get = (key) => $q.resolve(cache.get(key)); this.remove = (key) => { - if (!key) { + if (!key) { return cache.removeAll(); } @@ -29,7 +24,7 @@ function CacheService ($cacheFactory, $q) { } return key; - } + }; } CacheService.$inject = ['$cacheFactory', '$q']; diff --git a/awx/ui/client/lib/services/event.service.js b/awx/ui/client/lib/services/event.service.js index 1d4e95e1e3..d7b7a40538 100644 --- a/awx/ui/client/lib/services/event.service.js +++ b/awx/ui/client/lib/services/event.service.js @@ -1,6 +1,6 @@ function EventService () { this.addListeners = list => { - let listeners = []; + const listeners = []; list.forEach(args => listeners.push(this.addListener(...args))); @@ -8,7 +8,7 @@ function EventService () { }; this.addListener = (el, name, fn) => { - let listener = { + const listener = { fn, name, el diff --git a/awx/ui/client/lib/services/index.js b/awx/ui/client/lib/services/index.js index e314f89e99..89b5f1d73b 100644 --- a/awx/ui/client/lib/services/index.js +++ b/awx/ui/client/lib/services/index.js @@ -1,7 +1,7 @@ -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'; +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', []) diff --git a/awx/ui/client/src/vendor.js b/awx/ui/client/src/vendor.js index 8f616f8b74..4af531a78f 100644 --- a/awx/ui/client/src/vendor.js +++ b/awx/ui/client/src/vendor.js @@ -1,13 +1,14 @@ -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('~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'); diff --git a/awx/ui/client/test/e2e/.babelrc b/awx/ui/client/test/e2e/.babelrc new file mode 100644 index 0000000000..05758ba5a8 --- /dev/null +++ b/awx/ui/client/test/e2e/.babelrc @@ -0,0 +1,9 @@ +{ + "presets": [ + ["env", { + "targets": { + "node": 6 + } + }] + ] +} diff --git a/awx/ui/client/test/e2e/runner.js b/awx/ui/client/test/e2e/runner.js index e13cf9b17c..494d059abf 100755 --- a/awx/ui/client/test/e2e/runner.js +++ b/awx/ui/client/test/e2e/runner.js @@ -1,3 +1,3 @@ #!/usr/bin/env node -require('babel-register'); +require('babel-core/register'); require('nightwatch/bin/runner.js'); diff --git a/awx/ui/karma.conf.js b/awx/ui/karma.conf.js index da9a91d2f2..f35dea0200 100644 --- a/awx/ui/karma.conf.js +++ b/awx/ui/karma.conf.js @@ -4,7 +4,6 @@ module.exports = function(config) { config.set({ autoWatch: true, colors: true, - logLevel: config.LOG_INFO, browsers: ['Chrome', 'Firefox'], coverageReporter: { reporters: [ @@ -30,9 +29,7 @@ module.exports = function(config) { }, webpack: webpackTestConfig, webpackMiddleware: { - stats: { - colors: true - } + noInfo: true }, junitReporter: { outputDir: 'coverage', diff --git a/awx/ui/package.json b/awx/ui/package.json index 8744e3abe4..f79ca4aa32 100644 --- a/awx/ui/package.json +++ b/awx/ui/package.json @@ -24,28 +24,29 @@ "test": "karma start karma.conf.js", "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/unit/karma.conf.js", - "lint-dev": "./node_modules/.bin/nodemon --exec \"./node_modules/.bin/eslint -c .eslintrc.js .\" --watch \"client/components/**/*.js\"", - "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", - "e2e": "./client/test/e2e/runner.js --config ./client/test/e2e/nightwatch.conf.js" + "e2e": "./client/test/e2e/runner.js --config ./client/test/e2e/nightwatch.conf.js", + "component-test": "karma start client/test/karma.conf.js", + "lint": "eslint -c .eslintrc.js .", + "dev": "webpack --config build/webpack.development.js --progress", + "watch": "webpack-dev-server --config build/webpack.watch.js --progress", + "production": "webpack --config build/webpack.production.js" }, "devDependencies": { "angular-mocks": "~1.4.14", "babel-core": "^6.26.0", - "babel-istanbul": "^0.11.0", + "babel-istanbul": "^0.12.2", "babel-loader": "^7.1.2", - "babel-plugin-istanbul": "^2.0.0", - "babel-preset-es2015": "^6.24.1", + "babel-plugin-istanbul": "^4.1.5", + "babel-preset-env": "^1.6.0", "chromedriver": "^2.31.0", "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", + "eslint": "^4.6.1", + "eslint-config-airbnb-base": "^12.0.0", + "eslint-import-resolver-webpack": "^0.8.3", + "eslint-loader": "^1.9.0", + "eslint-plugin-import": "^2.7.0", "expose-loader": "^0.7.3", "extract-text-webpack-plugin": "^3.0.0", "grunt": "^1.0.1", @@ -57,14 +58,13 @@ "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", "jshint-stylish": "^2.2.0", "json-loader": "^0.5.4", "karma": "^1.4.1", - "karma-chrome-launcher": "^1.0.1", + "karma-chrome-launcher": "^2.2.0", "karma-coverage": "^1.1.1", "karma-firefox-launcher": "^1.0.0", "karma-html2js-preprocessor": "^1.0.0", @@ -73,15 +73,14 @@ "karma-ng-html2js-preprocessor": "^1.0.0", "karma-phantomjs-launcher": "^1.0.2", "karma-sourcemap-loader": "^0.3.7", - "karma-webpack": "^1.8.0", + "karma-webpack": "^2.0.4", "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", - "nightwatch": "^0.9.16", "ngtemplate-loader": "^2.0.1", + "nightwatch": "^0.9.16", "phantomjs-prebuilt": "^2.1.12", "script-loader": "^0.7.0", "style-loader": "^0.18.2", @@ -105,6 +104,7 @@ "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", + "babel-polyfill": "^6.26.0", "bootstrap": "^3.3.7", "bootstrap-datepicker": "^1.7.1", "codemirror": "^5.17.0",