From 8cdbaa83b2a50393821bedae00060ca15fd32fb0 Mon Sep 17 00:00:00 2001 From: chouseknecht Date: Fri, 6 Sep 2013 00:41:22 -0400 Subject: [PATCH] Latest UI changes. --- awx/ui/static/js/config.js | 12 +++-- awx/ui/static/js/controllers/Inventories.js | 4 +- awx/ui/static/js/controllers/Jobs.js | 6 +-- awx/ui/static/js/controllers/Projects.js | 50 ++++++++++++-------- awx/ui/static/js/forms/Jobs.js | 2 +- awx/ui/static/js/helpers/Events.js | 13 +++--- awx/ui/static/js/helpers/search.js | 4 +- awx/ui/static/js/lists/Inventories.js | 8 ++-- awx/ui/static/js/lists/Projects.js | 4 +- awx/ui/static/less/ansible-ui.less | 4 ++ awx/ui/static/lib/ansible/directives.js | 2 +- awx/ui/static/lib/ansible/form-generator.js | 29 ++++++++---- awx/ui/static/lib/ansible/pwdmeter.js | 51 ++++++--------------- awx/ui/templates/ui/index.html | 4 +- 14 files changed, 98 insertions(+), 95 deletions(-) diff --git a/awx/ui/static/js/config.js b/awx/ui/static/js/config.js index 9669af7652..b25166ecf3 100644 --- a/awx/ui/static/js/config.js +++ b/awx/ui/static/js/config.js @@ -15,6 +15,12 @@ var $AnsibleConfig = tooltip_delay: {show: 500, hide: 100}, // Default number of milliseconds to delay displaying/hiding tooltips - debug_mode: true // Enable console logging messages - -} + debug_mode: true, // Enable console logging messages + + password_strength: 45 // User password strength. Integer between 0 and 100, 100 being impossibly strong. + // This value controls progress bar colors: + // 0 to password_strength - 15 = red; + // password_strength - 15 to password_strength = yellow + // > password_strength = green + // It also controls password validation. Passwords are rejected if the score is not > password_strength. + } diff --git a/awx/ui/static/js/controllers/Inventories.js b/awx/ui/static/js/controllers/Inventories.js index c1383c9231..9e24b7da36 100644 --- a/awx/ui/static/js/controllers/Inventories.js +++ b/awx/ui/static/js/controllers/Inventories.js @@ -75,11 +75,11 @@ function InventoriesList ($scope, $rootScope, $location, $log, $routeParams, Res // Failed jobs link. Go to the jobs tabs, find all jobs for the inventory and sort by status scope.viewJobs = function(id) { - $location.url('/jobs/?inventory__int=' + id + '&order_by=status'); + $location.url('/jobs/?inventory__int=' + id); } scope.viewFailedJobs = function(id) { - $location.url('/jobs/?inventory__int=' + id + '&status=failed&order_by=status'); + $location.url('/jobs/?inventory__int=' + id + '&status=failed'); } scope.editHosts = function(id) { diff --git a/awx/ui/static/js/controllers/Jobs.js b/awx/ui/static/js/controllers/Jobs.js index 8ef251b965..fb09b5f8d7 100644 --- a/awx/ui/static/js/controllers/Jobs.js +++ b/awx/ui/static/js/controllers/Jobs.js @@ -63,12 +63,8 @@ function JobsListCtrl ($scope, $rootScope, $location, $log, $routeParams, Rest, scope[list.iterator + 'SearchValue'] = $routeParams['id__int']; scope[list.iterator + 'SearchFieldLabel'] = 'Job ID'; } - scope.search(list.iterator); - // Called from Inventories page, failed jobs link. Now sort by status so faild jobs appear at top of list - //if ($routeParams.order_by) { - // scope.sort($routeParams.order_by); - //} + scope.search(list.iterator); LoadBreadCrumbs(); diff --git a/awx/ui/static/js/controllers/Projects.js b/awx/ui/static/js/controllers/Projects.js index b2c17745c4..564554e824 100644 --- a/awx/ui/static/js/controllers/Projects.js +++ b/awx/ui/static/js/controllers/Projects.js @@ -58,26 +58,38 @@ function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest, } scope.showSCMStatus = function(id) { - var project; - for (var i=0; i < scope.projects.length; i++) { - if (scope.projects[i].id == id) { - project = scope.projects[i]; - break; + // Refresh the project list + var statusCheckRemove = scope.$on('PostRefresh', function() { + var project; + for (var i=0; i < scope.projects.length; i++) { + if (scope.projects[i].id == id) { + project = scope.projects[i]; + break; + } } - } - if (project.scm_type !== null) { - if (project.related.last_update !== undefined) { - ProjectStatus({ project_id: id, last_update: project.related.last_update }); - } - else { - Alert('No Updates Available', 'There is no SCM update information available for this project. An update has not yet been ' + - ' completed. If you have not already done so, start an update for this project.', 'alert-info'); - } - } - else { - Alert('Missing SCM Configuration', 'The selected project is not configured for SCM. You must first edit the project, provide SCM settings, ' + - 'and then start an update.', 'alert-info'); - } + if (project.scm_type !== null) { + if (project.related.last_update !== undefined && project.status !== 'updating') { + ProjectStatus({ project_id: id, last_update: project.related.last_update }); + } + else if (project.status == 'updating') { + Alert('Pending Status', 'An update is currently running. Status details cannot be viewed until the update process ' + + ' completes. Use the refresh button to monitor progress of the update proess.', 'alert-info'); + } + else { + Alert('No Updates Available', 'There is no SCM update information available for this project. An update has not yet been ' + + ' completed. If you have not already done so, start an update for this project.', 'alert-info'); + } + } + else { + Alert('Missing SCM Configuration', 'The selected project is not configured for SCM. You must first edit the project, provide SCM settings, ' + + 'and then run an update.', 'alert-info'); + } + statusCheckRemove(); + }); + + // Refresh the project list so we're looking at the latest data + scope.search(list.iterator); + } scope.deleteProject = function(id, name) { diff --git a/awx/ui/static/js/forms/Jobs.js b/awx/ui/static/js/forms/Jobs.js index 23b4326781..fcd2636df5 100644 --- a/awx/ui/static/js/forms/Jobs.js +++ b/awx/ui/static/js/forms/Jobs.js @@ -279,7 +279,7 @@ angular.module('JobFormDefinition', []) label: 'Refresh', icon: 'icon-refresh', ngClick: "refresh()", - "class": 'btn-sm btn-success', + "class": 'btn-sm btn-primary', awToolTip: 'Refresh job status & output', mode: 'all' }, diff --git a/awx/ui/static/js/helpers/Events.js b/awx/ui/static/js/helpers/Events.js index 9e6e909496..3e70433653 100644 --- a/awx/ui/static/js/helpers/Events.js +++ b/awx/ui/static/js/helpers/Events.js @@ -273,19 +273,18 @@ angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefini scope.formModalInfoAction = function() { var generator = GenerateForm; var scope = generator.inject(JobEventDataForm, { mode: 'edit', modal: true, related: false, - modal_selector: '#form-modal2', modal_body_id: 'form-modal2-body' }); + modal_selector: '#form-modal2', modal_body_id: 'form-modal2-body', modal_title_id: 'formModal2Header' }); generator.reset(); + scope.formModal2Header = data['event_display'].replace(/^\u00a0*/g,''); + scope.event_data = JSON.stringify(data['event_data'], null, '\t'); + scope.formModal2ActionLabel = 'OK'; + scope.formModal2CancelShow = false; + scope.formModal2Info = false; scope.formModalInfo = 'View JSON'; scope.formModal2Action = function() { $('#form-modal2').modal("hide"); } - scope.formModal2ActionLabel = 'OK'; - scope.formModal2CancelShow = false; - scope.formModal2Info = false; $('#form-modal2 .btn-success').removeClass('btn-success').addClass('btn-none'); - //$('#form-modal2').addClass('skinny-modal'); - scope.formModal2Header = data['event_display'].replace(/^\u00a0*/g,''); - scope.event_data = JSON.stringify(data['event_data'], null, '\t'); } if (typeof data['event_data']['res'] == 'string') { diff --git a/awx/ui/static/js/helpers/search.js b/awx/ui/static/js/helpers/search.js index 8f0ad7b02b..6bf83023f0 100644 --- a/awx/ui/static/js/helpers/search.js +++ b/awx/ui/static/js/helpers/search.js @@ -24,8 +24,8 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) var defaultUrl = params.url; var list = params.list; var iterator = (params.iterator) ? params.iterator : list.iterator; - var sort_order; - + var sort_order; + // Set default values for (fld in list.fields) { if (list.fields[fld].key) { diff --git a/awx/ui/static/js/lists/Inventories.js b/awx/ui/static/js/lists/Inventories.js index 07e81dea93..76fcd645ac 100644 --- a/awx/ui/static/js/lists/Inventories.js +++ b/awx/ui/static/js/lists/Inventories.js @@ -23,7 +23,9 @@ angular.module('InventoriesListDefinition', []) key: true, label: 'Name', badgeIcon: "\{\{ 'icon-failures-' + inventory.has_active_failures \}\}", - badgePlacement: 'left' + badgePlacement: 'left', + badgeToolTip: 'Inventory contains hosts with active failures', + badgeTipPlacement: 'bottom' }, description: { label: 'Description' @@ -52,10 +54,10 @@ angular.module('InventoriesListDefinition', []) dropdown: { type: 'DropDown', - label: 'View', + label: 'Jobs', 'class': 'btn-xs', options: [ - { ngClick: 'viewJobs(\{\{ inventory.id \}\})', label: 'Jobs' }, + { ngClick: 'viewJobs(\{\{ inventory.id \}\})', label: 'All Jobs' }, { ngClick: "viewFailedJobs(\{\{ inventory.id \}\})", label: 'Failed jobs' } ] }, diff --git a/awx/ui/static/js/lists/Projects.js b/awx/ui/static/js/lists/Projects.js index 899ec9ba05..4b1128f579 100644 --- a/awx/ui/static/js/lists/Projects.js +++ b/awx/ui/static/js/lists/Projects.js @@ -67,7 +67,7 @@ angular.module('ProjectsListDefinition', []) dataContainer: 'body', icon: "icon-question-sign", mode: 'all', - 'class': 'btn-xs btn-info btn-help', + 'class': 'btn-xs btn-info btn-help pull-right', awToolTip: 'Click for help', dataTitle: 'Project Status', iconSize: 'large', @@ -76,7 +76,6 @@ angular.module('ProjectsListDefinition', []) }, fieldActions: { - edit: { label: 'Edit', ngClick: "editProject(\{\{ project.id \}\})", @@ -98,7 +97,6 @@ angular.module('ProjectsListDefinition', []) ngClick: 'SCMUpdate(\{\{ project.id \}\})', awToolTip: 'Perform an SCM update on this project' }, - "delete": { label: 'Delete', ngClick: "deleteProject(\{\{ project.id \}\},'\{\{ project.name \}\}')", diff --git a/awx/ui/static/less/ansible-ui.less b/awx/ui/static/less/ansible-ui.less index d1505e02ef..0f43c4470a 100644 --- a/awx/ui/static/less/ansible-ui.less +++ b/awx/ui/static/less/ansible-ui.less @@ -59,6 +59,10 @@ body { opacity: .4; } +.popover { + z-index: 2000; +} + .tooltip { z-index: 1050; } diff --git a/awx/ui/static/lib/ansible/directives.js b/awx/ui/static/lib/ansible/directives.js index 6ad1e07279..c3beba37d0 100644 --- a/awx/ui/static/lib/ansible/directives.js +++ b/awx/ui/static/lib/ansible/directives.js @@ -360,7 +360,7 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Hos var validity = true; var score = chkPass(elm.val()); if (elm.val()) { - validity = (score > 67) ? true : false; + validity = (score > $AnsibleConfig.password_strength) ? true : false; } ctrl.$setValidity('complexity', validity); if (!scope.$$phase) { diff --git a/awx/ui/static/lib/ansible/form-generator.js b/awx/ui/static/lib/ansible/form-generator.js index 24fe19d4b5..407367cb0d 100644 --- a/awx/ui/static/lib/ansible/form-generator.js +++ b/awx/ui/static/lib/ansible/form-generator.js @@ -90,10 +90,15 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies']) if (options.modal) { this.scope.formModalActionDisabled = false; - if (form) { - this.scope.formModalHeader = (options.mode == 'add') ? form.addTitle : form.editTitle; //Default title for default modal - } this.scope.formModalInfo = false //Disable info button for default modal + if (form) { + if (options.modal_title_id) { + this.scope[options.modal_title_id] = (options.mode == 'add') ? form.addTitle : form.editTitle; + } + else { + this.scope.formModalHeader = (options.mode == 'add') ? form.addTitle : form.editTitle; //Default title for default modal + } + } if (options.modal_selector) { $(options.modal_selector).modal({ show: true, backdrop: 'static', keyboard: true }); $(options.modal_selector).on('shown.bs.modal', function() { @@ -434,23 +439,29 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies']) if (field.chkPass) { html += "
Password must meet minimum complexity
\n"; + ".$error.complexity\">Password must be stronger\n"; html += "
\n"; html += "
\n"; html += "
\n"; html += "
\n"; - html += "

