diff --git a/awx/ui/static/js/app.js b/awx/ui/static/js/app.js index 3fd08a0b21..628cef6f76 100644 --- a/awx/ui/static/js/app.js +++ b/awx/ui/static/js/app.js @@ -113,18 +113,18 @@ angular.module('ansible', [ controller: 'JobsListController' }). - when('/jobs/:id', { + /* when('/jobs/:id', { templateUrl: urlPrefix + 'partials/jobs.html', controller: 'JobsEdit' - }). + }). */ when('/jobs/:id/job_events', { - templateUrl: urlPrefix + 'partials/jobs.html', + templateUrl: urlPrefix + 'partials/job_events.html', controller: 'JobEventsList' }). when('/jobs/:id/job_host_summaries', { - templateUrl: urlPrefix + 'partials/jobs.html', + templateUrl: urlPrefix + 'partials/job_host_summaries.html', controller: 'JobHostSummaryList' }). diff --git a/awx/ui/static/js/controllers/Inventories.js b/awx/ui/static/js/controllers/Inventories.js index 5145bc42e1..6429cff4bf 100644 --- a/awx/ui/static/js/controllers/Inventories.js +++ b/awx/ui/static/js/controllers/Inventories.js @@ -189,7 +189,7 @@ function InventoriesList($scope, $rootScope, $location, $log, $routeParams, Rest Prompt({ hdr: 'Delete', - body: 'Are you sure you want to delete ' + name + '?', + body: '
Are you sure you want to delete group ' + node.name + '?
', + body: '" + val + "\n"; + $('#' + id).empty().html(html); + }; + }]) + .factory('EnvTable', [ function() { return function(params) { var id = params.id, diff --git a/awx/ui/static/js/helpers/Variables.js b/awx/ui/static/js/helpers/Variables.js index da6f3a6f04..c01d768fce 100644 --- a/awx/ui/static/js/helpers/Variables.js +++ b/awx/ui/static/js/helpers/Variables.js @@ -3,8 +3,6 @@ * * VariablesHelper * - * Show the CodeMirror variable editor and allow - * toggle between JSON and YAML * */ @@ -35,6 +33,7 @@ angular.module('VariablesHelper', ['Utilities']) $log.info('Attempt to parse extra_vars as JSON failed. Attempting to parse as YAML'); try { json_obj = jsyaml.safeLoad(variables); + json_obj = SortVariables(json_obj); result = jsyaml.safeDump(json_obj); } catch(e2) { diff --git a/awx/ui/static/js/lists/CompletedJobs.js b/awx/ui/static/js/lists/CompletedJobs.js index e39e6efddb..294f8f419b 100644 --- a/awx/ui/static/js/lists/CompletedJobs.js +++ b/awx/ui/static/js/lists/CompletedJobs.js @@ -22,7 +22,7 @@ angular.module('CompletedJobsDefinition', []) fields: { id: { label: 'Job ID', - linkTo: '/#/jobs/{{ completed_job.id }}', + ngClick:"viewJobLog(completed_job.id)", key: true, desc: true, searchType: 'int', @@ -30,13 +30,15 @@ angular.module('CompletedJobsDefinition', []) }, status: { label: 'Status', + columnClass: 'col-md-2 col-sm-2 col-xs-2', awToolTip: "{{ completed_job.status_tip }}", awTipPlacement: "top", dataTitle: "{{ completed_job.status_popover_title }}", icon: 'icon-job-{{ completed_job.status }}', iconOnly: true, - awPopOver: "{{ completed_job.status_popover }}", - dataPlacement: 'right', + ngClick:"viewJobLog(completed_job.id)", + /*awPopOver: "{{ completed_job.status_popover }}", + dataPlacement: 'right',*/ searchType: 'select', searchOptions: [ { name: "Success", value: "successful" }, @@ -50,8 +52,8 @@ angular.module('CompletedJobsDefinition', []) searchType: 'int', searchOnly: true }, - modified: { - label: 'Completed On', + finished: { + label: 'Finished On', link: false, searchable: false, filter: "date:'MM/dd/yy HH:mm:ss'", @@ -66,9 +68,7 @@ angular.module('CompletedJobsDefinition', []) name: { label: 'Name', columnClass: 'col-md-3 col-xs-5', - ngHref: 'nameHref', - sourceModel: 'template', - sourceField: 'name' + ngClick: "viewJobLog(completed_job.id, completed_job.nameHref)" }, failed: { label: 'Job failed?', @@ -85,7 +85,7 @@ angular.module('CompletedJobsDefinition', []) refresh: { mode: 'all', awToolTip: "Refresh the page", - ngClick: "refresh()" + ngClick: "refreshJobs()" } }, @@ -93,8 +93,8 @@ angular.module('CompletedJobsDefinition', []) submit: { icon: 'icon-rocket', mode: 'all', - ngClick: 'relaunch(completed_job.id)', - awToolTip: 'Relaunch the job', + ngClick: 'relaunchJob(completed_job.id)', + awToolTip: 'Relaunch using the same parameters', dataPlacement: 'top' }, "delete": { @@ -105,11 +105,12 @@ angular.module('CompletedJobsDefinition', []) }, dropdown: { type: 'DropDown', + ngShow: "completed_job.type === 'job'", label: 'View', icon: 'fa-search-plus', 'class': 'btn-default btn-xs', options: [ - { ngHref: '/#/jobs/{{ completed_job.id }}', label: 'Status' }, + //{ ngHref: '/#/jobs/{{ completed_job.id }}', label: 'Status' }, { ngHref: '/#/jobs/{{ completed_job.id }}/job_events', label: 'Events', ngHide: "completed_job.status == 'new'" }, { ngHref: '/#/jobs/{{ completed_job.id }}/job_host_summaries', label: 'Host Summary' } ] diff --git a/awx/ui/static/js/lists/JobEvents.js b/awx/ui/static/js/lists/JobEvents.js index ec52f1f173..8050e50d4c 100644 --- a/awx/ui/static/js/lists/JobEvents.js +++ b/awx/ui/static/js/lists/JobEvents.js @@ -21,12 +21,12 @@ angular.module('JobEventsListDefinition', []) filterBy: '{ show: true }', navigationLinks: { - details: { - href: '/#/jobs/{{ job_id }}', - label: 'Status', - icon: 'icon-zoom-in', - ngShow: 'job_id !== null' - }, + //details: { + // href: '/#/jobs/{{ job_id }}', + // label: 'Status', + // icon: 'icon-zoom-in', + // ngShow: 'job_id !== null' + //}, events: { href: '/#/jobs/{{ job_id }}/job_events', label: 'Events', diff --git a/awx/ui/static/js/lists/JobHosts.js b/awx/ui/static/js/lists/JobHosts.js index 025063456b..a78cbf0383 100644 --- a/awx/ui/static/js/lists/JobHosts.js +++ b/awx/ui/static/js/lists/JobHosts.js @@ -20,12 +20,12 @@ angular.module('JobHostDefinition', []) navigationLinks: { ngHide: 'host_id !== null', - details: { - href: "/#/jobs/{{ job_id }}", - label: 'Status', - icon: 'icon-zoom-in', - ngShow: "job_id !== null" - }, + //details: { + // href: "/#/jobs/{{ job_id }}", + // label: 'Status', + // icon: 'icon-zoom-in', + // ngShow: "job_id !== null" + //}, events: { href: "/#/jobs/{{ job_id }}/job_events", label: 'Events', diff --git a/awx/ui/static/js/lists/QueuedJobs.js b/awx/ui/static/js/lists/QueuedJobs.js index 7a4c5cd6db..3ed336d514 100644 --- a/awx/ui/static/js/lists/QueuedJobs.js +++ b/awx/ui/static/js/lists/QueuedJobs.js @@ -22,11 +22,22 @@ angular.module('QueuedJobsDefinition', []) fields: { id: { label: 'Job ID', + ngClick:"viewJobLog(queued_job.id)", key: true, desc: true, searchType: 'int', columnClass: 'col-md-1 col-sm-2 col-xs-2' }, + status: { + label: 'Status', + columnClass: 'col-md-2 col-sm-2 col-xs-2', + awToolTip: "{{ queued_job.status_tip }}", + awTipPlacement: "top", + dataTitle: "{{ queued_job.status_popover_title }}", + icon: 'icon-job-{{ queued_job.status }}', + iconOnly: true, + ngClick:"viewJobLog(queued_job.id)" + }, inventory: { label: 'Inventory ID', searchType: 'int', @@ -48,9 +59,7 @@ angular.module('QueuedJobsDefinition', []) name: { label: 'Name', columnClass: 'col-sm-3 col-xs-5', - ngHref: 'nameHref', - sourceModel: 'template', - sourceField: 'name' + ngClick: "viewJobLog(queued_job.id, queued_job.nameHref)" } }, @@ -59,22 +68,16 @@ angular.module('QueuedJobsDefinition', []) refresh: { mode: 'all', awToolTip: "Refresh the page", - ngClick: "refresh()" + ngClick: "refreshJobs()" } }, fieldActions: { - status: { - mode: 'all', - iconClass: 'fa icon-job-{{ queued_job.status }}', - awToolTip: "{{ queued_job.statusToolTip }}", - dataPlacement: 'top' - }, submit: { icon: 'icon-rocket', mode: 'all', - ngClick: 'relaunch(queued_job.id)', - awToolTip: 'Launch another instance of the job', + ngClick: 'relaunchJob(queued_job.id)', + awToolTip: 'Relaunch using the same parameters', dataPlacement: 'top' }, cancel: { diff --git a/awx/ui/static/js/lists/RunningJobs.js b/awx/ui/static/js/lists/RunningJobs.js index 811afaefd9..83b7605573 100644 --- a/awx/ui/static/js/lists/RunningJobs.js +++ b/awx/ui/static/js/lists/RunningJobs.js @@ -22,18 +22,29 @@ angular.module('RunningJobsDefinition', []) fields: { id: { label: 'Job ID', + ngClick:"viewJobLog(running_job.id)", key: true, desc: true, searchType: 'int', columnClass: 'col-md-1 col-sm-2 col-xs-2' }, + status: { + label: 'Status', + columnClass: 'col-md-2 col-sm-2 col-xs-2', + awToolTip: "{{ running_job.status_tip }}", + awTipPlacement: "top", + dataTitle: "{{ running_job.status_popover_title }}", + icon: 'icon-job-{{ running_job.status }}', + iconOnly: true, + ngClick:"viewJobLog(running_job.id)" + }, inventory: { label: 'Inventory ID', searchType: 'int', searchOnly: true }, - modified: { - label: 'Last Updated', + started: { + label: 'Started On', link: false, searchable: false, filter: "date:'MM/dd/yy HH:mm:ss'", @@ -48,9 +59,7 @@ angular.module('RunningJobsDefinition', []) name: { label: 'Name', columnClass: 'col-md-3 col-xs-5', - ngHref: 'nameHref', - sourceModel: 'template', - sourceField: 'name' + ngClick: "viewJobLog(running_job.id, running_job.nameHref)" } }, @@ -59,25 +68,16 @@ angular.module('RunningJobsDefinition', []) refresh: { mode: 'all', awToolTip: "Refresh the page", - ngClick: "refresh()" + ngClick: "refreshJobs()" } }, fieldActions: { - status: { - mode: 'all', - awToolTip: "{{ running_job.status_tip }}", - awTipPlacement: "top", - dataTitle: "{{ running_job.status_popover_title }}", - iconClass: 'fa icon-job-{{ running_job.status }}', - awPopOver: "{{ running_job.status_popover }}", - dataPlacement: 'left' - }, submit: { icon: 'icon-rocket', mode: 'all', - ngClick: 'relaunch(running_job.id)', - awToolTip: 'Launch another instance of the job', + ngClick: 'relaunchJob(running_job.id)', + awToolTip: 'Relaunch using the same parameters', dataPlacement: 'top' }, cancel: { @@ -88,11 +88,12 @@ angular.module('RunningJobsDefinition', []) }, dropdown: { type: 'DropDown', + ngShow: "running_job.type === 'job'", label: 'View', icon: 'fa-search-plus', 'class': 'btn-default btn-xs', options: [ - { ngHref: '/#/jobs/{{ running_job.id }}', label: 'Status' }, + //{ ngHref: '/#/jobs/{{ running_job.id }}', label: 'Status' }, { ngHref: '/#/jobs/{{ running_job.id }}/job_events', label: 'Events' }, { ngHref: '/#/jobs/{{ running_job.id }}/job_host_summaries', label: 'Host Summary' } ] diff --git a/awx/ui/static/js/lists/ScheduledJobs.js b/awx/ui/static/js/lists/ScheduledJobs.js index 6b0d77b0f2..e9bee7c964 100644 --- a/awx/ui/static/js/lists/ScheduledJobs.js +++ b/awx/ui/static/js/lists/ScheduledJobs.js @@ -53,7 +53,7 @@ angular.module('ScheduledJobsDefinition', []) refresh: { mode: 'all', awToolTip: "Refresh the page", - ngClick: "refresh()" + ngClick: "refreshJobs()" } }, diff --git a/awx/ui/static/less/ansible-ui.less b/awx/ui/static/less/ansible-ui.less index 721a1813e9..6423eb3a31 100644 --- a/awx/ui/static/less/ansible-ui.less +++ b/awx/ui/static/less/ansible-ui.less @@ -64,9 +64,14 @@ body.modal-open { .nowrap { white-space: nowrap; } .capitalize { text-transform: capitalize; } .grey-txt { color: @grey; } -.red-txt { color: @red; } a.red-txt:hover { color: @red; } //make red links (for things like cancel) .text-center { text-align: center !important; } +.red-txt, +a.red-txt:visited, +a.red-txt:hover, +a.red-txt:active { + color: @red; +} /* Used on inventory groups/hosts lists for long names */ .ellipsis { @@ -973,12 +978,9 @@ input[type="checkbox"].checkbox-no-label { color: @green; } - .icon-job-pending:before, .icon-job-running:before, .icon-job-success:before, .icon-job-successful:before, - .icon-job-waiting:before, - .icon-job-new:before, .icon-job-changed:before { content: "\f111"; } @@ -989,12 +991,16 @@ input[type="checkbox"].checkbox-no-label { content: "\f06a"; } - .icon-job-pending, + .icon-job-pending:before, + .icon-job-waiting:before, + .icon-job-new:before, + .icon-job-none:before { + content: "\f10c"; + } + .icon-job-running, .icon-job-success, - .icon-job-successful, - .icon-job-waiting, - .icon-job-new { + .icon-job-successful { color: @green; } @@ -1013,15 +1019,14 @@ input[type="checkbox"].checkbox-no-label { color: @red; } - .icon-job-none { + .icon-job-none, + .icon-job-pending, + .icon-job-waiting, + .icon-job-new { color: @grey; opacity: 0.45; } - .icon-job-none:before { - content: "\f10c"; - } - .icon-schedule-enabled-true:before { content: "\f04c"; } @@ -1048,14 +1053,11 @@ input[type="checkbox"].checkbox-no-label { .pagination li a { font-size: 12px; } - .list-table-container { + /*.list-table-container { min-height: 338px; - } + }*/ } - .job-list-target { - min-height: 445px; - } - + /* Inventory job status badge */ .failures-true { background-color: @red; diff --git a/awx/ui/static/less/jquery-ui-overrides.less b/awx/ui/static/less/jquery-ui-overrides.less index bcb1d8de1e..086a0eb1fa 100644 --- a/awx/ui/static/less/jquery-ui-overrides.less +++ b/awx/ui/static/less/jquery-ui-overrides.less @@ -88,3 +88,29 @@ table.ui-datepicker-calendar { .ui-dialog-content.ui-widget-content { padding-top: 20px; } + +.ui-widget-content { + a, + a:visited, + a:active { + color: @blue; + text-decoration: none; + } + + a:hover, + a:focus { + color: @blue-dark; + text-decoration: none; + } + + .red-txt, + a.red-txt:visited, + a.red-txt:hover, + a.red-txt:active { + color: @red; + } + + .dropdown-menu>li>a { + color: @black; + } +} diff --git a/awx/ui/static/less/log-viewer.less b/awx/ui/static/less/log-viewer.less index ab9824baf4..2f93c77d4e 100644 --- a/awx/ui/static/less/log-viewer.less +++ b/awx/ui/static/less/log-viewer.less @@ -10,7 +10,13 @@ #logviewer-modal-dialog { textarea { - overflow: auto; + overflow: scroll; + } + pre { + overflow: scroll; + word-wrap: normal; + word-break: normal; + white-space: pre-wrap; } } diff --git a/awx/ui/static/lib/ansible/InventoryTree.js b/awx/ui/static/lib/ansible/InventoryTree.js index 60c5a2cb56..52f60dbbe3 100644 --- a/awx/ui/static/lib/ansible/InventoryTree.js +++ b/awx/ui/static/lib/ansible/InventoryTree.js @@ -162,9 +162,7 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P } }) .error(function (data, status) { - Wait('stop'); - ProcessErrors(scope, data, status, null, { - hdr: 'Error!', + ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Failed to get inventory tree for: ' + inventory_id + '. GET returned: ' + status }); }); @@ -309,10 +307,10 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P html += "
Are you sure you want to move group " + inbound.name + " to the top level?
"; + html += "Are you sure you want to move group " + inbound.name + " from the top level and make it a child of " + - target.name + "?
"; + html += "Would you like to copy or move group " + inbound.name + " to group " + target.name + "?
\n"; @@ -502,7 +500,7 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P html += "Are you sure you want to copy host " + host.name + ' to group ' + target.name + '?
'; + html += "