From e7a0bbb5db4645291ec4032fa17d6b2758797774 Mon Sep 17 00:00:00 2001 From: John Mitchell Date: Thu, 15 Mar 2018 14:53:49 -0400 Subject: [PATCH 1/3] implement users tokens sub list --- awx/ui/client/lib/theme/index.less | 1 + .../authentication.service.js | 2 +- awx/ui/client/src/shared/form-generator.js | 8 +- .../list-generator/list-generator.factory.js | 3 +- .../src/users/edit/users-edit.controller.js | 1 + awx/ui/client/src/users/main.js | 45 +++++-- .../client/src/users/token-modal.block.less | 12 ++ awx/ui/client/src/users/tokens.strings.js | 30 +++++ .../users-tokens-add-application.route.js | 71 +++++++++++ .../src/users/users-tokens-add.controller.js | 99 +++++++++++++++ .../src/users/users-tokens-add.partial.html | 18 +++ .../src/users/users-tokens-add.route.js | 38 ++++++ .../src/users/users-tokens-list.controller.js | 119 ++++++++++++++++++ .../src/users/users-tokens-list.partial.html | 47 +++++++ .../src/users/users-tokens-list.route.js | 48 +++++++ awx/ui/client/src/users/users.form.js | 5 + 16 files changed, 533 insertions(+), 14 deletions(-) create mode 100644 awx/ui/client/src/users/token-modal.block.less create mode 100644 awx/ui/client/src/users/tokens.strings.js create mode 100644 awx/ui/client/src/users/users-tokens-add-application.route.js create mode 100644 awx/ui/client/src/users/users-tokens-add.controller.js create mode 100644 awx/ui/client/src/users/users-tokens-add.partial.html create mode 100644 awx/ui/client/src/users/users-tokens-add.route.js create mode 100644 awx/ui/client/src/users/users-tokens-list.controller.js create mode 100644 awx/ui/client/src/users/users-tokens-list.partial.html create mode 100644 awx/ui/client/src/users/users-tokens-list.route.js diff --git a/awx/ui/client/lib/theme/index.less b/awx/ui/client/lib/theme/index.less index b5ac04dfca..584be08ca6 100644 --- a/awx/ui/client/lib/theme/index.less +++ b/awx/ui/client/lib/theme/index.less @@ -136,6 +136,7 @@ @import '../../src/tooltip/tooltip.block.less'; @import '../../src/workflow-results/workflow-status-bar/workflow-status-bar.block.less'; @import '../../src/workflow-results/workflow-results.block.less'; +@import '../../src/users/token-modal.block.less'; /** diff --git a/awx/ui/client/src/login/authenticationServices/authentication.service.js b/awx/ui/client/src/login/authenticationServices/authentication.service.js index addeab821e..8aea962847 100644 --- a/awx/ui/client/src/login/authenticationServices/authentication.service.js +++ b/awx/ui/client/src/login/authenticationServices/authentication.service.js @@ -53,7 +53,7 @@ export default return $http({ method: 'POST', url: `/api/login/`, - data: `username=${username}&password=${password}&csrfmiddlewaretoken=${csrfmiddlewaretoken}&next=%2fapi%2f`, + data: `username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}&csrfmiddlewaretoken=${csrfmiddlewaretoken}&next=%2fapi%2f`, headers: { 'Content-Type': 'application/x-www-form-urlencoded' } diff --git a/awx/ui/client/src/shared/form-generator.js b/awx/ui/client/src/shared/form-generator.js index 6444370b3b..892b156d5c 100644 --- a/awx/ui/client/src/shared/form-generator.js +++ b/awx/ui/client/src/shared/form-generator.js @@ -166,14 +166,18 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat // Also wraps mess of generated HTML in a .Panel wrapPanel(html, ignorePanel){ if(ignorePanel) { - return `
+ return ` +
+
${html}
`; } else { - return `
+ return ` +
+
${html}
diff --git a/awx/ui/client/src/shared/list-generator/list-generator.factory.js b/awx/ui/client/src/shared/list-generator/list-generator.factory.js index 4e2fe0609a..3dbb9514c4 100644 --- a/awx/ui/client/src/shared/list-generator/list-generator.factory.js +++ b/awx/ui/client/src/shared/list-generator/list-generator.factory.js @@ -583,7 +583,8 @@ export default ['$compile', 'Attr', 'Icon', }, wrapPanel: function(html){ - return `
${html}
`; + return ` +
${html}
`; }, insertFormView: function(){ diff --git a/awx/ui/client/src/users/edit/users-edit.controller.js b/awx/ui/client/src/users/edit/users-edit.controller.js index 289f2d5556..0accb1bdcf 100644 --- a/awx/ui/client/src/users/edit/users-edit.controller.js +++ b/awx/ui/client/src/users/edit/users-edit.controller.js @@ -30,6 +30,7 @@ export default ['$scope', '$rootScope', '$stateParams', 'UserForm', 'Rest', init(); function init() { + $scope.isCurrentlyLoggedInUser = (parseInt(id) === $rootScope.current_user.id); $scope.hidePagination = false; $scope.hideSmartSearch = false; $scope.user_type_options = user_type_options; diff --git a/awx/ui/client/src/users/main.js b/awx/ui/client/src/users/main.js index aa883c7001..95765ffa3a 100644 --- a/awx/ui/client/src/users/main.js +++ b/awx/ui/client/src/users/main.js @@ -9,6 +9,11 @@ import UsersAdd from './add/users-add.controller'; import UsersEdit from './edit/users-edit.controller'; import UserForm from './users.form'; import UserList from './users.list'; +import UserTokensListRoute from './users-tokens-list.route'; +import UserTokensAddRoute from './users-tokens-add.route'; +import UserTokensAddApplicationRoute from './users-tokens-add-application.route'; +import TokensStrings from './tokens.strings'; + import { N_ } from '../i18n'; export default @@ -18,16 +23,15 @@ angular.module('Users', []) .controller('UsersEdit', UsersEdit) .factory('UserForm', UserForm) .factory('UserList', UserList) - .config(['$stateProvider', 'stateDefinitionsProvider', - function($stateProvider, stateDefinitionsProvider) { - let stateDefinitions = stateDefinitionsProvider.$get(); + .service('TokensStrings', TokensStrings) - // lazily generate a tree of substates which will replace this node in ui-router's stateRegistry - // see: stateDefinition.factory for usage documentation - $stateProvider.state({ - name: 'users.**', - url: '/users', - lazyLoad: () => stateDefinitions.generateTree({ + .config(['$stateProvider', 'stateDefinitionsProvider', '$stateExtenderProvider', + function($stateProvider, stateDefinitionsProvider, $stateExtenderProvider) { + let stateDefinitions = stateDefinitionsProvider.$get(); + let stateExtender = $stateExtenderProvider.$get(); + + function generateStateTree() { + let userTree = stateDefinitions.generateTree({ parent: 'users', modes: ['add', 'edit'], list: 'UserList', @@ -44,7 +48,28 @@ angular.module('Users', []) ncyBreadcrumb: { label: N_('USERS') } - }) + }); + + return Promise.all([ + userTree + ]).then((generated) => { + return { + states: _.reduce(generated, (result, definition) => { + return result.concat(definition.states); + }, [ + stateExtender.buildDefinition(UserTokensListRoute), + stateExtender.buildDefinition(UserTokensAddRoute), + stateExtender.buildDefinition(UserTokensAddApplicationRoute) + ]) + }; + }); + } + + $stateProvider.state({ + name: 'users.**', + url: '/users', + lazyLoad: () => generateStateTree() }); + } ]); diff --git a/awx/ui/client/src/users/token-modal.block.less b/awx/ui/client/src/users/token-modal.block.less new file mode 100644 index 0000000000..d913b3e3ef --- /dev/null +++ b/awx/ui/client/src/users/token-modal.block.less @@ -0,0 +1,12 @@ +/** @define TokenModal */ +.TokenModal { + display: flex; +} + +.TokenModal-label { + font-weight: bold; + width: 130px; +} + +.TokenModal-value { +} diff --git a/awx/ui/client/src/users/tokens.strings.js b/awx/ui/client/src/users/tokens.strings.js new file mode 100644 index 0000000000..2780661e79 --- /dev/null +++ b/awx/ui/client/src/users/tokens.strings.js @@ -0,0 +1,30 @@ +function TokensStrings (BaseString) { + BaseString.call(this, 'tokens'); + + const { t } = this; + const ns = this.tokens; + + ns.state = { + LIST_BREADCRUMB_LABEL: t.s('TOKENS'), + ADD_BREADCRUMB_LABEL: t.s('CREATE TOKEN'), + USER_LIST_BREADCRUMB_LABEL: t.s('TOKENS') + }; + + ns.tab = { + DETAILS: t.s('Details') + }; + + ns.add = { + PANEL_TITLE: t.s('CREATE TOKEN') + }; + + ns.list = { + ROW_ITEM_LABEL_EXPIRED: t.s('DESCRIPTION'), + ROW_ITEM_LABEL_EXPIRED: t.s('EXPIRATION'), + ROW_ITEM_LABEL_USED: t.s('LAST USED') + }; +} + +TokensStrings.$inject = ['BaseStringService']; + +export default TokensStrings; diff --git a/awx/ui/client/src/users/users-tokens-add-application.route.js b/awx/ui/client/src/users/users-tokens-add-application.route.js new file mode 100644 index 0000000000..4ab5998d74 --- /dev/null +++ b/awx/ui/client/src/users/users-tokens-add-application.route.js @@ -0,0 +1,71 @@ +export default { + name: 'users.edit.tokens.add.application', + url: '/application?selected', + searchPrefix: 'application', + params: { + application_search: { + value: { + page_size: 5, + order_by: 'name' + }, + dynamic: true, + squash: '' + } + }, + data: { + basePath: 'applications', + formChildState: true + }, + ncyBreadcrumb: { + skip: true + }, + views: { + 'application@users.edit.tokens.add': { + templateProvider: (ListDefinition, generateList) => { + const html = generateList.build({ + mode: 'lookup', + list: ListDefinition, + input_type: 'radio' + }); + + return `${html}`; + } + } + }, + resolve: { + ListDefinition: [() => { + return { + name: 'applications', + iterator: 'application', + hover: true, + index: false, + fields: { + name: { + key: true, + label: 'Name', + columnClass: 'col-lg-4 col-md-6 col-sm-8 col-xs-8', + awToolTip: '{{application.description | sanitize}}', + dataPlacement: 'top' + }, + }, + actions: { + }, + fieldActions: { + } + } + }], + Dataset: ['QuerySet', 'GetBasePath', '$stateParams', 'ListDefinition', + (qs, GetBasePath, $stateParams, list) => qs.search( + GetBasePath('applications'), + $stateParams[`${list.iterator}_search`] + ) + ] + }, + onExit ($state) { + if ($state.transition) { + $('#form-modal').modal('hide'); + $('.modal-backdrop').remove(); + $('body').removeClass('modal-open'); + } + } +} diff --git a/awx/ui/client/src/users/users-tokens-add.controller.js b/awx/ui/client/src/users/users-tokens-add.controller.js new file mode 100644 index 0000000000..7b63a8ce61 --- /dev/null +++ b/awx/ui/client/src/users/users-tokens-add.controller.js @@ -0,0 +1,99 @@ +function AddTokensController (models, $state, strings, Rest, Alert, Wait, GetBasePath, $filter) { + const vm = this || {}; + const { application } = models; + + vm.mode = 'add'; + vm.strings = strings; + vm.panelTitle = strings.get('add.PANEL_TITLE'); + + vm.form = {}; + + vm.form.application = { + type: 'field', + label: 'Application', + id: 'application' + }; + vm.form.description = { + type: 'String', + label: 'Description', + id: 'description' + }; + + vm.form.application._resource = 'application'; + vm.form.application._route = 'users.edit.tokens.add.application'; + vm.form.application._model = application; + vm.form.application._placeholder = strings.get('SELECT AN APPLICATION'); + vm.form.application.required = true; + + vm.form.description.required = false; + + vm.form.scope = { + choices: ['', 'read', 'write'], + help_text: 'Specify a scope for the token\'s access', + id: 'scope', + label: 'Scope', + required: true, + _component: 'at-input-select', + _data: ['', 'read', 'write'], + _exp: 'choice for (index, choice) in state._data', + _format: 'array' + } + + vm.form.save = data => { + Rest.setUrl(GetBasePath('users') + $state.params.user_id + '/authorized_tokens'); + return Rest.post(data) + .then(({data}) => { + Alert('TOKEN INFORMATION', ` +
+
+ TOKEN +
+
+ ${data.token} +
+
+
+
+ REFRESH TOKEN +
+
+ ${data.refresh_token} +
+
+
+
+ EXPIRES +
+
+ ${$filter('longDate')(data.expires)} +
+
+ `, null, null, null, null, null, true); + Wait('stop'); + }) + .catch(({data, status}) => { + ProcessErrors($scope, data, status, null, { + hdr: 'COULD NOT CREATE TOKEN', + msg: `Returned status: ${status}` + }); + Wait('stop'); + }); + }; + + vm.form.onSaveSuccess = res => { + $state.go('^', { user_id: $state.params.user_id }, { reload: true }); + }; +} + +AddTokensController.$inject = [ + 'resolvedModels', + '$state', + 'ApplicationsStrings', + 'Rest', + 'Alert', + 'Wait', + 'GetBasePath', + '$filter' +]; + +export default AddTokensController; diff --git a/awx/ui/client/src/users/users-tokens-add.partial.html b/awx/ui/client/src/users/users-tokens-add.partial.html new file mode 100644 index 0000000000..21f5a8be04 --- /dev/null +++ b/awx/ui/client/src/users/users-tokens-add.partial.html @@ -0,0 +1,18 @@ + + + {{ vm.panelTitle }} + + + + + + + + + + + + + + + diff --git a/awx/ui/client/src/users/users-tokens-add.route.js b/awx/ui/client/src/users/users-tokens-add.route.js new file mode 100644 index 0000000000..e3832133a9 --- /dev/null +++ b/awx/ui/client/src/users/users-tokens-add.route.js @@ -0,0 +1,38 @@ +import { N_ } from '../i18n'; +import AddController from './users-tokens-add.controller'; + +const addTemplate = require('~src/users/users-tokens-add.partial.html'); + +function TokensDetailResolve ($q, Application) { + + const promises = {}; + + promises.application = new Application('options'); + + return $q.all(promises); +} + +TokensDetailResolve.$inject = [ + '$q', + 'ApplicationModel' +]; + +export default { + url: "/add-token", + name: 'users.edit.tokens.add', + params: { + }, + ncyBreadcrumb: { + label: N_("ADD TOKEN") + }, + views: { + 'preFormView@users.edit': { + templateUrl: addTemplate, + controller: AddController, + controllerAs: 'vm' + } + }, + resolve: { + resolvedModels: TokensDetailResolve + } +}; diff --git a/awx/ui/client/src/users/users-tokens-list.controller.js b/awx/ui/client/src/users/users-tokens-list.controller.js new file mode 100644 index 0000000000..bee39f45ae --- /dev/null +++ b/awx/ui/client/src/users/users-tokens-list.controller.js @@ -0,0 +1,119 @@ +/** *********************************************** + * Copyright (c) 2018 Ansible, Inc. + * + * All Rights Reserved + ************************************************ */ +function ListTokensController ( + $filter, + $scope, + $state, + Dataset, + strings, + ProcessErrors, + Rest, + GetBasePath, + Prompt, + Wait +) { + const vm = this || {}; + + vm.strings = strings; + vm.activeId = $state.params.token_id; + + $scope.canAdd = true; + + // smart-search + const name = 'tokens'; + const iterator = 'token'; + const key = 'token_dataset'; + + $scope.list = { iterator, name, basePath: 'tokens' }; + $scope.collection = { iterator }; + $scope[key] = Dataset.data; + vm.tokensCount = Dataset.data.count; + $scope[name] = Dataset.data.results; + $scope.$on('updateDataset', (e, dataset) => { + $scope[key] = dataset; + $scope[name] = dataset.results; + vm.tokensCount = dataset.count; + }); + + vm.getLastUsed = token => { + const lastUsed = _.get(token, 'last_used'); + + if (!lastUsed) { + return undefined; + } + + let html = $filter('longDate')(lastUsed); + + const { username, id } = _.get(user, 'summary_fields.last_used', {}); + + if (username && id) { + html += ` by ${$filter('sanitize')(username)}`; + } + + return html; + }; + + vm.deleteToken = (tok) => { + const action = () => { + $('#prompt-modal').modal('hide'); + Wait('start'); + Rest.setUrl(`${GetBasePath('tokens')}${tok.id}`); + Rest.destroy() + .then(() => { + let reloadListStateParams = null; + + if ($scope.tokens.length === 1 && $state.params.token_search && + !_.isEmpty($state.params.token_search.page) && + $state.params.token_search.page !== '1') { + const page = `${(parseInt(reloadListStateParams + .token_search.page, 10) - 1)}`; + reloadListStateParams = _.cloneDeep($state.params); + reloadListStateParams.token_search.page = page; + } + + if (parseInt($state.params.token_id, 10) === tok.id) { + $state.go('^', reloadListStateParams, { reload: true }); + } else { + $state.go('.', reloadListStateParams, { reload: true }); + } + }) + .catch(({ data, status }) => { + ProcessErrors($scope, data, status, null, { + hdr: strings.get('error.HEADER'), + msg: strings.get('error.CALL', { path: `${GetBasePath('tokens')}${tok.id}`, status }) + }); + }) + .finally(() => { + Wait('stop'); + }); + }; + + const deleteModalBody = `
${strings.get('deleteResource.CONFIRM', 'token')}
`; + + Prompt({ + hdr: strings.get('deleteResource.HEADER'), + resourceName: 'token', + body: deleteModalBody, + action, + actionText: 'DELETE' + }); + }; +} + +ListTokensController.$inject = [ + '$filter', + '$scope', + '$state', + 'Dataset', + 'TokensStrings', + 'ProcessErrors', + 'Rest', + 'GetBasePath', + 'Prompt', + 'Wait' +]; + +export default ListTokensController; diff --git a/awx/ui/client/src/users/users-tokens-list.partial.html b/awx/ui/client/src/users/users-tokens-list.partial.html new file mode 100644 index 0000000000..390361faba --- /dev/null +++ b/awx/ui/client/src/users/users-tokens-list.partial.html @@ -0,0 +1,47 @@ +
+ + +
+ +
+
+ + + +
+ + + + + + + + +
+
+ + +
+
+
diff --git a/awx/ui/client/src/users/users-tokens-list.route.js b/awx/ui/client/src/users/users-tokens-list.route.js new file mode 100644 index 0000000000..81ec099adc --- /dev/null +++ b/awx/ui/client/src/users/users-tokens-list.route.js @@ -0,0 +1,48 @@ +import { N_ } from '../i18n'; + +import ListController from './users-tokens-list.controller'; + +const listTemplate = require('~src/users/users-tokens-list.partial.html'); + +export default { + url: "/tokens", + name: 'users.edit.tokens', + params: { + }, + ncyBreadcrumb: { + label: N_("TOKENS") + }, + views: { + 'related': { + templateUrl: listTemplate, + controller: ListController, + controllerAs: 'vm' + } + }, + searchPrefix: 'token', + params: { + token_search: { + value: { + page_size: 5, + order_by: 'application' + } + } + }, + resolve: { + Dataset: [ + '$stateParams', + 'Wait', + 'GetBasePath', + 'QuerySet', + ($stateParams, Wait, GetBasePath, qs) => { + const searchParam = $stateParams.token_search; + const searchPath = GetBasePath('users') + $stateParams.user_id + '/tokens'; + Wait('start'); + return qs.search(searchPath, searchParam) + .finally(() => { + Wait('stop'); + }); + } + ], + } +}; diff --git a/awx/ui/client/src/users/users.form.js b/awx/ui/client/src/users/users.form.js index 521a2cb75e..78ea4f33e4 100644 --- a/awx/ui/client/src/users/users.form.js +++ b/awx/ui/client/src/users/users.form.js @@ -227,6 +227,11 @@ export default ['i18n', function(i18n) { } }, //hideOnSuperuser: true // RBAC defunct + }, + tokens: { + ngIf: 'isCurrentlyLoggedInUser', + title: i18n._('Tokens'), + skipGenerator: true, } } From 8babac49a6cdebff607fe2d427a735dfde12fe67 Mon Sep 17 00:00:00 2001 From: John Mitchell Date: Fri, 16 Mar 2018 15:56:30 -0400 Subject: [PATCH 2/3] update users token crud list to utilize string file --- awx/ui/client/src/users/tokens.strings.js | 14 ++++++++++++-- .../src/users/users-tokens-add.controller.js | 16 ++++++++-------- .../client/src/users/users-tokens-add.route.js | 2 +- .../src/users/users-tokens-list.controller.js | 4 ++-- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/awx/ui/client/src/users/tokens.strings.js b/awx/ui/client/src/users/tokens.strings.js index 2780661e79..0dc2fa61b5 100644 --- a/awx/ui/client/src/users/tokens.strings.js +++ b/awx/ui/client/src/users/tokens.strings.js @@ -15,11 +15,21 @@ function TokensStrings (BaseString) { }; ns.add = { - PANEL_TITLE: t.s('CREATE TOKEN') + PANEL_TITLE: t.s('CREATE TOKEN'), + APP_PLACEHOLDER: t.s('SELECT AN APPLICATION'), + SCOPE_HELP_TEXT: t.s('Specify a scope for the token\'s access'), + TOKEN_MODAL_HEADER: t.s('TOKEN INFORMATION'), + TOKEN_LABEL: t.s('TOKEN'), + REFRESH_TOKEN_LABEL: t.s('REFRESH TOKEN'), + TOKEN_EXPIRES_LABEL: t.s('EXPIRES'), + ERROR_HEADER: t.s('COULD NOT CREATE TOKEN'), + ERROR_BODY_LABEL: t.s('Returned status:'), + LAST_USED_LABEL: t.s('by'), + DELETE_ACTION_LABEL: t.s('DELETE') }; ns.list = { - ROW_ITEM_LABEL_EXPIRED: t.s('DESCRIPTION'), + ROW_ITEM_LABEL_DESCRIPTION: t.s('DESCRIPTION'), ROW_ITEM_LABEL_EXPIRED: t.s('EXPIRATION'), ROW_ITEM_LABEL_USED: t.s('LAST USED') }; diff --git a/awx/ui/client/src/users/users-tokens-add.controller.js b/awx/ui/client/src/users/users-tokens-add.controller.js index 7b63a8ce61..6e5d4c4d26 100644 --- a/awx/ui/client/src/users/users-tokens-add.controller.js +++ b/awx/ui/client/src/users/users-tokens-add.controller.js @@ -22,14 +22,14 @@ function AddTokensController (models, $state, strings, Rest, Alert, Wait, GetBas vm.form.application._resource = 'application'; vm.form.application._route = 'users.edit.tokens.add.application'; vm.form.application._model = application; - vm.form.application._placeholder = strings.get('SELECT AN APPLICATION'); + vm.form.application._placeholder = strings.get('add.APP_PLACEHOLDER'); vm.form.application.required = true; vm.form.description.required = false; vm.form.scope = { choices: ['', 'read', 'write'], - help_text: 'Specify a scope for the token\'s access', + help_text: strings.get('add.SCOPE_HELP_TEXT'), id: 'scope', label: 'Scope', required: true, @@ -43,10 +43,10 @@ function AddTokensController (models, $state, strings, Rest, Alert, Wait, GetBas Rest.setUrl(GetBasePath('users') + $state.params.user_id + '/authorized_tokens'); return Rest.post(data) .then(({data}) => { - Alert('TOKEN INFORMATION', ` + Alert(strings.get('add.TOKEN_MODAL_HEADER'), `
- TOKEN + ${strings.get('add.TOKEN_LABEL')}
${data.token} @@ -54,7 +54,7 @@ function AddTokensController (models, $state, strings, Rest, Alert, Wait, GetBas
- REFRESH TOKEN + ${strings.get('add.REFRESH_TOKEN_LABEL')}
${data.refresh_token} @@ -62,7 +62,7 @@ function AddTokensController (models, $state, strings, Rest, Alert, Wait, GetBas
- EXPIRES + ${strings.get('add.TOKEN_EXPIRES_LABEL')}
${$filter('longDate')(data.expires)} @@ -73,8 +73,8 @@ function AddTokensController (models, $state, strings, Rest, Alert, Wait, GetBas }) .catch(({data, status}) => { ProcessErrors($scope, data, status, null, { - hdr: 'COULD NOT CREATE TOKEN', - msg: `Returned status: ${status}` + hdr: strings.get('add.ERROR_HEADER'), + msg: `${strings.get('add.ERROR_BODY_LABEL')} ${status}` }); Wait('stop'); }); diff --git a/awx/ui/client/src/users/users-tokens-add.route.js b/awx/ui/client/src/users/users-tokens-add.route.js index e3832133a9..f1047fb24b 100644 --- a/awx/ui/client/src/users/users-tokens-add.route.js +++ b/awx/ui/client/src/users/users-tokens-add.route.js @@ -23,7 +23,7 @@ export default { params: { }, ncyBreadcrumb: { - label: N_("ADD TOKEN") + label: N_("CREATE TOKEN") }, views: { 'preFormView@users.edit': { diff --git a/awx/ui/client/src/users/users-tokens-list.controller.js b/awx/ui/client/src/users/users-tokens-list.controller.js index bee39f45ae..da1de35507 100644 --- a/awx/ui/client/src/users/users-tokens-list.controller.js +++ b/awx/ui/client/src/users/users-tokens-list.controller.js @@ -50,7 +50,7 @@ function ListTokensController ( const { username, id } = _.get(user, 'summary_fields.last_used', {}); if (username && id) { - html += ` by ${$filter('sanitize')(username)}`; + html += ` ${strings.get('add.LAST_USED_LABEL')} ${$filter('sanitize')(username)}`; } return html; @@ -98,7 +98,7 @@ function ListTokensController ( resourceName: 'token', body: deleteModalBody, action, - actionText: 'DELETE' + actionText: strings.get('add.DELETE_ACTION_LABEL') }); }; } From cbc20093d7031b10ed2f78424685464a986fdea0 Mon Sep 17 00:00:00 2001 From: John Mitchell Date: Fri, 16 Mar 2018 17:15:28 -0400 Subject: [PATCH 3/3] move users tokens to features folder --- awx/ui/client/features/_index.less | 1 + awx/ui/client/features/index.js | 4 +- awx/ui/client/features/users/index.js | 8 ++++ .../users/tokens/_index.less} | 3 -- awx/ui/client/features/users/tokens/index.js | 9 +++++ .../users/tokens}/tokens.strings.js | 5 ++- .../users-tokens-add-application.route.js | 38 +++++++++---------- .../tokens}/users-tokens-add.controller.js | 38 ++++++++++++------- .../tokens}/users-tokens-add.partial.html | 0 .../users/tokens}/users-tokens-add.route.js | 9 ++--- .../tokens}/users-tokens-list.controller.js | 2 +- .../tokens}/users-tokens-list.partial.html | 0 .../users/tokens}/users-tokens-list.route.js | 14 +++---- .../lib/components/input/select.partial.html | 2 +- awx/ui/client/lib/theme/index.less | 1 - awx/ui/client/src/users/main.js | 10 ++--- 16 files changed, 84 insertions(+), 60 deletions(-) create mode 100644 awx/ui/client/features/users/index.js rename awx/ui/client/{src/users/token-modal.block.less => features/users/tokens/_index.less} (84%) create mode 100644 awx/ui/client/features/users/tokens/index.js rename awx/ui/client/{src/users => features/users/tokens}/tokens.strings.js (86%) rename awx/ui/client/{src/users => features/users/tokens}/users-tokens-add-application.route.js (68%) rename awx/ui/client/{src/users => features/users/tokens}/users-tokens-add.controller.js (77%) rename awx/ui/client/{src/users => features/users/tokens}/users-tokens-add.partial.html (100%) rename awx/ui/client/{src/users => features/users/tokens}/users-tokens-add.route.js (77%) rename awx/ui/client/{src/users => features/users/tokens}/users-tokens-list.controller.js (97%) rename awx/ui/client/{src/users => features/users/tokens}/users-tokens-list.partial.html (100%) rename awx/ui/client/{src/users => features/users/tokens}/users-tokens-list.route.js (76%) diff --git a/awx/ui/client/features/_index.less b/awx/ui/client/features/_index.less index 5046881522..e2339dc9e4 100644 --- a/awx/ui/client/features/_index.less +++ b/awx/ui/client/features/_index.less @@ -1 +1,2 @@ @import 'credentials/_index'; +@import 'users/tokens/_index'; diff --git a/awx/ui/client/features/index.js b/awx/ui/client/features/index.js index 75093bf39c..01216e575f 100644 --- a/awx/ui/client/features/index.js +++ b/awx/ui/client/features/index.js @@ -5,6 +5,7 @@ import atLibModels from '~models'; import atFeaturesApplications from '~features/applications'; import atFeaturesCredentials from '~features/credentials'; import atFeaturesTemplates from '~features/templates'; +import atFeaturesUsers from '~features/users'; const MODULE_NAME = 'at.features'; @@ -14,7 +15,8 @@ angular.module(MODULE_NAME, [ atLibModels, atFeaturesApplications, atFeaturesCredentials, - atFeaturesTemplates + atFeaturesTemplates, + atFeaturesUsers ]); export default MODULE_NAME; diff --git a/awx/ui/client/features/users/index.js b/awx/ui/client/features/users/index.js new file mode 100644 index 0000000000..b8f6a8052f --- /dev/null +++ b/awx/ui/client/features/users/index.js @@ -0,0 +1,8 @@ +import atFeaturesUsersTokens from '~features/users/tokens'; + +const MODULE_NAME = 'at.features.users'; + +angular + .module(MODULE_NAME, [atFeaturesUsersTokens]); + +export default MODULE_NAME; diff --git a/awx/ui/client/src/users/token-modal.block.less b/awx/ui/client/features/users/tokens/_index.less similarity index 84% rename from awx/ui/client/src/users/token-modal.block.less rename to awx/ui/client/features/users/tokens/_index.less index d913b3e3ef..f1052b5fa6 100644 --- a/awx/ui/client/src/users/token-modal.block.less +++ b/awx/ui/client/features/users/tokens/_index.less @@ -7,6 +7,3 @@ font-weight: bold; width: 130px; } - -.TokenModal-value { -} diff --git a/awx/ui/client/features/users/tokens/index.js b/awx/ui/client/features/users/tokens/index.js new file mode 100644 index 0000000000..6d635b572d --- /dev/null +++ b/awx/ui/client/features/users/tokens/index.js @@ -0,0 +1,9 @@ +import TokensStrings from './tokens.strings'; + +const MODULE_NAME = 'at.features.users.tokens'; + +angular + .module(MODULE_NAME, []) + .service('TokensStrings', TokensStrings); + +export default MODULE_NAME; diff --git a/awx/ui/client/src/users/tokens.strings.js b/awx/ui/client/features/users/tokens/tokens.strings.js similarity index 86% rename from awx/ui/client/src/users/tokens.strings.js rename to awx/ui/client/features/users/tokens/tokens.strings.js index 0dc2fa61b5..ac0af8e15f 100644 --- a/awx/ui/client/src/users/tokens.strings.js +++ b/awx/ui/client/features/users/tokens/tokens.strings.js @@ -25,7 +25,10 @@ function TokensStrings (BaseString) { ERROR_HEADER: t.s('COULD NOT CREATE TOKEN'), ERROR_BODY_LABEL: t.s('Returned status:'), LAST_USED_LABEL: t.s('by'), - DELETE_ACTION_LABEL: t.s('DELETE') + DELETE_ACTION_LABEL: t.s('DELETE'), + SCOPE_PLACEHOLDER: t.s('Select a scope'), + SCOPE_READ_LABEL: t.s('Read'), + SCOPE_WRITE_LABEL: t.s('Write') }; ns.list = { diff --git a/awx/ui/client/src/users/users-tokens-add-application.route.js b/awx/ui/client/features/users/tokens/users-tokens-add-application.route.js similarity index 68% rename from awx/ui/client/src/users/users-tokens-add-application.route.js rename to awx/ui/client/features/users/tokens/users-tokens-add-application.route.js index 4ab5998d74..13197ca11d 100644 --- a/awx/ui/client/src/users/users-tokens-add-application.route.js +++ b/awx/ui/client/features/users/tokens/users-tokens-add-application.route.js @@ -33,27 +33,25 @@ export default { } }, resolve: { - ListDefinition: [() => { - return { - name: 'applications', - iterator: 'application', - hover: true, - index: false, - fields: { - name: { - key: true, - label: 'Name', - columnClass: 'col-lg-4 col-md-6 col-sm-8 col-xs-8', - awToolTip: '{{application.description | sanitize}}', - dataPlacement: 'top' - }, + ListDefinition: [() => ({ + name: 'applications', + iterator: 'application', + hover: true, + index: false, + fields: { + name: { + key: true, + label: 'Name', + columnClass: 'col-lg-4 col-md-6 col-sm-8 col-xs-8', + awToolTip: '{{application.description | sanitize}}', + dataPlacement: 'top' }, - actions: { - }, - fieldActions: { - } + }, + actions: { + }, + fieldActions: { } - }], + })], Dataset: ['QuerySet', 'GetBasePath', '$stateParams', 'ListDefinition', (qs, GetBasePath, $stateParams, list) => qs.search( GetBasePath('applications'), @@ -68,4 +66,4 @@ export default { $('body').removeClass('modal-open'); } } -} +}; diff --git a/awx/ui/client/src/users/users-tokens-add.controller.js b/awx/ui/client/features/users/tokens/users-tokens-add.controller.js similarity index 77% rename from awx/ui/client/src/users/users-tokens-add.controller.js rename to awx/ui/client/features/users/tokens/users-tokens-add.controller.js index 6e5d4c4d26..1421077b1c 100644 --- a/awx/ui/client/src/users/users-tokens-add.controller.js +++ b/awx/ui/client/features/users/tokens/users-tokens-add.controller.js @@ -1,4 +1,7 @@ -function AddTokensController (models, $state, strings, Rest, Alert, Wait, GetBasePath, $filter) { +function AddTokensController ( + models, $state, strings, Rest, Alert, Wait, GetBasePath, + $filter, ProcessErrors +) { const vm = this || {}; const { application } = models; @@ -28,21 +31,29 @@ function AddTokensController (models, $state, strings, Rest, Alert, Wait, GetBas vm.form.description.required = false; vm.form.scope = { - choices: ['', 'read', 'write'], + choices: [ + '', + 'read', + 'write' + ], help_text: strings.get('add.SCOPE_HELP_TEXT'), id: 'scope', label: 'Scope', required: true, _component: 'at-input-select', - _data: ['', 'read', 'write'], + _data: [ + strings.get('add.SCOPE_PLACEHOLDER'), + strings.get('add.SCOPE_READ_LABEL'), + strings.get('add.SCOPE_WRITE_LABEL') + ], _exp: 'choice for (index, choice) in state._data', _format: 'array' - } + }; - vm.form.save = data => { - Rest.setUrl(GetBasePath('users') + $state.params.user_id + '/authorized_tokens'); - return Rest.post(data) - .then(({data}) => { + vm.form.save = payload => { + Rest.setUrl(`${GetBasePath('users')}${$state.params.user_id}/authorized_tokens`); + return Rest.post(payload) + .then(({ data }) => { Alert(strings.get('add.TOKEN_MODAL_HEADER'), `
@@ -71,8 +82,8 @@ function AddTokensController (models, $state, strings, Rest, Alert, Wait, GetBas `, null, null, null, null, null, true); Wait('stop'); }) - .catch(({data, status}) => { - ProcessErrors($scope, data, status, null, { + .catch(({ data, status }) => { + ProcessErrors(null, data, status, null, { hdr: strings.get('add.ERROR_HEADER'), msg: `${strings.get('add.ERROR_BODY_LABEL')} ${status}` }); @@ -80,7 +91,7 @@ function AddTokensController (models, $state, strings, Rest, Alert, Wait, GetBas }); }; - vm.form.onSaveSuccess = res => { + vm.form.onSaveSuccess = () => { $state.go('^', { user_id: $state.params.user_id }, { reload: true }); }; } @@ -88,12 +99,13 @@ function AddTokensController (models, $state, strings, Rest, Alert, Wait, GetBas AddTokensController.$inject = [ 'resolvedModels', '$state', - 'ApplicationsStrings', + 'TokensStrings', 'Rest', 'Alert', 'Wait', 'GetBasePath', - '$filter' + '$filter', + 'ProcessErrors' ]; export default AddTokensController; diff --git a/awx/ui/client/src/users/users-tokens-add.partial.html b/awx/ui/client/features/users/tokens/users-tokens-add.partial.html similarity index 100% rename from awx/ui/client/src/users/users-tokens-add.partial.html rename to awx/ui/client/features/users/tokens/users-tokens-add.partial.html diff --git a/awx/ui/client/src/users/users-tokens-add.route.js b/awx/ui/client/features/users/tokens/users-tokens-add.route.js similarity index 77% rename from awx/ui/client/src/users/users-tokens-add.route.js rename to awx/ui/client/features/users/tokens/users-tokens-add.route.js index f1047fb24b..350e9bd2dd 100644 --- a/awx/ui/client/src/users/users-tokens-add.route.js +++ b/awx/ui/client/features/users/tokens/users-tokens-add.route.js @@ -1,10 +1,9 @@ -import { N_ } from '../i18n'; +import { N_ } from '../../../src/i18n'; import AddController from './users-tokens-add.controller'; -const addTemplate = require('~src/users/users-tokens-add.partial.html'); +const addTemplate = require('~features/users/tokens/users-tokens-add.partial.html'); function TokensDetailResolve ($q, Application) { - const promises = {}; promises.application = new Application('options'); @@ -18,12 +17,12 @@ TokensDetailResolve.$inject = [ ]; export default { - url: "/add-token", + url: '/add-token', name: 'users.edit.tokens.add', params: { }, ncyBreadcrumb: { - label: N_("CREATE TOKEN") + label: N_('CREATE TOKEN') }, views: { 'preFormView@users.edit': { diff --git a/awx/ui/client/src/users/users-tokens-list.controller.js b/awx/ui/client/features/users/tokens/users-tokens-list.controller.js similarity index 97% rename from awx/ui/client/src/users/users-tokens-list.controller.js rename to awx/ui/client/features/users/tokens/users-tokens-list.controller.js index da1de35507..c2fe647928 100644 --- a/awx/ui/client/src/users/users-tokens-list.controller.js +++ b/awx/ui/client/features/users/tokens/users-tokens-list.controller.js @@ -47,7 +47,7 @@ function ListTokensController ( let html = $filter('longDate')(lastUsed); - const { username, id } = _.get(user, 'summary_fields.last_used', {}); + const { username, id } = _.get(token, 'summary_fields.last_used', {}); if (username && id) { html += ` ${strings.get('add.LAST_USED_LABEL')} ${$filter('sanitize')(username)}`; diff --git a/awx/ui/client/src/users/users-tokens-list.partial.html b/awx/ui/client/features/users/tokens/users-tokens-list.partial.html similarity index 100% rename from awx/ui/client/src/users/users-tokens-list.partial.html rename to awx/ui/client/features/users/tokens/users-tokens-list.partial.html diff --git a/awx/ui/client/src/users/users-tokens-list.route.js b/awx/ui/client/features/users/tokens/users-tokens-list.route.js similarity index 76% rename from awx/ui/client/src/users/users-tokens-list.route.js rename to awx/ui/client/features/users/tokens/users-tokens-list.route.js index 81ec099adc..c8a780e473 100644 --- a/awx/ui/client/src/users/users-tokens-list.route.js +++ b/awx/ui/client/features/users/tokens/users-tokens-list.route.js @@ -1,19 +1,17 @@ -import { N_ } from '../i18n'; +import { N_ } from '../../../src/i18n'; import ListController from './users-tokens-list.controller'; -const listTemplate = require('~src/users/users-tokens-list.partial.html'); +const listTemplate = require('~features/users/tokens/users-tokens-list.partial.html'); export default { - url: "/tokens", + url: '/tokens', name: 'users.edit.tokens', - params: { - }, ncyBreadcrumb: { - label: N_("TOKENS") + label: N_('TOKENS') }, views: { - 'related': { + related: { templateUrl: listTemplate, controller: ListController, controllerAs: 'vm' @@ -36,7 +34,7 @@ export default { 'QuerySet', ($stateParams, Wait, GetBasePath, qs) => { const searchParam = $stateParams.token_search; - const searchPath = GetBasePath('users') + $stateParams.user_id + '/tokens'; + const searchPath = `${GetBasePath('users')}${$stateParams.user_id}/tokens`; Wait('start'); return qs.search(searchPath, searchParam) .finally(() => { diff --git a/awx/ui/client/lib/components/input/select.partial.html b/awx/ui/client/lib/components/input/select.partial.html index aaa31bebee..f3ba5e845a 100644 --- a/awx/ui/client/lib/components/input/select.partial.html +++ b/awx/ui/client/lib/components/input/select.partial.html @@ -12,7 +12,7 @@