mirror of
https://github.com/ansible/awx.git
synced 2024-11-01 16:51:11 +03:00
Dashboard
Built the job status dashboard widget.
This commit is contained in:
parent
d46aa1c4de
commit
8477cb150e
@ -20,7 +20,7 @@ function JobsListController ($scope, $compile, $routeParams, ClearScope, Breadcr
|
||||
listCount = 0,
|
||||
api_complete = false,
|
||||
event_socket,
|
||||
event_queue = [{"status":"pending","endpoint":"/socket.io/jobs","unified_job_id":4129,"event":"status_changed"}],
|
||||
event_queue = [],
|
||||
expecting = 0,
|
||||
max_rows;
|
||||
|
||||
|
@ -372,7 +372,6 @@ function($location, Wait, GetBasePath, LookUpInit, JobTemplateForm, CredentialLi
|
||||
return function (params) {
|
||||
var scope = params.scope,
|
||||
id = params.id,
|
||||
base = $location.path().replace(/^\//, '').split('/')[0],
|
||||
url,
|
||||
job_template,
|
||||
new_job_id,
|
||||
@ -381,13 +380,7 @@ function($location, Wait, GetBasePath, LookUpInit, JobTemplateForm, CredentialLi
|
||||
prompt_for_vars = false,
|
||||
passwords;
|
||||
|
||||
if (!Empty($routeParams.template_id)) {
|
||||
// launching a job from job_template detail page
|
||||
url = GetBasePath('jobs') + id + '/';
|
||||
}
|
||||
else {
|
||||
url = GetBasePath(base) + id + '/';
|
||||
}
|
||||
url = GetBasePath('jobs') + id + '/';
|
||||
|
||||
if (scope.removePostTheJob) {
|
||||
scope.removePostTheJob();
|
||||
|
@ -46,7 +46,12 @@ angular.module('JobsHelper', ['Utilities', 'RestServices', 'FormGenerator', 'Job
|
||||
else if (scope.queued_jobs) {
|
||||
list = scope.queued_jobs;
|
||||
}
|
||||
else if (scope.jobs) {
|
||||
list = scope.jobs;
|
||||
}
|
||||
job = Find({ list: list, key: 'id', val: id });
|
||||
console.log('found job:');
|
||||
console.log(job);
|
||||
if (job.type === 'inventory_update') {
|
||||
typeId = job.inventory_source;
|
||||
}
|
||||
@ -81,6 +86,9 @@ angular.module('JobsHelper', ['Utilities', 'RestServices', 'FormGenerator', 'Job
|
||||
else if (scope.queued_jobs) {
|
||||
list = scope.queued_jobs;
|
||||
}
|
||||
else if (scope.jobs) {
|
||||
list = scope.jobs;
|
||||
}
|
||||
job = Find({ list: list, key: 'id', val: id });
|
||||
if (job.type === 'job') {
|
||||
$location.url('/jobs/' + job.id);
|
||||
@ -432,6 +440,9 @@ function(Find, GetBasePath, Rest, Wait, ProcessErrors, Prompt, Alert){
|
||||
else if (scope.queued_jobs) {
|
||||
jobs = scope.queued_jobs;
|
||||
}
|
||||
else if (scope.jobs) {
|
||||
jobs = scope.jobs;
|
||||
}
|
||||
job = Find({list: jobs, key: 'id', val: id });
|
||||
|
||||
if (job.status === 'pending' || job.status === 'running' || job.status === 'waiting') {
|
||||
|
@ -105,20 +105,8 @@ angular.module('CompletedJobsDefinition', [])
|
||||
stdout: {
|
||||
mode: 'all',
|
||||
href: '/#/jobs/{{ completed_job.id }}/stdout',
|
||||
awToolTip: 'View standard output. Opens in a new window or tab.',
|
||||
awToolTip: 'View standard output',
|
||||
dataPlacement: 'top'
|
||||
}
|
||||
/*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: '/#/job_events/{{ completed_job.id }}', label: 'Events', ngHide: "completed_job.status == 'new'" },
|
||||
{ ngHref: '/#/job_host_summaries/{{ completed_job.id }}', label: 'Host Summary' }
|
||||
]
|
||||
}*/
|
||||
}
|
||||
});
|
||||
|
@ -2,8 +2,10 @@
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* Jobs.js
|
||||
* List view object for Team data model.
|
||||
* List view object for job data model.
|
||||
*
|
||||
* Used on dashboard to provide a list of all jobs, regardless of
|
||||
* status.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -15,112 +17,92 @@ angular.module('JobsListDefinition', [])
|
||||
name: 'jobs',
|
||||
iterator: 'job',
|
||||
editTitle: 'Jobs',
|
||||
showTitle: false,
|
||||
'class': 'table-condensed',
|
||||
index: false,
|
||||
hover: true,
|
||||
well: false,
|
||||
"class": 'jobs-table',
|
||||
|
||||
fields: {
|
||||
id: {
|
||||
label: 'ID',
|
||||
ngClick:"viewJobLog(job.id)",
|
||||
key: true,
|
||||
desc: true,
|
||||
searchType: 'int'
|
||||
},
|
||||
inventory: {
|
||||
label: 'Inventory ID',
|
||||
searchType: 'int',
|
||||
searchOnly: true
|
||||
},
|
||||
created: {
|
||||
label: 'Create On',
|
||||
link: false,
|
||||
searchable: false,
|
||||
filter: "date:'MM/dd HH:mm:ss'"
|
||||
},
|
||||
name: {
|
||||
label: 'Name',
|
||||
link: false
|
||||
},
|
||||
failed: {
|
||||
label: 'Job failed?',
|
||||
searchSingleValue: true,
|
||||
searchType: 'boolean',
|
||||
searchValue: 'true',
|
||||
searchOnly: true,
|
||||
nosort: true
|
||||
columnClass: 'col-md-1 col-sm-2 col-xs-2',
|
||||
awToolTip: "{{ job.status_tip }}",
|
||||
awTipPlacement: "top",
|
||||
},
|
||||
status: {
|
||||
label: 'Status',
|
||||
"class": 'job-{{ job.status }}',
|
||||
columnClass: 'col-lg-1 col-md-2 col-sm-2 col-xs-2',
|
||||
awToolTip: "{{ job.status_tip }}",
|
||||
awTipPlacement: "top",
|
||||
dataTitle: "{{ job.status_popover_title }}",
|
||||
icon: 'icon-job-{{ job.status }}',
|
||||
iconOnly: true,
|
||||
ngClick:"viewJobLog(job.id)",
|
||||
searchable: false
|
||||
},
|
||||
started: {
|
||||
label: 'Started On',
|
||||
noLink: true,
|
||||
searchable: false,
|
||||
filter: "date:'MM/dd HH:mm:ss'",
|
||||
columnClass: "col-lg-1 col-md-2 hidden-xs"
|
||||
},
|
||||
type: {
|
||||
label: 'Type',
|
||||
ngBind: 'job.type_label',
|
||||
link: false,
|
||||
columnClass: "col-lg-1 col-md-2 hidden-sm hidden-xs",
|
||||
searchable: true,
|
||||
searchType: 'select',
|
||||
linkTo: "{{ job.statusLinkTo }}",
|
||||
searchOptions: [
|
||||
{ name: "new", value: "new" },
|
||||
{ name: "waiting", value: "waiting" },
|
||||
{ name: "pending", value: "pending" },
|
||||
{ name: "running", value: "running" },
|
||||
{ name: "successful", value: "successful" },
|
||||
{ name: "error", value: "error" },
|
||||
{ name: "failed", value: "failed" },
|
||||
{ name: "canceled", value: "canceled" }
|
||||
],
|
||||
badgeIcon: 'fa icon-job-{{ job.status }}',
|
||||
badgePlacement: 'left',
|
||||
badgeToolTip: "{{ job.statusBadgeToolTip }}",
|
||||
badgeTipPlacement: 'top',
|
||||
badgeNgHref: "{{ job.statusLinkTo }}",
|
||||
awToolTip: "{{ job.statusBadgeToolTip }}",
|
||||
dataPlacement: 'top'
|
||||
searchOptions: [] // populated via GetChoices() in controller
|
||||
},
|
||||
name: {
|
||||
label: 'Name',
|
||||
columnClass: 'col-md-3 col-xs-5',
|
||||
ngClick: "viewJobLog(job.id, job.nameHref)",
|
||||
defaultSearchField: true
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
refresh: {
|
||||
mode: 'all',
|
||||
awToolTip: "Refresh the page",
|
||||
ngClick: "refresh()"
|
||||
}
|
||||
},
|
||||
actions: { },
|
||||
|
||||
fieldActions: {
|
||||
submit: {
|
||||
label: 'Relaunch',
|
||||
icon: 'icon-rocket',
|
||||
mode: 'all',
|
||||
ngClick: 'submitJob(job.id, job.summary_fields.job_template.name)',
|
||||
awToolTip: 'Start the job',
|
||||
icon: 'icon-rocket',
|
||||
ngClick: 'relaunchJob($event, job.id)',
|
||||
awToolTip: 'Relaunch using the same parameters',
|
||||
dataPlacement: 'top'
|
||||
},
|
||||
cancel: {
|
||||
label: 'Stop',
|
||||
mode: 'all',
|
||||
ngClick: 'deleteJob(job.id)',
|
||||
awToolTip: 'Cancel a running or pending job',
|
||||
ngShow: "job.status == 'pending' || job.status == 'running' || job.status == 'waiting'",
|
||||
dataPlacement: 'top'
|
||||
awToolTip: 'Cancel the job',
|
||||
dataPlacement: 'top',
|
||||
ngShow: "job.status == 'running'"
|
||||
},
|
||||
"delete": {
|
||||
label: 'Delete',
|
||||
mode: 'all',
|
||||
ngClick: 'deleteJob(job.id)',
|
||||
awToolTip: 'Delete the job',
|
||||
ngShow: "job.status != 'pending' && job.status != 'running' && job.status != 'waiting'",
|
||||
dataPlacement: 'top',
|
||||
ngShow: "job.status != 'running'"
|
||||
},
|
||||
job_details: {
|
||||
mode: 'all',
|
||||
href: '/#/jobs/{{ job.id }}',
|
||||
awToolTip: 'View job details',
|
||||
dataPlacement: 'top'
|
||||
},
|
||||
dropdown: {
|
||||
type: 'DropDown',
|
||||
label: 'View',
|
||||
icon: 'fa-search-plus',
|
||||
'class': 'btn-default btn-xs',
|
||||
options: [
|
||||
{ ngClick: 'editJob(job.id, job.summary_fields.job_template.name)', label: 'Status' },
|
||||
{ ngClick: 'viewEvents(job.id, job.summary_fields.job_template.name)', label: 'Events',
|
||||
ngHide: "job.status == 'new'" },
|
||||
{ ngClick: 'viewSummary(job.id, job.summary_fields.job_template.name)', label: 'Host Summary',
|
||||
ngHide: "job.status == 'new'" }
|
||||
]
|
||||
stdout: {
|
||||
mode: 'all',
|
||||
href: '/#/jobs/{{ job.id }}/stdout',
|
||||
awToolTip: 'View standard output',
|
||||
dataPlacement: 'top'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -90,7 +90,7 @@ angular.module('RunningJobsDefinition', [])
|
||||
stdout: {
|
||||
mode: 'all',
|
||||
href: '/#/jobs/{{ running_job.id }}/stdout',
|
||||
awToolTip: 'View standard output. Opens in a new window or tab.',
|
||||
awToolTip: 'View standard output',
|
||||
dataPlacement: 'top'
|
||||
}
|
||||
/*dropdown: {
|
||||
|
@ -1,16 +1,16 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* ScheduledJobs.js
|
||||
* ScheduledJobs.js
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('ScheduledJobsDefinition', [])
|
||||
.value( 'ScheduledJobsList', {
|
||||
|
||||
|
||||
name: 'schedules',
|
||||
iterator: 'schedule',
|
||||
editTitle: 'Scheduled Jobs',
|
||||
@ -18,11 +18,11 @@ angular.module('ScheduledJobsDefinition', [])
|
||||
index: true,
|
||||
hover: true,
|
||||
well: false,
|
||||
|
||||
|
||||
fields: {
|
||||
status: {
|
||||
label: 'Status',
|
||||
columnClass: 'col-md-2 col-sm-2 col-xs-2',
|
||||
columnClass: 'col-lg-1 col-md-2 col-sm-2 col-xs-2',
|
||||
awToolTip: "{{ schedule.status_tip }}",
|
||||
awTipPlacement: "top",
|
||||
icon: 'icon-job-{{ schedule.status }}',
|
||||
@ -35,14 +35,14 @@ angular.module('ScheduledJobsDefinition', [])
|
||||
label: 'Next Run',
|
||||
noLink: true,
|
||||
searchable: false,
|
||||
columnClass: "col-md-2 hidden-xs",
|
||||
columnClass: "col-lg-1 col-md-2 hidden-xs",
|
||||
filter: "date:'MM/dd HH:mm:ss'",
|
||||
key: true
|
||||
},
|
||||
type: {
|
||||
label: 'Type',
|
||||
noLink: true,
|
||||
columnClass: "col-md-2 hidden-sm hidden-xs",
|
||||
columnClass: "col-lg-1 col-md-2 hidden-sm hidden-xs",
|
||||
sourceModel: 'unified_job_template',
|
||||
sourceField: 'unified_job_type',
|
||||
ngBind: 'schedule.type_label',
|
||||
@ -62,7 +62,7 @@ angular.module('ScheduledJobsDefinition', [])
|
||||
},
|
||||
|
||||
actions: { },
|
||||
|
||||
|
||||
fieldActions: {
|
||||
"play": {
|
||||
mode: "all",
|
||||
|
@ -10,13 +10,19 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('DashboardJobsWidget', ['RestServices', 'Utilities'])
|
||||
.factory('DashboardJobs', ['$rootScope', '$compile', 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait', function ($rootScope, $compile) {
|
||||
.factory('DashboardJobs', ['$rootScope', '$compile', 'LoadSchedulesScope', 'LoadJobsScope', 'JobsList', 'ScheduledJobsList', 'GetChoices', 'GetBasePath',
|
||||
function ($rootScope, $compile, LoadSchedulesScope, LoadJobsScope, JobsList, ScheduledJobsList, GetChoices, GetBasePath) {
|
||||
return function (params) {
|
||||
|
||||
var scope = params.scope,
|
||||
target = params.target,
|
||||
choicesCount = 0,
|
||||
listCount = 0,
|
||||
jobs_scope = scope.$new(true),
|
||||
scheduled_scope = scope.$new(true),
|
||||
max_rows = 15,
|
||||
html, e;
|
||||
|
||||
html = '';
|
||||
html += "<ul id=\"job_status_tabs\" class=\"nav nav-tabs\">\n";
|
||||
html += "<li class=\"active\"><a id=\"active_jobs_link\" ng-click=\"toggleTab($event, 'active_jobs_link', 'job_status_tabs')\"\n";
|
||||
html += " href=\"#active-jobs-tab\" data-toggle=\"tab\">Jobs</a></li>\n";
|
||||
@ -31,7 +37,68 @@ angular.module('DashboardJobsWidget', ['RestServices', 'Utilities'])
|
||||
e = angular.element(document.getElementById(target));
|
||||
e.html(html);
|
||||
$compile(e)(scope);
|
||||
scope.$emit('WidgetLoaded');
|
||||
|
||||
if (scope.removeListLoaded) {
|
||||
scope.removeListLoaded();
|
||||
}
|
||||
scope.removeListLoaded = scope.$on('listLoaded', function() {
|
||||
listCount++;
|
||||
if (listCount === 1) {
|
||||
//api_complete = true;
|
||||
scope.$emit('WidgetLoaded');
|
||||
}
|
||||
});
|
||||
|
||||
// After all choices are ready, load up the lists and populate the page
|
||||
if (scope.removeBuildJobsList) {
|
||||
scope.removeBuildJobsList();
|
||||
}
|
||||
scope.removeBuildJobsList = scope.$on('buildJobsList', function() {
|
||||
if (JobsList.fields.type) {
|
||||
JobsList.fields.type.searchOptions = scope.type_choices;
|
||||
}
|
||||
LoadJobsScope({
|
||||
parent_scope: scope,
|
||||
scope: jobs_scope,
|
||||
list: JobsList,
|
||||
id: 'active-jobs-tab',
|
||||
url: GetBasePath('unified_jobs') + '?status__in=running,completed,failed,successful,error,canceled',
|
||||
pageSize: max_rows
|
||||
});
|
||||
LoadSchedulesScope({
|
||||
parent_scope: scope,
|
||||
scope: scheduled_scope,
|
||||
list: ScheduledJobsList,
|
||||
id: 'scheduled-jobs-tab',
|
||||
url: GetBasePath('schedules') + '?next_run__isnull=false',
|
||||
pageSize: max_rows
|
||||
});
|
||||
});
|
||||
|
||||
if (scope.removeChoicesReady) {
|
||||
scope.removeChoicesReady();
|
||||
}
|
||||
scope.removeChoicesReady = scope.$on('choicesReady', function() {
|
||||
choicesCount++;
|
||||
if (choicesCount === 2) {
|
||||
scope.$emit('buildJobsList');
|
||||
}
|
||||
});
|
||||
|
||||
GetChoices({
|
||||
scope: scope,
|
||||
url: GetBasePath('unified_jobs'),
|
||||
field: 'status',
|
||||
variable: 'status_choices',
|
||||
callback: 'choicesReady'
|
||||
});
|
||||
|
||||
GetChoices({
|
||||
scope: scope,
|
||||
url: GetBasePath('unified_jobs'),
|
||||
field: 'type',
|
||||
variable: 'type_choices',
|
||||
callback: 'choicesReady'
|
||||
});
|
||||
};
|
||||
}]);
|
@ -1,21 +1,22 @@
|
||||
|
||||
<div class="tab-pane" id="home">
|
||||
<div ng-cloak id="htmlTemplate">
|
||||
<div id="refresh-row" class="row">
|
||||
<div class="col-lg-12">
|
||||
<div id="home-list-actions" class="list-actions pull-right"></div>
|
||||
<div id="refresh-row" class="row">
|
||||
<div class="col-lg-12">
|
||||
<div id="home-list-actions" class="list-actions pull-right"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div id="container1" class="col-lg-12"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div id="container2" class="col-lg-12"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div id="container3" class="col-lg-12"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div id="container1" class="col-lg-12"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div id="container2" class="col-lg-12"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div id="container3" class="col-lg-12"></div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div ng-include="'/static/partials/schedule_dialog.html'"></div>
|
Loading…
Reference in New Issue
Block a user