diff --git a/ui/app/components/console/command-input.js b/ui/app/components/console/command-input.js index 43854b0b7..d7907d3ab 100644 --- a/ui/app/components/console/command-input.js +++ b/ui/app/components/console/command-input.js @@ -11,9 +11,6 @@ export default Ember.Component.extend({ value: null, isFullscreen: null, - didRender() { - this.element.scrollIntoView(); - }, actions: { handleKeyUp(event) { const keyCode = event.keyCode; diff --git a/ui/app/components/console/ui-panel.js b/ui/app/components/console/ui-panel.js index 61c782a81..f3c9d18cd 100644 --- a/ui/app/components/console/ui-panel.js +++ b/ui/app/components/console/ui-panel.js @@ -1,4 +1,5 @@ import Ember from 'ember'; +import { task } from 'ember-concurrency'; import { parseCommand, extractDataAndFlags, @@ -8,22 +9,31 @@ import { executeUICommand, } from 'vault/lib/console-helpers'; -const { inject, computed } = Ember; +const { inject, computed, getOwner, run } = Ember; export default Ember.Component.extend({ classNames: 'console-ui-panel-scroller', classNameBindings: ['isFullscreen:fullscreen'], isFullscreen: false, console: inject.service(), + router: inject.service(), inputValue: null, log: computed.alias('console.log'), - logAndOutput(command, logContent) { - this.set('inputValue', ''); - this.get('console').logAndOutput(command, logContent); + didRender() { + this._super(...arguments); + this.scrollToBottom(); }, - executeCommand(command, shouldThrow = false) { + logAndOutput(command, logContent) { + this.get('console').logAndOutput(command, logContent); + run.schedule('afterRender', () => this.scrollToBottom()); + }, + + isRunning: computed.or('executeCommand.isRunning', 'refreshRoute.isRunning'), + + executeCommand: task(function*(command, shouldThrow = false) { + this.set('inputValue', ''); let service = this.get('console'); let serviceArgs; @@ -32,7 +42,8 @@ export default Ember.Component.extend({ command, args => this.logAndOutput(args), args => service.clearLog(args), - () => this.toggleProperty('isFullscreen') + () => this.toggleProperty('isFullscreen'), + () => this.get('refreshRoute').perform() ) ) { return; @@ -61,16 +72,26 @@ export default Ember.Component.extend({ this.logAndOutput(command, inputError); return; } - let serviceFn = service[method]; - serviceFn - .call(service, path, data, flags.wrapTTL) - .then(resp => { - this.logAndOutput(command, logFromResponse(resp, path, method, flags)); - }) - .catch(error => { - this.logAndOutput(command, logFromError(error, path, method)); - }); - }, + try { + let resp = yield service[method].call(service, path, data, flags.wrapTTL); + this.logAndOutput(command, logFromResponse(resp, path, method, flags)); + } catch(error) { + this.logAndOutput(command, logFromError(error, path, method)); + } + }), + + refreshRoute:task(function*() { + let owner = getOwner(this); + let routeName = this.get('router.currentRouteName'); + let route = owner.lookup(`route:${routeName}`); + + try { + yield route.refresh(); + this.logAndOutput(null, { type: 'success', content: 'The current screen has been refreshed!' }); + } catch (error) { + this.logAndOutput(null, { type: 'error', content: 'The was a problem refreshing the current screen.' }); + } + }), shiftCommandIndex(keyCode) { this.get('console').shiftCommandIndex(keyCode, val => { @@ -78,12 +99,16 @@ export default Ember.Component.extend({ }); }, + scrollToBottom() { + this.element.scrollTop = this.element.scrollHeight; + }, + actions: { toggleFullscreen() { this.toggleProperty('isFullscreen'); }, executeCommand(val) { - this.executeCommand(val, true); + this.get('executeCommand').perform(val, true); }, shiftCommandIndex(direction) { this.shiftCommandIndex(direction); diff --git a/ui/app/lib/console-helpers.js b/ui/app/lib/console-helpers.js index 163706335..77d5c29c0 100644 --- a/ui/app/lib/console-helpers.js +++ b/ui/app/lib/console-helpers.js @@ -2,7 +2,7 @@ import keys from 'vault/lib/keycodes'; import argTokenizer from 'yargs-parser-tokenizer'; const supportedCommands = ['read', 'write', 'list', 'delete']; -const uiCommands = ['clearall', 'clear', 'fullscreen']; +const uiCommands = ['clearall', 'clear', 'fullscreen', 'refresh']; export function extractDataAndFlags(data, flags) { return data.concat(flags).reduce((accumulator, val) => { @@ -29,7 +29,7 @@ export function extractDataAndFlags(data, flags) { }, { data: {}, flags: {} }); } -export function executeUICommand(command, logAndOutput, clearLog, toggleFullscreen) { +export function executeUICommand(command, logAndOutput, clearLog, toggleFullscreen, refreshFn) { const isUICommand = uiCommands.includes(command); if (isUICommand) { logAndOutput(command); @@ -44,6 +44,9 @@ export function executeUICommand(command, logAndOutput, clearLog, toggleFullscre case 'fullscreen': toggleFullscreen(); break; + case 'refresh': + refreshFn(); + break; } return isUICommand; diff --git a/ui/app/models/identity/group.js b/ui/app/models/identity/group.js index d8f3bb275..ca13e28aa 100644 --- a/ui/app/models/identity/group.js +++ b/ui/app/models/identity/group.js @@ -27,10 +27,10 @@ export default IdentityModel.extend({ readOnly: true, }), numMemberEntities: attr('number', { - readOnly: true + readOnly: true, }), numParentGroups: attr('number', { - readOnly: true + readOnly: true, }), metadata: attr('object', { editType: 'kv', diff --git a/ui/app/serializers/identity/_base.js b/ui/app/serializers/identity/_base.js index 217d13331..9c6de8b95 100644 --- a/ui/app/serializers/identity/_base.js +++ b/ui/app/serializers/identity/_base.js @@ -19,9 +19,8 @@ export default ApplicationSerializer.extend({ return model; }); delete payload.data.key_info; - return list.sort((a,b) => { + return list.sort((a, b) => { return a.name.localeCompare(b.name); }); }, - }); diff --git a/ui/app/services/console.js b/ui/app/services/console.js index 3e17842b8..407f7064a 100644 --- a/ui/app/services/console.js +++ b/ui/app/services/console.js @@ -61,8 +61,10 @@ export default Service.extend({ logAndOutput(command, logContent) { let log = this.get('log'); - log.pushObject({ type: 'command', content: command }); - this.set('commandIndex', null); + if (command) { + log.pushObject({ type: 'command', content: command }); + this.set('commandIndex', null); + } if (logContent) { log.pushObject(logContent); } diff --git a/ui/app/styles/components/console-ui-panel.scss b/ui/app/styles/components/console-ui-panel.scss index b9e75b261..e7157fe0c 100644 --- a/ui/app/styles/components/console-ui-panel.scss +++ b/ui/app/styles/components/console-ui-panel.scss @@ -62,7 +62,6 @@ align-items: center; display: flex; - input { background-color: rgba($black, 0.5); border: 0; @@ -152,3 +151,18 @@ header .navbar-sections { transform: translate3d(0, 0, 0); will-change: transform; } + +.console-spinner.control { + height: 21px; + width: 21px; + transform: scale(.75); + transform-origin: center; + &::after { + height: auto; + width: auto; + right: .25rem; + left: .25rem; + top: .25rem; + bottom: .25rem; + } +} diff --git a/ui/app/templates/application.hbs b/ui/app/templates/application.hbs index e4480ce1b..9a0e3abd2 100644 --- a/ui/app/templates/application.hbs +++ b/ui/app/templates/application.hbs @@ -9,7 +9,7 @@