Applied status field changes to home/groups page.

This commit is contained in:
Chris Houseknecht 2014-04-04 15:41:19 -04:00
parent 5e514c5849
commit 66c044daca
10 changed files with 241 additions and 25 deletions

View File

@ -122,7 +122,7 @@ Home.$inject = ['$scope', '$compile', '$routeParams', '$rootScope', '$location',
];
function HomeGroups($location, $routeParams, HomeGroupList, GenerateList, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
function HomeGroups($filter, $compile, $location, $routeParams, LogViewer, HomeGroupList, GenerateList, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
GetBasePath, SearchInit, PaginateInit, FormatDate, GetHostsStatusMsg, GetSyncStatusMsg, ViewUpdateStatus, Stream, GroupsEdit, Wait,
Alert, Rest, Empty, InventoryUpdate, Find) {
@ -135,6 +135,35 @@ function HomeGroups($location, $routeParams, HomeGroupList, GenerateList, Proces
scope = generator.inject(list, { mode: 'edit' }),
opt;
function ellipsis(a) {
if (a.length > 20) {
return a.substr(0,20) + '...';
}
return a;
}
function attachElem(event, html, title) {
var elem = $(event.target).parent();
try {
elem.tooltip('hide');
elem.popover('destroy');
}
catch(err) {
//ignore
}
elem.attr({ "aw-pop-over": html, "data-title": title, "data-placement": "right" });
$compile(elem)(scope);
elem.on('shown.bs.popover', function() {
$('.popover').each(function() {
$compile($(this))(scope); //make nested directives work!
});
$('.popover-content, .popover-title').click(function() {
elem.popover('hide');
});
});
elem.popover('show');
}
if (scope.removePostRefresh) {
scope.removePostRefresh();
}
@ -145,7 +174,9 @@ function HomeGroups($location, $routeParams, HomeGroupList, GenerateList, Proces
scope.home_groups[i].inventory_name = scope.home_groups[i].summary_fields.inventory.name;
stat = GetSyncStatusMsg({
status: scope.home_groups[i].summary_fields.inventory_source.status
status: scope.home_groups[i].summary_fields.inventory_source.status,
source: scope.home_groups[i].summary_fields.inventory_source.source,
has_inventory_sources: scope.home_groups[i].has_inventory_sources
}); // from helpers/Groups.js
hosts_status = GetHostsStatusMsg({
@ -174,6 +205,7 @@ function HomeGroups($location, $routeParams, HomeGroupList, GenerateList, Proces
list: list,
url: defaultUrl
});
PaginateInit({
scope: scope,
list: list,
@ -258,7 +290,8 @@ function HomeGroups($location, $routeParams, HomeGroupList, GenerateList, Proces
scope: scope,
group_id: group_id,
inventory_id: inventory_id,
groups_reload: false
groups_reload: false,
mode: 'edit'
});
};
@ -306,9 +339,136 @@ function HomeGroups($location, $routeParams, HomeGroupList, GenerateList, Proces
scope.search(list.iterator, null, false, true);
};
if (scope.removeHostSummaryReady) {
scope.removeHostSummaryReady();
}
scope.removeHostSummaryReady = scope.$on('HostSummaryReady', function(e, event, data) {
var html, title = "Recent Jobs", url = GetBasePath('jobs');
Wait('stop');
if (data.length > 0) {
html = "<table class=\"table table-condensed flyout\" style=\"width: 100%\">\n";
html += "<thead>\n";
html += "<tr>";
html += "<th>Status</th>";
html += "<th>View</th>";
html += "<th>Name</th>";
html += "</tr>\n";
html += "</thead>\n";
html += "<tbody>\n";
data.forEach(function(row) {
html += "<tr>\n";
html += "<td><a ng-click=\"viewJob('" + url + row.id + "/')\" " + "aw-tool-tip=\"" + row.status.charAt(0).toUpperCase() + row.status.slice(1) +
". Click for details\" aw-tip-placement=\"top\"><i class=\"fa icon-job-" +
row.status + "\"></i></a></td>\n";
//html += "<td>" + ($filter('date')(row.finished,'MM/dd HH:mm:ss')).replace(/ /,'<br />') + "</td>";
html += "<td><a href=\"/#/jobs/" + row.id + "/job_events\">Events</a><br />" +
"<a href=\"/#/jobs/" + row.id + "/job_host_summaries\">Hosts</a></td>";
html += "<td><a href=\"\" ng-click=\"viewJob('" + url + row.id + "/')\" >" + ellipsis(row.name) + "</a></td>";
html += "</tr>\n";
});
html += "</tbody>\n";
html += "</table>\n";
html += "<div class=\"popover-footer\"><span class=\"key\">esc</span> or click to close</div>\n";
}
else {
html = "<p>No recent job data available for this inventory.</p>\n" +
"<div class=\"popover-footer\"><span class=\"key\">esc</span> or click to close</div>\n";
}
attachElem(event, html, title);
});
if (scope.removeGroupSummaryReady) {
scope.removeGroupSummaryReady();
}
scope.removeGroupSummaryReady = scope.$on('GroupSummaryReady', function(e, event, inventory, data) {
var html, title;
Wait('stop');
// Build the html for our popover
html = "<table class=\"table table-condensed flyout\" style=\"width: 100%\">\n";
html += "<thead>\n";
html += "<tr>";
html += "<th>Status</th>";
html += "<th>Last Sync</th>";
html += "<th>Group</th>";
html += "</tr>";
html += "</thead>\n";
html += "<tbody>\n";
data.results.forEach( function(row) {
html += "<tr>";
html += "<td><a href=\"\" ng-click=\"viewJob('" + row.related.last_update + "')\" aw-tool-tip=\"" + row.status.charAt(0).toUpperCase() + row.status.slice(1) + ". Click for details\" aw-tip-placement=\"top\"><i class=\"fa icon-job-" + row.status + "\"></i></a></td>";
html += "<td>" + ($filter('date')(row.last_updated,'MM/dd HH:mm:ss')).replace(/ /,'<br />') + "</td>";
html += "<td><a href=\"\" ng-click=\"viewJob('" + row.related.last_update + "')\">" + ellipsis(row.summary_fields.group.name) + "</a></td>";
html += "</tr>\n";
});
html += "</tbody>\n";
html += "</table>\n";
html += "<div class=\"popover-footer\"><span class=\"key\">esc</span> or click to close</div>\n";
title = "Sync Status";
attachElem(event, html, title);
});
scope.showGroupSummary = function(event, id) {
var group, status;
if (!Empty(id)) {
group = Find({ list: scope.home_groups, key: 'id', val: id });
status = group.summary_fields.inventory_source.status;
if (status === 'failed' || status === 'error' || status === 'successful') {
Wait('start');
Rest.setUrl(group.related.inventory_sources + '?or__source=ec2&or__source=rax&order_by=-last_job_run&page_size=5');
Rest.get()
.success(function(data) {
scope.$emit('GroupSummaryReady', event, group, data);
})
.error(function(data, status) {
ProcessErrors( scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + group.related.inventory_sources + ' failed. GET returned status: ' + status
});
});
}
}
};
scope.showHostSummary = function(event, id) {
var url, jobs = [];
if (!Empty(id)) {
Wait('start');
url = GetBasePath('hosts') + "?groups__id=" + id + "&last_job__isnull=false&order_by=-last_job&page_size=5";
Rest.setUrl(url);
Rest.get()
.success( function(data) {
data.results.forEach(function(host) {
host.summary_fields.recent_jobs.every(function(job) {
if (job.id === host.last_job) {
jobs.push(job);
return false;
}
return true;
});
});
scope.$emit('HostSummaryReady', event, jobs);
})
.error( function(data, status) {
ProcessErrors( scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. GET returned: ' + status
});
});
}
};
scope.viewJob = function(url) {
LogViewer({
scope: scope,
url: url
});
};
}
HomeGroups.$inject = ['$location', '$routeParams', 'HomeGroupList', 'GenerateList', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller',
HomeGroups.$inject = ['$filter', '$compile', '$location', '$routeParams', 'LogViewer', 'HomeGroupList', 'GenerateList', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller',
'ClearScope', 'GetBasePath', 'SearchInit', 'PaginateInit', 'FormatDate', 'GetHostsStatusMsg', 'GetSyncStatusMsg', 'ViewUpdateStatus',
'Stream', 'GroupsEdit', 'Wait', 'Alert', 'Rest', 'Empty', 'InventoryUpdate', 'Find'
];

View File

@ -175,6 +175,12 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
launch_tip = 'Can only be updated by running a sync on the parent group.';
}
if (has_inventory_sources === false && Empty(source)) {
launch_class = 'btn-disabled';
status_tip = 'Cloud source not configured. Click <i class="fa fa-pencil"></i> to update.';
launch_tip = 'Cloud source not configured.';
}
return {
"class": stat_class,
"tooltip": status_tip,

View File

@ -45,11 +45,6 @@ angular.module('CompletedJobsDefinition', [])
{ name: "Canceled", value: "canceled" }
]
},
inventory: {
label: 'Inventory ID',
searchType: 'int',
searchOnly: true
},
finished: {
label: 'Finished On',
noLink: true,

View File

@ -21,6 +21,28 @@ angular.module('HomeGroupListDefinition', [])
well: true,
fields: {
status: {
label: 'Status',
columnClass: 'col-md-2 col-sm-2 col-xs-2',
searchable: false,
nosort: true,
ngClick: "null",
iconOnly: true,
icons: [{
icon: "{{ 'icon-cloud-' + group.status_class }}",
awToolTip: "{{ group.status_tooltip }}",
dataTipWatch: "group.launch_tooltip",
awTipPlacement: "top",
ngClick: "showGroupSummary($event, group.id)",
ngClass: "group.launch_class"
},{
icon: "{{ 'icon-job-' + group.hosts_status_class }}",
awToolTip: "{{ group.hosts_status_tip }}",
awTipPlacement: "top",
ngClick: "showHostSummary($event, group.id)",
ngClass: ""
}]
},
name: {
key: true,
label: 'Group',
@ -82,6 +104,7 @@ angular.module('HomeGroupListDefinition', [])
},
fieldActions: {
/*
sync_status: {
mode: 'all',
ngClick: "viewUpdateStatus(group.id, group.group_id)",
@ -96,6 +119,7 @@ angular.module('HomeGroupListDefinition', [])
ngHref: "/#/inventories/{{ group.inventory }}/",
iconClass: "{{ 'fa icon-failures-' + group.hosts_status_class }}"
},
*/
group_update: {
//label: 'Sync',
mode: 'all',

View File

@ -27,7 +27,7 @@ angular.module('InventoriesListDefinition', [])
searchable: false,
nosort: true,
ngClick: "null",
dataTitle: "Sync Status",
iconOnly: true,
icons: [{
icon: "{{ 'icon-cloud-' + inventory.syncStatus }}",
awToolTip: "{{ inventory.syncTip }}",

View File

@ -36,12 +36,8 @@ angular.module('QueuedJobsDefinition', [])
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',
searchOnly: true
ngClick:"viewJobLog(queued_job.id)",
searchable: false
},
created: {
label: 'Created On',

View File

@ -36,12 +36,8 @@ angular.module('RunningJobsDefinition', [])
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
ngClick:"viewJobLog(running_job.id)",
searchable: false
},
started: {
label: 'Started On',

View File

@ -1249,7 +1249,8 @@ input[type="checkbox"].checkbox-no-label {
/* Inventory Edit */
#inventories_table i[class*="icon-job-"] {
#inventories_table i[class*="icon-job-"],
#home_groups_table i[class*="icon-job-"] {
margin-left: 8px;
}

View File

@ -483,6 +483,7 @@ angular.module('GeneratorHelpers', [])
html += "aw-pop-over=\"" + field.awPopOver + "\" ";
html += (field.dataPlacement) ? "data-placement=\"" + field.dataPlacement + "\" " : "";
}
html += (field.ngClass) ? Attr(field, 'ngClass') : '';
html += ">";
// Add icon:

View File

@ -1,4 +1,41 @@
<div class="tab-pane" id="home">
<div ng-cloak id="htmlTemplate"></div>
<div id="inventory-modal-container"></div>
<div ng-cloak id="htmlTemplate"></div>
<div id="inventory-modal-container"></div>
<div id="group-modal-dialog" style="display: none;">
<ul id="group_tabs" class="nav nav-tabs">
<li class="active"><a id="properties_link" ng-click="toggleTab($event, 'properties_link', 'group_tabs')"
href="#properties-tab" data-toggle="tab">Properties</a></li>
<li><a id="source_link" ng-click="toggleTab($event, 'source_link', 'group_tabs')"
href="#sources-tab" data-toggle="tab">Source</a></li>
<li ng-show="showSourceTab"><a id="schedules_link" ng-click="toggleTab($event, 'schedules_link', 'group_tabs')"
href="#schedules-tab" data-toggle="tab">Schedule</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="properties-tab"></div>
<div class="tab-pane" id="sources-tab"></div>
<div class="tab-pane" id="schedules-tab">
<div id="schedules-overlay"></div>
<div id="schedules-list"></div>
<div id="schedules-form-container">
<div id="schedules-title">
<h4 ng-bind="schedulesTitle"></h4>
<button type="button" class="close pull-right" ng-click="cancelScheduleForm()">x</button>
</div>
<div id="schedules-form-container-body">
<div id="schedules-form"></div>
<div id="schedules-detail"></div>
</div>
<div id="schedules-buttons">
<a id="schedules-flip-link" ng-show="formShowing" ng-click="showScheduleDetail()" href=""><i class="fa fa-search-plus"></i> View Details</a>
<a id="schedules-flip-link" ng-show="!formShowing" ng-click="showScheduleDetail()" href=""><i class="fa fa-arrow-circle-left"></i> Back to options</a>
<button type="button" class="btn btn-default btn-sm" id="reset-button" ng-click="cancelScheduleForm()"><i class="fa fa-times"></i> Cancel</button>
<button type="button" class="btn btn-primary btn-sm" id="save-button" ng-click="saveScheduleForm()"><i class="fa fa-check"></i> Save</button>
</div>
</div>
</div>
</div>
</div>
<div id="host-modal-dialog" style="display: none;" class="dialog-content"></div>
<div ng-include="'/static/partials/logviewer.html'"></div>
</div>