Merge pull request #1872 from jaredevantabor/ux-audit

UX Audit items
This commit is contained in:
Jared Tabor 2016-05-10 11:33:09 -04:00
commit 5fd8ac7773
25 changed files with 141 additions and 124 deletions

View File

@ -51,8 +51,8 @@
.Form-title--is_superuser{
height:15px;
color: @btn-txt;
background-color: @btn-bg;
color: @default-interface-txt;
background-color: @default-list-header-bg;
border-radius: 5px;
border: 1px solid @btn-bord;
font-size: 10px;
@ -156,9 +156,19 @@
flex: 1 0 auto;
margin-bottom: 20px;
width: 33%;
max-width: 33%;
padding-right: 30px;
}
.Form-formGroup--fullWidth {
max-width: none;
}
.Form-formGroup--checkbox{
display: flex;
align-items: flex-end;
}
.Form-subForm {
width: 100%;
margin-bottom: 15px;
@ -211,12 +221,17 @@
border:1px solid @field-border-sel;
}
.Form-monospace{
font-family: Menlo,Monaco,Consolas,"Courier New",monospace!important;
}
.ui-spinner{
height: 30px;
background-color: @field-secondary-bg;
border-radius: 5px;
border:1px solid @field-border;
color: @field-input-text;
width:100%
}
.ui-spinner-input{
@ -480,10 +495,6 @@ input[type='radio']:checked:before {
color: @default-interface-txt;
}
.Form-formGroup {
max-width: 33%;
}
@media only screen and (max-width: 650px) {
.Form-formGroup {
flex: 1 0 auto;

View File

@ -233,6 +233,7 @@ var tower = angular.module('Tower', [
url: '/home',
templateUrl: urlPrefix + 'partials/home.html',
controller: Home,
params: {licenseMissing: null},
data: {
activityStream: true
},
@ -789,6 +790,10 @@ var tower = angular.module('Tower', [
if (fromState.name === 'signIn'){
CheckLicense.notify();
}
if(fromState.name === 'license' && toParams.hasOwnProperty('licenseMissing')){
$rootScope.licenseMissing = toParams.licenseMissing;
}
var list, id;
// broadcast event change if editing crud object
if ($location.$$path && $location.$$path.split("/")[3] && $location.$$path.split("/")[3] === "schedules") {

View File

@ -79,24 +79,7 @@ export default
dataTitle: 'Type',
dataPlacement: 'right',
dataContainer: "body",
hasSubForm: true,
// helpCollapse: [{
// hdr: 'Select a Credential Type',
// content: '<dl>\n' +
// '<dt>Machine</dt>\n' +
// '<dd>Authentication for remote machine access. This can include SSH keys, usernames, passwords, ' +
// 'and sudo information. Machine credentials are used when submitting jobs to run playbooks against ' +
// 'remote hosts.</dd>' +
// '<dt>Source Control</dt>\n' +
// '<dd>Used to check out and synchronize playbook repositories with a remote source control ' +
// 'management system such as Git, Subversion (svn), or Mercurial (hg). These credentials are ' +
// 'used on the Projects tab.</dd>\n' +
// '<dt>Others (Cloud Providers)</dt>\n' +
// '<dd>Access keys for authenticating to the specific ' +
// 'cloud provider, usually used for inventory sync ' +
// 'and deployment.</dd>\n' +
// '</dl>\n'
// }]
hasSubForm: true
},
access_key: {
label: 'Access Key',
@ -254,7 +237,8 @@ export default
reqExpression: 'key_required',
init: true
},
class: 'Form-textAreaLabel',
class: 'Form-textAreaLabel Form-formGroup--fullWidth',
elementClass: 'Form-monospace',
hintText: "{{ key_hint }}",
addRequired: false,
editRequired: false,

View File

@ -38,7 +38,7 @@ export default
variables: {
label: 'Variables',
type: 'textarea',
class: 'Form-textAreaLabel',
class: 'Form-textAreaLabel Form-formGroup--fullWidth',
addRequired: false,
editRequird: false,
rows: 12,
@ -161,7 +161,7 @@ export default
label: 'Environment Variables', //"{{vars_label}}" ,
ngShow: "source && source.value=='custom' ",
type: 'textarea',
class: 'Form-textAreaLabel',
class: 'Form-textAreaLabel Form-formGroup--fullWidth',
addRequired: false,
editRequired: false,
rows: 6,
@ -180,7 +180,7 @@ export default
label: 'Source Variables', //"{{vars_label}}" ,
ngShow: "source && (source.value == 'file' || source.value == 'ec2')",
type: 'textarea',
class: 'Form-textAreaLabel',
class: 'Form-textAreaLabel Form-formGroup--fullWidth',
addRequired: false,
editRequird: false,
rows: 6,
@ -207,7 +207,7 @@ export default
"source.value == 'openstack')",
type: 'textarea',
addRequired: false,
class: 'Form-textAreaLabel',
class: 'Form-textAreaLabel Form-formGroup--fullWidth',
editRequird: false,
rows: 6,
'default': '---',

View File

@ -49,6 +49,7 @@ export default
variables: {
label: 'Variables',
type: 'textarea',
class: 'Form-formGroup--fullWidth',
addRequired: false,
editRequird: false,
rows: 6,

View File

@ -239,7 +239,7 @@ export default
variables: {
label: 'Extra Variables',
type: 'textarea',
class: 'Form-textAreaLabel',
class: 'Form-textAreaLabel Form-formGroup--fullWidth',
rows: 6,
addRequired: false,
editRequired: false,

View File

@ -49,7 +49,6 @@ export default
script: scope.script
})
.success(function (data) {
$rootScope.addedItem = data.id;
$state.go('inventoryScripts', {}, {reload: true});
Wait('stop');
})

View File

@ -79,9 +79,8 @@ export default
script: $scope.script
})
.success(function () {
$state.transitionTo('inventoryScriptsList');
$state.transitionTo('inventoryScripts');
Wait('stop');
})
.error(function (data, status) {
ProcessErrors($scope, data, status, form, { hdr: 'Error!',

View File

@ -47,6 +47,8 @@ export default function() {
label: 'Custom Script',
type: 'textarea',
hintText: "Drag and drop an inventory script on the field below",
class: 'Form-formGroup--fullWidth',
elementClass: 'Form-monospace',
addRequired: true,
editRequired: true,
awDropFile: true,

View File

@ -737,7 +737,7 @@ export default
return true;
};
scope.toggleLessEvents = function(state) {
scope.toggleLessEvents = function() {
if (!scope.lessEvents) {
$('#events-summary').slideUp(200);
scope.lessEvents = true;

View File

@ -54,6 +54,7 @@
color: @login-notice-text;
overflow-y: scroll;
overflow-x: visible;
white-space: pre-line;
}
.License-field label{

View File

@ -40,33 +40,36 @@ export default
$window.open('https://www.ansible.com/license', '_blank');
};
$scope.newLicense = {};
$scope.submit = function(){
Wait('start');
CheckLicense.post($scope.newLicense.file, $scope.newLicense.eula)
.success(function(){
reset();
init();
$scope.success = true;
// for animation purposes
var successTimeout = setTimeout(function(){
$scope.success = false;
clearTimeout(successTimeout);
}, 4000);
if($rootScope.licenseMissing === true){
$rootScope.licenseMissing = false;
$state.go('dashboard');
}
else{
$rootScope.licenseMissing = false;
}
});
};
var calcDaysRemaining = function(seconds){
// calculate the number of days remaining on the license
var duration = moment.duration(seconds, 'seconds');
return duration.days();
};
$scope.newLicense = {};
$scope.submit = function(){
Wait('start');
CheckLicense.post($scope.newLicense.file, $scope.newLicense.eula)
.success(function(){
reset();
init();
if($rootScope.licenseMissing === true){
$state.go('dashboard', {
licenseMissing: false
});
}
else{
$scope.success = true;
$rootScope.licenseMissing = false;
// for animation purposes
var successTimeout = setTimeout(function(){
$scope.success = false;
clearTimeout(successTimeout);
}, 4000);
}
});
};
var calcDaysRemaining = function(seconds){
// calculate the number of days remaining on the license
var duration = moment.duration(seconds, 'seconds').days();
duration = (duration!==1) ? `${duration} Days` : `${duration} Day`;
return duration;
};
var calcExpiresOn = function(days){
// calculate the expiration date of the license

View File

@ -44,7 +44,7 @@
<div class="License-field">
<div class="License-field--label">Time Remaining</div>
<div class="License-field--content">
{{time.remaining}} Days
{{time.remaining}}
</div>
</div>
<div class="License-field">
@ -106,9 +106,7 @@
<div class="License-subTitleText prepend-asterisk"> End User License Agreement
</div>
<div id="eula_notice"
class="License-eulaNotice">
{{ license.eula }}
</div>
class="License-eulaNotice">{{ license.eula }}</div>
<div class="form-group License-detailsGroup">
<div class="checkbox">
<label class="License-details--label">

View File

@ -7,16 +7,14 @@
// import listGenerator from 'tower/shared/list-generator/main';
export default
[ 'Wait', '$location' , '$compile', 'CreateDialog',
'GetBasePath' , 'SearchInit' , 'PaginateInit',
'SchedulesList',
'Rest' , 'ProcessErrors', 'managementJobsListObject', '$rootScope',
'$state','$scope',
function( Wait, $location, $compile, CreateDialog,
GetBasePath, SearchInit, PaginateInit,
SchedulesList,
Rest, ProcessErrors, managementJobsListObject, $rootScope,
$state, $scope) {
[ 'Wait', '$location' , '$compile', 'CreateDialog', 'GetBasePath' ,
'SearchInit' , 'PaginateInit', 'SchedulesList', 'Rest' ,
'ProcessErrors', 'managementJobsListObject', '$rootScope', '$state',
'$scope', 'CreateSelect2',
function( Wait, $location, $compile, CreateDialog, GetBasePath,
SearchInit, PaginateInit, SchedulesList, Rest, ProcessErrors,
managementJobsListObject, $rootScope, $state, $scope,
CreateSelect2) {
var defaultUrl = GetBasePath('system_job_templates');
@ -154,6 +152,14 @@ export default
// $('#configure-tower-dialog').dialog('close');
$('#prompt-for-days-facts').show();
$('#prompt-for-days-facts').dialog('open');
CreateSelect2({
element: '#keep_unit',
multiple: false
});
CreateSelect2({
element: '#granularity_keep_unit',
multiple: false
});
Wait('stop');
});
};
@ -238,7 +244,7 @@ export default
};
$scope.chooseRunJob = function(id, name) {
if(id === 4) {
if(this.card.job_type === "cleanup_facts") {
// Run only for 'Cleanup Fact Details'
$scope.submitCleanupJob(id, name);
} else {

View File

@ -16,17 +16,20 @@
<h3 class="MgmtCards-label"> {{ card.name }}</h3>
<div class="MgmtCards-actionItems">
<button class="MgmtCards-actionItem List-actionButton"
ng-click='goToNotifications(card, card.id)'>
<i class="MgmtCards-actionItemIcon fa fa-bell-o"></i>
</button>
<button class="MgmtCards-actionItem List-actionButton"
ng-click='chooseRunJob(card.id, card.name)'>
ng-click='chooseRunJob(card.id, card.name)'
data-placement="top" aw-tool-tip="Launch Management Job" data-original-title="" title="">
<i class="MgmtCards-actionItemIcon fa fa-rocket"></i>
</button>
<button class="MgmtCards-actionItem List-actionButton"
ng-click='configureSchedule(card.id)'>
ng-click='configureSchedule(card.id)'
data-placement="top" aw-tool-tip="Schedule Management Job" data-original-title="" title="">
<i class="MgmtCards-actionItemIcon fa fa-calendar"></i>
</button>
<button class="MgmtCards-actionItem List-actionButton"
ng-click='goToNotifications(card, card.id)'
data-placement="top" aw-tool-tip="Configure Notifications" data-original-title="" title="">
<i class="MgmtCards-actionItemIcon fa fa-bell-o"></i>
</button>
</div>
</div>
<!-- End Card Header -->

View File

@ -22,6 +22,14 @@
border-left: 5px solid #337AB7;
}
.MgmtCards-card--promptElements{
padding-top: 10px;
}
.MgmtCards-promptText{
color:@default-interface-txt;
}
.MgmtCards-header {
display: flex;
flex-wrap: nowrap;

View File

@ -23,7 +23,7 @@ export default
view = GenerateList,
id = $stateParams.management_id;
list.listTitle = `${management_job.name} | Notifications`;
list.listTitle = `${management_job.name} <div class="List-titleLockup"></div> Notifications`;
view.inject( list, {
mode: 'edit',
cancelButton: true,

View File

@ -110,8 +110,7 @@ export default
Wait('start');
Rest.setUrl(url);
Rest.post(params)
.success(function (data) {
$rootScope.addedItem = data.id;
.success(function () {
$state.go('notifications', {}, {reload: true});
Wait('stop');
})

View File

@ -81,7 +81,7 @@ export default
master.notification_type = $scope.notification_type;
CreateSelect2({
element: '#notification_template_notification_typex',
element: '#notification_template_notification_type',
multiple: false
});
NotificationsTypeChange.getDetailFields($scope.notification_type.value).forEach(function(field) {
@ -155,8 +155,7 @@ export default
Wait('start');
Rest.setUrl(url+ id+'/');
Rest.put(params)
.success(function (data) {
$rootScope.addedItem = data.id;
.success(function () {
$state.go('notifications', {}, {reload: true});
Wait('stop');
})

View File

@ -24,10 +24,6 @@ export default
scope: scope
});
if (scope.removePostRefresh) {
scope.removePostRefresh();
}
scope.removePostRefresh = scope.$on('PostRefresh', function () {
Wait('stop');
if (scope.notification_templates) {
@ -192,7 +188,7 @@ export default
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
});
};
var bodyHtml = '<div class="Prompt-bodyQuery">Are you sure you want to delete the inventory below?</div><div class="Prompt-bodyTarget">' + name + '</div>';
var bodyHtml = '<div class="Prompt-bodyQuery">Are you sure you want to delete the notification template below?</div><div class="Prompt-bodyTarget">' + name + '</div>';
Prompt({
hdr: 'Delete',
body: bodyHtml,

View File

@ -66,12 +66,7 @@ export default function() {
ngShow: "notification_type.value == 'email' ",
subForm: 'typeSubForm'
},
use_tls: {
label: 'Use TLS',
type: 'checkbox',
ngShow: "notification_type.value == 'email' ",
subForm: 'typeSubForm'
},
host: {
label: 'Host',
type: 'text',
@ -119,12 +114,6 @@ export default function() {
ngShow: "notification_type.value == 'email' || notification_type.value == 'irc' ",
subForm: 'typeSubForm'
},
use_ssl: {
labelBind: 'sslLabel',
type: 'checkbox',
ngShow: "notification_type.value == 'email' || notification_type.value == 'irc' ",
subForm: 'typeSubForm'
},
port: {
labelBind: 'portLabel',
type: 'number',
@ -325,7 +314,8 @@ export default function() {
},
targets: {
label: 'Destination Channels or Users',
type: 'text',
type: 'textarea',
rows: 3,
awPopOver: '<p>Type an option on each line. The pound symbol (#) is not required.</p>'+
'<p>For example:<br>#support or support<br>\n @username or username<br>\n',
dataTitle: 'Destination Channels',
@ -338,6 +328,18 @@ export default function() {
ngShow: "notification_type.value == 'irc' ",
subForm: 'typeSubForm'
},
use_tls: {
label: 'Use TLS',
type: 'checkbox',
ngShow: "notification_type.value == 'email' ",
subForm: 'typeSubForm'
},
use_ssl: {
labelBind: 'sslLabel',
type: 'checkbox',
ngShow: "notification_type.value == 'email' || notification_type.value == 'irc' ",
subForm: 'typeSubForm'
},
},

View File

@ -593,7 +593,7 @@
</ul>
</div>
<div class="form-group Form-formGroup Form-textAreaLabel">
<div class="form-group Form-formGroup Form-textAreaLabel Form-formGroup--fullWidth">
<label for="Scheduler-extraVars">
<span class="Form-inputLabel">
Extra Variables

View File

@ -1,9 +1,9 @@
<section id="htmlTemplate" class="Container">
<div class="SetupMenu">
<a ui-sref="credentials" class="SetupItem">
<h4 class="SetupItem-title">Credentials</h4>
<a ui-sref="organizations" class="SetupItem">
<h4 class="SetupItem-title ">Organizations</h4>
<p class="SetupItem-description">
Add passwords, SSH keys, etc. for Tower to use when launching jobs against machines, or when syncing inventories or projects.
Group all of your content to manage permissions across departments in your company.
</p>
</a>
<a ui-sref="users" class="SetupItem">
@ -18,10 +18,10 @@
Split up your organization to associate content and control permissions for groups.
</p>
</a>
<a ui-sref="organizations" class="SetupItem">
<h4 class="SetupItem-title ">Organizations</h4>
<a ui-sref="credentials" class="SetupItem">
<h4 class="SetupItem-title">Credentials</h4>
<p class="SetupItem-description">
Group all of your content to manage permissions across departments in your company.
Add passwords, SSH keys, etc. for Tower to use when launching jobs against machines, or when syncing inventories or projects.
</p>
</a>
<a ui-sref="managementJobsList" class="SetupItem" ng-if="user_is_superuser">

View File

@ -787,6 +787,7 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
if ((!field.readonly) || (field.readonly && options.mode === 'edit')) {
html += "<div class='form-group Form-formGroup ";
html += (field.type === "checkbox") ? "Form-formGroup--checkbox" : "";
html += (field['class']) ? (field['class']) : "";
html += "'";
html += (field.ngShow) ? this.attr(field, 'ngShow') : "";

View File

@ -157,9 +157,9 @@
<div id="help-modal-dialog" style="display: none;"></div>
<div id="prompt-for-days" style="display:none">
<form name="prompt_for_days_form" id="prompt_for_days_form">
<form name="prompt_for_days_form" id="prompt_for_days_form" class="MgmtCards-promptText">
Set how many days of data should be retained. <br>
<input type="integer" id="days_to_keep" name="days_to_keep" ng-model="days_to_keep" ng-required="true" class="form-control" min=0 max=9999 style="margin-top:10px;" integer>
<input type="integer" id="days_to_keep" name="days_to_keep" ng-model="days_to_keep" ng-required="true" class="form-control Form-textInput" min=0 max=9999 style="margin-top:10px;" integer>
<div class="error" ng-show="prompt_for_days_form.days_to_keep.$dirty && (prompt_for_days_form.days_to_keep.$error.number || prompt_for_days_form.days_to_keep.$error.integer ||
prompt_for_days_form.days_to_keep.$error.required ||
prompt_for_days_form.days_to_keep.$error.min ||
@ -167,7 +167,7 @@
</form>
</div>
<div id="prompt-for-days-facts" style="display:none">
<form name="prompt_for_days_facts_form" id="prompt_for_days_facts_form">
<form name="prompt_for_days_facts_form" id="prompt_for_days_facts_form" class="MgmtCards-promptText">
<div style="padding-bottom:15px;">For facts collected older than the time period specified,
save one fact scan (snapshot) per time window (frequency).
For example, facts older than 30 days are purged, while one
@ -182,11 +182,11 @@
</span>
</label>
<div class="row">
<div class="col-xs-4">
<input type="integer" id="keep_amount" name="keep_amount" ng-model="keep_amount" ng-required="true" class="form-control" min=0 max=9999 style="margin-top:10px;" integer></input>
<div class="col-xs-6">
<input type="integer" id="keep_amount" name="keep_amount" ng-model="keep_amount" ng-required="true" class="form-control Form-textInput MgmtCards-card--promptElements" min=0 max=9999 integer></input>
</div>
<div class="col-xs-4">
<select id="keep_unit" name="keep_unit" ng-model="keep_unit" ng-options="type.label for type in keep_unit_choices track by type.value" ng-required="true" class="form-control" style="margin-top:10px;"></select>
<div class="col-xs-6">
<select id="keep_unit" name="keep_unit" ng-model="keep_unit" ng-options="type.label for type in keep_unit_choices track by type.value" ng-required="true" class="form-control MgmtCards-card--promptElements"></select>
</div>
</div>
<div class="error" ng-show="prompt_for_days_facts_form.keep_amount.$dirty && (prompt_for_days_facts_form.keep_amount.$error.number || prompt_for_days_facts_form.keep_amount.$error.integer ||
@ -201,12 +201,12 @@
</span>
</label>
<div class="row">
<div class="col-xs-4">
<input type="integer" id="granularity_keep_amount" name="granularity_keep_amount" ng-model="granularity_keep_amount" ng-required="true" class="form-control" min=0 max=9999 style="margin-top:10px;" integer></input>
<div class="col-xs-6">
<input type="integer" id="granularity_keep_amount" name="granularity_keep_amount" ng-model="granularity_keep_amount" ng-required="true" class="form-control Form-textInput MgmtCards-card--promptElements" min=0 max=9999 integer></input>
</div>
<div class="col-xs-4">
<div class="col-xs-6">
<select id="granularity_keep_unit" name="granularity_keep_unit" ng-model="granularity_keep_unit"
ng-options="type.label for type in granularity_keep_unit_choices track by type.value" ng-required="true" class="form-control" style="margin-top:10px;"></select>
ng-options="type.label for type in granularity_keep_unit_choices track by type.value" ng-required="true" class="form-control MgmtCards-card--promptElements" ></select>
</div>
</div>
<div class="error" ng-show="prompt_for_days_facts_form.granularity_keep_amount.$dirty && (prompt_for_days_facts_form.granularity_keep_amount.$error.number || prompt_for_days_facts_form.granularity_keep_amount.$error.integer ||