mirror of
https://github.com/ZwareBear/awx.git
synced 2026-04-21 07:21:49 -05:00
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
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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 = '';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -2,12 +2,15 @@
|
||||
<div class="form-group at-u-flat">
|
||||
<at-input-label></at-input-label>
|
||||
<div class="checkbox at-InputCheckbox">
|
||||
<input type="checkbox"
|
||||
ng-class="{ 'at-Input--rejected': state.rejected }"
|
||||
ng-model="state._value"
|
||||
ng-attr-tabindex="{{ tab || undefined }}"
|
||||
ng-change="vm.check()"
|
||||
ng-disabled="state._disabled || form.disabled" />
|
||||
<label>
|
||||
<input type="checkbox"
|
||||
ng-class="{ 'at-Input--rejected': state.rejected }"
|
||||
ng-model="state._value"
|
||||
ng-attr-tabindex="{{ tab || undefined }}"
|
||||
ng-change="vm.check()"
|
||||
ng-disabled="state._disabled || form.disabled" />
|
||||
<p>{{ label }}</p>
|
||||
</label>
|
||||
</div>
|
||||
<at-input-message></at-input-message>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<input type="checkbox"
|
||||
ng-model="state._promptOnLaunch"
|
||||
ng-change="vm.togglePromptOnLaunch()" />
|
||||
<p>Prompt on launch?</p>
|
||||
<p>Prompt on launch</p>
|
||||
</label>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
@@ -26,6 +26,7 @@ function AtInputSecretController (baseInputController) {
|
||||
vm.toggle = vm.toggleShowHide;
|
||||
} else {
|
||||
scope.state._buttonText = 'REPLACE';
|
||||
scope.state._placeholder = 'ENCRYPTED';
|
||||
vm.toggle = vm.toggleRevertReplace;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<at-input-label></at-input-label>
|
||||
|
||||
<div class="input-group">
|
||||
<span class="input-group-btn">
|
||||
<span class="input-group-btn at-InputGroup-button">
|
||||
<button class="btn at-ButtonHollow--white at-Input-button"
|
||||
ng-disabled="!state._enableToggle && (state._disabled || form.disabled)"
|
||||
ng-click="vm.toggle()">
|
||||
@@ -16,7 +16,7 @@
|
||||
ng-class="{ 'at-Input--rejected': state._rejected }"
|
||||
ng-attr-maxlength="{{ state.max_length || undefined }}"
|
||||
ng-attr-tabindex="{{ tab || undefined }}"
|
||||
ng-attr-placeholder="{{::state._placeholder || undefined }}"
|
||||
ng-attr-placeholder="{{state._placeholder || undefined }}"
|
||||
ng-change="vm.check()"
|
||||
ng-disabled="state._disabled || form.disabled" />
|
||||
</div>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -18,9 +18,10 @@
|
||||
<textarea class="form-control at-Input at-InputTextarea"
|
||||
ng-model="state[state._activeModel]"
|
||||
ng-class="{ 'at-Input--rejected': state._rejected }"
|
||||
ng-attr-rows="{{::state._rows || 6 }}"
|
||||
ng-attr-maxlength="{{ state.max_length || undefined }}"
|
||||
ng-attr-tabindex="{{ tab || undefined }}"
|
||||
ng-attr-placeholder="{{::state._placeholder || undefined }}"
|
||||
ng-attr-placeholder="{{state._placeholder || undefined }}"
|
||||
ng-change="vm.check()"
|
||||
ng-disabled="state._disabled || form.disabled" />
|
||||
</textarea>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<textarea class="form-control at-Input at-InputTextarea"
|
||||
ng-model="state._value"
|
||||
ng-class="{ 'at-Input--rejected': state._rejected }"
|
||||
ng-attr-rows="{{::state._rows || 6 }}"
|
||||
ng-attr-maxlength="{{ state.max_length || undefined }}"
|
||||
ng-attr-tabindex="{{ tab || undefined }}"
|
||||
ng-attr-placeholder="{{::state._placeholder || undefined }}"
|
||||
|
||||
@@ -21,4 +21,5 @@
|
||||
|
||||
.at-Panel-headingTitle {
|
||||
.at-mixin-Heading(@at-font-size-3x);
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<div class="at-Panel-dismiss">
|
||||
<i class="fa fa-times fa-lg" ng-click="dismiss()"></i>
|
||||
<i class="fa fa-times-circle fa-lg" ng-click="dismiss()"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
}
|
||||
|
||||
.at-Popover-title {
|
||||
.at-mixin-Heading(@at-font-size-2x);
|
||||
.at-mixin-Heading(@at-font-size);
|
||||
color: @at-white;
|
||||
margin-bottom: @at-space-4x;
|
||||
}
|
||||
@@ -47,5 +47,5 @@
|
||||
.at-Popover-text {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
line-height: 1;
|
||||
font-size: @at-font-size;
|
||||
}
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
|
||||
.at-Tab {
|
||||
margin: 0 @at-space-5x 0 0;
|
||||
font-size: @at-font-size;
|
||||
}
|
||||
|
||||
.at-Tab--active {
|
||||
&, &:hover, &:active, &:focus {
|
||||
color: @at-white;
|
||||
background-color: @at-gray-dark-2x;
|
||||
border-color: @at-gray-dark-2x;
|
||||
background-color: @at-gray-dark-3x;
|
||||
border-color: @at-gray-dark-3x;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
@@ -18,8 +19,8 @@
|
||||
.at-Tab--disabled {
|
||||
&, &:hover, &:active, &:focus {
|
||||
background-color: @at-white;
|
||||
color: @at-gray-dark-3x;
|
||||
border-color: @at-gray-dark-3x;
|
||||
color: @at-gray-dark-2x;
|
||||
border-color: @at-gray-dark-2x;
|
||||
opacity: 0.65;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
@@ -128,10 +128,17 @@ function normalizePath (resource) {
|
||||
return `${version}${resource}/`;
|
||||
}
|
||||
|
||||
function getById (id) {
|
||||
let item = this.get('results').filter(result => result.id === id);
|
||||
|
||||
return item ? item[0] : undefined;
|
||||
}
|
||||
|
||||
function BaseModel (path) {
|
||||
this.model = {};
|
||||
this.get = get;
|
||||
this.normalizePath = normalizePath;
|
||||
this.getById = getById;
|
||||
this.request = request;
|
||||
this.http = {
|
||||
get: httpGet.bind(this),
|
||||
|
||||
@@ -26,18 +26,11 @@ function mergeInputProperties (type) {
|
||||
});
|
||||
}
|
||||
|
||||
function getById (id) {
|
||||
let type = this.get('results').filter(type => type.id === id);
|
||||
|
||||
return type ? type[0] : undefined;
|
||||
}
|
||||
|
||||
function CredentialTypeModel (method, id) {
|
||||
BaseModel.call(this, 'credential_types');
|
||||
|
||||
this.categorizeByKind = categorizeByKind.bind(this);
|
||||
this.mergeInputProperties = mergeInputProperties.bind(this);
|
||||
this.getById = getById.bind(this);
|
||||
|
||||
return this.request(method, id)
|
||||
.then(() => this);
|
||||
|
||||
18
awx/ui/client/lib/models/Organization.js
Normal file
18
awx/ui/client/lib/models/Organization.js
Normal file
@@ -0,0 +1,18 @@
|
||||
let BaseModel;
|
||||
|
||||
function OrganizationModel (method) {
|
||||
BaseModel.call(this, 'organizations');
|
||||
|
||||
return this.request(method)
|
||||
.then(() => this);
|
||||
}
|
||||
|
||||
function OrganizationModelLoader (_BaseModel_) {
|
||||
BaseModel = _BaseModel_;
|
||||
|
||||
return OrganizationModel;
|
||||
}
|
||||
|
||||
OrganizationModelLoader.$inject = ['BaseModel'];
|
||||
|
||||
export default OrganizationModelLoader;
|
||||
@@ -2,11 +2,13 @@ import Base from './Base';
|
||||
import Credential from './Credential';
|
||||
import CredentialType from './CredentialType';
|
||||
import Me from './Me';
|
||||
import Organization from './Organization';
|
||||
|
||||
angular
|
||||
.module('at.lib.models', [])
|
||||
.service('BaseModel', Base)
|
||||
.service('CredentialModel', Credential)
|
||||
.service('CredentialTypeModel', CredentialType)
|
||||
.service('MeModel', Me);
|
||||
.service('MeModel', Me)
|
||||
.service('OrganizationModel', Organization);
|
||||
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
.at-Button--green {
|
||||
.at-mixin-Button();
|
||||
.at-mixin-ButtonColor('at-green', 'at-white');
|
||||
|
||||
&[disabled] {
|
||||
background: @at-gray-dark;
|
||||
}
|
||||
}
|
||||
|
||||
.at-Button--blue {
|
||||
@@ -25,6 +29,7 @@
|
||||
.at-ButtonHollow--white {
|
||||
.at-mixin-Button();
|
||||
.at-mixin-ButtonHollow('at-gray-dark-3x', 'at-gray-dark-2x');
|
||||
border-color: @at-gray-dark;
|
||||
}
|
||||
|
||||
.at-ButtonIcon {
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
.at-mixin-Button () {
|
||||
height: @at-input-height;
|
||||
padding: @at-space-2x @at-space-4x;
|
||||
font-size: @at-font-size;
|
||||
}
|
||||
|
||||
.at-mixin-ButtonColor (@background, @color, @hover: '@{background}--hover') {
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
@at-font-weight-3x: 900;
|
||||
|
||||
@at-line-height-short: 0.9;
|
||||
@at-line-height-tall: 2;
|
||||
@at-line-height: 24px;
|
||||
|
||||
// 3. Layout --------------------------------------------------------------------------------------
|
||||
@@ -68,3 +69,4 @@
|
||||
@at-border-radius: 5px;
|
||||
@at-popover-width: 320px;
|
||||
@at-inset-width: 5px;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user