From fa330db9c54ebe4bca54d993a07bdbce468a67e2 Mon Sep 17 00:00:00 2001 From: gconsidine Date: Fri, 16 Jun 2017 15:23:18 -0400 Subject: [PATCH] Add UI/UX polish in prep for merge * Bring UI/UX inline with recent changes * Use select components as a stopgap for credential_types and orgs * Add tabs to permissions view * Add Organization model --- .../credentials/add-credentials.controller.js | 12 +++++++- .../add-edit-credentials.view.html | 7 ++++- .../edit-credentials.controller.js | 25 +++++++++++++++- awx/ui/client/features/credentials/index.js | 12 ++++---- .../client/lib/components/input/_index.less | 30 +++++++++++++------ .../lib/components/input/base.controller.js | 2 ++ .../components/input/checkbox.directive.js | 2 ++ .../components/input/checkbox.partial.html | 15 ++++++---- .../lib/components/input/label.partial.html | 2 +- .../lib/components/input/secret.directive.js | 1 + .../lib/components/input/secret.partial.html | 4 +-- .../lib/components/input/select.directive.js | 9 ++++++ .../input/textarea-secret.directive.js | 3 ++ .../input/textarea-secret.partial.html | 3 +- .../components/input/textarea.partial.html | 1 + .../client/lib/components/panel/_index.less | 1 + .../lib/components/panel/heading.partial.html | 2 +- .../client/lib/components/popover/_index.less | 4 +-- awx/ui/client/lib/components/tabs/_index.less | 9 +++--- awx/ui/client/lib/models/Base.js | 7 +++++ awx/ui/client/lib/models/CredentialType.js | 7 ----- awx/ui/client/lib/models/Organization.js | 18 +++++++++++ awx/ui/client/lib/models/index.js | 4 ++- awx/ui/client/lib/theme/_common.less | 5 ++++ awx/ui/client/lib/theme/_mixins.less | 1 + awx/ui/client/lib/theme/_variables.less | 2 ++ 26 files changed, 145 insertions(+), 43 deletions(-) create mode 100644 awx/ui/client/lib/models/Organization.js diff --git a/awx/ui/client/features/credentials/add-credentials.controller.js b/awx/ui/client/features/credentials/add-credentials.controller.js index 7b0a2460f6..b9a0a9fce6 100644 --- a/awx/ui/client/features/credentials/add-credentials.controller.js +++ b/awx/ui/client/features/credentials/add-credentials.controller.js @@ -1,11 +1,14 @@ +const DEFAULT_ORGANIZATION_PLACEHOLDER = 'SELECT AN ORGANIZATION'; + function AddCredentialsController (models, $state) { let vm = this || {}; let me = models.me; let credential = models.credential; let credentialType = models.credentialType; + let organization = models.organization; - vm.panelTitle = 'New Credential'; + vm.panelTitle = 'NEW CREDENTIAL'; vm.tab = { details: { @@ -20,6 +23,13 @@ function AddCredentialsController (models, $state) { omit: ['user', 'team', 'inputs'] }); + vm.form.organization._placeholder = DEFAULT_ORGANIZATION_PLACEHOLDER; + vm.form.organization._data = organization.get('results'); + vm.form.organization._format = 'objects'; + vm.form.organization._exp = 'org as org.name for org in state._data'; + vm.form.organization._display = 'name'; + vm.form.organization._key = 'id'; + vm.form.credential_type._data = credentialType.get('results'); vm.form.credential_type._placeholder = 'SELECT A TYPE'; vm.form.credential_type._format = 'grouped-object'; diff --git a/awx/ui/client/features/credentials/add-edit-credentials.view.html b/awx/ui/client/features/credentials/add-edit-credentials.view.html index 977e5da1d6..d8b45d7a30 100644 --- a/awx/ui/client/features/credentials/add-edit-credentials.view.html +++ b/awx/ui/client/features/credentials/add-edit-credentials.view.html @@ -10,7 +10,7 @@ - + @@ -32,6 +32,11 @@ $state.current.name === 'credentials.edit.permissions.add'"> Credentials Permissions + + Details + Permissions + +
diff --git a/awx/ui/client/features/credentials/edit-credentials.controller.js b/awx/ui/client/features/credentials/edit-credentials.controller.js index 7e31f84b7e..b7370fe7c6 100644 --- a/awx/ui/client/features/credentials/edit-credentials.controller.js +++ b/awx/ui/client/features/credentials/edit-credentials.controller.js @@ -1,13 +1,18 @@ +const DEFAULT_ORGANIZATION_PLACEHOLDER = 'SELECT AN ORGANIZATION'; + function EditCredentialsController (models, $state, $scope) { let vm = this || {}; let me = models.me; let credential = models.credential; let credentialType = models.credentialType; + let organization = models.organization; vm.tab = { details: { - _active: true + _active: true, + _go: 'credentials.edit', + _params: { credential_id: credential.get('id') } }, permissions:{ _go: 'credentials.edit.permissions', @@ -15,6 +20,16 @@ function EditCredentialsController (models, $state, $scope) { } }; + $scope.$watch('$state.current.name', (value) => { + if (value === 'credentials.edit') { + vm.tab.details._active = true; + vm.tab.details._permissions = false; + } else { + vm.tab.permissions._active = true; + vm.tab.details._active = false; + } + }); + // Only exists for permissions compatibility $scope.credential_obj = credential.get(); @@ -24,6 +39,14 @@ function EditCredentialsController (models, $state, $scope) { omit: ['user', 'team', 'inputs'] }); + vm.form.organization._placeholder = DEFAULT_ORGANIZATION_PLACEHOLDER; + vm.form.organization._data = organization.get('results'); + vm.form.organization._format = 'objects'; + vm.form.organization._exp = 'org as org.name for org in state._data'; + vm.form.organization._display = 'name'; + vm.form.organization._key = 'id'; + vm.form.organization._value = organization.getById(credential.get('organization')); + vm.form.credential_type._data = credentialType.get('results'); vm.form.credential_type._format = 'grouped-object'; vm.form.credential_type._display = 'name'; diff --git a/awx/ui/client/features/credentials/index.js b/awx/ui/client/features/credentials/index.js index 525ec6c00e..e8c5670cbe 100644 --- a/awx/ui/client/features/credentials/index.js +++ b/awx/ui/client/features/credentials/index.js @@ -6,12 +6,13 @@ import AddController from './add-credentials.controller.js'; import EditController from './edit-credentials.controller.js'; import { N_ } from '../../src/i18n'; -function CredentialsResolve ($q, $stateParams, Me, Credential, CredentialType) { +function CredentialsResolve ($q, $stateParams, Me, Credential, CredentialType, Organization) { let id = $stateParams.credential_id; let promises = { me: new Me('get'), - credentialType: new CredentialType('get') + credentialType: new CredentialType('get'), + organization: new Organization('get') }; if (id) { @@ -28,13 +29,13 @@ CredentialsResolve.$inject = [ '$stateParams', 'MeModel', 'CredentialModel', - 'CredentialTypeModel' + 'CredentialTypeModel', + 'OrganizationModel' ]; -function CredentialsConfig ($stateProvider, $stateExtenderProvider, stateDefinitionsProvider, pathServiceProvider) { +function CredentialsConfig ($stateProvider, $stateExtenderProvider, pathServiceProvider) { let pathService = pathServiceProvider.$get(); let stateExtender = $stateExtenderProvider.$get(); - let stateDefinitions = stateDefinitionsProvider.$get(); stateExtender.addState({ name: 'credentials', @@ -272,7 +273,6 @@ function CredentialsConfig ($stateProvider, $stateExtenderProvider, stateDefinit CredentialsConfig.$inject = [ '$stateProvider', '$stateExtenderProvider', - 'stateDefinitionsProvider', 'PathServiceProvider' ]; diff --git a/awx/ui/client/lib/components/input/_index.less b/awx/ui/client/lib/components/input/_index.less index 7e6d191351..bc04b24246 100644 --- a/awx/ui/client/lib/components/input/_index.less +++ b/awx/ui/client/lib/components/input/_index.less @@ -7,7 +7,7 @@ color: @at-gray-dark-5x; &, &:active { - border-color: @at-gray-dark-3x; + border-color: @at-gray-dark-2x; } &:focus { @@ -19,25 +19,33 @@ margin: 0; padding: 0; - & > input[type=checkbox] { - height: @at-input-height; - margin: 0; - padding: 0; + & > label { + & > input[type=checkbox] { + height: @at-input-height; + margin: 0; + padding: 0; + } + + & > p { + margin: 0; + padding: 0 0 0 @at-space-6x; + line-height: @at-line-height-tall; + } } } .at-InputContainer { - margin-top: @at-space-6x;; + margin-top: @at-space-6x; } .at-Input-button { min-width: @at-input-button-width; display: block; - height: 100%; + height: @at-input-height; &, &:active, &:hover, &:focus { color: @at-gray-dark-3x; - border-color: @at-gray-dark-3x; + border-color: @at-gray-dark-2x; background-color: @at-white; cursor: pointer; } @@ -76,12 +84,16 @@ position: absolute; width: @at-inset-width; height: 100%; - background: @at-gray; + background: @at-gray-dark; left: -@at-inset-width; } .at-InputGroup-button { height: 100%; + + & > button { + height: 100%; + } } .at-InputGroup-title { diff --git a/awx/ui/client/lib/components/input/base.controller.js b/awx/ui/client/lib/components/input/base.controller.js index 729dd6cb11..71591ca129 100644 --- a/awx/ui/client/lib/components/input/base.controller.js +++ b/awx/ui/client/lib/components/input/base.controller.js @@ -84,12 +84,14 @@ function BaseInputController () { scope.state._enableToggle = true; scope.state._value = scope.state._preEditValue; scope.state._activeModel = '_displayValue'; + scope.state._placeholder = 'ENCRYPTED'; } else { scope.state._buttonText = 'REVERT'; scope.state._disabled = false; scope.state._enableToggle = false; scope.state._activeModel = '_value'; scope.state._value = ''; + scope.state._placeholder = ''; } }; diff --git a/awx/ui/client/lib/components/input/checkbox.directive.js b/awx/ui/client/lib/components/input/checkbox.directive.js index aaef13519d..9380eae846 100644 --- a/awx/ui/client/lib/components/input/checkbox.directive.js +++ b/awx/ui/client/lib/components/input/checkbox.directive.js @@ -14,6 +14,8 @@ function AtInputCheckboxController (baseInputController) { vm.init = (scope, element, form) => { baseInputController.call(vm, 'input', scope, element, form); + scope.label = scope.state.label; + scope.state.label = 'OPTIONS'; vm.check(); }; diff --git a/awx/ui/client/lib/components/input/checkbox.partial.html b/awx/ui/client/lib/components/input/checkbox.partial.html index 60cc234efd..df171e5cb5 100644 --- a/awx/ui/client/lib/components/input/checkbox.partial.html +++ b/awx/ui/client/lib/components/input/checkbox.partial.html @@ -2,12 +2,15 @@
- +
diff --git a/awx/ui/client/lib/components/input/label.partial.html b/awx/ui/client/lib/components/input/label.partial.html index b771232e8f..d53a4a7a25 100644 --- a/awx/ui/client/lib/components/input/label.partial.html +++ b/awx/ui/client/lib/components/input/label.partial.html @@ -8,7 +8,7 @@ -

Prompt on launch?

+

Prompt on launch

diff --git a/awx/ui/client/lib/components/input/secret.directive.js b/awx/ui/client/lib/components/input/secret.directive.js index c17933868d..b7ba061bda 100644 --- a/awx/ui/client/lib/components/input/secret.directive.js +++ b/awx/ui/client/lib/components/input/secret.directive.js @@ -26,6 +26,7 @@ function AtInputSecretController (baseInputController) { vm.toggle = vm.toggleShowHide; } else { scope.state._buttonText = 'REPLACE'; + scope.state._placeholder = 'ENCRYPTED'; vm.toggle = vm.toggleRevertReplace; } diff --git a/awx/ui/client/lib/components/input/secret.partial.html b/awx/ui/client/lib/components/input/secret.partial.html index b9979f5520..9102c59b0d 100644 --- a/awx/ui/client/lib/components/input/secret.partial.html +++ b/awx/ui/client/lib/components/input/secret.partial.html @@ -3,7 +3,7 @@
- +
diff --git a/awx/ui/client/lib/components/input/select.directive.js b/awx/ui/client/lib/components/input/select.directive.js index 2ed8d2ef11..cbc6c2b0fa 100644 --- a/awx/ui/client/lib/components/input/select.directive.js +++ b/awx/ui/client/lib/components/input/select.directive.js @@ -1,3 +1,5 @@ +const DEFAULT_EMPTY_PLACEHOLDER = 'NO OPTIONS AVAILABLE'; + function atInputSelectLink (scope, element, attrs, controllers) { let formController = controllers[0]; let inputController = controllers[1]; @@ -25,6 +27,11 @@ function AtInputSelectController (baseInputController, eventService) { input = element.find('input')[0]; select = element.find('select')[0]; + if (!scope.state._data || scope.state._data.length === 0) { + scope.state._disabled = true; + scope.state._placeholder = DEFAULT_EMPTY_PLACEHOLDER; + } + vm.setListeners(); vm.check(); @@ -55,6 +62,8 @@ function AtInputSelectController (baseInputController, eventService) { vm.updateDisplayModel = () => { if (scope.state._format === 'array') { scope.displayModel = scope.state._data[scope.state._value]; + } else if (scope.state._format === 'objects') { + scope.displayModel = scope.state._value[scope.state._display]; } else if (scope.state._format === 'grouped-object') { scope.displayModel = scope.state._value[scope.state._display]; } else { 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 3ad318b63a..a22491b3de 100644 --- a/awx/ui/client/lib/components/input/textarea-secret.directive.js +++ b/awx/ui/client/lib/components/input/textarea-secret.directive.js @@ -34,6 +34,7 @@ function AtInputTextareaSecretController (baseInputController, eventService) { if (scope.state._value) { scope.state._buttonText = 'REPLACE'; + scope.state._placeholder = 'ENCRYPTED'; } else { if (scope.state.format === 'ssh_private_key') { vm.listeners = vm.setFileListeners(textarea, input); @@ -48,10 +49,12 @@ function AtInputTextareaSecretController (baseInputController, eventService) { vm.toggleRevertReplace(); if (scope.state._isBeingReplaced) { + scope.state._placeholder = ''; scope.state._displayHint = true; vm.listeners = vm.setFileListeners(textarea, input); } else { scope.state._displayHint = false; + scope.state._placeholder = 'ENCRYPTED'; eventService.remove(vm.listeners); } }; diff --git a/awx/ui/client/lib/components/input/textarea-secret.partial.html b/awx/ui/client/lib/components/input/textarea-secret.partial.html index 11d1f7a3df..dd0bc6e5ac 100644 --- a/awx/ui/client/lib/components/input/textarea-secret.partial.html +++ b/awx/ui/client/lib/components/input/textarea-secret.partial.html @@ -18,9 +18,10 @@ diff --git a/awx/ui/client/lib/components/input/textarea.partial.html b/awx/ui/client/lib/components/input/textarea.partial.html index 673094668b..bc0738dc9f 100644 --- a/awx/ui/client/lib/components/input/textarea.partial.html +++ b/awx/ui/client/lib/components/input/textarea.partial.html @@ -5,6 +5,7 @@