Password strength requirements:

"; + html += "
\n"; + html += "
Password Strength
\n"; + html += "
\n"; + html += "

A password with reasonable strength is required. As you type the password " + + "a progress bar will measure the strength. Sufficient strength is reached when the bar turns green.

" + + "

Password strength is judged using the following:

"; html += "
    \n"; html += "
  • Minimum 8 characters in length
  • \n"; - html += "
  • Contains 3/4 of the following items:\n"; + html += "
  • Contains a sufficient combination of the following items:\n"; html += "
      \n"; html += "
    • UPPERCASE letters
    • \n"; - html += "
    • lowercase letters
    • \n"; html += "
    • Numbers
    • \n"; - html += "
    • Symbols !@#$%^&*()
    • \n"; + html += "
    • Symbols _!@#$%^&*()
    • \n"; html += "
    \n"; html += "
  • \n"; - html += "
\n"; + html += "\n"; + html += "
\n"; + html += "
\n"; html += "
\n"; } diff --git a/awx/ui/static/lib/ansible/pwdmeter.js b/awx/ui/static/lib/ansible/pwdmeter.js index 69e6edd58a..535b53d587 100644 --- a/awx/ui/static/lib/ansible/pwdmeter.js +++ b/awx/ui/static/lib/ansible/pwdmeter.js @@ -1,8 +1,8 @@ /* ** Created by: Jeff Todnem (http://www.todnem.com/) ** Created on: 2007-08-14 -** Last modified: 2013-07-31 by James Cammarata -** +** Modified: 2013-07-31 by James Cammarata +** ** License Information: ** ------------------------------------------------------------------------- ** Copyright (C) 2007 Jeff Todnem @@ -20,35 +20,9 @@ ** You should have received a copy of the GNU General Public License along ** with this program; if not, write to the Free Software Foundation, Inc., ** 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -** -*/ - -/* -function addLoadEvent(func) { - var oldonload = window.onload; - if (typeof window.onload != "function") { - window.onload = func; - } - else { - window.onload = function() { - if (oldonload) { - oldonload(); - } - func(); - }; - } -} - -function $() { - var arrElms = []; - for (var i=0; i < arguments.length; i++) { - var elm = arguments[i]; - if (typeof(elm == "string")) { elm = document.getElementById(elm); } - if (arguments.length == 1) { return elm; } - arrElms.push(elm); - } - return arrElms; -} +** +** +** CLH 9/5/13 - Set required strength in config.js */ String.prototype.strReverse = function() { @@ -57,8 +31,6 @@ String.prototype.strReverse = function() { newstring = this.charAt(s) + newstring; } return newstring; - //strOrig = ' texttotrim '; - //strReversed = strOrig.revstring(); }; var nScore = 0; @@ -80,7 +52,7 @@ function chkPass(pwd) { sConsecNumber="0", sSeqAlpha="0", sSeqNumber="0", sSeqSymbol="0"; var sAlphas = "abcdefghijklmnopqrstuvwxyz"; var sNumerics = "01234567890"; - var sSymbols = ")!@#$%^&*()"; + var sSymbols = ")_!@#$%^&*()"; var sComplexity = "Too Short"; var sStandards = "Below"; var nMinPwdLen = 8; @@ -225,17 +197,20 @@ function chkPass(pwd) { if (nScore > 100) { nScore = 100; } else if (nScore < 0) { nScore = 0; } var progbar = $("#progbar"); + var required_strength = $AnsibleConfig.password_strength; + var warning_level = ($AnsibleConfig.password_strength - 15 < 0) ? 0 : $AnsibleConfig.password_strength - 15; + progbar.css("width", nScore + '%'); - if (nScore >= 0 && nScore <= 33) { + if (nScore >= 0 && nScore <= warning_level) { sComplexity = 'Weak'; progbar.addClass('progress-bar-danger') progbar.removeClass('progress-bar-success progress-bar-warning') - } else if (nScore > 33 && nScore <= 67) { + } else if (nScore > warning_level && nScore <= required_strength) { sComplexity = 'Good'; progbar.addClass('progress-bar-warning') progbar.removeClass('progress-bar-success progress-bar-danger') - } else if (nScore > 67) { + } else if (nScore > required_strength) { sComplexity = "Strong"; progbar.addClass('progress-bar-success') progbar.removeClass('progress-bar-warning progress-bar-danger') @@ -245,7 +220,7 @@ function chkPass(pwd) { /* no password, so reset the displays */ var progbar = $("#progbar"); progbar.css("width", '0%'); - progbar.removeClass('progress-bar-success progress-bar-warning progress-bar-danger') + progbar.removeClass('progress-bar-success progress-bar-warning') } return nScore; } \ No newline at end of file diff --git a/awx/ui/templates/ui/index.html b/awx/ui/templates/ui/index.html index 98d5bbe34e..b00f390717 100644 --- a/awx/ui/templates/ui/index.html +++ b/awx/ui/templates/ui/index.html @@ -240,12 +240,12 @@