diff --git a/awx/ui/static/ansible-bootstrap/dropdowns.less b/awx/ui/static/ansible-bootstrap/dropdowns.less
index f165165e7a..ba4acf069a 100644
--- a/awx/ui/static/ansible-bootstrap/dropdowns.less
+++ b/awx/ui/static/ansible-bootstrap/dropdowns.less
@@ -210,4 +210,3 @@
}
}
}
-
diff --git a/awx/ui/static/js/app.js b/awx/ui/static/js/app.js
index b7848c93cc..64e684fa11 100644
--- a/awx/ui/static/js/app.js
+++ b/awx/ui/static/js/app.js
@@ -29,11 +29,7 @@ import {Authenticate} from 'tower/controllers/Authentication';
import {CredentialsAdd, CredentialsEdit, CredentialsList} from 'tower/controllers/Credentials';
import {JobsListController} from 'tower/controllers/Jobs';
import {PortalController} from 'tower/controllers/Portal';
-
-import dataServices from 'tower/services/_data-services';
-import dashboardGraphs from 'tower/directives/_dashboard-graphs';
import systemTracking from 'tower/system-tracking/main';
-
import routeExtensions from 'tower/shared/route-extensions/main';
import breadcrumbs from 'tower/shared/breadcrumbs/main';
@@ -41,6 +37,7 @@ import breadcrumbs from 'tower/shared/breadcrumbs/main';
import setupMenu from 'tower/setup-menu/main';
import mainMenu from 'tower/main-menu/main';
import browserData from 'tower/browser-data/main';
+import dashboard from 'tower/dashboard/main';
import {JobDetailController} from 'tower/controllers/JobDetail';
import {JobStdoutController} from 'tower/controllers/JobStdout';
@@ -79,14 +76,13 @@ var tower = angular.module('Tower', [
'ngSanitize',
'ngCookies',
'RestServices',
- dataServices.name,
- dashboardGraphs.name,
routeExtensions.name,
browserData.name,
breadcrumbs.name,
systemTracking.name,
setupMenu.name,
mainMenu.name,
+ dashboard.name,
'AuthService',
'Utilities',
'LicenseHelper',
@@ -149,8 +145,6 @@ var tower = angular.module('Tower', [
'AccessHelper',
'SelectionHelper',
'HostGroupsFormDefinition',
- 'DashboardCountsWidget',
- 'DashboardJobsWidget',
'PortalJobsWidget',
'StreamWidget',
'JobsHelper',
@@ -863,10 +857,9 @@ var tower = angular.module('Tower', [
templateUrl: urlPrefix + 'partials/home.html',
controller: Home,
resolve: {
- graphData: ['$q', 'jobStatusGraphData', 'hostCountGraphData', 'FeaturesService', function($q, jobStatusGraphData, hostCountGraphData, FeaturesService) {
+ graphData: ['$q', 'jobStatusGraphData', 'FeaturesService', function($q, jobStatusGraphData, FeaturesService) {
return $q.all({
jobStatus: jobStatusGraphData.get("month", "all"),
- hostCounts: hostCountGraphData.get(),
features: FeaturesService.get()
});
}]
diff --git a/awx/ui/static/js/controllers/Home.js b/awx/ui/static/js/controllers/Home.js
index 00664fc466..5ed11aa665 100644
--- a/awx/ui/static/js/controllers/Home.js
+++ b/awx/ui/static/js/controllers/Home.js
@@ -26,41 +26,31 @@
*
*/
-export function Home($scope, $compile, $routeParams, $rootScope, $location, $log, Wait, DashboardCounts, DashboardJobs,
+export function Home($scope, $compile, $routeParams, $rootScope, $location, $log, Wait,
ClearScope, Stream, Rest, GetBasePath, ProcessErrors, $window, graphData){
ClearScope('home');
- var borderStyles;
+ var dataCount = 0;
- if (!$routeParams.login) {
- // If we're not logging in, start the Wait widget. Otherwise, it's already running.
- //Wait('start');
+ if ($scope.removeDashboardDataLoadComplete) {
+ $scope.removeDashboardDataLoadComplete();
}
+ $scope.removeDashboardDataLoadComplete = $scope.$on('dashboardDataLoadComplete', function () {
+ dataCount++;
+ if (dataCount === 3) {
+ Wait("stop");
+ dataCount = 0;
+ }
+ });
if ($scope.removeDashboardReady) {
$scope.removeDashboardReady();
}
$scope.removeDashboardReady = $scope.$on('dashboardReady', function (e, data) {
-
- nv.dev=false;
-
-
- borderStyles = {"border": "1px solid #A9A9A9",
- "border-radius": "4px",
- "padding": "5px",
- "margin-bottom": "15px"};
- $('.graph-container').css(borderStyles);
-
- DashboardCounts({
- scope: $scope,
- target: 'dash-counts',
- dashboard: data
- });
-
- // // chart.update();
-
+ $scope.dashboardCountsData = data;
$scope.graphData = graphData;
+ $scope.$emit('dashboardDataLoadComplete');
var cleanupJobListener =
$rootScope.$on('DataReceived:JobStatusGraph', function(e, data) {
@@ -70,16 +60,25 @@ export function Home($scope, $compile, $routeParams, $rootScope, $location, $log
$scope.$on('$destroy', function() {
cleanupJobListener();
});
-
-
- DashboardJobs({
- scope: $scope,
- target: 'dash-jobs-list',
- dashboard: data
- });
-
});
+ if ($scope.removeDashboardJobsListReady) {
+ $scope.removeDashboardJobsListReady();
+ }
+ $scope.removeDashboardJobsListReady = $scope.$on('dashboardJobsListReady', function (e, data) {
+ $scope.dashboardJobsListData = data;
+ $scope.$emit('dashboardDataLoadComplete');
+ });
+
+ if ($scope.removeDashboardJobTemplatesListReady) {
+ $scope.removeDashboardJobTemplatesListReady();
+ }
+ $scope.removeDashboardJobTemplatesListReady = $scope.$on('dashboardJobTemplatesListReady', function (e, data) {
+ $scope.dashboardJobTemplatesListData = data;
+ $scope.$emit('dashboardDataLoadComplete');
+ });
+
+
$scope.showActivity = function () {
Stream({
scope: $scope
@@ -97,13 +96,30 @@ export function Home($scope, $compile, $routeParams, $rootScope, $location, $log
.error(function (data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to get dashboard: ' + status });
});
+ Rest.setUrl(GetBasePath("jobs") + "?order_by=-finished&page_size=5&finished__isnull=false");
+ Rest.get()
+ .success(function (data) {
+ data = data.results;
+ $scope.$emit('dashboardJobsListReady', data);
+ })
+ .error(function (data, status) {
+ ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to get dashboard jobs list: ' + status });
+ });
+ Rest.setUrl(GetBasePath("job_templates") + "?order_by=-last_job_run&page_size=5&last_job_run__isnull=false");
+ Rest.get()
+ .success(function (data) {
+ data = data.results;
+ $scope.$emit('dashboardJobTemplatesListReady', data);
+ })
+ .error(function (data, status) {
+ ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to get dashboard job templates list: ' + status });
+ });
};
$scope.refresh();
-
}
-Home.$inject = ['$scope', '$compile', '$routeParams', '$rootScope', '$location', '$log','Wait', 'DashboardCounts', 'DashboardJobs',
+Home.$inject = ['$scope', '$compile', '$routeParams', '$rootScope', '$location', '$log','Wait',
'ClearScope', 'Stream', 'Rest', 'GetBasePath', 'ProcessErrors', '$window', 'graphData'
];
diff --git a/awx/ui/static/js/dashboard/counts/dashboard-counts.block.less b/awx/ui/static/js/dashboard/counts/dashboard-counts.block.less
new file mode 100644
index 0000000000..4905af1dbc
--- /dev/null
+++ b/awx/ui/static/js/dashboard/counts/dashboard-counts.block.less
@@ -0,0 +1,70 @@
+/** @define DashboardCounts */
+
+.DashboardCounts {
+ display: flex;
+ flex-direction: row;
+ align-items: stretch;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ width: 100%;
+ padding-top: 0;
+ margin-top: 0;
+}
+
+.DashboardCounts-buttonStyle {
+ text-align: center;
+ padding: 8px;
+ padding-bottom: 11px;
+ padding-left: 15px;
+ padding-right: 15px;
+ border-radius: 3px;
+}
+
+@media only screen and (max-width: 710px) {
+ .DashboardCounts {
+ margin-bottom: -15px;
+ }
+
+ .DashboardCounts-buttonStyle {
+ border: 1px solid #aaa;
+ margin-bottom: 15px;
+ width: 33%;
+ flex-basis: ~"calc(33% - 7px)";
+ }
+}
+
+.DashboardCounts-buttonStyle:hover {
+ background-color: #1778c3;
+ border-color: #1778c3;
+
+ .DashboardCounts-number,
+ .DashboardCounts-label {
+ color: #fff;
+ }
+}
+
+.DashboardCounts-buttonStyle.is-failure:hover {
+ background-color: #ff5850;
+ border-color: #ff5850;
+
+ .DashboardCounts-number,
+ .DashboardCounts-label {
+ color: #fff;
+ }
+}
+
+.DashboardCounts-number {
+ font-size: 30px;
+ line-height: 26px;
+ flex: 1;
+}
+
+.DashboardCounts-number.is-failure {
+ color: #ff5850;
+}
+
+.DashboardCounts-label {
+ flex: 1;
+ margin-bottom: 0px;
+ color: #000;
+}
diff --git a/awx/ui/static/js/dashboard/counts/dashboard-counts.directive.js b/awx/ui/static/js/dashboard/counts/dashboard-counts.directive.js
new file mode 100644
index 0000000000..ac0f201237
--- /dev/null
+++ b/awx/ui/static/js/dashboard/counts/dashboard-counts.directive.js
@@ -0,0 +1,73 @@
+/* jshint unused: vars */
+export default
+ [ '$rootScope',
+ function() {
+ return {
+ restrict: 'E',
+ scope: {
+ data: '='
+ },
+ replace: false,
+ templateUrl: '/static/js/dashboard/counts/dashboard-counts.partial.html',
+ link: function(scope, element, attrs) {
+ scope.$watch("data", function(data) {
+ if (data && data.hosts) {
+ createCounts(data);
+ }
+ });
+
+ function addFailureToCount(val) {
+ if (val.isFailureCount) {
+ // delete isFailureCount
+ if (val.number > 0) {
+ val.isFailure = true;
+ } else {
+ val.isFailure = false;
+ }
+ } else {
+ val.isFailure = false;
+ }
+ return val;
+ }
+
+ function createCounts(data) {
+ scope.counts = _.map([
+ {
+ url: "/#/home/hosts",
+ number: scope.data.hosts.total,
+ label: "Hosts"
+ },
+ {
+ url: "/#/home/hosts?has_active_failures=true",
+ number: scope.data.hosts.failed,
+ label: "Failed Hosts",
+ isFailureCount: true
+ },
+ {
+ url: "/#/inventories",
+ number: scope.data.inventories.total,
+ label: "Inventories",
+ },
+ {
+ url: "/#/inventories/?inventory_sources_with_failures",
+ number: scope.data.inventories.inventory_failed,
+ label: "Inventory Sync Failures",
+ isFailureCount: true
+ },
+ {
+ url: "/#/projects",
+ number: scope.data.projects.total,
+ label: "Projects"
+ },
+ {
+ url: "/#/projects/?status=failed",
+ number: scope.data.projects.failed,
+ label: "Projects Sync Failures",
+ isFailureCount: true
+ }
+ ], function(val) { return addFailureToCount(val); });
+ }
+ }
+ };
+ }
+ ];
diff --git a/awx/ui/static/js/dashboard/counts/dashboard-counts.partial.html b/awx/ui/static/js/dashboard/counts/dashboard-counts.partial.html
new file mode 100644
index 0000000000..522b4fff4d
--- /dev/null
+++ b/awx/ui/static/js/dashboard/counts/dashboard-counts.partial.html
@@ -0,0 +1,10 @@
+
diff --git a/awx/ui/static/js/dashboard/counts/main.js b/awx/ui/static/js/dashboard/counts/main.js
new file mode 100644
index 0000000000..0c069d9588
--- /dev/null
+++ b/awx/ui/static/js/dashboard/counts/main.js
@@ -0,0 +1,5 @@
+import dashboardCountsDirective from 'tower/dashboard/counts/dashboard-counts.directive';
+
+export default
+ angular.module('DashboardCountModules', [])
+ .directive('dashboardCounts', dashboardCountsDirective);
diff --git a/awx/ui/static/js/dashboard/dashboard.block.less b/awx/ui/static/js/dashboard/dashboard.block.less
new file mode 100644
index 0000000000..e7b77e5fb4
--- /dev/null
+++ b/awx/ui/static/js/dashboard/dashboard.block.less
@@ -0,0 +1,43 @@
+/** @define Dashboard */
+
+.Dashboard {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ width: 100%;
+}
+
+.Dashboard-counts {
+ flex: initial;
+ width: 100%;
+ border: 1px solid #a9a9a9;
+ border-radius: 4px;
+ padding: 9px;
+}
+
+.Dashboard-graphs {
+ flex: initial;
+ width: 100%;
+}
+
+.Dashboard-list {
+ display: flex;
+ border: 1px solid #a9a9a9;
+ border-radius: 4px;
+ margin-top: 15px;
+ width: 50%;
+ padding: 15px;
+ flex-basis: ~"calc(50% - 7px)";
+}
+
+@media only screen and (max-width: 710px) {
+ .Dashboard-counts {
+ border: 0;
+ padding: 0;
+ }
+
+ .Dashboard-list {
+ flex: initial;
+ width: 100%;
+ }
+}
diff --git a/awx/ui/static/js/dashboard/dashboard.directive.js b/awx/ui/static/js/dashboard/dashboard.directive.js
new file mode 100644
index 0000000000..c330aeb137
--- /dev/null
+++ b/awx/ui/static/js/dashboard/dashboard.directive.js
@@ -0,0 +1,13 @@
+/* jshint unused: vars */
+export default
+ [ '$rootScope',
+ function() {
+ return {
+ restrict: 'E',
+ scope: true,
+ templateUrl: '/static/js/dashboard/dashboard.partial.html',
+ link: function(scope, element, attrs) {
+ }
+ };
+ }
+ ];
diff --git a/awx/ui/static/js/dashboard/dashboard.partial.html b/awx/ui/static/js/dashboard/dashboard.partial.html
new file mode 100644
index 0000000000..dc2aa78245
--- /dev/null
+++ b/awx/ui/static/js/dashboard/dashboard.partial.html
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
diff --git a/awx/ui/static/js/dashboard/graphs/dashboard-graphs.block.less b/awx/ui/static/js/dashboard/graphs/dashboard-graphs.block.less
new file mode 100644
index 0000000000..e4167e5ed1
--- /dev/null
+++ b/awx/ui/static/js/dashboard/graphs/dashboard-graphs.block.less
@@ -0,0 +1,101 @@
+/** @define DashboardGraphs */
+
+.DashboardGraphs {
+ display: flex;
+ flex-direction: column;
+ margin-top: 15px;
+ border: solid 1px #a9a9a9;
+ border-radius: 4px;
+}
+
+.DashboardGraphs-tabSection {
+ flex: 1;
+ display: flex;
+}
+
+.DashboardGraphs-tab {
+ flex: 1;
+ padding: 10px;
+ border-right: solid 1px #a9a9a9;
+ border-bottom: solid 1px #a9a9a9;
+ text-align: center;
+ font-size: 20px;
+ background-color: #ccc;
+ color: #545454;
+ background-color: #EAEAEA;
+}
+
+.DashboardGraphs-tab--firstTab {
+ border-top-left-radius: 4px;
+}
+
+.DashboardGraphs-tab--lastTab {
+ border-top-right-radius: 4px;
+ border-right: 0;
+}
+
+.DashboardGraphs-tab:hover {
+ color: #000;
+ cursor: pointer;
+}
+
+.DashboardGraphs-tab.is-selected {
+ background-color: #fff;
+ color: #000;
+ border-bottom: 0;
+}
+
+.DashboardGraphs-tab.is-selected:hover {
+ cursor: default;
+}
+
+.DashboardGraphs-graphSection {
+ display: block;
+ flex: 1;
+}
+
+.DashboardGraphs-graphContainer {
+ width: 0%;
+ display: none;
+}
+
+.DashboardGraphs-graphContainer.is-selected {
+ width: 100%;
+ display: block;
+}
+
+.DashboardGraphs-graph {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ margin-bottom: 19px;
+ padding: 20px;
+}
+
+.DashboardGraphs-graphToolbar {
+ display: flex;
+ justify-content: flex-end;
+ margin-bottom: 6px;
+}
+
+.DashboardGraphs-filterDropdown {
+ flex: initial;
+ font-size: 12px;
+ padding-right: 15px;
+}
+
+.DashboardGraphs-filterDropdownItems {
+ position: fixed;
+ left: initial;
+ top: initial;
+ box-shadow: none;
+}
+
+.DashboardGraphs-filterDropdownItems--period {
+ margin-left: -42px;
+}
+
+.DashboardGraphs-filterDropdownItems--jobType {
+ margin-left: -84px;
+}
diff --git a/awx/ui/static/js/dashboard/graphs/dashboard-graphs.directive.js b/awx/ui/static/js/dashboard/graphs/dashboard-graphs.directive.js
new file mode 100644
index 0000000000..b27418a94c
--- /dev/null
+++ b/awx/ui/static/js/dashboard/graphs/dashboard-graphs.directive.js
@@ -0,0 +1,31 @@
+/* jshint unused: vars */
+export default
+ [ '$rootScope',
+ function() {
+ return {
+ restrict: 'E',
+ scope: true,
+ templateUrl: '/static/js/dashboard/graphs/dashboard-graphs.partial.html',
+ link: function(scope, element, attrs) {
+ function clearGraphs() {
+ scope.jobStatusSelected = false;
+ scope.hostStatusSelected = false;
+ }
+
+ scope.toggleGraphStatus = function (graphType) {
+ clearGraphs();
+ if (graphType === "jobStatus") {
+ scope.jobStatusSelected = true;
+ } else if (graphType === "hostStatus") {
+ scope.hostStatusSelected = true;
+ }
+ scope.$broadcast("resizeGraphs");
+ };
+
+ // initially toggle jobStatus graph
+ clearGraphs();
+ scope.toggleGraphStatus("jobStatus");
+ }
+ };
+ }
+ ];
diff --git a/awx/ui/static/js/dashboard/graphs/dashboard-graphs.partial.html b/awx/ui/static/js/dashboard/graphs/dashboard-graphs.partial.html
new file mode 100644
index 0000000000..5c69410f15
--- /dev/null
+++ b/awx/ui/static/js/dashboard/graphs/dashboard-graphs.partial.html
@@ -0,0 +1,32 @@
+
+
+
+ Job Status
+
+
+ Host Status
+
+
+
+
diff --git a/awx/ui/static/js/services/adjust-graph-size.js b/awx/ui/static/js/dashboard/graphs/graph-helpers/adjust-graph-size.service.js
similarity index 70%
rename from awx/ui/static/js/services/adjust-graph-size.js
rename to awx/ui/static/js/dashboard/graphs/graph-helpers/adjust-graph-size.service.js
index 51777c9521..97d6803219 100644
--- a/awx/ui/static/js/services/adjust-graph-size.js
+++ b/awx/ui/static/js/dashboard/graphs/graph-helpers/adjust-graph-size.service.js
@@ -53,37 +53,35 @@ export default function() {
// Calling chartModel.update() at the end instructs nv to process our changes.
//
return function adjustGraphSize(chartModel, element) {
- var parentHeight = element.parent().parent().height();
- var toolbarHeight = element.find('.toolbar').height();
- var container = element.find('svg').parent();
- var margins = chartModel.margin();
+ if (chartModel) {
+ var margins = chartModel.margin();
+ var graph = d3.select(element.find('svg')[0]);
+ var width = parseInt(graph.style('width')) - margins.left - margins.right;
+ // var height = parseInt(graph.style('height')) - margins.top - margins.bottom;
+ // console.log(height);
+ var height = 200;
- var newHeight = parentHeight - toolbarHeight - margins.bottom;
+ chartModel.xRange([0, width]);
+ chartModel.yRange([height, 0]);
- $(container).height(newHeight);
+ chartModel.xAxis.ticks(Math.max(width / 75, 2));
+ chartModel.yAxis.ticks(Math.max(height / 50, 2));
- var graph = d3.select(element.find('svg')[0]);
- var width = parseInt(graph.style('width')) - margins.left - margins.right;
- var height = parseInt(graph.style('height')) - margins.top - margins.bottom;
+ if (height < 160) {
+ graph.select('.y.nv-axis').select('.domain').style('display', 'none');
+ graph.select('.y.nv-axis').select('.domain').style('display', 'initial');
+ }
- chartModel.xRange([0, width]);
- chartModel.yRange([height, 0]);
+ graph.select('.x.nv-axis')
+ .attr('transform', 'translate(0, ' + height + ')')
+ .call(chartModel.xAxis);
- chartModel.xAxis.ticks(Math.max(width / 75, 2));
- chartModel.yAxis.ticks(Math.max(height / 50, 2));
+ graph.selectAll('.line')
+ .attr('d', chartModel.lines);
- if (height < 160) {
- graph.select('.y.nv-axis').select('.domain').style('display', 'none');
- graph.select('.y.nv-axis').select('.domain').style('display', 'initial');
+ if (chartModel.update) {
+ chartModel.update();
+ }
}
-
- graph.select('.x.nv-axis')
- .attr('transform', 'translate(0, ' + height + ')')
- .call(chartModel.xAxis);
-
- graph.selectAll('.line')
- .attr('d', chartModel.lines);
-
- chartModel.update();
};
}
diff --git a/awx/ui/static/js/directives/auto-size-module.js b/awx/ui/static/js/dashboard/graphs/graph-helpers/auto-size.directive.js
similarity index 63%
rename from awx/ui/static/js/directives/auto-size-module.js
rename to awx/ui/static/js/dashboard/graphs/graph-helpers/auto-size.directive.js
index 3c63914a94..fa7e7424bc 100644
--- a/awx/ui/static/js/directives/auto-size-module.js
+++ b/awx/ui/static/js/dashboard/graphs/graph-helpers/auto-size.directive.js
@@ -9,16 +9,18 @@ function AutoSizeModule($window) {
// fit into a single a page; assumes there are 2 rows
// of modules, with the available height being offset
// by the navbar & the count summaries module
- return function(scope, element) {
-
- function adjustSizeInitially() {
- adjustSize();
- }
+ return function(scope, element, attrs) {
function adjustSize() {
- var winHeight = $($window).height(),
- available_height = winHeight - $('#main-menu-container .navbar').outerHeight() - $('#count-container').outerHeight() - 120;
- element.height(available_height/2);
+ if (attrs.graphType === "hostStatus") {
+ if (element.parent().width() > 596) {
+ element.height(596);
+ } else {
+ element.height(element.parent().width());
+ }
+ } else {
+ element.height(320);
+ }
}
$($window).resize(adjustSize);
@@ -30,8 +32,8 @@ function AutoSizeModule($window) {
// This makes sure count-container div is loaded
// by controllers/Home.js before we use it
// to determine the available window height
- scope.$on('dashboardReady', function() {
- adjustSizeInitially();
+ scope.$on('resizeGraphs', function() {
+ adjustSize();
});
};
diff --git a/awx/ui/static/js/dashboard/graphs/graph-helpers/main.js b/awx/ui/static/js/dashboard/graphs/graph-helpers/main.js
new file mode 100644
index 0000000000..ae8dd9174e
--- /dev/null
+++ b/awx/ui/static/js/dashboard/graphs/graph-helpers/main.js
@@ -0,0 +1,6 @@
+import AutoSize from 'tower/dashboard/graphs/graph-helpers/auto-size.directive';
+import AdjustGraphSize from 'tower/dashboard/graphs/graph-helpers/adjust-graph-size.service';
+
+export default angular.module('DashboardGraphHelpers', [])
+ .directive('autoSizeModule', AutoSize)
+ .service('adjustGraphSize', AdjustGraphSize);
diff --git a/awx/ui/static/js/directives/host-status-graph.js b/awx/ui/static/js/dashboard/graphs/host-status/host-status-graph.directive.js
similarity index 84%
rename from awx/ui/static/js/directives/host-status-graph.js
rename to awx/ui/static/js/dashboard/graphs/host-status/host-status-graph.directive.js
index e56d3991df..1c467d2d9b 100644
--- a/awx/ui/static/js/directives/host-status-graph.js
+++ b/awx/ui/static/js/dashboard/graphs/host-status/host-status-graph.directive.js
@@ -1,14 +1,15 @@
export default
[ '$compile',
'$window',
- HostStatusGraph
+ 'adjustGraphSize',
+ HostStatusGraph,
];
-function HostStatusGraph($compile, $window) {
+function HostStatusGraph($compile, $window, adjustGraphSize) {
return {
restrict: 'E',
link: link,
- templateUrl: '/static/partials/host_status_graph.html'
+ templateUrl: '/static/js/dashboard/graphs/host-status/host_status_graph.partial.html'
};
function link(scope, element, attr) {
@@ -20,12 +21,10 @@ function HostStatusGraph($compile, $window) {
}
});
- function adjustGraphSize() {
-
+ function adjustHostGraphSize() {
if (angular.isUndefined(host_pie_chart)) {
return;
}
-
var parentHeight = element.parent().parent().height();
var toolbarHeight = element.find('.toolbar').height();
var container = element.find('svg').parent();
@@ -38,10 +37,12 @@ function HostStatusGraph($compile, $window) {
host_pie_chart.update();
}
- angular.element($window).on('resize', adjustGraphSize);
+ angular.element($window).on('resize', adjustHostGraphSize);
+ $(".DashboardGraphs-graph--hostStatusGraph").resize(adjustHostGraphSize);
element.on('$destroy', function() {
- angular.element($window).off('resize', adjustGraphSize);
+ angular.element($window).off('resize', adjustHostGraphSize);
+ $(".DashboardGraphs-graph--hostStatusGraph").removeResize(adjustHostGraphSize);
});
function createGraph(data) {
@@ -58,7 +59,7 @@ function HostStatusGraph($compile, $window) {
];
host_pie_chart = nv.models.pieChart()
- .margin({top: 5, right: 75, bottom: 25, left: 85})
+ .margin({bottom: 15})
.x(function(d) { return d.label; })
.y(function(d) { return d.value; })
.showLabels(true)
@@ -101,6 +102,7 @@ function HostStatusGraph($compile, $window) {
element.find('svg').replaceWith(notFoundContainer);
}
+
}
}
}
diff --git a/awx/ui/static/js/dashboard/graphs/host-status/host_status_graph.partial.html b/awx/ui/static/js/dashboard/graphs/host-status/host_status_graph.partial.html
new file mode 100644
index 0000000000..15396d31ec
--- /dev/null
+++ b/awx/ui/static/js/dashboard/graphs/host-status/host_status_graph.partial.html
@@ -0,0 +1,3 @@
+
+
+
diff --git a/awx/ui/static/js/dashboard/graphs/host-status/main.js b/awx/ui/static/js/dashboard/graphs/host-status/main.js
new file mode 100644
index 0000000000..b7ab1d6b3e
--- /dev/null
+++ b/awx/ui/static/js/dashboard/graphs/host-status/main.js
@@ -0,0 +1,5 @@
+import HostStatusGraphDirective from 'tower/dashboard/graphs/host-status/host-status-graph.directive';
+import DashboardGraphHelpers from 'tower/dashboard/graphs/graph-helpers/main';
+
+export default angular.module('HostStatusGraph', [DashboardGraphHelpers.name])
+ .directive('hostStatusGraph', HostStatusGraphDirective);
diff --git a/awx/ui/static/js/directives/job-status-graph.js b/awx/ui/static/js/dashboard/graphs/job-status/job-status-graph.directive.js
similarity index 93%
rename from awx/ui/static/js/directives/job-status-graph.js
rename to awx/ui/static/js/dashboard/graphs/job-status/job-status-graph.directive.js
index f154379c84..3b5fe958c0 100644
--- a/awx/ui/static/js/directives/job-status-graph.js
+++ b/awx/ui/static/js/dashboard/graphs/job-status/job-status-graph.directive.js
@@ -15,7 +15,7 @@ function JobStatusGraph($rootScope, $compile , $location, $window, Wait, adjustG
scope: {
data: '='
},
- templateUrl: '/static/partials/job_status_graph.html',
+ templateUrl: '/static/js/dashboard/graphs/job-status/job_status_graph.partial.html',
link: link
};
@@ -38,10 +38,10 @@ function JobStatusGraph($rootScope, $compile , $location, $window, Wait, adjustG
scope.period = period;
scope.jobType = jobType;
});
+
}
function createGraph(period, jobtype, data){
-
scope.period = period;
scope.jobType = jobtype;
@@ -73,7 +73,6 @@ function JobStatusGraph($rootScope, $compile , $location, $window, Wait, adjustG
});
job_status_chart
- .margin({top: 5, right: 75, bottom: 40, left: 85}) //Adjust chart margins to give the x-axis some breathing room.
.x(function(d,i) { return i; })
.useInteractiveGuideline(true) //We want nice looking tooltips and a guideline!
.showLegend(true) //Show the legend, allowing users to turn on/off line series.
@@ -120,17 +119,23 @@ function JobStatusGraph($rootScope, $compile , $location, $window, Wait, adjustG
recreateGraph(period, job_type);
});
+ job_status_chart.legend.margin({top: 1, right:0, left:24, bottom: 0});
+
adjustGraphSize(job_status_chart, element);
+
}
function onResize() {
adjustGraphSize(job_status_chart, element);
+
}
angular.element($window).on('resize', onResize);
+ $(".DashboardGraphs-graph--jobStatusGraph").resize(onResize);
element.on('$destroy', function() {
angular.element($window).off('resize', onResize);
+ $(".DashboardGraphs-graph--jobStatusGraph").removeResize(onResize);
});
if (scope.removeGraphDataReady) {
diff --git a/awx/ui/static/js/services/job-status-graph-data.js b/awx/ui/static/js/dashboard/graphs/job-status/job-status-graph.service.js
similarity index 83%
rename from awx/ui/static/js/services/job-status-graph-data.js
rename to awx/ui/static/js/dashboard/graphs/job-status/job-status-graph.service.js
index 9c92eafd5d..85152f2825 100644
--- a/awx/ui/static/js/services/job-status-graph-data.js
+++ b/awx/ui/static/js/dashboard/graphs/job-status/job-status-graph.service.js
@@ -39,12 +39,12 @@ function JobStatusGraphData(Rest, getBasePath, processErrors, $rootScope, $q) {
setupWatcher: function(period, jobType) {
this.destroyWatcher =
$rootScope.$on('JobStatusChange-home', function() {
- getData(period, jobType).then(function(result) {
- $rootScope.
- $broadcast('DataReceived:JobStatusGraph',
- result);
- return result;
- });
+ getData(period, jobType).then(function(result) {
+ $rootScope.
+ $broadcast('DataReceived:JobStatusGraph',
+ result);
+ return result;
+ });
});
},
get: function(period, jobType) {
diff --git a/awx/ui/static/js/dashboard/graphs/job-status/job_status_graph.partial.html b/awx/ui/static/js/dashboard/graphs/job-status/job_status_graph.partial.html
new file mode 100644
index 0000000000..6c07f3674b
--- /dev/null
+++ b/awx/ui/static/js/dashboard/graphs/job-status/job_status_graph.partial.html
@@ -0,0 +1,49 @@
+
+
+
+
+
+
diff --git a/awx/ui/static/js/dashboard/graphs/job-status/main.js b/awx/ui/static/js/dashboard/graphs/job-status/main.js
new file mode 100644
index 0000000000..5758354a28
--- /dev/null
+++ b/awx/ui/static/js/dashboard/graphs/job-status/main.js
@@ -0,0 +1,8 @@
+import JobStatusGraphDirective from 'tower/dashboard/graphs/job-status/job-status-graph.directive';
+import JobStatusGraphService from 'tower/dashboard/graphs/job-status/job-status-graph.service';
+import DashboardGraphHelpers from 'tower/dashboard/graphs/graph-helpers/main';
+import ApiLoader from 'tower/shared/api-loader';
+
+export default angular.module('JobStatusGraph', [DashboardGraphHelpers.name, ApiLoader.name])
+ .directive('jobStatusGraph', JobStatusGraphDirective)
+ .service('jobStatusGraphData', JobStatusGraphService);
diff --git a/awx/ui/static/js/dashboard/graphs/main.js b/awx/ui/static/js/dashboard/graphs/main.js
new file mode 100644
index 0000000000..9442e279c8
--- /dev/null
+++ b/awx/ui/static/js/dashboard/graphs/main.js
@@ -0,0 +1,7 @@
+import hostStatus from 'tower/dashboard/graphs/host-status/main';
+import jobStatus from 'tower/dashboard/graphs/job-status/main';
+import dashboardGraphsDirective from 'tower/dashboard/graphs/dashboard-graphs.directive';
+
+export default
+ angular.module('DashboardGraphModules', [hostStatus.name, jobStatus.name])
+ .directive('dashboardGraphs', dashboardGraphsDirective);
diff --git a/awx/ui/static/js/dashboard/lists/job-templates/job-templates-list.block.less b/awx/ui/static/js/dashboard/lists/job-templates/job-templates-list.block.less
new file mode 100644
index 0000000000..b0e9bd8d52
--- /dev/null
+++ b/awx/ui/static/js/dashboard/lists/job-templates/job-templates-list.block.less
@@ -0,0 +1,124 @@
+/** @define DashboardJobTemplates */
+
+.DashboardJobTemplates {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+}
+.DashboardJobTemplates--noJobTemplates {
+ color: #8d8d8d;
+}
+
+.DashboardJobTemplates-header {
+ flex: initial;
+ margin-top: 0;
+ font-size: 20px;
+}
+
+.DashboardJobTemplates-container {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ padding-bottom: 15px;
+}
+
+.DashboardJobTemplates-item {
+ flex: 1;
+ display: flex;
+ flex-wrap: wrap;
+ padding-bottom: 7px;
+ padding-top: 5px;
+ border-bottom: 1px solid #a9a9a9;
+ align-items: center;
+}
+
+.DashboardJobTemplates-item--snapRows {
+ flex: initial;
+}
+
+.DashboardJobTemplates-item:last-of-type {
+ border-bottom: 0px;
+}
+
+.DashboardJobTemplates-seeMore {
+ padding-top: 11px;
+ padding-bottom: 11px;
+ width: ~"calc(100% + 32px)";
+ margin-left: -16px;
+ margin-bottom: -16px;
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ color: #fff;
+ font-size: 17px;
+ text-align: center;
+ background-color: #1778c3;
+}
+
+.DashboardJobTemplates-seeMore:hover {
+ font-weight: 600;
+ color: #fff;
+}
+
+
+.DashboardJobTemplates-smartStatus {
+ flex: initial;
+ width: 88px;
+ margin-left: 10px;
+}
+
+.DashboardJobTemplates-name {
+ flex: 1;
+}
+
+.DashboardJobTemplates-name:hover {
+ font-weight: 700;
+ color: #2a6496;
+ cursor: pointer;
+}
+
+
+.DashboardJobTemplates-launch {
+ font-size: 25px;
+ height: 28px;
+ width: 27px;
+ margin-left: 1px;
+ color: #1778c3;
+ margin-right: 13px;
+ flex: initial;
+}
+
+.DashboardJobTemplates-launch:hover {
+ margin-left: 0px;
+ width: 28px;
+ font-size: 28px;
+ color: #2a6496;
+ cursor: pointer;
+}
+
+@media only screen and (max-width: 710px) {
+ .DashboardJobTemplates-item {
+ padding-bottom: 9px;
+ padding-top: 7px;
+ }
+
+ .DashboardJobTemplates-name {
+ font-size:19px;
+ border-left: 1px solid #a9a9a9;
+ padding-left: 14px;
+ }
+
+ .DashboardJobTemplates-launch {
+ font-size: 35px;
+ height: 35px;
+ width: 30px;
+ margin-left: 10px;
+ margin-right: 16px;
+ }
+
+ .DashboardJobTemplates-launch:hover {
+ margin-left: 9px;
+ width: 31px;
+ font-size: 38px;
+ }
+}
diff --git a/awx/ui/static/js/dashboard/lists/job-templates/job-templates-list.directive.js b/awx/ui/static/js/dashboard/lists/job-templates/job-templates-list.directive.js
new file mode 100644
index 0000000000..6dc6f20afb
--- /dev/null
+++ b/awx/ui/static/js/dashboard/lists/job-templates/job-templates-list.directive.js
@@ -0,0 +1,47 @@
+/* jshint unused: vars */
+export default
+ [ "PlaybookRun",
+ function JobTemplatesList(PlaybookRun) {
+ return {
+ restrict: 'E',
+ link: link,
+ scope: {
+ data: '='
+ },
+ templateUrl: '/static/js/dashboard/lists/job-templates/job-templates-list.partial.html'
+ };
+
+ function link(scope, element, attr) {
+ scope.$watch("data", function(data) {
+ if (data) {
+ if (data.length > 0) {
+ createList(data);
+ scope.noJobTemplates = false;
+ } else {
+ scope.noJobTemplates = true;
+ }
+ }
+ });
+
+ function createList(list) {
+ // smartStatus?, launchUrl, editUrl, name
+ scope.job_templates = _.map(list, function(job_template){ return {
+ recent_jobs: job_template.summary_fields.recent_jobs,
+ launch_url: job_template.url,
+ edit_url: job_template.url.replace('api/v1', '#'),
+ name: job_template.name,
+ id: job_template.id
+ }; });
+
+ scope.snapRows = (list.length < 4);
+ }
+
+ scope.isSuccessful = function (status) {
+ return (status === "successful");
+ };
+
+ scope.launchJobTemplate = function(jobTemplateId){
+ PlaybookRun({ scope: scope, id: jobTemplateId });
+ };
+ }
+}];
diff --git a/awx/ui/static/js/dashboard/lists/job-templates/job-templates-list.partial.html b/awx/ui/static/js/dashboard/lists/job-templates/job-templates-list.partial.html
new file mode 100644
index 0000000000..dac0405a63
--- /dev/null
+++ b/awx/ui/static/js/dashboard/lists/job-templates/job-templates-list.partial.html
@@ -0,0 +1,28 @@
+
+
+
+
It doesn't seem like you have used any job templates.
+ You can create a job template here.
+
diff --git a/awx/ui/static/js/dashboard/lists/job-templates/main.js b/awx/ui/static/js/dashboard/lists/job-templates/main.js
new file mode 100644
index 0000000000..abf26b9c63
--- /dev/null
+++ b/awx/ui/static/js/dashboard/lists/job-templates/main.js
@@ -0,0 +1,6 @@
+import JobTemplatesListDirective from 'tower/dashboard/lists/job-templates/job-templates-list.directive';
+import systemStatus from 'tower/smart-status/main';
+import jobSubmissionHelper from 'tower/helpers/JobSubmission';
+
+export default angular.module('JobTemplatesList', [systemStatus.name, jobSubmissionHelper.name])
+ .directive('jobTemplatesList', JobTemplatesListDirective);
diff --git a/awx/ui/static/js/dashboard/lists/jobs/jobs-list.block.less b/awx/ui/static/js/dashboard/lists/jobs/jobs-list.block.less
new file mode 100644
index 0000000000..07d744ca9c
--- /dev/null
+++ b/awx/ui/static/js/dashboard/lists/jobs/jobs-list.block.less
@@ -0,0 +1,113 @@
+/** @define DashboardJobs */
+
+.DashboardJobs {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+}
+
+.DashboardJobs--noJobs {
+ color: #8d8d8d;
+}
+
+.DashboardJobs-header {
+ flex: initial;
+ margin-top: 0;
+ font-size: 20px;
+}
+
+.DashboardJobs-container {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ padding-bottom: 15px;
+}
+
+.DashboardJobs-item {
+ flex: 1;
+ display: flex;
+ flex-wrap: wrap;
+ padding-bottom: 0;
+ padding-top: 0;
+ border-bottom: 1px solid #a9a9a9;
+ align-items: center;
+}
+
+
+.DashboardJobs-item--snapRows {
+ flex: initial;
+}
+
+.DashboardJobs-itemLink {
+ flex: 2;
+ display: flex;
+ padding-bottom: 9px;
+ padding-top: 7px;
+ align-items: center;
+}
+
+.DashboardJobs-status {
+ flex: initial;
+ height: 18px;
+ width: 23px;
+ font-size: 18px;
+ margin-bottom: -3px;
+}
+
+.DashboardJobs-nameContainer {
+ flex: 1;
+ margin-left: 10px;
+}
+
+.DashboardJobs-time {
+ flex: initial;
+ text-align: right;
+ margin-bottom: 0px;
+ margin-left: 10px;
+ color: #000;
+}
+
+.DashboardJobs-itemLink:hover {
+ .DashboardJobs-nameContainer,
+ .DashboardJobs-time {
+ font-weight: 600;
+ }
+
+ .DashboardJobs-status--success {
+ color: #5DF370;
+ }
+
+ .DashboardJobs-status--failed {
+ color: #FF1105;
+ }
+}
+
+.DashboardJobs-item:last-of-type {
+ border-bottom: 0px;
+}
+
+.DashboardJobs-seeMore {
+ padding-top: 11px;
+ padding-bottom: 11px;
+ width: ~"calc(100% + 32px)";
+ margin-left: -16px;
+ margin-bottom: -16px;
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ color: #fff;
+ font-size: 17px;
+ text-align: center;
+ background-color: #1778c3;
+}
+
+.DashboardJobs-seeMore:hover {
+ font-weight: 600;
+ color: #fff;
+}
+
+@media only screen and (max-width: 710px) {
+ .DashboardJobs-nameContainer {
+ font-size: 19px;
+ }
+}
diff --git a/awx/ui/static/js/dashboard/lists/jobs/jobs-list.directive.js b/awx/ui/static/js/dashboard/lists/jobs/jobs-list.directive.js
new file mode 100644
index 0000000000..0ebdc16c7a
--- /dev/null
+++ b/awx/ui/static/js/dashboard/lists/jobs/jobs-list.directive.js
@@ -0,0 +1,42 @@
+/* jshint unused: vars */
+export default
+ [function JobsList() {
+ return {
+ restrict: 'E',
+ link: link,
+ scope: {
+ data: '='
+ },
+ templateUrl: '/static/js/dashboard/lists/jobs/jobs-list.partial.html'
+ };
+
+ function link(scope, element, attr) {
+ scope.$watch("data", function(data) {
+ if (data) {
+ if (data.length > 0) {
+ createList(data);
+ scope.noJobs = false;
+ } else {
+ scope.noJobs = true;
+ }
+ }
+ });
+
+ function createList(list) {
+ // detailsUrl, status, name, time
+ scope.jobs = _.map(list, function(job){
+ return {
+ detailsUrl: job.url.replace("api/v1", "#"),
+ status: job.status,
+ name: job.name,
+ time: moment(job.finished).fromNow()
+ }; });
+
+ scope.snapRows = (list.length < 4);
+ }
+
+ scope.isSuccessful = function (status) {
+ return (status === "successful");
+ };
+ }
+}];
diff --git a/awx/ui/static/js/dashboard/lists/jobs/jobs-list.partial.html b/awx/ui/static/js/dashboard/lists/jobs/jobs-list.partial.html
new file mode 100644
index 0000000000..8db9ef61d9
--- /dev/null
+++ b/awx/ui/static/js/dashboard/lists/jobs/jobs-list.partial.html
@@ -0,0 +1,35 @@
+
+
+
+
+
It doesn't seem like you have any recent job runs.
+
diff --git a/awx/ui/static/js/dashboard/lists/jobs/main.js b/awx/ui/static/js/dashboard/lists/jobs/main.js
new file mode 100644
index 0000000000..0c9e2d290d
--- /dev/null
+++ b/awx/ui/static/js/dashboard/lists/jobs/main.js
@@ -0,0 +1,4 @@
+import JobsListDirective from 'tower/dashboard/lists/jobs/jobs-list.directive';
+
+export default angular.module('JobsList', [])
+ .directive('jobsList', JobsListDirective);
diff --git a/awx/ui/static/js/dashboard/lists/main.js b/awx/ui/static/js/dashboard/lists/main.js
new file mode 100644
index 0000000000..ff103de668
--- /dev/null
+++ b/awx/ui/static/js/dashboard/lists/main.js
@@ -0,0 +1,5 @@
+import jobTemplates from 'tower/dashboard/lists/job-templates/main';
+import jobs from 'tower/dashboard/lists/jobs/main';
+
+export default
+ angular.module('DashboardListsModules', [jobTemplates.name, jobs.name]);
diff --git a/awx/ui/static/js/dashboard/main.js b/awx/ui/static/js/dashboard/main.js
new file mode 100644
index 0000000000..85f4c5dd10
--- /dev/null
+++ b/awx/ui/static/js/dashboard/main.js
@@ -0,0 +1,8 @@
+import dashboardCounts from 'tower/dashboard/counts/main';
+import dashboardGraphs from 'tower/dashboard/graphs/main';
+import dashboardLists from 'tower/dashboard/lists/main';
+import dashboardDirective from 'tower/dashboard/dashboard.directive';
+
+export default
+ angular.module('dashboard', [dashboardCounts.name, dashboardGraphs.name, dashboardLists.name])
+ .directive('dashboard', dashboardDirective);
diff --git a/awx/ui/static/js/directives/_dashboard-graphs.js b/awx/ui/static/js/directives/_dashboard-graphs.js
deleted file mode 100644
index ccacb29f77..0000000000
--- a/awx/ui/static/js/directives/_dashboard-graphs.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import JobStatusGraph from 'tower/directives/job-status-graph';
-import HostCountGraph from 'tower/directives/host-count-graph';
-import HostStatusGraph from 'tower/directives/host-status-graph';
-import AutoSizeModule from 'tower/directives/auto-size-module';
-import AdjustGraphSize from 'tower/services/adjust-graph-size';
-
-export default angular.module('DashboardGraphs', [])
- .directive('jobStatusGraph', JobStatusGraph)
- .directive('hostCountGraph', HostCountGraph)
- .directive('hostStatusGraph', HostStatusGraph)
- .directive('autoSizeModule', AutoSizeModule)
- .service('adjustGraphSize', AdjustGraphSize);
diff --git a/awx/ui/static/js/directives/host-count-graph.js b/awx/ui/static/js/directives/host-count-graph.js
deleted file mode 100644
index b9041fd53a..0000000000
--- a/awx/ui/static/js/directives/host-count-graph.js
+++ /dev/null
@@ -1,124 +0,0 @@
-export default
-[ 'adjustGraphSize',
- '$window',
- HostCountGraph
-];
-
-function HostCountGraph(adjustGraphSize, $window) {
-
- return {
- restrict: 'E',
- templateUrl: '/static/partials/host_count_graph.html',
- link: link
- };
-
- function link(scope, element, attr) {
- var license_graph;
-
- scope.$watch(attr.data, function(data) {
-
- if(!data) {
- return;
- }
-
- createGraph(data.hosts, data.license);
- });
-
- function onResize() {
-
- if(!license_graph) {
- return;
- }
-
- adjustGraphSize(license_graph, element);
- }
-
- angular.element($window).on('resize', onResize);
-
- element.on('$destroy', function() {
- angular.element($window).off('resize', onResize);
- });
-
-
-
- function createGraph(data, license) {
- //url = getBasePath('dashboard')+'graphs/';
- var graphData = [
- { "key" : "Hosts" ,
- "color" : "#1778c3",
- "values": data.hosts
- },
- { "key" : "License" ,
- "color" : "#171717",
- "values": data.hosts
- }
- ];
-
- graphData.map(function(series) {
- if(series.key==="Hosts"){
- series.values = series.values.map(function(d) {
- return {
- x: d[0],
- y: d[1]
- };
- });
- }
- if(series.key==="License"){
- series.values = series.values.map(function(d) {
- return {
- x: d[0],
- y: license
- };
- });
-
- }
- return series;
-
- });
-
- var width = $('.graph-container').width(), // nv.utils.windowSize().width/3,
- height = $('.graph-container').height()*0.6; //nv.utils.windowSize().height/5,
- license_graph = nv.models.lineChart()
- .margin({top: 15, right: 75, bottom: 40, left: 85})
- .x(function(d,i) { return i ;})
- .useInteractiveGuideline(true) //We want nice looking tooltips and a guideline!
- .duration(350) //how fast do you want the lines to transition?
- .showLegend(true) //Show the legend, allowing users to turn on/off line series.
- .showYAxis(true) //Show the y-axis
- .showXAxis(true) //Show the x-axis
- ;
-
- license_graph.xAxis
- .axisLabel("Time")
- .tickFormat(function(d) {
- var dx = graphData[0].values[d] && graphData[0].values[d].x || 0;
- return dx ? d3.time.format('%m/%d')(new Date(Number(dx+'000'))) : '';
- });
-
- license_graph.yAxis //Chart y-axis settings
- .axisLabel('Hosts')
- .tickFormat(d3.format('.f'));
-
- d3.select(element.find('svg')[0])
- .datum(graphData).transition()
- .attr('width', width)
- .attr('height', height)
- .duration(500)
- .call(license_graph)
- .style({
- "font-family": 'Open Sans',
- "font-style": "normal",
- "font-weight":400,
- "src": "url(/static/fonts/OpenSans-Regular.ttf)"
- });
-
-
- scope.$emit('WidgetLoaded');
-
- adjustGraphSize(license_graph, element);
-
- return license_graph;
-
- }
- }
-}
diff --git a/awx/ui/static/js/helpers/JobSubmission.js b/awx/ui/static/js/helpers/JobSubmission.js
index 3ec4b2f8ef..0185f59ac8 100644
--- a/awx/ui/static/js/helpers/JobSubmission.js
+++ b/awx/ui/static/js/helpers/JobSubmission.js
@@ -744,7 +744,7 @@ function($compile, Rest, GetBasePath, TextareaResize,CreateDialog, GenerateForm,
launch_url,
html;
scope.job_template_id = id;
- if (base === 'job_templates' || base === 'portal' || base === 'inventories') {
+ if (base === 'job_templates' || base === 'portal' || base === 'inventories' || base === 'home') {
url = GetBasePath('job_templates') + id + '/launch/';
}
else {
@@ -777,7 +777,8 @@ function($compile, Rest, GetBasePath, TextareaResize,CreateDialog, GenerateForm,
}
scope.removePlaybookLaunchFinished = scope.$on('PlaybookLaunchFinished', function(e, data) {
var job = data.job || data.system_job;
- if((scope.portalMode===false || scope.$parent.portalMode===false ) && Empty(data.system_job)){
+ if((scope.portalMode===false || scope.$parent.portalMode===false ) && Empty(data.system_job) ||
+ (base === 'home')){
$location.path('/jobs/' + job);
}
diff --git a/awx/ui/static/js/services/_data-services.js b/awx/ui/static/js/services/_data-services.js
deleted file mode 100644
index 8f61c082c7..0000000000
--- a/awx/ui/static/js/services/_data-services.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import JobStatusGraphData from 'tower/services/job-status-graph-data';
-import HostCountGraphData from 'tower/services/host-count-graph-data';
-
-export default
- angular.module('DataServices', ['ApiLoader'])
- .service('jobStatusGraphData', JobStatusGraphData)
- .service('hostCountGraphData', HostCountGraphData);
diff --git a/awx/ui/static/js/services/host-count-graph-data.js b/awx/ui/static/js/services/host-count-graph-data.js
deleted file mode 100644
index 5ace42cf47..0000000000
--- a/awx/ui/static/js/services/host-count-graph-data.js
+++ /dev/null
@@ -1,47 +0,0 @@
-export default
- [ "Rest",
- "GetBasePath",
- "ProcessErrors",
- "$q",
- HostCountGraphData
- ];
-
-function HostCountGraphData(Rest, getBasePath, processErrors, $q) {
-
- function pluck(property, promise) {
- return promise.then(function(value) {
- return value[property];
- });
- }
-
- function getLicenseData() {
- var url = getBasePath('config');
- Rest.setUrl(url);
- return Rest.get()
- .then(function (data){
- var license = data.data.license_info.instance_count;
- return license;
- });
- }
-
- function getHostData() {
- var url = getBasePath('dashboard')+'graphs/inventory/';
- Rest.setUrl(url);
- return pluck('data', Rest.get());
- }
-
- return {
- get: function() {
- return $q.all({
- license: getLicenseData(),
- hosts: getHostData()
- }).catch(function (response) {
- var errorMessage = 'Failed to get: ' + response.url + ' GET returned: ' + response.status;
- processErrors(null, response.data, response.status, null, { hdr: 'Error!',
- msg: errorMessage
- });
- return $q.reject(response);
- });
- }
- };
-}
diff --git a/awx/ui/static/js/smart-status/smart-status.directive.js b/awx/ui/static/js/smart-status/smart-status.directive.js
index f3fca643ed..73f60f7bdc 100644
--- a/awx/ui/static/js/smart-status/smart-status.directive.js
+++ b/awx/ui/static/js/smart-status/smart-status.directive.js
@@ -6,14 +6,15 @@ export default [ function() {
},
restrict: 'E',
link: function (scope, element){
-
scope.formatter = function(sparklines, options, point){
var status = options.userOptions.tooltipValueLookups.status[point.offset];
//capitalize first letter
- status = status.charAt(0).toUpperCase() + status.slice(1);
- return "Job ID: " +
- options.userOptions.tooltipValueLookups.jobs[point.offset] +
- "
Status: ●"+status+"
" ;
+ if (status) {
+ status = status.charAt(0).toUpperCase() + status.slice(1);
+ return "Job ID: " +
+ options.userOptions.tooltipValueLookups.jobs[point.offset] +
+ "
Status: ●"+status+"
" ;
+ }
};
element.sparkline(scope.sparkArray, {
diff --git a/awx/ui/static/js/widgets.js b/awx/ui/static/js/widgets.js
index 16d85acc5a..f173fb5c79 100644
--- a/awx/ui/static/js/widgets.js
+++ b/awx/ui/static/js/widgets.js
@@ -1,12 +1,6 @@
-import "tower/widgets/DashboardCounts";
-import "tower/widgets/DashboardJobs";
-import "tower/widgets/HostGraph";
-import "tower/widgets/HostPieChart";
import "tower/widgets/InventorySyncStatus";
import "tower/widgets/JobStatus";
-import "tower/widgets/JobStatusGraph";
import "tower/widgets/ObjectCount";
import "tower/widgets/PortalJobs";
import "tower/widgets/SCMSyncStatus";
import "tower/widgets/Stream";
-
diff --git a/awx/ui/static/js/widgets/DashboardCounts.js b/awx/ui/static/js/widgets/DashboardCounts.js
deleted file mode 100644
index cc8bcac3ee..0000000000
--- a/awx/ui/static/js/widgets/DashboardCounts.js
+++ /dev/null
@@ -1,60 +0,0 @@
-/*********************************************
- * Copyright (c) 2014 AnsibleWorks, Inc.
- */
- /**
- * @ngdoc overview
- * @name widgets
- * @description Various widgets, including widgets on the dashboard
- /**
- * @ngdoc function
- * @name widgets.function:DashboardCounts
- * @description
- * The dashboard widget with stats across the top
- *
- */
-
-
-
-angular.module('DashboardCountsWidget', ['RestServices', 'Utilities'])
- .factory('DashboardCounts', ['$rootScope', '$compile', 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait',
- function ($rootScope, $compile) {
- return function (params) {
-
- var scope = params.scope,
- target = params.target,
- dashboard = params.dashboard,
- html, element;
-
-
- html = "\n";
-
- html = "
\n";
- html += "
\n";
- html += "
\n";
- html += "
\n";
- html += "
\n";
- html += "
\n";
- html += "
\n";
- // html += "
\n";
- html += "
\n";
-
- html += "
\n";
-
-
- element = angular.element(document.getElementById(target));
- element.html(html);
- $compile(element)(scope);
- if(dashboard.hosts.failed>0 ){
- $('#failed-hosts').replaceWith(""+dashboard.hosts.failed+"");
- }
- if(dashboard.inventories.inventory_failed>0 ){
- $('#failed-inventories').replaceWith(""+dashboard.inventories.inventory_failed+"");
- }
- if(dashboard.projects.failed>0 ){
- $('#failed-projects').replaceWith(""+dashboard.projects.failed+"");
- }
- scope.$emit('WidgetLoaded');
-
- };
- }
- ]);
\ No newline at end of file
diff --git a/awx/ui/static/js/widgets/DashboardJobs.js b/awx/ui/static/js/widgets/DashboardJobs.js
deleted file mode 100644
index 1eeb44d040..0000000000
--- a/awx/ui/static/js/widgets/DashboardJobs.js
+++ /dev/null
@@ -1,183 +0,0 @@
-/*********************************************
- * Copyright (c) 2014 AnsibleWorks, Inc.
- */
- /**
- * @ngdoc function
- * @name widgets.function:DashboardJobs
- * @description
- *
- */
-
-
-
-angular.module('DashboardJobsWidget', ['RestServices', 'Utilities'])
-.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,
- html, e;
-
- html = '';
- html += "\n";
- html += "
\n";
- html += "- Jobs
\n";
- html += "- Schedule
\n";
- html += "
\n";
- html += "
\n";
- html += "
\n";
- html += "
\n";
- html += "
\n";
- html += "
\n"; //row
- html += "
\n";
- html += "
\n";
- html += "
\n"; //list
- html += "
\n"; //active-jobs-tab
- html += "
\n";
- html += "
\n"; // jobs-list-container
- html += "
\n";
-
- e = angular.element(document.getElementById(target));
- e.html(html);
- $compile(e)(scope);
-
- $rootScope.$on('JobStatusChange-home', function() {
- jobs_scope.refreshJobs();
- });
-
- if (scope.removeListLoaded) {
- scope.removeListLoaded();
- }
- scope.removeListLoaded = scope.$on('listLoaded', function() {
- listCount++;
- if (listCount === 1) {
- //api_complete = true;
- scope.$emit('WidgetLoaded', "dashboard_jobs", jobs_scope, scheduled_scope);
- }
- });
-
- // 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',
- url: GetBasePath('unified_jobs') + '?status__in=pending,running,completed,failed,successful,error,canceled',
- pageSize: max_rows,
- spinner: false
- });
- LoadSchedulesScope({
- parent_scope: scope,
- scope: scheduled_scope,
- list: ScheduledJobsList,
- id: 'scheduled-jobs-tab',
- url: GetBasePath('schedules') + '?next_run__isnull=false',
- pageSize: max_rows,
- spinner: false
- });
-
- $(window).resize(_.debounce(function() {
- resizeDashboardJobsWidget();
- }, 500));
- });
-
- if (scope.removeChoicesReady) {
- scope.removeChoicesReady();
- }
- scope.removeChoicesReady = scope.$on('choicesReady', function() {
- choicesCount++;
- if (choicesCount === 2) {
- setDashboardJobsHeight();
- 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'
- });
-
-
-
- // Set the height of each container and calc max number of rows containers can hold
- function setDashboardJobsHeight() {
- var docw = $(window).width(),
- box_height, available_height, search_row, page_row, height, header, row_height;
-
- available_height = Math.floor(($(window).height() - $('#main-menu-container .navbar').outerHeight() - $('#count-container').outerHeight() - 120)/2);
- $('.dashboard-jobs-list-container').height(available_height);
- search_row = Math.max($('.search-row:eq(0)').outerHeight(), 50);
- page_row = Math.max($('.page-row:eq(0)').outerHeight(), 33);
- header = Math.max($('#completed_jobs_table thead').height(), 41);
- height = Math.floor(available_height) - header - page_row - search_row -30 ;
- // if (docw < 765 && docw >= 493) {
- // row_height = 27;
- // }
- if (docw < 480) {
- row_height = 87;
- }
- else if (docw < 767) {
- row_height = 44;
- }
- else if (docw < 926) {
- row_height = 87;
- }
- else if (docw < 1200) {
- row_height = 44;
- }
- else if (docw < 1415) {
- row_height = 55;
- }
- else {
- row_height = 44;
- }
- max_rows = Math.floor(height / row_height);
- if (max_rows < 5){
- box_height = header+page_row + search_row + 40 + (5 * row_height);
- if (docw < 1140) {
- box_height += 40;
- }
- $('.dashboard-jobs-list-container').height(box_height);
- max_rows = 5;
- }
- }
-
- // Set container height and return the number of allowed rows
- function resizeDashboardJobsWidget() {
- setDashboardJobsHeight();
- jobs_scope[JobsList.iterator + '_page_size'] = max_rows;
- jobs_scope.changePageSize(JobsList.name, JobsList.iterator, false);
- scheduled_scope[ScheduledJobsList.iterator + '_page_size'] = max_rows;
- scheduled_scope.changePageSize(ScheduledJobsList.name, ScheduledJobsList.iterator, false);
- }
-
-
-
- };
-}
-]);
diff --git a/awx/ui/static/js/widgets/HostGraph.js b/awx/ui/static/js/widgets/HostGraph.js
deleted file mode 100644
index 58b38b7e18..0000000000
--- a/awx/ui/static/js/widgets/HostGraph.js
+++ /dev/null
@@ -1,180 +0,0 @@
-/*********************************************
- * Copyright (c) 2014 AnsibleWorks, Inc.
- */
- /**
- * @ngdoc function
- * @name widgets.function:HostGraph
- * @description
- *
- */
-
-
-
-
-angular.module('HostGraphWidget', ['RestServices', 'Utilities'])
- .factory('HostGraph', ['$rootScope', '$compile', '$location', 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait',
- function ($rootScope, $compile, $location, Rest, GetBasePath, ProcessErrors) {
- return function (params) {
-
- var scope = params.scope,
- target = params.target,
- html, element, url, license, license_graph;
-
-
- // html = "\n";
- html ="
\n";
- html += "
Host Count
\n";
- html += "
\n";
- html +="
\n";
- html += "
\n";
-
- // html += "
\n";
-
-
-
- element = angular.element(document.getElementById(target));
- element.html(html);
- $compile(element)(scope);
-
- url = GetBasePath('config');
-
- if (scope.removeResizeHostGraph) {
- scope.removeResizeHostGraph();
- }
- scope.removeResizeHostGraph= scope.$on('ResizeHostGraph', function () {
- if($(window).width()<500){
- $('.graph-container').height(300);
- }
- else{
- var winHeight = $(window).height(),
- available_height = winHeight - $('#main-menu-container .navbar').outerHeight() - $('#count-container').outerHeight() - 120;
- $('.graph-container').height(available_height/2);
- license_graph.update();
- }
- });
-
- Rest.setUrl(url);
- Rest.get()
- .success(function (data){
- license = data.license_info.instance_count;
- scope.$emit('licenseCountReady', license);
- })
- .error(function (data, status) {
- ProcessErrors(scope, data, status, null, { hdr: 'Error!',
- msg: 'Failed to get: ' + url + ' GET returned: ' + status });
- });
-
- if (scope.removeLicenseCountReady) {
- scope.removeLicenseCountReady();
- }
- scope.removeLicenseCountReady = scope.$on('licenseCountReady', function (e, license) {
- url = GetBasePath('dashboard')+'graphs/inventory/';
- Rest.setUrl(url);
- Rest.get()
- .success(function (data) {
- scope.$emit('hostDataReady', data, license);
- })
- .error(function (data, status) {
- ProcessErrors(scope, data, status, null, { hdr: 'Error!',
- msg: 'Failed to get: ' + url + ' GET returned: ' + status });
- });
-
- });
-
- if (scope.removeHostDataReady) {
- scope.removeHostDataReady();
- }
- scope.removeHostDataReady = scope.$on('hostDataReady', function (e, data, license) {
-
- //url = GetBasePath('dashboard')+'graphs/';
- var graphData = [
- {
- "key" : "Hosts" ,
- "color" : "#1778c3",
- "values": data.hosts
- },
- {
- "key" : "License" ,
- "color" : "#171717",
- "values": data.hosts
- }
- ];
-
- graphData.map(function(series) {
- if(series.key==="Hosts"){
- series.values = series.values.map(function(d) {
- return {
- x: d[0],
- y: d[1]
- };
- });
- }
- if(series.key==="License"){
- series.values = series.values.map(function(d) {
- return {
- x: d[0],
- y: license
- };
- });
-
- }
- return series;
-
- });
-
- nv.addGraph({
- generate: function() {
- var width = $('.graph-container').width(), // nv.utils.windowSize().width/3,
- height = $('.graph-container').height()*0.6; //nv.utils.windowSize().height/5,
- license_graph = nv.models.lineChart()
- .margin({top: 15, right: 75, bottom: 40, left: 85})
- .x(function(d,i) { return i ;})
- .useInteractiveGuideline(true) //We want nice looking tooltips and a guideline!
- .transitionDuration(350) //how fast do you want the lines to transition?
- .showLegend(true) //Show the legend, allowing users to turn on/off line series.
- .showYAxis(true) //Show the y-axis
- .showXAxis(true) //Show the x-axis
- ;
-
- license_graph.xAxis
- .axisLabel("Time")
- .tickFormat(function(d) {
- var dx = graphData[0].values[d] && graphData[0].values[d].x || 0;
- return dx ? d3.time.format('%m/%d')(new Date(Number(dx+'000'))) : '';
- });
-
- license_graph.yAxis //Chart y-axis settings
- .axisLabel('Hosts')
- .tickFormat(d3.format('.f'));
-
- d3.select('.host-count-graph svg')
- .datum(graphData).transition()
- .attr('width', width)
- .attr('height', height)
- .duration(500)
- .call(license_graph)
- .style({
- // 'width': width,
- // 'height': height,
- "font-family": 'Open Sans',
- "font-style": "normal",
- "font-weight":400,
- "src": "url(/static/fonts/OpenSans-Regular.ttf)"
- });
-
-
- // nv.utils.windowResize(license_graph.update);
- scope.$emit('WidgetLoaded');
- return license_graph;
-
- },
-
- });
- //});
- });
-
-
-
- };
- }
- ]);
\ No newline at end of file
diff --git a/awx/ui/static/js/widgets/HostPieChart.js b/awx/ui/static/js/widgets/HostPieChart.js
deleted file mode 100644
index 29625e0ea3..0000000000
--- a/awx/ui/static/js/widgets/HostPieChart.js
+++ /dev/null
@@ -1,128 +0,0 @@
-/*********************************************
- * Copyright (c) 2014 AnsibleWorks, Inc.
- */
- /**
- * @ngdoc function
- * @name widgets.function:HostPieChart
- * @description
- * HostPieChart.js
- *
- * file for the host status pie chart
- *
- */
-
-
-
-angular.module('HostPieChartWidget', ['RestServices', 'Utilities'])
- .factory('HostPieChart', ['$rootScope', '$compile',
- //'Rest', 'GetBasePath', 'ProcessErrors', 'Wait',
- function ($rootScope, $compile){
- //, Rest, GetBasePath, ProcessErrors) {
- return function (params) {
-
- var scope = params.scope,
- target = params.target,
- dashboard = params.dashboard,
- html, element, data,
- canvas, context, winHeight, available_height, host_pie_chart;
-
- // html = "
\n";
-
- html ="
\n";
- html += "
Host Status
\n";
- html += "
\n";
-
- html +="
\n";
- html += "
\n";
- html += "
\n";
-
- // html += "
\n";
-
- element = angular.element(document.getElementById(target));
- element.html(html);
- $compile(element)(scope);
-
- if (scope.removeResizeHostPieGraph) {
- scope.removeResizeHostPieGraph();
- }
- scope.removeResizeHostPieGraph= scope.$on('ResizeHostPieGraph', function () {
- if($(window).width()<500){
- $('.graph-container').height(300);
- }
- else{
- var winHeight = $(window).height(),
- available_height = winHeight - $('#main-menu-container .navbar').outerHeight() - $('#count-container').outerHeight() - 120;
- $('.graph-container').height(available_height/2);
- if(host_pie_chart){
- host_pie_chart.update();
- }
- }
- });
-
- if(dashboard.hosts.total+dashboard.hosts.failed>0){
- data = [
- {
- "label": "Successful",
- "color": "#60D66F",
- "value" : dashboard.hosts.total
- } ,
- {
- "label": "Failed",
- "color" : "#ff5850",
- "value" : dashboard.hosts.failed
- }
- ];
-
- nv.addGraph(function() {
- var width = $('.graph-container').width(), // nv.utils.windowSize().width/3,
- height = $('.graph-container').height()*0.7; //nv.utils.windowSize().height/5,
- host_pie_chart = nv.models.pieChart()
- .margin({top: 5, right: 75, bottom: 40, left: 85})
- .x(function(d) { return d.label; })
- .y(function(d) { return d.value; })
- .showLabels(true)
- .labelThreshold(0.01)
- .tooltipContent(function(x, y) {
- return '
'+x+''+ '
' + Math.floor(y.replace(',','')) + ' Hosts ' + '
';
- })
- .color(['#60D66F', '#ff5850']);
-
- host_pie_chart.pie.pieLabelsOutside(true).labelType("percent");
-
- d3.select(".host-pie-chart svg")
- .datum(data)
- .attr('width', width)
- .attr('height', height)
- .transition().duration(350)
- .call(host_pie_chart)
- .style({
- "font-family": 'Open Sans',
- "font-style": "normal",
- "font-weight":400,
- "src": "url(/static/fonts/OpenSans-Regular.ttf)"
- });
- // nv.utils.windowResize(host_pie_chart.update);
- scope.$emit('WidgetLoaded');
- return host_pie_chart;
- });
- }
- else{
- winHeight = $(window).height();
- available_height = winHeight - $('#main-menu-container .navbar').outerHeight() - $('#count-container').outerHeight() - 120;
- $('.graph-container:eq(1)').height(available_height/2);
- $('.host-pie-chart svg').replaceWith('
');
-
- canvas = document.getElementById("circlecanvas");
- context = canvas.getContext("2d");
- context.arc(55, 55, 50, 0, Math.PI * 2, false);
- context.lineWidth = 1;
- context.strokeStyle = '#1778c3';
- context.stroke();
- context.font = "12px Open Sans";
- context.fillText("No Host data",18,55);
-
- scope.$emit('WidgetLoaded');
- }
- };
- }
- ]);
diff --git a/awx/ui/static/js/widgets/JobStatusGraph.js b/awx/ui/static/js/widgets/JobStatusGraph.js
deleted file mode 100644
index d83098a55c..0000000000
--- a/awx/ui/static/js/widgets/JobStatusGraph.js
+++ /dev/null
@@ -1,219 +0,0 @@
-/*********************************************
- * Copyright (c) 2014 AnsibleWorks, Inc.
- */
- /**
- * @ngdoc function
- * @name widgets.function:JobStatusGraph
- * @description
- */
-
-
-
-
-angular.module('JobStatusGraphWidget', ['RestServices', 'Utilities'])
- .factory('JobStatusGraph', ['$rootScope', '$compile', '$location' , 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait',
- function ($rootScope, $compile , $location, Rest, GetBasePath, ProcessErrors) {
- return function (params) {
-
- var scope = params.scope,
- target = params.target,
- // dashboard = params.dashboard,
- html, element, url, job_status_chart,
- period="month",
- job_type="all";
-
- // html = "
\n";
-
- html = "
\n";
- html += "
Job Status
\n"; // for All Jobs, Past Month
-
- html += "
\n";
- html += "
\n";
-
- html += "
\n"; //end of filter div
-
- html += "
\n";
- html += "
\n";
- html += "
\n"; //end of filter div
-
- html += "
\n"; // end of row
-
- html +="
\n";
- html += "
\n";
- html += "
\n";
-
- // html += "
\n";
-
- function createGraph(){
-
- url = GetBasePath('dashboard')+'graphs/jobs/?period='+period+'&job_type='+job_type;
- Rest.setUrl(url);
- Rest.get()
- .success(function (data){
- scope.$emit('graphDataReady', data);
- return job_type, period;
-
- })
- .error(function (data, status) {
- ProcessErrors(scope, data, status, null, { hdr: 'Error!',
- msg: 'Failed to get: ' + url + ' GET returned: ' + status });
- });
- }
-
- if ($rootScope.removeReloadJobStatusGraph) {
- $rootScope.removeReloadJobStatusGraph();
- }
- $rootScope.removeReloadJobStatusGraph = $rootScope.$on('ReloadJobStatusGraph', function() {
- createGraph();
- });
-
- element = angular.element(document.getElementById(target));
- element.html(html);
- $compile(element)(scope);
-
- createGraph();
-
- if (scope.removeResizeJobGraph) {
- scope.removeResizeJobGraph();
- }
- scope.removeResizeJobGraph= scope.$on('ResizeJobGraph', function () {
- if($(window).width()<500){
- $('.graph-container').height(300);
- }
- else{
- var winHeight = $(window).height(),
- available_height = winHeight - $('#main-menu-container .navbar').outerHeight() - $('#count-container').outerHeight() - 120;
- $('.graph-container').height(available_height/2);
- job_status_chart.update();
- }
- });
-
- if (scope.removeGraphDataReady) {
- scope.removeGraphDataReady();
- }
- scope.removeGraphDataReady = scope.$on('graphDataReady', function (e, data) {
-
-
- var timeFormat, graphData = [
- {
- "color": "#60D66F",
- "key": "Successful",
- "values": data.jobs.successful
- },
- {
- "key" : "Failed" ,
- "color" : "#ff5850",
- "values": data.jobs.failed
- }
- ];
-
- if(period==="day"){
- timeFormat="%H:%M";
- }
- else {
- timeFormat = '%m/%d';
- }
- graphData.map(function(series) {
- series.values = series.values.map(function(d) {
- return {
- x: d[0],
- y: d[1]
- };
- });
- return series;
- });
-
- nv.addGraph({
- generate: function() {
- var width = $('.graph-container').width(), // nv.utils.windowSize().width/3,
- height = $('.graph-container').height()*0.7; //nv.utils.windowSize().height/5,
- job_status_chart = nv.models.lineChart()
- .margin({top: 5, right: 75, bottom: 80, left: 85}) //Adjust chart margins to give the x-axis some breathing room.
- .x(function(d,i) { return i; })
- .useInteractiveGuideline(true) //We want nice looking tooltips and a guideline!
- .transitionDuration(350) //how fast do you want the lines to transition?
- .showLegend(true) //Show the legend, allowing users to turn on/off line series.
- .showYAxis(true) //Show the y-axis
- .showXAxis(true) //Show the x-axis
- // .width(width)
- // .height(height)
- ;
-
- job_status_chart.xAxis
- .axisLabel("Time")//.showMaxMin(true)
- .tickFormat(function(d) {
- var dx = graphData[0].values[d] && graphData[0].values[d].x || 0;
- return dx ? d3.time.format(timeFormat)(new Date(Number(dx+'000'))) : '';
- });
-
- job_status_chart.yAxis //Chart y-axis settings
- .axisLabel('Jobs')
- .tickFormat(d3.format('.f'));
-
- d3.select('.job-status-graph svg')
- .datum(graphData).transition()
- .attr('width', width)
- .attr('height', height)
- .duration(1000)
- .call(job_status_chart)
- .style({
- // 'width': width,
- // 'height': height,
- "font-family": 'Open Sans',
- "font-style": "normal",
- "font-weight":400,
- "src": "url(/static/fonts/OpenSans-Regular.ttf)"
- });
-
- // when the Period drop down filter is used, create a new graph based on the
- d3.selectAll(".n")
- .on("click", function() {
- period = this.getAttribute("id");
- $('#period-dropdown').replaceWith("
"+this.text+"\n");
-
- createGraph();
- });
-
- //On click, update with new data
- d3.selectAll(".m")
- .on("click", function() {
- job_type = this.getAttribute("id");
- $('#type-dropdown').replaceWith(""+this.text+"\n");
-
- createGraph();
- });
-
- scope.$emit('WidgetLoaded');
- return job_status_chart;
-
- },
-
-
- });
-
- });
-
- };
- }
- ]);
diff --git a/awx/ui/static/less/ansible-ui.less b/awx/ui/static/less/ansible-ui.less
index f0dae5bc79..20ae33f979 100644
--- a/awx/ui/static/less/ansible-ui.less
+++ b/awx/ui/static/less/ansible-ui.less
@@ -1964,3 +1964,15 @@ tr td button i {
}
}
+
+.nvtooltip {
+ border-radius: 4px;
+}
+
+.nvtooltip td.value {
+ padding-right: 0px;
+}
+
+.nvd3 g.nv-groups path.nv-line {
+ stroke-width: 3px;
+}
diff --git a/awx/ui/static/lib/javascript-detect-element-resize/.bower.json b/awx/ui/static/lib/javascript-detect-element-resize/.bower.json
index d9ba4f7d25..b65096ef42 100644
--- a/awx/ui/static/lib/javascript-detect-element-resize/.bower.json
+++ b/awx/ui/static/lib/javascript-detect-element-resize/.bower.json
@@ -30,4 +30,4 @@
"_source": "git://github.com/sdecima/javascript-detect-element-resize.git",
"_target": "~0.5.3",
"_originalSource": "javascript-detect-element-resize"
-}
\ No newline at end of file
+}
diff --git a/awx/ui/static/lib/javascript-detect-element-resize/jquery.resize.js b/awx/ui/static/lib/javascript-detect-element-resize/jquery.resize.js
index ba42a80058..d6a6827ce0 100644
--- a/awx/ui/static/lib/javascript-detect-element-resize/jquery.resize.js
+++ b/awx/ui/static/lib/javascript-detect-element-resize/jquery.resize.js
@@ -10,9 +10,9 @@
(function ( $ ) {
var attachEvent = document.attachEvent,
stylesCreated = false;
-
+
var jQuery_resize = $.fn.resize;
-
+
$.fn.resize = function(callback) {
return this.each(function() {
if(this == window)
@@ -27,14 +27,14 @@
removeResizeListener(this, callback);
});
}
-
+
if (!attachEvent) {
var requestFrame = (function(){
var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame ||
function(fn){ return window.setTimeout(fn, 20); };
return function(fn){ return raf(fn); };
})();
-
+
var cancelFrame = (function(){
var cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame ||
window.clearTimeout;
@@ -58,7 +58,7 @@
return element.offsetWidth != element.__resizeLast__.width ||
element.offsetHeight != element.__resizeLast__.height;
}
-
+
function scrollListener(e){
var element = this;
resetTriggers(this);
@@ -73,7 +73,7 @@
}
});
};
-
+
/* Detect CSS Animations support to detect element display/re-attach */
var animation = false,
animationstring = 'animation',
@@ -84,8 +84,8 @@
pfx = '';
{
var elm = document.createElement('fakeelement');
- if( elm.style.animationName !== undefined ) { animation = true; }
-
+ if( elm.style.animationName !== undefined ) { animation = true; }
+
if( animation === false ) {
for( var i = 0; i < domPrefixes.length; i++ ) {
if( elm.style[ domPrefixes[i] + 'AnimationName' ] !== undefined ) {
@@ -99,12 +99,12 @@
}
}
}
-
+
var animationName = 'resizeanim';
var animationKeyframes = '@' + keyframeprefix + 'keyframes ' + animationName + ' { from { opacity: 0; } to { opacity: 0; } } ';
var animationStyle = keyframeprefix + 'animation: 1ms ' + animationName + '; ';
}
-
+
function createStyles() {
if (!stylesCreated) {
//opacity:0 works around a chrome bug https://code.google.com/p/chromium/issues/detail?id=286360
@@ -113,7 +113,7 @@
'.resize-triggers, .resize-triggers > div, .contract-trigger:before { content: \" \"; display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; } .resize-triggers > div { background: #eee; overflow: auto; } .contract-trigger:before { width: 200%; height: 200%; }',
head = document.head || document.getElementsByTagName('head')[0],
style = document.createElement('style');
-
+
style.type = 'text/css';
if (style.styleSheet) {
style.styleSheet.cssText = css;
@@ -125,7 +125,7 @@
stylesCreated = true;
}
}
-
+
window.addResizeListener = function(element, fn){
if (attachEvent) element.attachEvent('onresize', fn);
else {
@@ -140,7 +140,7 @@
element.appendChild(element.__resizeTriggers__);
resetTriggers(element);
element.addEventListener('scroll', scrollListener, true);
-
+
/* Listen for a css animation to detect element display/re-attach */
animationstartevent && element.__resizeTriggers__.addEventListener(animationstartevent, function(e) {
if(e.animationName == animationName)
@@ -150,7 +150,7 @@
element.__resizeListeners__.push(fn);
}
};
-
+
window.removeResizeListener = function(element, fn){
if (attachEvent) element.detachEvent('onresize', fn);
else {
@@ -161,4 +161,4 @@
}
}
}
-}( jQuery ));
\ No newline at end of file
+}( jQuery ));
diff --git a/awx/ui/static/lib/nvd3/build/nv.d3.js b/awx/ui/static/lib/nvd3/build/nv.d3.js
index f02b6d6aa6..0e27f9f1d5 100644
--- a/awx/ui/static/lib/nvd3/build/nv.d3.js
+++ b/awx/ui/static/lib/nvd3/build/nv.d3.js
@@ -11354,4 +11354,4 @@ nv.models.stackedAreaChart = function() {
};
nv.version = "1.7.1";
-})();
\ No newline at end of file
+})();
diff --git a/awx/ui/static/partials/home.html b/awx/ui/static/partials/home.html
index 21ce6c07c2..c1c9c849db 100644
--- a/awx/ui/static/partials/home.html
+++ b/awx/ui/static/partials/home.html
@@ -1,58 +1,35 @@
-
+
+
+
diff --git a/awx/ui/static/partials/host_count_graph.html b/awx/ui/static/partials/host_count_graph.html
deleted file mode 100644
index 3b154ab50a..0000000000
--- a/awx/ui/static/partials/host_count_graph.html
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
diff --git a/awx/ui/static/partials/host_status_graph.html b/awx/ui/static/partials/host_status_graph.html
deleted file mode 100644
index 57193bf023..0000000000
--- a/awx/ui/static/partials/host_status_graph.html
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
diff --git a/awx/ui/static/partials/job_status_graph.html b/awx/ui/static/partials/job_status_graph.html
deleted file mode 100644
index c57c242b30..0000000000
--- a/awx/ui/static/partials/job_status_graph.html
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
diff --git a/config/awx-munin.conf b/config/awx-munin.conf
index 833a6f36bf..90c479f77a 100644
--- a/config/awx-munin.conf
+++ b/config/awx-munin.conf
@@ -1,12 +1,17 @@
-Alias /munin /var/www/html/munin/
-
+
+Alias /munin /var/cache/munin/www
+
Order Allow,Deny
Allow from all
+ Options FollowSymLinks
AuthUserFile /var/lib/awx/.munin_htpasswd
AuthName "Munin"
AuthType Basic
require valid-user
+
+ ExpiresActive On
+ ExpiresDefault M310
+
-ScriptAlias /munin-cgi/munin-cgi-graph /var/www/cgi-bin/munin-cgi-graph
\ No newline at end of file