diff --git a/awx/ui/client/legacy-styles/ansible-ui.less b/awx/ui/client/legacy-styles/ansible-ui.less index f9e4941053..b8f9032596 100644 --- a/awx/ui/client/legacy-styles/ansible-ui.less +++ b/awx/ui/client/legacy-styles/ansible-ui.less @@ -1093,13 +1093,13 @@ input[type="checkbox"].checkbox-no-label { .icon-job-changed:before, .icon-job-ok:before, .icon-job-OK:before, + .icon-job-failed:before, .icon-job-skipped:before { content: "\f111"; } .icon-job-stopped:before, .icon-job-error:before, - .icon-job-failed:before, .icon-job-canceled:before, .icon-job-unreachable:before { content: "\f06a"; diff --git a/awx/ui/client/legacy-styles/main-layout.less b/awx/ui/client/legacy-styles/main-layout.less index 643c486a7a..e67a4d617e 100644 --- a/awx/ui/client/legacy-styles/main-layout.less +++ b/awx/ui/client/legacy-styles/main-layout.less @@ -24,6 +24,7 @@ body { padding-left: 20px; padding-right: 20px; } + #main-menu-container { .navbar { margin-bottom: 0; diff --git a/awx/ui/client/lib/nvd3/build/nv.d3.css b/awx/ui/client/lib/nvd3/build/nv.d3.css index e60a4deacc..1ba83e267d 100644 --- a/awx/ui/client/lib/nvd3/build/nv.d3.css +++ b/awx/ui/client/lib/nvd3/build/nv.d3.css @@ -35,11 +35,12 @@ svg.nvd3-svg { .nvtooltip { position: absolute; - background-color: rgba(255,255,255,1.0); + background-color: #848992; padding: 1px; - border: 1px solid rgba(0,0,0,.2); + border: 1px solid #848992; + border-radius: 5px; z-index: 10000; - + color: #ffffff; font-family: Arial; font-size: 13px; text-align: left; @@ -70,7 +71,7 @@ svg.nvd3-svg { .nvtooltip.x-nvtooltip, .nvtooltip.y-nvtooltip { - padding: 8px; + padding: 10px; } .nvtooltip h3 { @@ -127,9 +128,11 @@ svg.nvd3-svg { } .nvtooltip table td.legend-color-guide div { - width: 8px; - height: 8px; + width: 12px; + height: 12px; vertical-align: middle; + border: 1px solid #ffffff; + border-radius: 5px; } .nvtooltip .footer { @@ -569,6 +572,8 @@ svg.nvd3-svg { .nvd3.nv-historicalStockChart .nv-axis .nv-axislabel { font-weight: bold; + fill: #848992; + font-family: 'Open Sans'; } .nvd3.nv-historicalStockChart .nv-dragTarget { diff --git a/awx/ui/client/lib/nvd3/build/nv.d3.js b/awx/ui/client/lib/nvd3/build/nv.d3.js index 0e27f9f1d5..42ffed47a4 100644 --- a/awx/ui/client/lib/nvd3/build/nv.d3.js +++ b/awx/ui/client/lib/nvd3/build/nv.d3.js @@ -476,7 +476,7 @@ nv.nearestValueIndex = function (values, searchVal, threshold) { theadEnter.append("tr") .append("td") .attr("colspan",3) - .append("strong") + // .append("strong") .classed("x-value",true) .html(headerFormatter(d.value)); @@ -9744,8 +9744,8 @@ nv.models.scatterChart = function() { , showYAxis = true , rightAlignYAxis = false , tooltips = true - , tooltipX = function(key, x, y) { return '' + x + '' } - , tooltipY = function(key, x, y) { return '' + y + '' } + , tooltipX = function(key, x, y) { return '
' + date + '
' } , state = nv.utils.state() diff --git a/awx/ui/client/src/dashboard/graphs/dashboard-graphs.block.less b/awx/ui/client/src/dashboard/graphs/dashboard-graphs.block.less index 4824eec6e8..8a5e49ab1a 100644 --- a/awx/ui/client/src/dashboard/graphs/dashboard-graphs.block.less +++ b/awx/ui/client/src/dashboard/graphs/dashboard-graphs.block.less @@ -3,54 +3,76 @@ @import "../../shared/branding/colors.less"; .DashboardGraphs { - margin-top: 15px; - border: solid 1px #a9a9a9; - border-radius: 4px; + margin-top: 20px; + border: solid 1px #e1e1e1; + border-radius: 5px; + background-color: #ffffff; + padding-top:20px; + padding-left: 20px; + padding-right: 20px; } -.DashboardGraphs-tabSection { - flex: 1; +.DashboardGraphs-headerSection{ display: flex; + // align-items: baseline; + flex-direction: row; + flex-wrap: wrap; + align-items: flex-start; + justify-content: flex-start; } .DashboardGraphs-tab { - flex: 1; - padding: 10px; - border-right: solid 1px @disabled-item-border; - border-bottom: solid 1px @disabled-item-border; + color: #b7b7b7; + background-color: #ffffff; + font-size: 12px; + border: 1px solid #e1e1e1; + height: 30px; + border-radius: 5px; + margin-right: 20px; + padding-left: 10px; + padding-right: 10px; + padding-bottom: 5px; + padding-top: 5px; + transition: background-color 0.2s; + text-transform: uppercase; text-align: center; - font-size: 20px; - color: @disabled-item-text; - background-color: @disabled-item-background; + white-space: nowrap; } .DashboardGraphs-tab--firstTab { - border-top-left-radius: 4px; + width: 90px; } .DashboardGraphs-tab--lastTab { - border-top-right-radius: 4px; - border-right: 0; + width:100px; + margin-right: auto; } .DashboardGraphs-tab:hover { - color: #000; + color: #b7b7b7; + background-color: #f6f6f6; cursor: pointer; } -.DashboardGraphs-tab.is-selected { - background-color: @enabled-item-background; - color: @enabled-item-text; - border-bottom: 0; +.DashboardGraphs-tab:active { + color: #b7b7b7; + background-color: #d7d7d7; + cursor: pointer; } -.DashboardGraphs-tab.is-selected:hover { - cursor: default; +.DashboardGraphs-tab:focus { + color: #b7b7b7; +} + +.DashboardGraphs-tab.is-selected { + color: #ffffff; + background-color: #d7d7d7; } .DashboardGraphs-graphSection { display: block; flex: 1; + padding-top:20px; } .DashboardGraphs-graphContainer { @@ -63,25 +85,72 @@ display: block; } +.DashboardGraphs-filterLabelIcon{ + color: #d7d7d7; + font-size: 14px; + padding-top: 5px; +} + +.DashboardGraphs-filterLabel{ + color: #d7d7d7; + font-size: 12px; + padding-right: 10px; + padding-left: 10px; + padding-top: 2px; + text-transform: uppercase; + padding-top:5px; +} + .DashboardGraphs-graph { width: 100%; height: 100%; display: flex; flex-direction: column; - margin-bottom: 19px; - padding: 20px; +} + +.nv-axislabel { + font-weight: bold !important; + fill: #b7b7b7 !important; + font-family: 'Open Sans' !important; +} + +.nv-axis text { + fill: #b7b7b7 !important; //rgb(169, 178, 189); + font-family: 'Open Sans' !important; } .DashboardGraphs-graphToolbar { display: flex; - justify-content: flex-end; - margin-bottom: 6px; + flex-direction: row; + flex-wrap: wrap; } -.DashboardGraphs-filterDropdown { +.DashboardGraphs-filterDropdownText { flex: initial; + color: #b7b7b7; + background-color: #ffffff; font-size: 12px; - padding-right: 15px; + text-transform: uppercase; + white-space: nowrap; + padding-right: 10px; + padding-left: 10px; + height: 20px; + border: 1px solid #e1e1e1; + border-radius: 5px; + transition: background-color 0.2s; +} + +.DashboardGraphs-filterDropdownText:hover { + color: #b7b7b7; + background-color: #f6f6f6; +} + +.DashboardGraphs-filterIcon{ + color: #d7d7d7; + font-size: 14px; + width: 20px; + padding-left:10px; + padding-right: 10px; } .DashboardGraphs-filterDropdownItems { @@ -89,6 +158,15 @@ left: auto; top: auto; box-shadow: none; + text-transform: uppercase; +} + +.DashboardGraphs-periodDropdown{ + padding-top:5px; +} + +.DashboardGraphs-jobTypeDropdown{ + padding-top:5px; } .DashboardGraphs-filterDropdownItems--period { @@ -98,3 +176,41 @@ .DashboardGraphs-filterDropdownItems--jobType { margin-left: -84px; } + +.DashboardGraphs-statusFilters{ + padding-top: 5px; + +} + +.DashboardGraphs-statusFilter{ + color: #b7b7b7; + background-color: #ffffff; + font-size: 12px; + text-transform: uppercase; + padding-right: 10px; + padding-left: 10px; + height: 20px; + border: 1px solid #e1e1e1; + border-radius: 5px; + transition: background-color 0.2s; + margin-left: 10px; + line-height:1; +} + +.DashboardGraphs-statusFilter:hover{ + cursor: pointer; + background-color: #f6f6f6; +} + +.DashboardGraphs-statusFilter.is-selected { + color: #ffffff; + background-color: #d7d7d7; +} + +.DashboardGraphs-hostStatusLabel--successful{ + text-anchor: start !important; +} + +.DashboardGraphs-hostStatusLabel--failed{ + text-anchor: end !important; +} diff --git a/awx/ui/client/src/dashboard/graphs/dashboard-graphs.directive.js b/awx/ui/client/src/dashboard/graphs/dashboard-graphs.directive.js index ce0052e132..9d5405b473 100644 --- a/awx/ui/client/src/dashboard/graphs/dashboard-graphs.directive.js +++ b/awx/ui/client/src/dashboard/graphs/dashboard-graphs.directive.js @@ -12,6 +12,11 @@ export default scope.hostStatusSelected = false; } + function clearStatus() { + scope.isSuccessful = true; + scope.isFailed = true; + } + scope.toggleGraphStatus = function (graphType) { clearGraphs(); if (graphType === "jobStatus") { @@ -22,7 +27,38 @@ export default scope.$broadcast("resizeGraphs"); }; + scope.toggleJobStatusGraph = function (status) { + if (status === "successful") { + scope.isSuccessful = !scope.isSuccessful; + if(!scope.isSuccessful && scope.isFailed){ + status = 'successful'; + } + else if(scope.isSuccessful && scope.isFailed){ + status = 'both'; + } + else if(!scope.isSuccessful && !scope.isFailed){ + status = 'successful'; + scope.isFailed = true; + } + } else if (status === "failed") { + scope.isFailed = !scope.isFailed; + if(scope.isSuccessful && scope.isFailed){ + status = 'both'; + } + if(scope.isSuccessful && !scope.isFailed){ + status = 'failed'; + } + else if(!scope.isSuccessful && !scope.isFailed){ + status = 'failed'; + scope.isSuccessful = true; + } + + } + scope.$broadcast("jobStatusChange", status); + }; + // initially toggle jobStatus graph + clearStatus(); clearGraphs(); scope.toggleGraphStatus("jobStatus"); } diff --git a/awx/ui/client/src/dashboard/graphs/dashboard-graphs.partial.html b/awx/ui/client/src/dashboard/graphs/dashboard-graphs.partial.html index 5c69410f15..d8b7f49206 100644 --- a/awx/ui/client/src/dashboard/graphs/dashboard-graphs.partial.html +++ b/awx/ui/client/src/dashboard/graphs/dashboard-graphs.partial.html @@ -1,5 +1,5 @@' + Math.floor(y.replace(',','')) + ' Hosts ' + '
'; + return ''+x+'
'+ '' + Math.floor(y.replace(',','')) + ' HOSTS ' + '
'; }) - .labelType("percent") - .color(['#60D66F', '#ff5850']); + .color(colors); d3.select(element.find('svg')[0]) .datum(data) @@ -88,6 +110,33 @@ function HostStatusGraph($compile, $window, adjustGraphSize, templateUrl) { "font-weight":400, "src": "url(/static/assets/OpenSans-Regular.ttf)" }); + if(scope.status === "failed"){ + color = "#ff5850"; + } + else{ + color = "#5bbdbf"; + } + + d3.select(element.find(".nv-label text")[0]) + .attr("class", "DashboardGraphs-hostStatusLabel--successful") + .style({ + "font-family": 'Open Sans', + "text-anchor": "start", + "font-size": "16px", + "text-transform" : "uppercase", + "fill" : color, + "src": "url(/static/assets/OpenSans-Regular.ttf)" + }); + d3.select(element.find(".nv-label text")[1]) + .attr("class", "DashboardGraphs-hostStatusLabel--failed") + .style({ + "font-family": 'Open Sans', + "text-anchor" : "end !imporant", + "font-size": "16px", + "text-transform" : "uppercase", + "fill" : "#ff5850", + "src": "url(/static/assets/OpenSans-Regular.ttf)" + }); adjustGraphSize(); return host_pie_chart; diff --git a/awx/ui/client/src/dashboard/graphs/host-status/host_status_graph.partial.html b/awx/ui/client/src/dashboard/graphs/host-status/host_status_graph.partial.html index c02f102eea..4f7c406a66 100644 --- a/awx/ui/client/src/dashboard/graphs/host-status/host_status_graph.partial.html +++ b/awx/ui/client/src/dashboard/graphs/host-status/host_status_graph.partial.html @@ -1 +1 @@ - + diff --git a/awx/ui/client/src/dashboard/graphs/job-status/job-status-graph.directive.js b/awx/ui/client/src/dashboard/graphs/job-status/job-status-graph.directive.js index 4c86c1e999..c8297b6f48 100644 --- a/awx/ui/client/src/dashboard/graphs/job-status/job-status-graph.directive.js +++ b/awx/ui/client/src/dashboard/graphs/job-status/job-status-graph.directive.js @@ -34,35 +34,46 @@ function JobStatusGraph($rootScope, $compile , $location, $window, Wait, adjustG scope.$watch('data', function(value) { if (value) { - createGraph(scope.period, scope.jobType, value); + createGraph(scope.period, scope.jobType, value, scope.status); } }, true); - function recreateGraph(period, jobType) { - graphDataService.get(period, jobType) + function recreateGraph(period, jobType, status) { + graphDataService.get(period, jobType, status) .then(function(data) { scope.data = data; scope.period = period; scope.jobType = jobType; + scope.status = status; }); - } - function createGraph(period, jobtype, data){ + scope.$on('jobStatusChange', function(event, status){ + recreateGraph(scope.period, scope.jobType, status); + }); + + function createGraph(period, jobtype, data, status){ scope.period = period; scope.jobType = jobtype; + scope.status = status; var timeFormat, graphData = [ - { "color": "#60D66F", - "key": "Successful", + { "color": "#5bbdbf", + "key": "SUCCESSFUL", "values": data.jobs.successful }, - { "key" : "Failed" , + { "key" : "FAILED" , "color" : "#ff5850", "values": data.jobs.failed } ]; + graphData = _.reject(graphData, function(num){ + if(status!== undefined && status === num.key.toLowerCase()){ + return num; + } + }); + if(period==="day") { timeFormat="%H:%M"; } @@ -82,20 +93,22 @@ function JobStatusGraph($rootScope, $compile , $location, $window, Wait, adjustG job_status_chart .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. + .showLegend(false) //Show the legend, allowing users to turn on/off line series. .showYAxis(true) //Show the y-axis .showXAxis(true); //Show the x-axis + job_status_chart.interactiveLayer.tooltip.fixedTop(-10); //distance from the top of the chart to tooltip + job_status_chart.interactiveLayer.tooltip.distance(-1); //distance from interactive line to tooltip job_status_chart.xAxis - .axisLabel("Time")//.showMaxMin(true) + .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') + .axisLabel('JOBS') .tickFormat(d3.format('.f')); d3.select(element.find('svg')[0]) @@ -109,27 +122,25 @@ function JobStatusGraph($rootScope, $compile , $location, $window, Wait, adjustG }); // when the Period drop down filter is used, create a new graph based on the - d3.selectAll(element.find(".n")) - .on("click", function() { + $('.n').on("click", function(){ period = this.getAttribute("id"); - $('#period-dropdown').replaceWith(""+this.text+"\n"); - + $('#period-dropdown').replaceWith(""+this.text+ + "\n"); + scope.$parent.isFailed = true; + scope.$parent.isSuccessful = true; recreateGraph(period, job_type); }); //On click, update with new data - d3.selectAll(element.find(".m")) - .on("click", function() { + $('.m').on("click", function(){ job_type = this.getAttribute("id"); - $('#type-dropdown').replaceWith(""+this.text+"\n"); - + $('#type-dropdown').replaceWith(""+this.text+ + "\n"); + scope.$parent.isFailed = true; + scope.$parent.isSuccessful = true; recreateGraph(period, job_type); }); - - job_status_chart.legend.margin({top: 1, right:0, left:24, bottom: 0}); - adjustGraphSize(job_status_chart, element); - } function onResize() { diff --git a/awx/ui/client/src/dashboard/graphs/job-status/job-status-graph.service.js b/awx/ui/client/src/dashboard/graphs/job-status/job-status-graph.service.js index 26b5b89029..50a5a2968b 100644 --- a/awx/ui/client/src/dashboard/graphs/job-status/job-status-graph.service.js +++ b/awx/ui/client/src/dashboard/graphs/job-status/job-status-graph.service.js @@ -14,13 +14,16 @@ export default function JobStatusGraphData(Rest, getBasePath, processErrors, $rootScope, $q) { - function pluck(property, promise) { + function pluck(property, promise, status) { return promise.then(function(value) { + if(status === "successful" || status === "failed"){ + delete value[property].jobs[status]; + } return value[property]; }); } - function getData(period, jobType) { + function getData(period, jobType, status) { var url, dash_path = getBasePath('dashboard'); if(dash_path === '' ){ processErrors(null, @@ -48,7 +51,7 @@ function JobStatusGraphData(Rest, getBasePath, processErrors, $rootScope, $q) { return $q.reject(response); }); - return pluck('data', result); + return pluck('data', result, status); } return { @@ -64,12 +67,12 @@ function JobStatusGraphData(Rest, getBasePath, processErrors, $rootScope, $q) { }); }); }, - get: function(period, jobType) { + get: function(period, jobType, status) { this.destroyWatcher(); this.setupWatcher(period, jobType); - return getData(period, jobType); + return getData(period, jobType, status); } }; diff --git a/awx/ui/client/src/dashboard/graphs/job-status/job_status_graph.partial.html b/awx/ui/client/src/dashboard/graphs/job-status/job_status_graph.partial.html index 8ecfb137bf..adfd5df6dd 100644 --- a/awx/ui/client/src/dashboard/graphs/job-status/job_status_graph.partial.html +++ b/awx/ui/client/src/dashboard/graphs/job-status/job_status_graph.partial.html @@ -1,46 +1 @@ - - diff --git a/awx/ui/client/src/footer/footer.block.less b/awx/ui/client/src/footer/footer.block.less index 7276d7179a..86ca6888b5 100644 --- a/awx/ui/client/src/footer/footer.block.less +++ b/awx/ui/client/src/footer/footer.block.less @@ -2,7 +2,7 @@ .Footer { height: 40px; - background-color: #d7d7d7; + background-color: #f6f6f6; color: #848992; width: 100%; z-index: 1040; diff --git a/awx/ui/client/src/main-menu/main-menu.directive.js b/awx/ui/client/src/main-menu/main-menu.directive.js index 5f45fc7a18..80acd52a0a 100644 --- a/awx/ui/client/src/main-menu/main-menu.directive.js +++ b/awx/ui/client/src/main-menu/main-menu.directive.js @@ -62,7 +62,6 @@ export default // if the user clicks outside of the mobile menu, // close it if it's open $("body").on('click', function(e) { - e.stopPropagation(); if ($(e.target).parents(".MainMenu").length === 0) { scope.isHiddenOnMobile = true; } diff --git a/awx/ui/client/src/shared/branding/colors.less b/awx/ui/client/src/shared/branding/colors.less index 9d67873631..36868068c4 100644 --- a/awx/ui/client/src/shared/branding/colors.less +++ b/awx/ui/client/src/shared/branding/colors.less @@ -26,7 +26,7 @@ @tip-background: #0088CC; @tip-color: #fff; -@green: #60D66F; +@green: #5bbdbf; @red: #ff5850; @red-hover: #FA8C87; @red-focus: #FF1105; diff --git a/awx/ui/templates/ui/index.html b/awx/ui/templates/ui/index.html index 360b34b97f..53bc6ba1f5 100644 --- a/awx/ui/templates/ui/index.html +++ b/awx/ui/templates/ui/index.html @@ -50,9 +50,6 @@