diff --git a/awx/ui/client/components/_index.less b/awx/ui/client/components/_index.less index 068cb5f609..5bd6f2be23 100644 --- a/awx/ui/client/components/_index.less +++ b/awx/ui/client/components/_index.less @@ -1,4 +1,5 @@ @import 'badge/_index'; +@import 'form/_index'; @import 'input/_index'; @import 'panel/_index'; @import 'popover/_index'; diff --git a/awx/ui/client/components/badge/_index.less b/awx/ui/client/components/badge/_index.less index c3d69b7ef4..a3f3927a81 100644 --- a/awx/ui/client/components/badge/_index.less +++ b/awx/ui/client/components/badge/_index.less @@ -1,8 +1,8 @@ .at-Badge { - font-size: @at-font-sm; - padding: 0 @at-padding-sm; + font-size: @at-font-size; + padding: 0 @at-space-2x; margin: 0; background-color: @at-gray; color: @at-white; - border-radius: @at-border-radius-md; + border-radius: @at-border-radius; } diff --git a/awx/ui/client/components/form/_index.less b/awx/ui/client/components/form/_index.less new file mode 100644 index 0000000000..593626f5ca --- /dev/null +++ b/awx/ui/client/components/form/_index.less @@ -0,0 +1,7 @@ +.at-FormActionGroup { + margin-top: @at-space-6x; + + button:last-child { + margin-left: @at-space-5x; + } +} diff --git a/awx/ui/client/components/form/form-action-group.directive.js b/awx/ui/client/components/form/form-action-group.directive.js new file mode 100644 index 0000000000..f13fcf7250 --- /dev/null +++ b/awx/ui/client/components/form/form-action-group.directive.js @@ -0,0 +1,16 @@ +function atFormActionGroup (pathService) { + return { + restrict: 'E', + transclude: true, + replace: true, + require: '^^at-form', + templateUrl: pathService.getPartialPath('components/form/form-action-group'), + scope: { + config: '=' + } + }; +} + +atFormActionGroup.$inject = ['PathService']; + +export default atFormActionGroup; diff --git a/awx/ui/client/components/form/form-action-group.partial.html b/awx/ui/client/components/form/form-action-group.partial.html new file mode 100644 index 0000000000..4c7d3d00c3 --- /dev/null +++ b/awx/ui/client/components/form/form-action-group.partial.html @@ -0,0 +1,5 @@ +
+
+ +
+
diff --git a/awx/ui/client/components/form/form-action.directive.js b/awx/ui/client/components/form/form-action.directive.js new file mode 100644 index 0000000000..0f99d2d332 --- /dev/null +++ b/awx/ui/client/components/form/form-action.directive.js @@ -0,0 +1,44 @@ +function link (scope, el, attrs, form) { + form.use('action', scope, el); + + switch(scope.config.type) { + case 'cancel': + applyCancelProperties(scope); + break; + case 'save': + applySaveProperties(scope); + break; + } +} + +function applyCancelProperties (scope) { + scope.text = 'CANCEL'; + scope.fill = 'Hollow'; + scope.color = 'white'; + scope.disabled = false; +} + +function applySaveProperties (scope) { + scope.text = 'SAVE'; + scope.fill = ''; + scope.color = 'green'; + scope.disabled = true; +} + +function atFormAction (pathService) { + return { + restrict: 'E', + transclude: true, + replace: true, + require: '^^at-form', + templateUrl: pathService.getPartialPath('components/form/form-action'), + link, + scope: { + config: '=' + } + }; +} + +atFormAction.$inject = ['PathService']; + +export default atFormAction; diff --git a/awx/ui/client/components/form/form-action.partial.html b/awx/ui/client/components/form/form-action.partial.html new file mode 100644 index 0000000000..bb85f7ed1e --- /dev/null +++ b/awx/ui/client/components/form/form-action.partial.html @@ -0,0 +1,4 @@ + diff --git a/awx/ui/client/components/form/form.directive.js b/awx/ui/client/components/form/form.directive.js index 5922a08b20..38f0924471 100644 --- a/awx/ui/client/components/form/form.directive.js +++ b/awx/ui/client/components/form/form.directive.js @@ -1,12 +1,23 @@ -function use (componentScope, componentElement) { +function use (type, componentScope, componentElement) { let vm = this; - let input = vm.track(componentElement); + let component; - componentScope.meta = input; + switch (type) { + case 'input': + component = vm.trackInput(componentElement); + break; + case 'action': + component = vm.trackAction(componentElement); + break; + default: + throw new Error('An at-form cannot use component type:', type); + } + + componentScope.meta = component; } -function track (componentElement) { +function trackInput (componentElement) { let vm = this; let input = { @@ -24,12 +35,27 @@ function track (componentElement) { return input; } -function controller () { +function trackAction (componentElement) { + let vm = this; + + let action = { + el: componentElement + }; + + vm.actions.push(action); + + return action; +} + +function AtFormController () { let vm = this; vm.inputs = []; + vm.actions = []; + vm.use = use; - vm.track = track; + vm.trackInput = trackInput; + vm.trackAction = trackAction; } function atForm (pathService) { @@ -37,7 +63,7 @@ function atForm (pathService) { restrict: 'E', transclude: true, templateUrl: pathService.getPartialPath('components/form/form'), - controller, + controller: AtFormController, controllerAs: 'vm', scope: { config: '=' diff --git a/awx/ui/client/components/index.js b/awx/ui/client/components/index.js index 6877297d62..c71407dbe3 100644 --- a/awx/ui/client/components/index.js +++ b/awx/ui/client/components/index.js @@ -1,5 +1,7 @@ import badge from './badge/badge.directive'; import form from './form/form.directive'; +import formAction from './form/form-action.directive'; +import formActionGroup from './form/form-action-group.directive'; import inputLabel from './input/label.directive'; import inputSearch from './input/search.directive'; import inputSelect from './input/select.directive'; @@ -15,6 +17,8 @@ angular .module('at.components', []) .directive('atBadge', badge) .directive('atForm', form) + .directive('atFormAction', formAction) + .directive('atFormActionGroup', formActionGroup) .directive('atInputLabel', inputLabel) .directive('atInputSearch', inputSearch) .directive('atInputSelect', inputSelect) diff --git a/awx/ui/client/components/input/_index.less b/awx/ui/client/components/input/_index.less index 1c15dca610..129c386dfe 100644 --- a/awx/ui/client/components/input/_index.less +++ b/awx/ui/client/components/input/_index.less @@ -1,40 +1,36 @@ .at-Input { - .at-Placeholder(@at-gray-dark); + .at-mixin-Placeholder(@at-gray-dark-3x); background: @at-white; - border-radius: @at-border-radius-md; - color: @at-gray-darkest; + border-radius: @at-border-radius; + color: @at-gray-dark-3x; &, &:active { - border-color: @at-gray-light; + border-color: @at-gray-dark-2x; } &:focus { - border-color: @at-link; + border-color: @at-blue; } } -.at-Input--placeholder { - color: @at-gray; -} - .at-Input--focus { - border-color: @at-link; + border-color: @at-blue; } .at-InputLabel { - color: @at-gray-dark; - font-size: @at-font-sm; - font-weight: @at-font-weight-sm; + color: @at-gray-dark-4x; + font-size: @at-font-size-2x; + font-weight: @at-font-weight; text-transform: uppercase; } .at-InputLabel-required { - color: @at-danger; - font-weight: @at-font-weight-lg; - font-size: @at-font-lg; - line-height: @at-font-xs; - margin: @at-margin-xs @at-margin-xs 0 0; + color: @at-red; + font-weight: @at-font-weight-2x; + font-size: @at-font-size-4x; + line-height: @at-line-height-short; + margin: @at-space @at-space 0 0; } .at-InputGroup { @@ -45,13 +41,13 @@ position: absolute; z-index: 3; pointer-events: none; - right: @at-padding-sm; - top: @at-padding-sm; + right: @at-space-4x; + top: @at-space-4x; } } .at-InputSelect { - height: @at-input-height-md; + height: @at-input-height; position: relative; } @@ -62,6 +58,7 @@ } .at-InputSelect-select { + cursor: pointer; position: absolute; z-index: 1; top: 0; diff --git a/awx/ui/client/components/input/select.directive.js b/awx/ui/client/components/input/select.directive.js index 4bd605df44..d1ef291dc4 100644 --- a/awx/ui/client/components/input/select.directive.js +++ b/awx/ui/client/components/input/select.directive.js @@ -2,7 +2,7 @@ let eventService; let pathService; function link (scope, el, attrs, form) { - form.use(scope, el); + form.use('input', scope, el); let apply = eventService.listenWith(scope); @@ -11,9 +11,8 @@ function link (scope, el, attrs, form) { input.addEventListener('focus', apply(select.focus)); select.addEventListener('mousedown', apply(() => scope.open = !scope.open)); - select.addEventListener('change', () => apply(() => scope.open = false)); + select.addEventListener('change', apply(() => scope.open = false)); select.addEventListener('focus', apply(() => input.classList.add('at-Input--focus'))); - select.addEventListener('blur', apply(() => { input.classList.remove('at-Input--focus'); scope.open = scope.open && false; diff --git a/awx/ui/client/components/input/text.directive.js b/awx/ui/client/components/input/text.directive.js index 5bb3b57490..c46a7a9a18 100644 --- a/awx/ui/client/components/input/text.directive.js +++ b/awx/ui/client/components/input/text.directive.js @@ -1,5 +1,5 @@ function link (scope, el, attrs, form) { - form.use(scope, el); + form.use('input', scope, el); } function atInputText (pathService) { diff --git a/awx/ui/client/components/panel/_index.less b/awx/ui/client/components/panel/_index.less index fca076deb3..3770023b6c 100644 --- a/awx/ui/client/components/panel/_index.less +++ b/awx/ui/client/components/panel/_index.less @@ -1,6 +1,7 @@ .at-Panel { - margin: @at-margin-md 0 0 0; - padding: @at-padding-md; + margin: @at-space-6x 0 0 0; + padding: @at-space-6x; + border-color: @at-gray-dark; } .at-Panel-heading { @@ -9,20 +10,20 @@ } .at-Panel-dismiss { - .at-IconButton(); + .at-mixin-ButtonIcon(); text-align: right; } .at-Panel-body { - margin: @at-margin-md 0 0 0; + margin: @at-space-6x 0 0 0; padding: 0; } .at-Panel-headingTitle { - color: @at-gray-dark; - font-size: @at-font-md; - font-weight: bold; - line-height: 0.9; + color: @at-gray-dark-4x; + font-size: @at-font-size-3x; + font-weight: @at-font-weight-2x; + line-height: @at-line-height-short; text-transform: uppercase; margin: 0; padding: 0; diff --git a/awx/ui/client/components/panel/heading.partial.html b/awx/ui/client/components/panel/heading.partial.html index 1f5b2ed682..d6aa273e8c 100644 --- a/awx/ui/client/components/panel/heading.partial.html +++ b/awx/ui/client/components/panel/heading.partial.html @@ -6,7 +6,7 @@
- +
diff --git a/awx/ui/client/components/popover/_index.less b/awx/ui/client/components/popover/_index.less index 72fe359eba..b3bbb5f60a 100644 --- a/awx/ui/client/components/popover/_index.less +++ b/awx/ui/client/components/popover/_index.less @@ -1,7 +1,7 @@ .at-Popover-icon { - .at-IconButton(); - font-size: @at-font-md; - padding: 0 0 0 @at-padding-xxs; + .at-mixin-ButtonIcon(); + font-size: @at-font-size-3x; + padding: 0 0 0 @at-space-2x; margin: 0; } @@ -9,22 +9,22 @@ visibility: hidden; opacity: 0; color: @at-white; - background-color: @at-gray-dark; + background-color: @at-gray-dark-4x; max-width: @at-popover-width; - padding: @at-padding-md; + padding: @at-space-4x; height: auto; position: fixed; z-index: 2000; - margin: 0 0 0 @at-margin-md; - border-radius: @at-border-radius-md; + margin: 0 0 0 @at-space-6x; + border-radius: @at-border-radius; box-shadow: 0 5px 10px rgba(0,0,0, 0.2); transition: opacity .15s linear; } .at-Popover-arrow { - color: @at-gray-dark; + color: @at-gray-dark-4x; position: fixed; z-index: 1999; padding: 0; - margin: -@at-margin-xxs 0 0 0; + margin: -@at-space 0 0 0; } diff --git a/awx/ui/client/components/toggle/_index.less b/awx/ui/client/components/toggle/_index.less index 4e5a52f4bf..0c3e0a824a 100644 --- a/awx/ui/client/components/toggle/_index.less +++ b/awx/ui/client/components/toggle/_index.less @@ -5,7 +5,7 @@ } &:hover { - background-color: @at-gray-lighter; + background-color: @at-gray-light-2x; } & > span:hover { @@ -16,17 +16,17 @@ .at-ToggleButton--show { &, &:hover, &:focus { - background-color: @at-link; - border-color: @at-link; + background-color: @at-blue; + border-color: @at-blue; color: @at-white; } } .at-ToggleContent-well { - margin: @at-margin-sm 0 0 0; - padding: @at-padding-md; - border-radius: 4px; + margin: @at-space-2x 0 0 0; + padding: @at-space-3x; + border-radius: @at-border-radius; border: 1px solid transparent; - background-color: @at-gray-lightest; - color: @at-gray-dark; + background-color: @at-gray-light-2x; + color: @at-gray-dark-2x; } diff --git a/awx/ui/client/src/credentials/add-credentials.controller.js b/awx/ui/client/src/credentials/add-credentials.controller.js index 2f32e4a66b..5fa9eea0cb 100644 --- a/awx/ui/client/src/credentials/add-credentials.controller.js +++ b/awx/ui/client/src/credentials/add-credentials.controller.js @@ -34,6 +34,14 @@ function AddCredentialsController (credentialType) { value: 'id', data: credentialType.categorizeByKind() }; + + vm.save = { + type: 'save' + }; + + vm.cancel = { + type: 'cancel' + }; } AddCredentialsController.$inject = [ diff --git a/awx/ui/client/src/credentials/add-credentials.view.html b/awx/ui/client/src/credentials/add-credentials.view.html index cb5f3f5c83..05ba307a44 100644 --- a/awx/ui/client/src/credentials/add-credentials.view.html +++ b/awx/ui/client/src/credentials/add-credentials.view.html @@ -1,12 +1,21 @@ - - + + + + + + + + + + + diff --git a/awx/ui/client/theme/_common.less b/awx/ui/client/theme/_common.less index d85df32ae1..35317df60c 100644 --- a/awx/ui/client/theme/_common.less +++ b/awx/ui/client/theme/_common.less @@ -5,29 +5,36 @@ * */ -// 1. Buttons -// ------------------------------------------------------------------------------------------------ -.at-Button--success { - .at-Button(@at-success, @at-white); -} -.at-Button--link { - .at-Button(@at-link, @at-white); -} -.at-Button--danger { - .at-Button(@at-danger, @at-white); -} -.at-Button--default { - .at-Button(@at-white, @at-gray); +// 1. Buttons ------------------------------------------------------------------------------------- - border-color: @at-gray-light; - - &:hover { - background: @at-gray-lightest; - } +.at-Button--green { + .at-mixin-Button(); + .at-mixin-ButtonColor('at-green', 'at-white'); +} + +.at-Button--blue { + .at-mixin-Button(); + .at-mixin-ButtonColor('at-blue', 'at-white'); } -.at-Button--icon { - padding: @at-padding-xxs @at-padding-sm; - font-size: @at-font-lg; +.at-Button--red { + .at-mixin-Button(); + .at-mixin-ButtonColor('at-red', 'at-white'); } +.at-ButtonHollow--white { + .at-mixin-Button(); + .at-mixin-ButtonHollow('at-gray-dark-4x', 'at-gray-dark-2x'); + + border-color: @at-gray-dark-2x; + + &:hover, &:focus { + color: @at-gray-dark-4x; + background-color: @at-white--hover; + } +} + +.at-ButtonIcon { + padding: @at-space-2x @at-space-4x; + font-size: @at-font-size-3x; +} diff --git a/awx/ui/client/theme/_mixins.less b/awx/ui/client/theme/_mixins.less index ab8627e33f..28368fa30a 100644 --- a/awx/ui/client/theme/_mixins.less +++ b/awx/ui/client/theme/_mixins.less @@ -1,17 +1,4 @@ -.at-IconButton () { - line-height: 0.9; - color: @at-gray-light; - - & > i { - cursor: pointer; - } - - & > i:hover { - color: @at-gray; - } -} - -.at-Placeholder (@color) { +.at-mixin-Placeholder (@color) { &:-moz-placeholder { color: @color; } @@ -23,13 +10,54 @@ } } -.at-Button (@bg, @color) { - color: @color; - background-color: @bg; - padding: @at-padding-xs @at-padding-md; +.at-mixin-Button () { + padding: @at-space-2x @at-space-4x; +} - &:hover { - color: @color; - background-color: '@{bg}-dark'; +.at-mixin-ButtonColor (@background, @color, @hover: '@{background}--hover') { + background-color: @@background; + + &, &:hover, &:focus { + color: @@color; + } + + &:hover, &:focus { + background-color: @@hover; + } + + &[disabled] { + background-color: fade(@@background, 60%); + } +} + +.at-mixin-ButtonHollow (@color, @hover: '@{color}--hover') { + background-color: @at-white; + + color: @@color; + border-color: @@color; + + &:hover, &:focus { + color: @@hover; + border-color: @@hover; + background-color: @at-white; + } + + &[disabled] { + background-color: fade(@@color, 30%); + border-color: fade(@@color, 30%); + color: @at-white; + } +} + +.at-mixin-ButtonIcon () { + line-height: @at-line-height-short; + color: @at-gray-dark-2x; + + & > i { + cursor: pointer; + } + + & > i:hover { + color: @at-gray-dark-3x; } } diff --git a/awx/ui/client/theme/_variables.less b/awx/ui/client/theme/_variables.less index 047990befc..852700b147 100644 --- a/awx/ui/client/theme/_variables.less +++ b/awx/ui/client/theme/_variables.less @@ -1,39 +1,65 @@ +/** + * All variables used in the UI. + * + * 1. Colors + * 2. Typography + * 3. Layout + * 4. Misc + */ + +// 1. Colors -------------------------------------------------------------------------------------- +@at-gray-light-5x: #fcfcfc; +@at-gray-light-4x: #fafafa; +@at-gray-light-3x: #f6f6f6; +@at-gray-light-2x: #f2f2f2; +@at-gray-light: #ebebeb; +@at-gray: #e1e1e1; +@at-gray-dark: #d7d7d7; +@at-gray-dark-2x: #b7b7b7; +@at-gray-dark-3x: #8f8992; +@at-gray-dark-4x: #707070; +@at-gray-dark-5x: #161b1f; + @at-white: #ffffff; -@at-gray-lightest: #fafafa; -@at-gray-lighter: #f6f6f6; -@at-gray-light: #b7b7b7; -@at-gray: #848992; -@at-gray-dark: #707070; -@at-gray-darkest: #161b1f; -@at-link: #337ab7; -@at-link-dark: #286090; -@at-success: #5cb85c; -@at-success-dark: #449D44; -@at-danger: #d9534f; +@at-white--hover: #f2f2f2; -@at-font-xs: 12px; -@at-font-sm: 13px; -@at-font-md: 14px; -@at-font-lg: 16px; +@at-blue: #337ab7; +@at-blue--hover: #286090; -@at-font-weight-sm: 400; -@at-font-weight-md: 700; -@at-font-weight-lg: 900; +@at-green: #5cb85c; +@at-green--hover: #449D44; -@at-padding-xxs: 5px; -@at-padding-xs: 6px; -@at-padding-sm: 10px; -@at-padding-md: 20px; +@at-yellow: #f0ad4e; +@at-yellow--hover: #ec971f; -@at-margin-xxs: 3px; -@at-margin-xs: 4px; -@at-margin-sm: 10px; -@at-margin-md: 20px; +@at-red: #d9534f; +@at-red--hover: #c9302c; -@at-border-radius-md: 5px; +@at-redAlert: #ff0000; +@at-redAlert--hover: #d81f1f; -@at-input-height-md: 34px; +// 2. Typography ---------------------------------------------------------------------------------- +@at-font-size: 12px; +@at-font-size-2x: 13px; +@at-font-size-3x: 14px; +@at-font-size-4x: 16px; -@at-line-height-md: 24px; +@at-font-weight: 400; +@at-font-weight-2x: 700; +@at-font-weight-3x: 900; +@at-line-height-short: 0.9; +@at-line-height: 24px; + +// 3. Layout -------------------------------------------------------------------------------------- +@at-space: 3px; +@at-space-2x: 4px; +@at-space-3x: 5px; +@at-space-4x: 10px; +@at-space-5x: 15px; +@at-space-6x: 20px; + +// 4. Misc -------------------------------------------------------------------------------------- +@at-border-radius: 5px; +@at-input-height: 34px; @at-popover-width: 320px;