mirror of
https://github.com/ansible/awx.git
synced 2024-11-02 01:21:21 +03:00
Merge pull request #6447 from jaredevantabor/insights
Insights UI Integration
This commit is contained in:
commit
641099f941
61
awx/ui/client/assets/i_severity_critical.svg
Normal file
61
awx/ui/client/assets/i_severity_critical.svg
Normal file
@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 146 166"
|
||||
style="enable-background:new 0 0 146 166;"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="i_critical.svg"
|
||||
inkscape:version="0.92.1 r"><metadata
|
||||
id="metadata4612"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs4610" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1055"
|
||||
id="namedview4608"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.4216867"
|
||||
inkscape:cx="73"
|
||||
inkscape:cy="83"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="1050"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_1" /><style
|
||||
type="text/css"
|
||||
id="style4593">
|
||||
.st0{fill:#808080;}
|
||||
.st1{fill:#CC0000;}
|
||||
</style><g
|
||||
id="g4605"><path
|
||||
class="st1"
|
||||
d="M114.6,143.3H31c-7.2,0-13-4.8-13-10.6l0,0c0-5.9,5.9-10.6,13-10.6h83.6c7.2,0,13,4.8,13,10.6l0,0 C127.7,138.5,121.8,143.3,114.6,143.3z"
|
||||
id="path4597" /><path
|
||||
class="st1"
|
||||
d="M114.6,110.2H31c-7.2,0-13-4.8-13-10.6l0,0C18,93.7,23.9,89,31,89h83.6c7.2,0,13,4.8,13,10.6l0,0 C127.7,105.4,121.8,110.2,114.6,110.2z"
|
||||
id="path4599" /><path
|
||||
class="st1"
|
||||
d="M115,77.1H31.4c-7.2,0-13-4.8-13-10.6l0,0c0-5.9,5.9-10.6,13-10.6H115c7.2,0,13,4.8,13,10.6l0,0 C128,72.3,122.1,77.1,115,77.1z"
|
||||
id="path4601" /><path
|
||||
class="st1"
|
||||
d="M114.6,44H31c-7.2,0-13-4.8-13-10.6l0,0c0-5.9,5.9-10.7,13-10.7h83.6c7.2,0,13,4.8,13,10.6l0,0 C127.7,39.2,121.8,44,114.6,44z"
|
||||
id="path4603" /></g></svg>
|
After Width: | Height: | Size: 2.4 KiB |
61
awx/ui/client/assets/i_severity_high.svg
Normal file
61
awx/ui/client/assets/i_severity_high.svg
Normal file
@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 146 166"
|
||||
style="enable-background:new 0 0 146 166;"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="i_high.svg"
|
||||
inkscape:version="0.92.1 r"><metadata
|
||||
id="metadata6016"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs6014" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1055"
|
||||
id="namedview6012"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.4216867"
|
||||
inkscape:cx="73"
|
||||
inkscape:cy="83"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="1050"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_1" /><style
|
||||
type="text/css"
|
||||
id="style5999">
|
||||
.st0{fill:#808080;}
|
||||
.st1{fill:#F39800;}
|
||||
.st2{fill:#CCCCCC;}
|
||||
</style><path
|
||||
class="st1"
|
||||
d="M114.6,143.3H31c-7.2,0-13-4.8-13-10.6l0,0c0-5.9,5.9-10.6,13-10.6h83.6c7.2,0,13,4.8,13,10.6l0,0 C127.7,138.5,121.8,143.3,114.6,143.3z"
|
||||
id="path6003" /><path
|
||||
class="st1"
|
||||
d="M114.6,110.2H31c-7.2,0-13-4.8-13-10.6l0,0C18,93.7,23.9,89,31,89h83.6c7.2,0,13,4.8,13,10.6l0,0 C127.7,105.4,121.8,110.2,114.6,110.2z"
|
||||
id="path6005" /><path
|
||||
class="st1"
|
||||
d="M115,77.1H31.4c-7.2,0-13-4.8-13-10.6l0,0c0-5.9,5.9-10.6,13-10.6H115c7.2,0,13,4.8,13,10.6l0,0 C128,72.3,122.1,77.1,115,77.1z"
|
||||
id="path6007" /><path
|
||||
class="st2"
|
||||
d="M99.6,40.2H46c-4.6,0-8.4-3.1-8.4-6.8l0,0c0-3.8,3.8-6.9,8.4-6.9h53.7c4.6,0,8.4,3.1,8.4,6.8l0,0 C108.1,37.1,104.3,40.2,99.6,40.2z"
|
||||
id="path6009" /></svg>
|
After Width: | Height: | Size: 2.4 KiB |
62
awx/ui/client/assets/i_severity_low.svg
Normal file
62
awx/ui/client/assets/i_severity_low.svg
Normal file
@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 146 166"
|
||||
style="enable-background:new 0 0 146 166;"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="i_low.svg"
|
||||
inkscape:version="0.92.1 r"><metadata
|
||||
id="metadata6693"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs6691" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1055"
|
||||
id="namedview6689"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.4216867"
|
||||
inkscape:cx="73"
|
||||
inkscape:cy="83"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="1050"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_1" /><style
|
||||
type="text/css"
|
||||
id="style6674">
|
||||
.st0{fill:#808080;}
|
||||
.st1{fill:#94D400;}
|
||||
.st2{fill:#CCCCCC;}
|
||||
</style><g
|
||||
id="g6678" /><path
|
||||
class="st1"
|
||||
d="M114.6,143.3H31c-7.2,0-13-4.8-13-10.6l0,0c0-5.9,5.9-10.6,13-10.6h83.6c7.2,0,13,4.8,13,10.6l0,0 C127.7,138.5,121.8,143.3,114.6,143.3z"
|
||||
id="path6680" /><path
|
||||
class="st2"
|
||||
d="M99.6,40.2H46c-4.6,0-8.4-3.1-8.4-6.8l0,0c0-3.8,3.8-6.9,8.4-6.9h53.7c4.6,0,8.4,3.1,8.4,6.8l0,0 C108.1,37.1,104.3,40.2,99.6,40.2z"
|
||||
id="path6682" /><path
|
||||
class="st2"
|
||||
d="M99.6,73.3H46c-4.6,0-8.4-3.1-8.4-6.8l0,0c0-3.8,3.8-6.9,8.4-6.9h53.7c4.6,0,8.4,3.1,8.4,6.8l0,0 C108.1,70.2,104.3,73.3,99.6,73.3z"
|
||||
id="path6684" /><path
|
||||
class="st2"
|
||||
d="M99.6,106.4H46c-4.6,0-8.4-3.1-8.4-6.8l0,0c0-3.8,3.8-6.9,8.4-6.9h53.7c4.6,0,8.4,3.1,8.4,6.8l0,0 C108.1,103.3,104.3,106.4,99.6,106.4z"
|
||||
id="path6686" /></svg>
|
After Width: | Height: | Size: 2.4 KiB |
62
awx/ui/client/assets/i_severity_med.svg
Normal file
62
awx/ui/client/assets/i_severity_med.svg
Normal file
@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 146 166"
|
||||
style="enable-background:new 0 0 146 166;"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="i_med.svg"
|
||||
inkscape:version="0.92.1 r"><metadata
|
||||
id="metadata7574"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs7572" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="834"
|
||||
inkscape:window-height="480"
|
||||
id="namedview7570"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.4216867"
|
||||
inkscape:cx="73"
|
||||
inkscape:cy="83"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="1050"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="Layer_1" /><style
|
||||
type="text/css"
|
||||
id="style7555">
|
||||
.st0{fill:#808080;}
|
||||
.st1{fill:#DEC800;}
|
||||
.st2{fill:#CCCCCC;}
|
||||
</style><g
|
||||
id="g7559" /><path
|
||||
class="st1"
|
||||
d="M114.6,143.3H31c-7.2,0-13-4.8-13-10.6l0,0c0-5.9,5.9-10.6,13-10.6h83.6c7.2,0,13,4.8,13,10.6l0,0 C127.7,138.5,121.8,143.3,114.6,143.3z"
|
||||
id="path7561" /><path
|
||||
class="st1"
|
||||
d="M114.6,110.2H31c-7.2,0-13-4.8-13-10.6l0,0C18,93.7,23.9,89,31,89h83.6c7.2,0,13,4.8,13,10.6l0,0 C127.7,105.4,121.8,110.2,114.6,110.2z"
|
||||
id="path7563" /><path
|
||||
class="st2"
|
||||
d="M99.6,40.2H46c-4.6,0-8.4-3.1-8.4-6.8l0,0c0-3.8,3.8-6.9,8.4-6.9h53.7c4.6,0,8.4,3.1,8.4,6.8l0,0 C108.1,37.1,104.3,40.2,99.6,40.2z"
|
||||
id="path7565" /><path
|
||||
class="st2"
|
||||
d="M99.6,73.3H46c-4.6,0-8.4-3.1-8.4-6.8l0,0c0-3.8,3.8-6.9,8.4-6.9h53.7c4.6,0,8.4,3.1,8.4,6.8l0,0 C108.1,70.2,104.3,73.3,99.6,73.3z"
|
||||
id="path7567" /></svg>
|
After Width: | Height: | Size: 2.4 KiB |
@ -125,7 +125,8 @@ function(i18n) {
|
||||
awToolTip: i18n._('Please save before viewing Insights'),
|
||||
dataPlacement: 'top',
|
||||
title: i18n._('Insights'),
|
||||
skipGenerator: true
|
||||
skipGenerator: true,
|
||||
ngIf: 'host.insights_system_id!==null'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -74,6 +74,9 @@
|
||||
</td>
|
||||
<td class="List-actionsContainer">
|
||||
<div class="List-actionButtonCell List-tableCell">
|
||||
<button id="insights-action" class="List-actionButton " data-placement="top" ng-click="goToInsights(host.id)" aw-tool-tip="View Insights Data" ng-show="host.insights_system_id">
|
||||
<i class="fa fa-info"></i>
|
||||
</button>
|
||||
<button id="edit-action" class="List-actionButton " ng-class="{'List-editButton--selected' : $stateParams['host_id'] == host.id}" data-placement="top" ng-click="editHost(host.id)" aw-tool-tip="Edit host" ng-show="host.summary_fields.user_capabilities.edit">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</button>
|
||||
|
@ -65,6 +65,9 @@ function HostsList($scope, HostsList, $rootScope, GetBasePath,
|
||||
$scope.editHost = function(id){
|
||||
$state.go('hosts.edit', {host_id: id});
|
||||
};
|
||||
$scope.goToInsights = function(id){
|
||||
$state.go('hosts.edit.insights', {host_id:id});
|
||||
};
|
||||
$scope.deleteHost = function(id, name){
|
||||
var body = '<div class=\"Prompt-bodyQuery\">Are you sure you want to permanently delete the host below from the inventory?</div><div class=\"Prompt-bodyTarget\">' + $filter('sanitize')(name) + '</div>';
|
||||
var action = function(){
|
||||
|
@ -1,5 +1,12 @@
|
||||
@import "../../shared/branding/colors.default.less";
|
||||
|
||||
.InsightsLastCheck{
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding-bottom: 20px;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.InsightsNav{
|
||||
width: 100%;
|
||||
display: flex;
|
||||
@ -8,7 +15,6 @@
|
||||
flex-wrap: wrap;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
.InsightsNav-rightSide{
|
||||
@ -16,7 +22,8 @@
|
||||
display: flex;
|
||||
flex: 1 0 auto;
|
||||
flex-wrap: wrap;
|
||||
padding: 10px 0px 10px 0px
|
||||
max-width: 100%;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.InsightsNav-leftSide{
|
||||
@ -26,6 +33,45 @@
|
||||
justify-content: flex-end;
|
||||
flex-wrap: wrap;
|
||||
max-width: 100%;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.InsightsNav-badgeTitle{
|
||||
color: #707070;
|
||||
font-size: 14px;
|
||||
margin-right: 10px;
|
||||
font-weight: normal;
|
||||
text-transform: uppercase;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.InsightsIcon{
|
||||
height: 30px;
|
||||
width:30px;
|
||||
}
|
||||
|
||||
.InsightsIcon-warning{
|
||||
color:@default-warning;
|
||||
padding-right: 7px;
|
||||
}
|
||||
|
||||
.InsightsNav-anchor{
|
||||
display:flex;
|
||||
align-items: center;
|
||||
cursor:pointer;
|
||||
height: 40px;
|
||||
padding-right:10px;
|
||||
}
|
||||
|
||||
.InsightsNav-anchor.is-currentFilter{
|
||||
padding-top: 5px;
|
||||
border-bottom: 5px solid @menu-link-btm-hov;
|
||||
}
|
||||
|
||||
.InsightsNav-anchor:hover{
|
||||
background-color: @menu-link-bg-hov;
|
||||
padding-top: 5px;
|
||||
border-bottom: 5px solid @menu-link-btm-hov;
|
||||
}
|
||||
|
||||
.InsightsNav-totalIssues{
|
||||
@ -42,7 +88,7 @@
|
||||
}
|
||||
|
||||
.InsightsNav-mediumIssues{
|
||||
background-color: @default-succ;
|
||||
background-color: @insights-yellow;
|
||||
}
|
||||
|
||||
.InsightsNav-lowIssues{
|
||||
@ -52,6 +98,29 @@
|
||||
.InsightsNav-solvableBadge{
|
||||
background-color: @b7grey;
|
||||
}
|
||||
.InsightsNav-solvableBadge:last-of-type{
|
||||
margin-right: 20px;
|
||||
|
||||
.InsightsRow{
|
||||
margin-top:10px;
|
||||
}
|
||||
.InsightsRow-title{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.InsightsRow-description{
|
||||
font-size:14px;
|
||||
font-weight: bold;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.InsightsRow-category{
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.InsightsRow-body{
|
||||
padding-left: 35px;
|
||||
}
|
||||
|
||||
.InsightsRow-plan{
|
||||
padding-left: 35px;
|
||||
}
|
||||
|
@ -4,13 +4,71 @@
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
export default [
|
||||
function () {
|
||||
export default [ 'InsightsData', '$scope', 'moment', '$state', 'resourceData',
|
||||
function (data, $scope, moment, $state, resourceData) {
|
||||
|
||||
function init() {
|
||||
// $scope.insights
|
||||
|
||||
$scope.reports = data.reports;
|
||||
$scope.reports_dataset = data;
|
||||
$scope.currentFilter = "total";
|
||||
$scope.solvable_count = _.filter($scope.reports_dataset.reports, (report) => {return report.maintenance_actions.length > 0;}).length;
|
||||
$scope.not_solvable_count = _.filter($scope.reports_dataset.reports, (report) => {return report.maintenance_actions.length === 0; }).length;
|
||||
$scope.critical_count = 0 || _.filter($scope.reports_dataset.reports, (report) => {return report.rule.severity === "CRITICAL"; }).length;
|
||||
$scope.high_count = _.filter($scope.reports_dataset.reports, (report) => {return report.rule.severity === "ERROR"; }).length;
|
||||
$scope.med_count = _.filter($scope.reports_dataset.reports, (report) => {return report.rule.severity === "WARN"; }).length;
|
||||
$scope.low_count = _.filter($scope.reports_dataset.reports, (report) => {return report.rule.severity === "INFO"; }).length;
|
||||
let a = moment(), b = moment($scope.reports_dataset.last_check_in);
|
||||
$scope.last_check_in = a.diff(b, 'hours');
|
||||
$scope.inventory = resourceData.data;
|
||||
$scope.insights_credential = resourceData.data.summary_fields.insights_credential.id;
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
$scope.filter = function(filter){
|
||||
$scope.currentFilter = filter;
|
||||
if(filter === "total"){
|
||||
$scope.reports = $scope.reports_dataset.reports;
|
||||
}
|
||||
if(filter === "solvable"){
|
||||
$scope.reports = _.filter($scope.reports_dataset.reports, function(report){
|
||||
return (report.maintenance_actions.length > 0);
|
||||
});
|
||||
}
|
||||
if(filter === "not_solvable"){
|
||||
$scope.reports = _.filter($scope.reports_dataset.reports, function(report){
|
||||
return (report.maintenance_actions.length === 0);
|
||||
});
|
||||
}
|
||||
if(filter === "critical"){
|
||||
$scope.reports = _.filter($scope.reports_dataset.reports, function(report){
|
||||
return (report.rule.severity === 'CRITICAL');
|
||||
});
|
||||
}
|
||||
if(filter === "high"){
|
||||
$scope.reports = _.filter($scope.reports_dataset.reports, function(report){
|
||||
return (report.rule.severity === 'ERROR');
|
||||
});
|
||||
}
|
||||
if(filter === "medium"){
|
||||
$scope.reports = _.filter($scope.reports_dataset.reports, function(report){
|
||||
return (report.rule.severity === 'WARN');
|
||||
});
|
||||
}
|
||||
if(filter === "low"){
|
||||
$scope.reports = _.filter($scope.reports_dataset.reports, function(report){
|
||||
return (report.rule.severity === 'INFO');
|
||||
});
|
||||
}
|
||||
};
|
||||
$scope.viewDataInInsights = function(){
|
||||
window.open(`https://access.redhat.com/insights/inventory?machine=${$scope.$parent.host.insights_system_id}`, '_blank');
|
||||
};
|
||||
$scope.remediateInventory = function(inv_id, inv_name, insights_credential){
|
||||
$state.go('templates.addJobTemplate', {inventory_id: inv_id, inventory_name:inv_name, credential_id: insights_credential});
|
||||
};
|
||||
$scope.formCancel = function(){
|
||||
$state.go('inventories', null, {reload: true});
|
||||
};
|
||||
}];
|
||||
|
@ -1,20 +1,81 @@
|
||||
<div class="InsightsLastCheck"
|
||||
ng-show="isCheckingIn=false">
|
||||
<i class="fa icon-job-failed InsightsIcon-warning"></i>
|
||||
<translate>This machine has not checked in with Insights in {{last_check_in}} hours</translate>
|
||||
</div>
|
||||
<div class="InsightsNav">
|
||||
<div class="InsightsNav-rightSide">
|
||||
<div class="JobResults-badgeTitle">Total Issues</div>
|
||||
<span class="badge List-titleBadge InsightsNav-totalIssues">4</span>
|
||||
<div class="JobResults-badgeTitle">Critical</div>
|
||||
<span class="badge List-titleBadge InsightsNav-criticalIssues">1</span>
|
||||
<div class="JobResults-badgeTitle">High</div>
|
||||
<span class="badge List-titleBadge InsightsNav-highIssues">1</span>
|
||||
<div class="JobResults-badgeTitle">Medium</div>
|
||||
<span class="badge List-titleBadge InsightsNav-mediumIssues">1</span>
|
||||
<div class="JobResults-badgeTitle">Low</div>
|
||||
<span class="badge List-titleBadge InsightsNav-lowIssues">1</span>
|
||||
<div class="InsightsNav-anchor" ng-click="filter('total')"
|
||||
ng-class="{'is-currentFilter' : (currentFilter === 'total')}">
|
||||
<div class="InsightsNav-badgeTitle"><translate>Total Issues</translate></div>
|
||||
<span class="badge List-titleBadge InsightsNav-totalIssues">{{reports_dataset.reports.length}}</span>
|
||||
</div>
|
||||
|
||||
<div class="InsightsNav-anchor" ng-click="filter('critical')"
|
||||
ng-class="{'is-currentFilter' : (currentFilter === 'critical')}"
|
||||
ng-show="critical_count>0">
|
||||
<div class="InsightsNav-badgeTitle"><translate>Critical</translate></div>
|
||||
<span class="badge List-titleBadge InsightsNav-criticalIssues">{{critical_count}}</span>
|
||||
</div>
|
||||
<div class="InsightsNav-anchor" ng-click="filter('high')"
|
||||
ng-class="{'is-currentFilter' : (currentFilter === 'high')}"
|
||||
ng-show="high_count>0">
|
||||
<div class="InsightsNav-badgeTitle"><translate>High</translate></div>
|
||||
<span class="badge List-titleBadge InsightsNav-highIssues">{{high_count}}</span>
|
||||
</div>
|
||||
<div class="InsightsNav-anchor" ng-click="filter('medium')"
|
||||
ng-class="{'is-currentFilter' : (currentFilter === 'medium')}"
|
||||
ng-show="med_count>0">
|
||||
<div class="InsightsNav-badgeTitle"><translate>Medium</translate></div>
|
||||
<span class="badge List-titleBadge InsightsNav-mediumIssues">{{med_count}}</span>
|
||||
</div>
|
||||
<div class="InsightsNav-anchor" ng-click="filter('low')"
|
||||
ng-class="{'is-currentFilter' : (currentFilter === 'low')}"
|
||||
ng-show="low_count>0">
|
||||
<div class="InsightsNav-badgeTitle"><translate>Low</translate></div>
|
||||
<span class="badge List-titleBadge InsightsNav-lowIssues">{{low_count}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="InsightsNav-leftSide">
|
||||
<div class="JobResults-badgeTitle">Solvable With Playbook</div>
|
||||
<span class="badge List-titleBadge InsightsNav-solvableBadge">4</span>
|
||||
<div class="JobResults-badgeTitle">Not Solvable With Playbook</div>
|
||||
<span class="badge List-titleBadge InsightsNav-solvableBadge">1</span>
|
||||
|
||||
<div class="InsightsNav-anchor" ng-click="filter('solvable')"
|
||||
ng-class="{'is-currentFilter' : (currentFilter === 'solvable')}"
|
||||
ng-show="solvable_count>0">
|
||||
<div class="InsightsNav-badgeTitle"><translate>Solvable With Playbook</translate></div>
|
||||
<span class="badge List-titleBadge InsightsNav-solvableBadge">{{solvable_count}}</span>
|
||||
</div>
|
||||
<div class="InsightsNav-anchor" ng-click="filter('not_solvable')"
|
||||
ng-class="{'is-currentFilter' : (currentFilter === 'not_solvable')}"
|
||||
ng-show="not_solvable_count>0">
|
||||
<div class="InsightsNav-badgeTitle"><translate>Not Solvable With Playbook</translate></div>
|
||||
<span class="badge List-titleBadge InsightsNav-solvableBadge">{{not_solvable_count}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="InsightsBody">
|
||||
<div class="InsightsRow" ng-repeat="report in reports">
|
||||
<div class="InsightsRow-title">
|
||||
<img class="InsightsIcon" src="/static/assets/i_severity_critical.svg" ng-show="report.rule.severity === 'CRITICAL'"
|
||||
aw-tool-tip="Critical Risk" data-placement="right" data-original-title="" title="">
|
||||
<img class="InsightsIcon" src="/static/assets/i_severity_high.svg" ng-show="report.rule.severity === 'ERROR'"
|
||||
aw-tool-tip="High Risk" data-placement="top" data-original-title="" title="">
|
||||
<img class="InsightsIcon" src="/static/assets/i_severity_med.svg" ng-show="report.rule.severity === 'WARN'"
|
||||
aw-tool-tip="Medium Risk" data-placement="top">
|
||||
<img class="InsightsIcon" src="/static/assets/i_severity_low.svg" ng-show="report.rule.severity === 'INFO'"
|
||||
aw-tool-tip="Low Risk" data-placement="top">
|
||||
<div class="InsightsRow-description"><translate>ISSUE: {{report.rule.description}}</translate></div>
|
||||
<span class="Form-title--is_superuser">{{report.rule.category}}</span>
|
||||
</div>
|
||||
<div class="InsightsRow-body">{{report.rule.summary}}</div>
|
||||
<div ng-repeat="plan in report.maintenance_actions">
|
||||
<div class="InsightsRow-plan" ng-bind-html="plan | planFilter"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="buttons Form-buttons">
|
||||
<button type="button" class="btn btn-sm Form-primaryButton" ng-click="viewDataInInsights()"> <i class="fa fa-sign-out"></i> VIEW DATA IN INSIGHTS</button>
|
||||
<button type="button" class="btn btn-sm Form-primaryButton" ng-click="remediateInventory(inventory.id, inventory.name, insights_credential)"> REMEDIATE INVENTORY</button>
|
||||
<button type="button" class="btn btn-sm Form-cancelButton" ng-click="formCancel()"> Close</button>
|
||||
</div>
|
||||
|
@ -13,15 +13,21 @@ export default {
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
Facts: ['$stateParams', 'GetBasePath', 'Rest',
|
||||
function($stateParams, GetBasePath, Rest) {
|
||||
let ansibleFactsUrl = GetBasePath('hosts') + $stateParams.host_id + '/ansible_facts';
|
||||
Rest.setUrl(ansibleFactsUrl);
|
||||
InsightsData: ['Rest', '$stateParams', 'GetBasePath', 'ProcessErrors',
|
||||
(Rest, $stateParams, GetBasePath, ProcessErrors) => {
|
||||
var path = `${GetBasePath('hosts')}${$stateParams.host_id}/insights`;
|
||||
Rest.setUrl(path);
|
||||
return Rest.get()
|
||||
.success(function(data) {
|
||||
return data;
|
||||
.then(function(data) {
|
||||
return (data.data.insights_content);
|
||||
}).catch(function(response) {
|
||||
ProcessErrors(null, response.data, response.status, null, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to get insights info. GET returned status: ' +
|
||||
response.status
|
||||
});
|
||||
});
|
||||
}
|
||||
]
|
||||
],
|
||||
}
|
||||
};
|
||||
|
@ -5,7 +5,9 @@
|
||||
*************************************************/
|
||||
|
||||
import controller from './insights.controller';
|
||||
import planFilter from './plan-filter';
|
||||
|
||||
export default
|
||||
angular.module('insightsDashboard', [])
|
||||
.filter('planFilter', planFilter)
|
||||
.controller('InsightsController', controller);
|
||||
|
16
awx/ui/client/src/inventories/insights/plan-filter.js
Normal file
16
awx/ui/client/src/inventories/insights/plan-filter.js
Normal file
@ -0,0 +1,16 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2017 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
export default function(){
|
||||
return function(plan) {
|
||||
if(plan === null || plan === undefined){
|
||||
return "PLAN: Not Available <a href='https://access.redhat.com/insights/info/' target='_blank'>CREATE A NEW PLAN IN INSIGHTS</a>";
|
||||
} else {
|
||||
let name = (plan.maintenance_plan.name === null) ? "Unnamed Plan" : plan.maintenance_plan.name;
|
||||
return `<a href="https://access.redhat.com/insights/planner/${plan.maintenance_plan.maintenance_id}" target="_blank">${name} (${plan.maintenance_plan.maintenance_id})</a>`;
|
||||
}
|
||||
};
|
||||
}
|
@ -86,6 +86,9 @@ export default ['$scope', 'ListDefinition', '$rootScope', 'GetBasePath',
|
||||
$scope.editHost = function(id){
|
||||
$state.go('inventories.edit.hosts.edit', {host_id: id});
|
||||
};
|
||||
$scope.goToInsights = function(id){
|
||||
$state.go('inventories.edit.hosts.edit.insights', {host_id:id});
|
||||
};
|
||||
$scope.deleteHost = function(id, name){
|
||||
var body = '<div class=\"Prompt-bodyQuery\">Are you sure you want to permanently delete the host below from the inventory?</div><div class=\"Prompt-bodyTarget\">' + $filter('sanitize')(name) + '</div>';
|
||||
var action = function(){
|
||||
|
@ -125,7 +125,8 @@ function(i18n) {
|
||||
awToolTip: i18n._('Please save before viewing Insights'),
|
||||
dataPlacement: 'top',
|
||||
title: i18n._('Insights'),
|
||||
skipGenerator: true
|
||||
skipGenerator: true,
|
||||
ngIf: 'host.insights_system_id!==null'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -50,6 +50,13 @@ export default {
|
||||
fieldActions: {
|
||||
|
||||
columnClass: 'col-lg-6 col-md-4 col-sm-4 col-xs-5 text-right',
|
||||
insights: {
|
||||
ngClick: "goToInsights(host.id)",
|
||||
icon: 'fa-info',
|
||||
awToolTip: 'View Insights Data',
|
||||
dataPlacement: 'top',
|
||||
ngShow: 'host.insights_system_id'
|
||||
},
|
||||
copy: {
|
||||
mode: 'all',
|
||||
ngClick: "copyMoveHost(host.id)",
|
||||
|
@ -29,6 +29,7 @@ function InventoriesEdit($scope, $location,
|
||||
|
||||
$scope = angular.extend($scope, inventoryData);
|
||||
|
||||
$scope.credential_name = (inventoryData.summary_fields.insights_credential && inventoryData.summary_fields.insights_credential.name) ? inventoryData.summary_fields.insights_credential.name : null;
|
||||
$scope.organization_name = inventoryData.summary_fields.organization.name;
|
||||
$scope.inventory_variables = inventoryData.variables === null || inventoryData.variables === '' ? '---' : ParseVariableString(inventoryData.variables);
|
||||
$scope.parseType = 'yaml';
|
||||
@ -90,6 +91,10 @@ function InventoriesEdit($scope, $location,
|
||||
$state.go('inventories');
|
||||
};
|
||||
|
||||
$scope.remediateInventory = function(inv_id, inv_name, insights_credential){
|
||||
$state.go('templates.addJobTemplate', {inventory_id: inv_id, inventory_name:inv_name, credential_id: insights_credential});
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
export default ['$scope', '$location',
|
||||
|
@ -68,6 +68,17 @@ function(i18n, InventoryCompletedJobsList) {
|
||||
ngDisabled: '!(inventory_obj.summary_fields.user_capabilities.edit || canAdd) || !canEditOrg',
|
||||
awLookupWhen: '(inventory_obj.summary_fields.user_capabilities.edit || canAdd) && canEditOrg'
|
||||
},
|
||||
insights_credential: {
|
||||
label: i18n._('Insights Credential'),
|
||||
type: 'lookup',
|
||||
list: 'CredentialList',
|
||||
basePath: 'credentials',
|
||||
sourceModel: 'credential',
|
||||
sourceField: 'name',
|
||||
search: {
|
||||
credential_type: 13 //insights
|
||||
}
|
||||
},
|
||||
inventory_variables: {
|
||||
realName: 'variables',
|
||||
label: i18n._('Variables'),
|
||||
@ -177,6 +188,14 @@ function(i18n, InventoryCompletedJobsList) {
|
||||
skipGenerator: true
|
||||
},
|
||||
completed_jobs: completed_jobs_object
|
||||
},
|
||||
relatedButtons: {
|
||||
remediate_inventory: {
|
||||
ngClick: 'remediateInventory(id, name, insights_credential)',
|
||||
ngShow: 'insights_credential!==null',
|
||||
label: i18n._('Remediate Inventory'),
|
||||
class: 'Form-primaryButton'
|
||||
}
|
||||
}
|
||||
|
||||
};}];
|
||||
|
@ -7,9 +7,10 @@
|
||||
export default ['$scope', '$location', '$stateParams', 'GenerateForm',
|
||||
'ProjectsForm', 'Rest', 'Alert', 'ProcessErrors', 'GetBasePath',
|
||||
'GetProjectPath', 'GetChoices', 'Wait', '$state', 'CreateSelect2', 'i18n',
|
||||
'CredentialTypes',
|
||||
function($scope, $location, $stateParams, GenerateForm, ProjectsForm, Rest,
|
||||
Alert, ProcessErrors, GetBasePath, GetProjectPath, GetChoices, Wait, $state,
|
||||
CreateSelect2, i18n) {
|
||||
CreateSelect2, i18n, CredentialTypes) {
|
||||
|
||||
var form = ProjectsForm(),
|
||||
base = $location.path().replace(/^\//, '').split('/')[0],
|
||||
@ -121,6 +122,7 @@ export default ['$scope', '$location', '$stateParams', 'GenerateForm',
|
||||
if ($scope.scm_type.value) {
|
||||
switch ($scope.scm_type.value) {
|
||||
case 'git':
|
||||
$scope.credentialLabel = "SCM Credential";
|
||||
$scope.urlPopover = '<p>' +
|
||||
i18n._('Example URLs for GIT SCM include:') +
|
||||
'</p><ul class=\"no-bullets\"><li>https://github.com/ansible/ansible.git</li>' +
|
||||
@ -130,11 +132,13 @@ export default ['$scope', '$location', '$stateParams', 'GenerateForm',
|
||||
'SSH. GIT read only protocol (git://) does not use username or password information.'), '<strong>', '</strong>');
|
||||
break;
|
||||
case 'svn':
|
||||
$scope.credentialLabel = "SCM Credential";
|
||||
$scope.urlPopover = '<p>' + i18n._('Example URLs for Subversion SCM include:') + '</p>' +
|
||||
'<ul class=\"no-bullets\"><li>https://github.com/ansible/ansible</li><li>svn://servername.example.com/path</li>' +
|
||||
'<li>svn+ssh://servername.example.com/path</li></ul>';
|
||||
break;
|
||||
case 'hg':
|
||||
$scope.credentialLabel = "SCM Credential";
|
||||
$scope.urlPopover = '<p>' + i18n._('Example URLs for Mercurial SCM include:') + '</p>' +
|
||||
'<ul class=\"no-bullets\"><li>https://bitbucket.org/username/project</li><li>ssh://hg@bitbucket.org/username/project</li>' +
|
||||
'<li>ssh://server.example.com/path</li></ul>' +
|
||||
@ -142,8 +146,15 @@ export default ['$scope', '$location', '$stateParams', 'GenerateForm',
|
||||
'Do not put the username and key in the URL. ' +
|
||||
'If using Bitbucket and SSH, do not supply your Bitbucket username.'), '<strong>', '</strong>');
|
||||
break;
|
||||
case 'insights':
|
||||
$scope.pathRequired = false;
|
||||
$scope.scmRequired = false;
|
||||
$scope.credRequired = true;
|
||||
$scope.credentialLabel = "Credential";
|
||||
break;
|
||||
default:
|
||||
$scope.urlPopover = '<p> ' + i18n._('URL popover text');
|
||||
$scope.credentialLabel = "SCM Credential";
|
||||
$scope.urlPopover = '<p> ' + i18n._('URL popover text') + '</p>';
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,5 +162,20 @@ export default ['$scope', '$location', '$stateParams', 'GenerateForm',
|
||||
$scope.formCancel = function() {
|
||||
$state.go('projects');
|
||||
};
|
||||
$scope.lookupCredential = function(){
|
||||
// Perform a lookup on the credential_type. Git, Mercurial, and Subversion
|
||||
// all use SCM as their credential type.
|
||||
let credType = _.filter(CredentialTypes, function(credType){
|
||||
return ($scope.scm_type.value !== "insights" && credType.kind === "scm" ||
|
||||
$scope.scm_type.value === "insights" && credType.kind === "insights");
|
||||
});
|
||||
$state.go('.credential', {
|
||||
credential_search: {
|
||||
credential_type: credType[0].id,
|
||||
page_size: '5',
|
||||
page: '1'
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
];
|
||||
|
@ -8,11 +8,11 @@ export default ['$scope', '$rootScope', '$stateParams', 'ProjectsForm', 'Rest',
|
||||
'Alert', 'ProcessErrors', 'GenerateForm', 'Prompt', 'ClearScope',
|
||||
'GetBasePath', 'GetProjectPath', 'Authorization', 'GetChoices', 'Empty',
|
||||
'Wait', 'ProjectUpdate', '$state', 'CreateSelect2', 'ToggleNotification',
|
||||
'i18n',
|
||||
'i18n', 'CredentialTypes',
|
||||
function($scope, $rootScope, $stateParams, ProjectsForm, Rest, Alert,
|
||||
ProcessErrors, GenerateForm, Prompt, ClearScope, GetBasePath,
|
||||
GetProjectPath, Authorization, GetChoices, Empty, Wait, ProjectUpdate,
|
||||
$state, CreateSelect2, ToggleNotification, i18n) {
|
||||
$state, CreateSelect2, ToggleNotification, i18n, CredentialTypes) {
|
||||
|
||||
ClearScope('htmlTemplate');
|
||||
|
||||
@ -254,6 +254,7 @@ export default ['$scope', '$rootScope', '$stateParams', 'ProjectsForm', 'Rest',
|
||||
if ($scope.scm_type.value) {
|
||||
switch ($scope.scm_type.value) {
|
||||
case 'git':
|
||||
$scope.credentialLabel = "SCM Credential";
|
||||
$scope.urlPopover = '<p>' + i18n._('Example URLs for GIT SCM include:') + '</p><ul class=\"no-bullets\"><li>https://github.com/ansible/ansible.git</li>' +
|
||||
'<li>git@github.com:ansible/ansible.git</li><li>git://servername.example.com/ansible.git</li></ul>' +
|
||||
'<p>' + i18n.sprintf(i18n._('%sNote:%s When using SSH protocol for GitHub or Bitbucket, enter an SSH key only, ' +
|
||||
@ -261,11 +262,13 @@ export default ['$scope', '$rootScope', '$stateParams', 'ProjectsForm', 'Rest',
|
||||
'SSH. GIT read only protocol (git://) does not use username or password information.'), '<strong>', '</strong>');
|
||||
break;
|
||||
case 'svn':
|
||||
$scope.credentialLabel = "SCM Credential";
|
||||
$scope.urlPopover = '<p>' + i18n._('Example URLs for Subversion SCM include:') + '</p>' +
|
||||
'<ul class=\"no-bullets\"><li>https://github.com/ansible/ansible</li><li>svn://servername.example.com/path</li>' +
|
||||
'<li>svn+ssh://servername.example.com/path</li></ul>';
|
||||
break;
|
||||
case 'hg':
|
||||
$scope.credentialLabel = "SCM Credential";
|
||||
$scope.urlPopover = '<p>' + i18n._('Example URLs for Mercurial SCM include:') + '</p>' +
|
||||
'<ul class=\"no-bullets\"><li>https://bitbucket.org/username/project</li><li>ssh://hg@bitbucket.org/username/project</li>' +
|
||||
'<li>ssh://server.example.com/path</li></ul>' +
|
||||
@ -273,12 +276,35 @@ export default ['$scope', '$rootScope', '$stateParams', 'ProjectsForm', 'Rest',
|
||||
'Do not put the username and key in the URL. ' +
|
||||
'If using Bitbucket and SSH, do not supply your Bitbucket username.'), '<strong>', '</strong>');
|
||||
break;
|
||||
case 'insights':
|
||||
$scope.pathRequired = false;
|
||||
$scope.scmRequired = false;
|
||||
$scope.credRequired = true;
|
||||
$scope.credentialLabel = "Credential";
|
||||
break;
|
||||
default:
|
||||
$scope.credentialLabel = "SCM Credential";
|
||||
$scope.urlPopover = '<p> ' + i18n._('URL popover text');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.lookupCredential = function(){
|
||||
// Perform a lookup on the credential_type. Git, Mercurial, and Subversion
|
||||
// all use SCM as their credential type.
|
||||
let credType = _.filter(CredentialTypes, function(credType){
|
||||
return ($scope.scm_type.value !== "insights" && credType.kind === "scm" ||
|
||||
$scope.scm_type.value === "insights" && credType.kind === "insights");
|
||||
});
|
||||
$state.go('.credential', {
|
||||
credential_search: {
|
||||
credential_type: credType[0].id,
|
||||
page_size: '5',
|
||||
page: '1'
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.SCMUpdate = function() {
|
||||
if ($scope.project_obj.scm_type === "Manual" || Empty($scope.project_obj.scm_type)) {
|
||||
// ignore
|
||||
|
@ -28,7 +28,24 @@ angular.module('Projects', [revisions.name])
|
||||
.config(['$stateProvider', 'stateDefinitionsProvider',
|
||||
function($stateProvider, stateDefinitionsProvider) {
|
||||
let stateDefinitions = stateDefinitionsProvider.$get();
|
||||
|
||||
var projectResolve = {
|
||||
CredentialTypes: ['Rest', '$stateParams', 'GetBasePath', 'ProcessErrors',
|
||||
(Rest, $stateParams, GetBasePath, ProcessErrors) => {
|
||||
var path = GetBasePath('credential_types');
|
||||
Rest.setUrl(path);
|
||||
return Rest.get()
|
||||
.then(function(data) {
|
||||
return (data.data.results);
|
||||
}).catch(function(response) {
|
||||
ProcessErrors(null, response.data, response.status, null, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to get credential tpyes. GET returned status: ' +
|
||||
response.status
|
||||
});
|
||||
});
|
||||
}
|
||||
]
|
||||
};
|
||||
// lazily generate a tree of substates which will replace this node in ui-router's stateRegistry
|
||||
// see: stateDefinition.factory for usage documentation
|
||||
$stateProvider.state({
|
||||
@ -55,6 +72,10 @@ angular.module('Projects', [revisions.name])
|
||||
},
|
||||
ncyBreadcrumb: {
|
||||
label: N_('PROJECTS')
|
||||
},
|
||||
resolve: {
|
||||
add: projectResolve,
|
||||
edit: projectResolve
|
||||
}
|
||||
})
|
||||
});
|
||||
|
@ -131,9 +131,10 @@ export default ['i18n', 'NotificationsList', function(i18n, NotificationsList) {
|
||||
basePath: 'credentials',
|
||||
list: 'CredentialList',
|
||||
// apply a default search filter to show only scm credentials
|
||||
search: {
|
||||
kind: 'scm'
|
||||
},
|
||||
// search: {
|
||||
// kind: 'scm'
|
||||
// },
|
||||
ngClick: 'lookupCredential()',
|
||||
autopopulateLookup: false,
|
||||
awRequiredWhen: {
|
||||
reqExpression: "credRequired",
|
||||
|
@ -23,6 +23,7 @@
|
||||
@egrey: #EEEEEE;
|
||||
@cgrey: #CCCCCC;
|
||||
@f7grey: #F7F7F7;
|
||||
@insights-yellow: #dedc4f;
|
||||
|
||||
|
||||
@default-warning: #F0AD4E;
|
||||
|
@ -1507,6 +1507,7 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
|
||||
collection = this.form.related[itm];
|
||||
html += `<div id="${itm}_tab" `+
|
||||
`class="Form-tab" `;
|
||||
html += (this.form.related[itm].ngIf) ? ` ng-if="${this.form.related[itm].ngIf}" ` : "";
|
||||
html += (this.form.related[itm].ngClick) ? `ng-click="` + this.form.related[itm].ngClick + `" ` : `ng-click="$state.go('${this.form.stateTree}.edit.${itm}')" `;
|
||||
if (collection.awToolTip && collection.awToolTipTabEnabledInEditMode === true) {
|
||||
html += `aw-tool-tip="${collection.awToolTip}" ` +
|
||||
|
@ -191,6 +191,9 @@ angular.module('GeneratorHelpers', [systemStatus.name])
|
||||
case 'copy':
|
||||
icon = "fa-copy";
|
||||
break;
|
||||
case 'insights':
|
||||
icon = "fa-info";
|
||||
break;
|
||||
case 'cancel':
|
||||
icon = "fa-minus-circle";
|
||||
break;
|
||||
|
@ -9,13 +9,13 @@
|
||||
'$stateParams', 'JobTemplateForm', 'GenerateForm', 'Rest', 'Alert',
|
||||
'ProcessErrors', 'ClearScope', 'GetBasePath', 'md5Setup', 'ParseTypeChange', 'Wait',
|
||||
'Empty', 'ToJSON', 'CallbackHelpInit', 'GetChoices', '$state',
|
||||
'CreateSelect2', '$q', 'i18n',
|
||||
'CreateSelect2', '$q', 'i18n', 'Inventory', 'Project',
|
||||
function(
|
||||
$filter, $scope,
|
||||
$stateParams, JobTemplateForm, GenerateForm, Rest, Alert,
|
||||
ProcessErrors, ClearScope, GetBasePath, md5Setup, ParseTypeChange, Wait,
|
||||
Empty, ToJSON, CallbackHelpInit, GetChoices,
|
||||
$state, CreateSelect2, $q, i18n
|
||||
$state, CreateSelect2, $q, i18n, Inventory, Project
|
||||
) {
|
||||
|
||||
Rest.setUrl(GetBasePath('job_templates'));
|
||||
@ -80,24 +80,6 @@
|
||||
}
|
||||
$scope.job_type = $scope.job_type_options[form.fields.job_type.default];
|
||||
|
||||
// if you're getting to the form from the scan job section on inventories,
|
||||
// set the job type select to be scan
|
||||
if ($stateParams.inventory_id) {
|
||||
// This means that the job template form was accessed via inventory prop's
|
||||
// This also means the job is a scan job.
|
||||
$scope.job_type.value = 'scan';
|
||||
$scope.jobTypeChange();
|
||||
$scope.inventory = $stateParams.inventory_id;
|
||||
Rest.setUrl(GetBasePath('inventory') + $stateParams.inventory_id + '/');
|
||||
Rest.get()
|
||||
.success(function (data) {
|
||||
$scope.inventory_name = data.name;
|
||||
})
|
||||
.error(function (data, status) {
|
||||
ProcessErrors($scope, data, status, form, { hdr: 'Error!',
|
||||
msg: 'Failed to lookup inventory: ' + data.id + '. GET returned status: ' + status });
|
||||
});
|
||||
}
|
||||
CreateSelect2({
|
||||
element:'#job_template_job_type',
|
||||
multiple: false
|
||||
@ -254,6 +236,17 @@
|
||||
}
|
||||
};
|
||||
|
||||
if(Inventory){
|
||||
$scope.inventory = Inventory.inventory_id;
|
||||
$scope.inventory_name = Inventory.inventory_name;
|
||||
}
|
||||
if(Project){
|
||||
$scope.project = Project.id;
|
||||
$scope.project_name = Project.name;
|
||||
selectPlaybook('force_load');
|
||||
checkSCMStatus();
|
||||
}
|
||||
|
||||
// Register a watcher on project_name
|
||||
if ($scope.selectPlaybookUnregister) {
|
||||
$scope.selectPlaybookUnregister();
|
||||
|
@ -77,10 +77,7 @@ export default ['$scope', '$rootScope',
|
||||
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
|
||||
});
|
||||
});
|
||||
$scope.addJobTemplate = function() {
|
||||
$state.go('jobTemplates.add');
|
||||
};
|
||||
|
||||
|
||||
$scope.editJobTemplate = function(template) {
|
||||
if(template) {
|
||||
if(template.type && (template.type === 'Job Template' || template.type === 'job_template')) {
|
||||
|
@ -52,11 +52,41 @@ angular.module('templates', [surveyMaker.name, templatesList.name, jobTemplatesA
|
||||
|
||||
addJobTemplate = stateDefinitions.generateTree({
|
||||
name: 'templates.addJobTemplate',
|
||||
url: '/add_job_template',
|
||||
url: '/add_job_template?inventory_id&inventory_name&credential_id',
|
||||
modes: ['add'],
|
||||
form: 'JobTemplateForm',
|
||||
controllers: {
|
||||
add: 'JobTemplateAdd'
|
||||
},
|
||||
resolve: {
|
||||
add: {
|
||||
Inventory: ['$stateParams',
|
||||
function($stateParams){
|
||||
if($stateParams.inventory_id){
|
||||
let obj = {};
|
||||
obj.inventory_id = Number($stateParams.inventory_id);
|
||||
obj.inventory_name = $stateParams.inventory_name;
|
||||
return obj;
|
||||
}
|
||||
}],
|
||||
Project: ['$stateParams', 'Rest', 'GetBasePath', 'ProcessErrors',
|
||||
function($stateParams, Rest, GetBasePath, ProcessErrors){
|
||||
if($stateParams.credential_id){
|
||||
let path = `${GetBasePath('projects')}?credential__id=${Number($stateParams.credential_id)}`;
|
||||
Rest.setUrl(path);
|
||||
return Rest.get().
|
||||
then(function(data){
|
||||
return data.data.results[0];
|
||||
}).catch(function(response) {
|
||||
ProcessErrors(null, response.data, response.status, null, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to get project info. GET returned status: ' +
|
||||
response.status
|
||||
});
|
||||
});
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user