mirror of
https://github.com/ansible/awx.git
synced 2026-01-13 02:50:02 -03:30
Revamp of the Dashboard Lists
This commit includes the face lift for the lists on the dashboard. Remaining items/Known errors are: sort doesn't work on table columns I need to remove sparklines from the project fixing column resize issues and adding ellipses for long text that overflows the table cell. adding 20px spacing between columns per request of Taufique SmartStatus "running" icon and links for jobs list removing JQuery's Sparklines lib adding more padding to main layout for nav and footer
This commit is contained in:
parent
521177130c
commit
8b3faa24e2
@ -2018,10 +2018,15 @@ button.dropdown-toggle,
|
||||
border-bottom-color: #848992;
|
||||
}
|
||||
|
||||
|
||||
.tooltip.top .tooltip-arrow {
|
||||
border-top-color: #848992;
|
||||
}
|
||||
|
||||
.tooltip.left .tooltip-arrow {
|
||||
border-left-color: #848992;
|
||||
}
|
||||
|
||||
.tooltip.Tooltip.fade.bottom.in {
|
||||
opacity: 1;
|
||||
padding-top: 4px;
|
||||
|
||||
@ -13,10 +13,11 @@ body {
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-weight: 400;
|
||||
color: @black;
|
||||
padding-top: 50px;
|
||||
padding-top: 60px;
|
||||
min-height: 100%;
|
||||
padding-bottom: 40px;
|
||||
padding-bottom: 50px;
|
||||
position: relative;
|
||||
background-color: #f6f6f6;
|
||||
}
|
||||
|
||||
#main-menu-container {
|
||||
|
||||
@ -1,24 +0,0 @@
|
||||
{
|
||||
"name": "kapusta-jquery.sparkline",
|
||||
"version": "2.1.3",
|
||||
"main": "dist/jquery.sparkline.min.js",
|
||||
"ignore": [
|
||||
"Changelog.txt",
|
||||
"Gruntfile.js",
|
||||
"package.json",
|
||||
".gitignore",
|
||||
"bower.json",
|
||||
"package.json",
|
||||
"src"
|
||||
],
|
||||
"homepage": "https://github.com/kapusta/jquery.sparkline",
|
||||
"_release": "2.1.3",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "2.1.3",
|
||||
"commit": "1d1d6a7db64b36e342141a4a5db73390fc8baf2f"
|
||||
},
|
||||
"_source": "git://github.com/kapusta/jquery.sparkline.git",
|
||||
"_target": "^2.1.3",
|
||||
"_originalSource": "kapusta-jquery.sparkline"
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
jQuery Sparklines
|
||||
=================
|
||||
|
||||
This jQuery plugin makes it easy to generate a number of different types
|
||||
of sparklines directly in the browser, using online a line of two of HTML
|
||||
and Javascript.
|
||||
|
||||
The plugin has no dependencies other than jQuery and works with all modern
|
||||
browsers and also Internet Explorer 6 and later (excanvas is not required
|
||||
for IE support).
|
||||
|
||||
See the [jQuery Sparkline project page](http://omnipotent.net/jquery.sparkline/)
|
||||
for live examples and documentation.
|
||||
|
||||
## License
|
||||
|
||||
Released under the New BSD License
|
||||
|
||||
(c) Splunk, Inc 2012
|
||||
|
||||
|
||||
## About this fork
|
||||
|
||||
* The intent of this fork is to build the Javascript files with Grunt 0.4 and to check the built files into the repo.
|
||||
* The min file is minified using [UglifyJS](https://github.com/mishoo/UglifyJS) with default settings.
|
||||
* Checking in built files is [not what the original author wants](https://github.com/gwatts/jquery.sparkline/pull/77) in his repo.
|
||||
* So why does this fork do that? Well, the built files will then be available to developers who use jquery.sparkline and use Bower for dependency management and Grunt to pluck the files they need in their project. This lets the developer avoid having to run Grunt in dependency directories (eg, node_modules) before running their own builds.
|
||||
* In order to allow for tag level targeting via Bower, new tags will be made, starting at 2.1.3
|
||||
@ -1,6 +0,0 @@
|
||||
{
|
||||
"name": "kapusta-jquery.sparkline",
|
||||
"version": "2.1.3",
|
||||
"main": "dist/jquery.sparkline.min.js",
|
||||
"ignore": ["Changelog.txt", "Gruntfile.js", "package.json", ".gitignore", "bower.json", "package.json", "src"]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -21,16 +21,17 @@
|
||||
}
|
||||
|
||||
.Dashboard-list {
|
||||
border: 1px solid #a9a9a9;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #e1e1e1;
|
||||
border-radius: 5px;
|
||||
margin-top: 15px;
|
||||
width: 50%;
|
||||
padding: 15px;
|
||||
// padding: 20px;
|
||||
background-color: #ffffff;
|
||||
max-width: ~"calc(50% - 7px)";
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 710px) {
|
||||
@media only screen and (max-width: 865px) {
|
||||
.Dashboard-counts {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
|
||||
176
awx/ui/client/src/dashboard/lists/dashboard-list.block.less
Normal file
176
awx/ui/client/src/dashboard/lists/dashboard-list.block.less
Normal file
@ -0,0 +1,176 @@
|
||||
/** @define DashboardList */
|
||||
|
||||
.DashboardList {
|
||||
flex: 1;
|
||||
}
|
||||
.DashboardList--noJobTemplates {
|
||||
color: #8d8d8d;
|
||||
}
|
||||
|
||||
.DashboardList-header {
|
||||
display: flex;
|
||||
border-bottom: 1px solid #e1e1e1;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.DashboardList-headerText {
|
||||
flex: 1;
|
||||
margin: 0px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: #b7b7b7;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
white-space: nowrap;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.DashboardList-viewAll {
|
||||
color: #b7b7b7;
|
||||
background-color: #ffffff;
|
||||
font-size: 12px;
|
||||
border: 1px solid #e1e1e1;
|
||||
border-radius: 5px;
|
||||
margin-right: 15px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
padding-bottom: 5px;
|
||||
padding-top: 5px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.DashboardList-viewAll:hover {
|
||||
color: #b7b7b7;
|
||||
background-color: #f6f6f6;
|
||||
}
|
||||
|
||||
.DashboardList-container {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.DashboardList-table{
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.DashboardList-tableHeader{
|
||||
height: 30px;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
text-transform: uppercase;
|
||||
color: #ffffff;
|
||||
background-color: #d7d7d7;
|
||||
}
|
||||
|
||||
.DashboardList-tableHeader--name{
|
||||
border-top-left-radius: 5px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
.DashboardList-tableHeader--activity{
|
||||
width: 205px;
|
||||
padding-left:20px
|
||||
}
|
||||
|
||||
.DashboardList-tableHeader--time{
|
||||
width: 190px;
|
||||
padding-left:20px;
|
||||
}
|
||||
|
||||
.DashboardList-tableHeader--actions{
|
||||
border-top-right-radius: 5px;
|
||||
width: 90px;
|
||||
padding-right: 15px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.DashboardList-tableRow{
|
||||
height: 50px;
|
||||
font-size: 14px;
|
||||
color: #161b1f;
|
||||
}
|
||||
|
||||
.DashboardList-tableRow--evenRow{
|
||||
background-color: #f6f6f6;
|
||||
}
|
||||
|
||||
.DashboardList-status{
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.DashboardList-status--success{
|
||||
color: #5bbdbf;
|
||||
}
|
||||
|
||||
.DashboardList-status--failed{
|
||||
color: #ff5850;
|
||||
}
|
||||
|
||||
.DashboardList-nameCell {
|
||||
padding-left: 15px;
|
||||
text-overflow: ellipsis;
|
||||
overflow:hidden;
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.DashboardList-nameContainer {
|
||||
color: #1678c4;
|
||||
}
|
||||
|
||||
.DashboardList-activityCell{
|
||||
padding-right: 20px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.DashboardList-timeCell {
|
||||
white-space: nowrap;
|
||||
padding-right: 20px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.DashboardList-nameContainer:hover {
|
||||
color: #5ca6db;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.DashboardList-actionButtonCell{
|
||||
padding-top:10px;
|
||||
padding-right: 15px;
|
||||
display:flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.DashboardList-actionButton{
|
||||
font-size: 16px;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
color: #b7b7b7;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #e1e1e1;
|
||||
border-radius: 50%;
|
||||
transition: background-color 0.2s, border-color 0.2s;;
|
||||
}
|
||||
|
||||
.DashboardList-actionButton:hover{
|
||||
background-color: #1678c4;
|
||||
color: #ffffff;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.DashboardList-actionButton--launch {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.DashboardList-actionButton--edit:hover {
|
||||
background-color: #1678c4;
|
||||
color: #ffffff;
|
||||
border: 1px solid #1678c4;
|
||||
}
|
||||
|
||||
.DashboardList-noJobs{
|
||||
color: #b7b7b7;
|
||||
}
|
||||
@ -1,129 +0,0 @@
|
||||
/** @define DashboardJobTemplates */
|
||||
|
||||
.DashboardJobTemplates {
|
||||
flex: 1;
|
||||
}
|
||||
.DashboardJobTemplates--noJobTemplates {
|
||||
color: #8d8d8d;
|
||||
}
|
||||
|
||||
.DashboardJobTemplates-header {
|
||||
flex: initial;
|
||||
margin-top: 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.DashboardJobTemplates-container {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
padding-bottom: 42px;
|
||||
}
|
||||
|
||||
.DashboardJobTemplates-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding-bottom: 7px;
|
||||
padding-top: 5px;
|
||||
border-bottom: 1px solid #a9a9a9;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.DashboardJobTemplates-item--snapRows {
|
||||
flex: initial;
|
||||
}
|
||||
|
||||
.DashboardJobTemplates-item:last-of-type {
|
||||
border-bottom: 0px;
|
||||
}
|
||||
|
||||
.DashboardJobTemplates-seeMore {
|
||||
padding-top: 11px;
|
||||
padding-bottom: 11px;
|
||||
width: ~"calc(100% + 2px)";
|
||||
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;
|
||||
display: block;
|
||||
position: absolute;
|
||||
max-width: ~"calc(100% + 2px)";
|
||||
bottom: 16px;
|
||||
}
|
||||
|
||||
.DashboardJobTemplates-seeMore:hover {
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
|
||||
.DashboardJobTemplates-smartStatus {
|
||||
flex: initial;
|
||||
width: 88px;
|
||||
margin-left: 10px;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.DashboardJobTemplates-name {
|
||||
max-width: 100%;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.DashboardJobTemplates-nameContainer {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.DashboardJobTemplates-name:hover {
|
||||
color: #2a6496;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.DashboardJobTemplates-launch {
|
||||
font-size: 25px;
|
||||
height: 28px;
|
||||
width: 27px;
|
||||
margin-left: 1px;
|
||||
color: #1778c3;
|
||||
margin-right: 13px;
|
||||
flex: initial;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.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-nameContainer {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,8 @@
|
||||
export default
|
||||
[ "PlaybookRun",
|
||||
'templateUrl',
|
||||
function JobTemplatesList(PlaybookRun, templateUrl) {
|
||||
'$location',
|
||||
function JobTemplatesList(PlaybookRun, templateUrl, $location) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
link: link,
|
||||
@ -44,5 +45,9 @@ export default
|
||||
scope.launchJobTemplate = function(jobTemplateId){
|
||||
PlaybookRun({ scope: scope, id: jobTemplateId });
|
||||
};
|
||||
|
||||
scope.editJobTemplate = function (jobTemplateId) {
|
||||
$location.path( '/job_templates/' + jobTemplateId);
|
||||
};
|
||||
}
|
||||
}];
|
||||
|
||||
@ -1,28 +1,60 @@
|
||||
<div class="DashboardJobTemplates" ng-hide="noJobTemplates">
|
||||
<h3 class="DashboardJobTemplates-header">
|
||||
Recently Used Job Templates
|
||||
</h3>
|
||||
<div class="DashboardJobTemplates-container">
|
||||
<div class="DashboardJobTemplates-item"
|
||||
ng-class="{'DashboardJobTemplates-item--snapRows': {{ snapRows }}}"
|
||||
ng-repeat="job_template in job_templates">
|
||||
<i class="fa fa-rocket
|
||||
DashboardJobTemplates-launch"
|
||||
ng-click="launchJobTemplate(job_template.id)"></i>
|
||||
<a href="#/job_templates/{{ job_template.id }}" class="DashboardJobTemplates-nameContainer">
|
||||
<span class="DashboardJobTemplates-name">{{ job_template.name }}</span>
|
||||
</a>
|
||||
<aw-smart-status jobs="job_template.recent_jobs" class="DashboardJobTemplates-smartStatus"></aw-smart-status>
|
||||
</div>
|
||||
<div class="DashboardList" ng-hide="noJobTemplates">
|
||||
<div class="DashboardList-header">
|
||||
<h3 class="DashboardList-headerText">
|
||||
RECENTLY USED JOB TEMPLATES
|
||||
</h3>
|
||||
<a href="/#/job_templates" class="DashboardList-viewAll">
|
||||
VIEW ALL
|
||||
</a>
|
||||
</div>
|
||||
<div class="DashboardList-container">
|
||||
<table class="DashboardList-table">
|
||||
<tr class="DashboardList-tableHeaderRow">
|
||||
<th class="DashboardList-tableHeader DashboardList-tableHeader--name"
|
||||
ng-click="sort('job_templates','name')">
|
||||
Title
|
||||
<i class="fa fa-sort-up"></i>
|
||||
</th>
|
||||
<th class="DashboardList-tableHeader DashboardList-tableHeader--activity">
|
||||
Activity
|
||||
</th>
|
||||
<th class="DashboardList-tableHeader DashboardList-tableHeader--actions">
|
||||
Actions
|
||||
</th>
|
||||
</tr>
|
||||
<tr class="DashboardList-tableRow"
|
||||
ng-class-odd="'DashboardList-tableRow--oddRow'"
|
||||
ng-class-even="'DashboardList-tableRow--evenRow'"
|
||||
ng-repeat = "job_template in job_templates">
|
||||
<td class="DashboardList-nameCell">
|
||||
<a href="#/job_templates/{{ job_template.id }}" class="DashboardList-nameContainer">
|
||||
{{ job_template.name }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="DashboardList-activityCell">
|
||||
<aw-smart-status jobs="job_template.recent_jobs"></aw-smart-status>
|
||||
</td>
|
||||
<td class="DashboardList-actionButtonCell">
|
||||
<button class="DashboardList-actionButton DashboardList-actionButton--launch" ng-click="launchJobTemplate(job_template.id)">
|
||||
<i class="icon-launch"></i>
|
||||
</button>
|
||||
<button class="DashboardList-actionButton DashboardList-actionButton--edit"
|
||||
ng-click="editJobTemplate(job_template.id)">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<a href="/#/job_templates" class="DashboardJobTemplates-seeMore">
|
||||
See all job templates
|
||||
</a>
|
||||
</div>
|
||||
<div class="DashboardJobTemplates DashboardJobTemplates--noJobTemplates" ng-show="noJobTemplates">
|
||||
<h3 class="DashboardJobTemplates-header">
|
||||
Recently Used Job Templates
|
||||
</h3>
|
||||
<p>It doesn't seem like you have used any currently available job templates.<br />
|
||||
You can create a job template <a href="#/job_templates/add">here</a>.</p>
|
||||
<div class="DashboardList" ng-show="noJobTemplates">
|
||||
<div class="DashboardList-header">
|
||||
<h3 class="DashboardList-headerText">
|
||||
RECENTLY USED JOB TEMPLATES
|
||||
</h3>
|
||||
</div>
|
||||
<div class="DashboardList-container">
|
||||
<p class="DashboardList-noJobs">It doesn't seem like you have used any currently available job templates.<br />
|
||||
You can create a job template <a href="#/job_templates/add">here</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,117 +0,0 @@
|
||||
/** @define DashboardJobs */
|
||||
|
||||
.DashboardJobs {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.DashboardJobs--noJobs {
|
||||
color: #8d8d8d;
|
||||
}
|
||||
|
||||
.DashboardJobs-header {
|
||||
flex: initial;
|
||||
margin-top: 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.DashboardJobs-container {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
padding-bottom: 42px;
|
||||
}
|
||||
|
||||
.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;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.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: #6f6f6f;
|
||||
}
|
||||
|
||||
.DashboardJobs-itemLink:hover {
|
||||
.DashboardJobs-nameContainer {
|
||||
color: #2a6496;
|
||||
}
|
||||
|
||||
.DashboardJobs-time {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.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% + 2px)";
|
||||
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;
|
||||
display: block;
|
||||
position: absolute;
|
||||
max-width: ~"calc(100% + 2px)";
|
||||
bottom: 16px;
|
||||
}
|
||||
|
||||
.DashboardJobs-seeMore:hover {
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 710px) {
|
||||
.DashboardJobs-nameContainer {
|
||||
font-size: 19px;
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,9 @@
|
||||
/* jshint unused: vars */
|
||||
export default
|
||||
[ 'moment',
|
||||
[ '$filter',
|
||||
'templateUrl',
|
||||
function JobsList(moment, templateUrl) {
|
||||
'$location',
|
||||
function JobsList($filter, templateUrl, $location) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
link: link,
|
||||
@ -31,7 +32,8 @@ export default
|
||||
detailsUrl: job.url.replace("api/v1", "#"),
|
||||
status: job.status,
|
||||
name: job.name,
|
||||
time: moment(job.finished).fromNow()
|
||||
id: job.id,
|
||||
time: $filter('longDate')(job.finished)
|
||||
}; });
|
||||
|
||||
scope.snapRows = (list.length < 4);
|
||||
@ -40,5 +42,9 @@ export default
|
||||
scope.isSuccessful = function (status) {
|
||||
return (status === "successful");
|
||||
};
|
||||
|
||||
scope.editJob = function (jobId) {
|
||||
$location.path( '/jobs/' + jobId + "/stdout");
|
||||
};
|
||||
}
|
||||
}];
|
||||
|
||||
@ -1,35 +1,53 @@
|
||||
<div class="DashboardJobs" ng-hide="noJobs">
|
||||
<h3 class="DashboardJobs-header">
|
||||
Recent Job Runs
|
||||
</h3>
|
||||
<div class="DashboardJobs-container">
|
||||
<div class="DashboardJobs-item"
|
||||
ng-class="{'DashboardJobs-item--snapRows': {{ snapRows }}}"
|
||||
ng-repeat="job in jobs">
|
||||
<a ng-href="{{ job.detailsUrl }}"
|
||||
class="DashboardJobs-itemLink">
|
||||
<i class="fa
|
||||
DashboardJobs-status"
|
||||
ng-class="{'DashboardJobs-status--success icon-job-successful': isSuccessful(job.status),
|
||||
'DashboardJobs-status--failed icon-job-failed': !isSuccessful(job.status)}">
|
||||
</i>
|
||||
<span class="DashboardJobs-nameContainer">
|
||||
{{job.name}}
|
||||
</span>
|
||||
<div class="DashboardJobs-time">
|
||||
{{ job.time }}
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="DashboardList" ng-hide="noJobs">
|
||||
<div class="DashboardList-header">
|
||||
<h3 class="DashboardList-headerText">
|
||||
RECENT JOB RUNS
|
||||
</h3>
|
||||
<a href="/#/jobs" class="DashboardList-viewAll">
|
||||
VIEW ALL
|
||||
</a>
|
||||
</div>
|
||||
<div class="DashboardList-container">
|
||||
<table class="DashboardList-table">
|
||||
<tr>
|
||||
<th class="DashboardList-tableHeader DashboardList-tableHeader--name" ng-click="sort('job_templates','name')">Title <i class="fa fa-sort-up"></i></th>
|
||||
<th class="DashboardList-tableHeader DashboardList-tableHeader--time">Time</th>
|
||||
<th class="DashboardList-tableHeader DashboardList-tableHeader--actions">Actions</th>
|
||||
</tr>
|
||||
<tr class="DashboardList-tableRow"
|
||||
ng-class-odd="'DashboardList-tableRow--oddRow'"
|
||||
ng-class-even="'DashboardList-tableRow--evenRow'"
|
||||
ng-repeat = "job in jobs">
|
||||
<td class="DashboardList-nameCell">
|
||||
<i class="fa
|
||||
DashboardList-status"
|
||||
ng-class="{'DashboardList-status--success icon-job-successful': isSuccessful(job.status),
|
||||
'DashboardList-status--failed icon-job-successful': !isSuccessful(job.status)}">
|
||||
</i>
|
||||
<a href="{{ job.detailsUrl }}" class="DashboardList-nameContainer">
|
||||
{{ job.name }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="DashboardList-timeCell">
|
||||
{{job.time}}
|
||||
</td>
|
||||
<td class="DashboardList-actionButtonCell">
|
||||
<button class="DashboardList-actionButton DashboardList-actionButton--edit" ng-click="editJob(job.id)">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<a href="/#/jobs" class="DashboardJobs-seeMore">
|
||||
See all job runs
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="DashboardJobs DashboardJobs--noJobs" ng-show="noJobs">
|
||||
<h3 class="DashboardJobs-header">
|
||||
Recent Job Runs
|
||||
</h3>
|
||||
<p>It doesn't seem like you have any recent job runs.</p>
|
||||
<div class="DashboardList" ng-show="noJobs">
|
||||
<div class="DashboardList-header">
|
||||
<h3 class="DashboardList-headerText">
|
||||
RECENT JOB RUNS
|
||||
</h3>
|
||||
</div>
|
||||
<div class="DashboardList-container">
|
||||
<p class="DashboardList-noJobs">It doesn't seem like you have any recent job runs.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -494,9 +494,10 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'JobsHelper'])
|
||||
placement = (attrs.placement !== undefined && attrs.placement !== null) ? attrs.placement : 'left';
|
||||
}
|
||||
|
||||
var template;
|
||||
if (attrs.tooltipInnerClass) {
|
||||
template = '<div class="tooltip Tooltip" role="tooltip"><div class="tooltip-arrow Tooltip-arrow"></div><div class="tooltip-inner Tooltip-inner ' + attrs.tooltipInnerClass + '"></div></div>';
|
||||
var template, custom_class;
|
||||
if (attrs.tooltipInnerClass || attrs.tooltipinnerclass) {
|
||||
custom_class = attrs.tooltipInnerClass || attrs.tooltipinnerclass;
|
||||
template = '<div class="tooltip Tooltip" role="tooltip"><div class="tooltip-arrow Tooltip-arrow"></div><div class="tooltip-inner Tooltip-inner ' + custom_class + '"></div></div>';
|
||||
} else {
|
||||
template = '<div class="tooltip Tooltip" role="tooltip"><div class="tooltip-arrow Tooltip-arrow"></div><div class="tooltip-inner Tooltip-inner"></div></div>';
|
||||
}
|
||||
|
||||
56
awx/ui/client/src/smart-status/smart-status.block.less
Normal file
56
awx/ui/client/src/smart-status/smart-status.block.less
Normal file
@ -0,0 +1,56 @@
|
||||
/** @define smartStatus */
|
||||
@import "awx/ui/client/legacy-styles/animations.less";
|
||||
|
||||
.smartStatus-container{
|
||||
max-width: 165px;
|
||||
display:flex;
|
||||
}
|
||||
|
||||
.smartStatus-iconContainer{
|
||||
padding: 2px;
|
||||
flex: 0 1 auto;
|
||||
}
|
||||
|
||||
.smartStatus--success{
|
||||
color: #5bbdbf;
|
||||
margin-bottom: 20px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.smartStatus--failed{
|
||||
color: #ff5850;
|
||||
margin-top: 20px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.smartStatus--running{
|
||||
color: #5bbdbf;
|
||||
margin-top: 10px;
|
||||
padding: 0px;
|
||||
.pulsate();
|
||||
}
|
||||
|
||||
.smartStatus-tooltip{
|
||||
text-align: left;
|
||||
max-width: 250px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.smartStatus-tooltip--success{
|
||||
color: #5bbdbf;
|
||||
padding-left: 5px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.smartStatus-tooltip--failed{
|
||||
color: #ff5850;
|
||||
padding-left: 5px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.smartStatus-tooltip--running{
|
||||
color: #5bbdbf;
|
||||
padding-left: 5px;
|
||||
padding-right: 0px;
|
||||
.pulsate();
|
||||
}
|
||||
@ -20,25 +20,23 @@ export default ['$scope', '$filter',
|
||||
|
||||
if (job.status === 'successful') {
|
||||
data.value = 1;
|
||||
data.smartStatus = "<i class=\"fa DashboardList-status smartStatus-tooltip--success icon-job-successful\"></i> " + job.status.charAt(0).toUpperCase() + job.status.slice(1);
|
||||
} else if (isFailureState(job.status)) {
|
||||
data.value = -1;
|
||||
data.smartStatus = "<i class=\"fa DashboardList-status smartStatus-tooltip--failed icon-job-successful\"></i> " + job.status.charAt(0).toUpperCase() + job.status.slice(1);
|
||||
} else {
|
||||
data.value = 0;
|
||||
data.smartStatus = "<i class=\"fa DashboardList-status smartStatus-tooltip--running icon-job-successful\"></i> " + job.status.charAt(0).toUpperCase() + job.status.slice(1);
|
||||
}
|
||||
|
||||
data.jobId = job.id;
|
||||
data.smartStatus = job.status;
|
||||
data.sortDate = job.finished || "running" + data.jobId;
|
||||
data.finished = $filter('longDate')(job.finished) || "running";
|
||||
data.finished = $filter('longDate')(job.finished) || job.status+"";
|
||||
|
||||
return data;
|
||||
}), "sortDate").reverse();
|
||||
|
||||
$scope.sparkArray = _.pluck(sparkData, 'value');
|
||||
$scope.jobIds = _.pluck(sparkData, 'jobId');
|
||||
$scope.smartStatus = _.pluck(sparkData, 'smartStatus');
|
||||
$scope.finished = _.pluck(sparkData, 'finished');
|
||||
|
||||
$scope.sparkArray = sparkData;
|
||||
}];
|
||||
|
||||
//
|
||||
|
||||
@ -5,61 +5,14 @@
|
||||
*************************************************/
|
||||
|
||||
import smartStatusController from './smart-status.controller';
|
||||
export default [ function() {
|
||||
export default [ 'templateUrl',
|
||||
function(templateUrl) {
|
||||
return {
|
||||
scope: {
|
||||
jobs: '='
|
||||
},
|
||||
templateUrl: templateUrl('smart-status/smart-status'),
|
||||
restrict: 'E',
|
||||
link: function (scope, element){
|
||||
scope.formatter = function(sparklines, options, point){
|
||||
var status = options.userOptions.tooltipValueLookups.status[point.offset],
|
||||
finished = options.userOptions.tooltipValueLookups.finished[point.offset];
|
||||
//capitalize first letter
|
||||
if (status) {
|
||||
status = status.charAt(0).toUpperCase() + status.slice(1);
|
||||
var tooltip = "<div class=\"smart-status-tooltip\">Job ID: " +
|
||||
options.userOptions.tooltipValueLookups.jobs[point.offset] +
|
||||
"<br>Status: <span style=\"color: " + point.color + "\">●</span>"+status;
|
||||
if (finished !== "running") {
|
||||
tooltip += "<br>Finished: " + finished +"</div>" ;
|
||||
}
|
||||
return tooltip;
|
||||
}
|
||||
};
|
||||
|
||||
element.sparkline(scope.sparkArray, {
|
||||
type: 'tristate',
|
||||
width: '4em',
|
||||
height: '2em',
|
||||
barWidth: 7,
|
||||
barSpacing: 2,
|
||||
zeroBarColor: 'grey',
|
||||
posBarColor: '#60D66F',
|
||||
negBarColor: '#ff5850',
|
||||
tooltipFormatter: scope.formatter,
|
||||
tooltipFormat: '{{value:jobs}}',
|
||||
tooltipValueLookups: {
|
||||
jobs: scope.jobIds,
|
||||
status: scope.smartStatus,
|
||||
finished: scope.finished
|
||||
}
|
||||
});
|
||||
|
||||
element.bind('sparklineClick', function(ev) {
|
||||
var sparkline = ev.sparklines[0],
|
||||
job = sparkline.getCurrentRegionFields(),
|
||||
id;
|
||||
id = sparkline.options.userOptions.tooltipValueLookups.jobs[job.offset];
|
||||
if(id === undefined){
|
||||
return;
|
||||
}
|
||||
else {
|
||||
location.href = '/#/jobs/' + id;
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
controller: smartStatusController
|
||||
};
|
||||
}];
|
||||
|
||||
20
awx/ui/client/src/smart-status/smart-status.partial.html
Normal file
20
awx/ui/client/src/smart-status/smart-status.partial.html
Normal file
@ -0,0 +1,20 @@
|
||||
<div class="smartStatus-container">
|
||||
<div ng-repeat="job in sparkArray track by $index" class='smartStatus-iconContainer'>
|
||||
<a href="#/jobs/{{ job.jobId }}"
|
||||
aw-tool-tip="
|
||||
JOB ID: {{job.jobId}} <br>STATUS: {{job.smartStatus}} <br>FINISHED: {{job.finished}}"
|
||||
aw-tip-placement="left"
|
||||
data-original-title=""
|
||||
data-trigger="hover"
|
||||
data-container="body"
|
||||
tooltipInnerClass="smartStatus-tooltip"
|
||||
title="">
|
||||
<i class="fa
|
||||
DashboardList-status"
|
||||
ng-class="{'smartStatus--success icon-job-successful': job.value === 1,
|
||||
'smartStatus--failed icon-job-successful': job.value === -1,
|
||||
'smartStatus--running icon-job-successful': job.value === 0}">
|
||||
</i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
Loading…
x
Reference in New Issue
Block a user