mirror of
https://github.com/ansible/awx.git
synced 2026-02-24 14:36:00 -03:30
Merge pull request #1679 from leigh-johnson/DashboardHosts
Dashboard Hosts, Form Generator headerFields options
This commit is contained in:
@@ -15,12 +15,25 @@
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Form-textArea{
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Form-header--fields{
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Form-header-field{
|
||||||
|
margin-left: 10px;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
.Form-header{
|
.Form-header{
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Form-title{
|
.Form-title{
|
||||||
flex: 1 0 auto;
|
flex: 0 1 auto;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: @list-header-txt;
|
color: @list-header-txt;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import './lists';
|
|||||||
import './widgets';
|
import './widgets';
|
||||||
import './help';
|
import './help';
|
||||||
import './filters';
|
import './filters';
|
||||||
import {Home, HomeGroups, HomeHosts} from './controllers/Home';
|
import {Home, HomeGroups} from './controllers/Home';
|
||||||
import {SocketsController} from './controllers/Sockets';
|
import {SocketsController} from './controllers/Sockets';
|
||||||
import {CredentialsAdd, CredentialsEdit, CredentialsList} from './controllers/Credentials';
|
import {CredentialsAdd, CredentialsEdit, CredentialsList} from './controllers/Credentials';
|
||||||
import {JobsListController} from './controllers/Jobs';
|
import {JobsListController} from './controllers/Jobs';
|
||||||
@@ -173,7 +173,6 @@ var tower = angular.module('Tower', [
|
|||||||
'CredentialsHelper',
|
'CredentialsHelper',
|
||||||
'StreamListDefinition',
|
'StreamListDefinition',
|
||||||
'HomeGroupListDefinition',
|
'HomeGroupListDefinition',
|
||||||
'HomeHostListDefinition',
|
|
||||||
'ActivityDetailDefinition',
|
'ActivityDetailDefinition',
|
||||||
'VariablesHelper',
|
'VariablesHelper',
|
||||||
'SchedulesListDefinition',
|
'SchedulesListDefinition',
|
||||||
@@ -267,25 +266,6 @@ var tower = angular.module('Tower', [
|
|||||||
}
|
}
|
||||||
}).
|
}).
|
||||||
|
|
||||||
state('dashboardHosts', {
|
|
||||||
url: '/home/hosts?has_active_failures&name&id',
|
|
||||||
templateUrl: urlPrefix + 'partials/subhome.html',
|
|
||||||
controller: HomeHosts,
|
|
||||||
data: {
|
|
||||||
activityStream: true,
|
|
||||||
activityStreamTarget: 'host'
|
|
||||||
},
|
|
||||||
ncyBreadcrumb: {
|
|
||||||
parent: 'dashboard',
|
|
||||||
label: "HOSTS"
|
|
||||||
},
|
|
||||||
resolve: {
|
|
||||||
features: ['FeaturesService', function(FeaturesService) {
|
|
||||||
return FeaturesService.get();
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
}).
|
|
||||||
|
|
||||||
state('jobs', {
|
state('jobs', {
|
||||||
url: '/jobs',
|
url: '/jobs',
|
||||||
templateUrl: urlPrefix + 'partials/jobs.html',
|
templateUrl: urlPrefix + 'partials/jobs.html',
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*************************************************
|
/*************************************************
|
||||||
* Copyright (c) 2015 Ansible, Inc.
|
* Copyright (c) 2016 Ansible, Inc.
|
||||||
*
|
*
|
||||||
* All Rights Reserved
|
* All Rights Reserved
|
||||||
*************************************************/
|
*************************************************/
|
||||||
@@ -155,7 +155,6 @@ export function HomeGroups($rootScope, $log, $scope, $filter, $compile, $locatio
|
|||||||
|
|
||||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||||
//scope.
|
//scope.
|
||||||
|
|
||||||
var generator = GenerateList,
|
var generator = GenerateList,
|
||||||
list = HomeGroupList,
|
list = HomeGroupList,
|
||||||
defaultUrl = GetBasePath('groups'),
|
defaultUrl = GetBasePath('groups'),
|
||||||
@@ -516,112 +515,3 @@ HomeGroups.$inject = ['$rootScope', '$log', '$scope', '$filter', '$compile', '$l
|
|||||||
* @description This loads the page for 'home/hosts'
|
* @description This loads the page for 'home/hosts'
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function HomeHosts($scope, $location, $stateParams, HomeHostList, GenerateList, ProcessErrors, ReturnToCaller, ClearScope,
|
|
||||||
GetBasePath, SearchInit, PaginateInit, FormatDate, SetStatus, ToggleHostEnabled, HostsEdit, Find, ShowJobSummary) {
|
|
||||||
|
|
||||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
|
||||||
//scope.
|
|
||||||
|
|
||||||
var generator = GenerateList,
|
|
||||||
list = HomeHostList,
|
|
||||||
defaultUrl = GetBasePath('hosts');
|
|
||||||
|
|
||||||
if ($scope.removePostRefresh) {
|
|
||||||
$scope.removePostRefresh();
|
|
||||||
}
|
|
||||||
$scope.removePostRefresh = $scope.$on('PostRefresh', function () {
|
|
||||||
for (var i = 0; i < $scope.hosts.length; i++) {
|
|
||||||
$scope.hosts[i].inventory_name = $scope.hosts[i].summary_fields.inventory.name;
|
|
||||||
//SetHostStatus($scope['hosts'][i]);
|
|
||||||
SetStatus({
|
|
||||||
$scope: $scope,
|
|
||||||
host: $scope.hosts[i]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
generator.inject(list, { mode: 'edit', scope: $scope });
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
SearchInit({
|
|
||||||
scope: $scope,
|
|
||||||
set: 'hosts',
|
|
||||||
list: list,
|
|
||||||
url: defaultUrl
|
|
||||||
});
|
|
||||||
|
|
||||||
PaginateInit({
|
|
||||||
scope: $scope,
|
|
||||||
list: list,
|
|
||||||
url: defaultUrl
|
|
||||||
});
|
|
||||||
|
|
||||||
// Process search params
|
|
||||||
if ($stateParams.name) {
|
|
||||||
$scope[HomeHostList.iterator + 'InputDisable'] = false;
|
|
||||||
$scope[HomeHostList.iterator + 'SearchValue'] = $stateParams.name;
|
|
||||||
$scope[HomeHostList.iterator + 'SearchField'] = 'name';
|
|
||||||
$scope[HomeHostList.iterator + 'SearchFieldLabel'] = list.fields.name.label;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($stateParams.id) {
|
|
||||||
$scope[HomeHostList.iterator + 'InputDisable'] = false;
|
|
||||||
$scope[HomeHostList.iterator + 'SearchValue'] = $stateParams.id;
|
|
||||||
$scope[HomeHostList.iterator + 'SearchField'] = 'id';
|
|
||||||
$scope[HomeHostList.iterator + 'SearchFieldLabel'] = list.fields.id.label;
|
|
||||||
$scope[HomeHostList.iterator + 'SearchSelectValue'] = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($stateParams.has_active_failures) {
|
|
||||||
$scope[HomeHostList.iterator + 'InputDisable'] = true;
|
|
||||||
$scope[HomeHostList.iterator + 'SearchValue'] = $stateParams.has_active_failures;
|
|
||||||
$scope[HomeHostList.iterator + 'SearchField'] = 'has_active_failures';
|
|
||||||
$scope[HomeHostList.iterator + 'SearchFieldLabel'] = HomeHostList.fields.has_active_failures.label;
|
|
||||||
$scope[HomeHostList.iterator + 'SearchSelectValue'] = ($stateParams.has_active_failures === 'true') ? { value: 1 } : { value: 0 };
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.search(list.iterator);
|
|
||||||
|
|
||||||
$scope.refreshHosts = function() {
|
|
||||||
$scope.search(list.iterator);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.toggleHostEnabled = function (id, sources) {
|
|
||||||
ToggleHostEnabled({
|
|
||||||
host_id: id,
|
|
||||||
external_source: sources,
|
|
||||||
host_scope: $scope
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.editHost = function (host_id) {
|
|
||||||
var host = Find({
|
|
||||||
list: $scope.hosts,
|
|
||||||
key: 'id',
|
|
||||||
val: host_id
|
|
||||||
});
|
|
||||||
if (host) {
|
|
||||||
HostsEdit({
|
|
||||||
host_scope: $scope,
|
|
||||||
host_id: host_id,
|
|
||||||
inventory_id: host.inventory,
|
|
||||||
group_id: null,
|
|
||||||
hostsReload: false,
|
|
||||||
mode: 'edit'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.showJobSummary = function (job_id) {
|
|
||||||
ShowJobSummary({
|
|
||||||
job_id: job_id
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
HomeHosts.$inject = ['$scope', '$location', '$stateParams', 'HomeHostList', 'generateList', 'ProcessErrors', 'ReturnToCaller',
|
|
||||||
'ClearScope', 'GetBasePath', 'SearchInit', 'PaginateInit', 'FormatDate', 'SetStatus', 'ToggleHostEnabled', 'HostsEdit',
|
|
||||||
'Find', 'ShowJobSummary'
|
|
||||||
];
|
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ export function ProjectsList ($scope, $rootScope, $location, $log, $stateParams,
|
|||||||
mode = (base === 'projects') ? 'edit' : 'select',
|
mode = (base === 'projects') ? 'edit' : 'select',
|
||||||
url = (base === 'teams') ? GetBasePath('teams') + $stateParams.team_id + '/projects/' : defaultUrl,
|
url = (base === 'teams') ? GetBasePath('teams') + $stateParams.team_id + '/projects/' : defaultUrl,
|
||||||
choiceCount = 0;
|
choiceCount = 0;
|
||||||
|
|
||||||
view.inject(list, { mode: mode, scope: $scope });
|
view.inject(list, { mode: mode, scope: $scope });
|
||||||
|
|
||||||
$rootScope.flashMessage = null;
|
$rootScope.flashMessage = null;
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*************************************************
|
||||||
|
* Copyright (c) 2016 Ansible, Inc.
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*************************************************/
|
||||||
|
|
||||||
|
export default
|
||||||
|
['$scope', '$state', '$stateParams', 'DashboardHostsForm', 'GenerateForm', 'ParseTypeChange', 'DashboardHostService', 'host',
|
||||||
|
function($scope, $state, $stateParams, DashboardHostsForm, GenerateForm, ParseTypeChange, DashboardHostService, host){
|
||||||
|
var generator = GenerateForm,
|
||||||
|
form = DashboardHostsForm;
|
||||||
|
$scope.parseType = 'yaml';
|
||||||
|
$scope.formCancel = function(){
|
||||||
|
$state.go('^', null, {reload: true});
|
||||||
|
};
|
||||||
|
$scope.toggleHostEnabled = function(){
|
||||||
|
$scope.host.enabled = !$scope.host.enabled;
|
||||||
|
};
|
||||||
|
$scope.toggleEnabled = function(){
|
||||||
|
$scope.host.enabled = !$scope.host.enabled;
|
||||||
|
};
|
||||||
|
$scope.formSave = function(){
|
||||||
|
var host = {
|
||||||
|
id: $scope.host.id,
|
||||||
|
variables: $scope.extraVars === '---' || $scope.extraVars === '{}' ? null : $scope.extraVars,
|
||||||
|
name: $scope.name,
|
||||||
|
description: $scope.description,
|
||||||
|
enabled: $scope.host.enabled
|
||||||
|
};
|
||||||
|
DashboardHostService.putHost(host).then(function(res){
|
||||||
|
$state.go('^', null, {reload: true});
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
var init = function(){
|
||||||
|
$scope.host = host;
|
||||||
|
$scope.extraVars = host.variables === '' ? '---' : host.variables;
|
||||||
|
generator.inject(form, {mode: 'edit', related: false, scope: $scope});
|
||||||
|
$scope.extraVars = $scope.host.variables === '' ? '---' : $scope.host.variables;
|
||||||
|
$scope.name = host.name;
|
||||||
|
$scope.description = host.description;
|
||||||
|
ParseTypeChange({
|
||||||
|
scope: $scope,
|
||||||
|
field_id: 'host_variables',
|
||||||
|
variable: 'extraVars',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
init();
|
||||||
|
}];
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<div class="tab-pane" id="organizations">
|
||||||
|
<div ui-view></div>
|
||||||
|
<div ng-cloak id="htmlTemplate" class="Panel"></div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/*************************************************
|
||||||
|
* Copyright (c) 2016 Ansible, Inc.
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*************************************************/
|
||||||
|
|
||||||
|
export default
|
||||||
|
['$scope', '$state', '$stateParams', 'PageRangeSetup', 'GetBasePath', 'DashboardHostsList',
|
||||||
|
'generateList', 'PaginateInit', 'SetStatus', 'DashboardHostService', 'hosts',
|
||||||
|
function($scope, $state, $stateParams, PageRangeSetup, GetBasePath, DashboardHostsList, GenerateList, PaginateInit, SetStatus, DashboardHostService, hosts){
|
||||||
|
var generator = GenerateList,
|
||||||
|
list = DashboardHostsList,
|
||||||
|
defaultUrl = GetBasePath('hosts');
|
||||||
|
$scope.hostPageSize = 10;
|
||||||
|
$scope.editHost = function(id){
|
||||||
|
$state.go('dashboardHosts.edit', {id: id});
|
||||||
|
};
|
||||||
|
$scope.toggleHostEnabled = function(host){
|
||||||
|
DashboardHostService.setHostStatus(host, !host.enabled)
|
||||||
|
.then(function(res){
|
||||||
|
var index = _.findIndex($scope.hosts, function(o) {return o.id === res.data.id;});
|
||||||
|
$scope.hosts[index].enabled = res.data.enabled;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
$scope.$on('PostRefresh', function(){
|
||||||
|
$scope.hosts = _.map($scope.hosts, function(value, key){
|
||||||
|
value.inventory_name = value.summary_fields.inventory.name;
|
||||||
|
value.inventory_id = value.summary_fields.inventory.id;
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
setJobStatus();
|
||||||
|
});
|
||||||
|
var setJobStatus = function(){
|
||||||
|
_.forEach($scope.hosts, function(value, key){
|
||||||
|
SetStatus({
|
||||||
|
scope: $scope,
|
||||||
|
host: value
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var init = function(){
|
||||||
|
$scope.list = list;
|
||||||
|
$scope.host_active_search = false;
|
||||||
|
$scope.host_total_rows = hosts.results.length;
|
||||||
|
$scope.hosts = hosts.results;
|
||||||
|
setJobStatus();
|
||||||
|
generator.inject(list, {mode: 'edit', scope: $scope});
|
||||||
|
PaginateInit({
|
||||||
|
scope: $scope,
|
||||||
|
list: list,
|
||||||
|
url: defaultUrl,
|
||||||
|
pageSize: 10
|
||||||
|
});
|
||||||
|
PageRangeSetup({
|
||||||
|
scope: $scope,
|
||||||
|
count: hosts.count,
|
||||||
|
next: hosts.next,
|
||||||
|
previous: hosts.previous,
|
||||||
|
iterator: list.iterator
|
||||||
|
});
|
||||||
|
$scope.hostLoading = false;
|
||||||
|
};
|
||||||
|
init();
|
||||||
|
}];
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<div class="tab-pane" id="HomeHosts">
|
||||||
|
<div ui-view></div>
|
||||||
|
<div ng-cloak id="htmlTemplate" class="Panel"></div>
|
||||||
|
</div>
|
||||||
77
awx/ui/client/src/dashboard/hosts/dashboard-hosts.form.js
Normal file
77
awx/ui/client/src/dashboard/hosts/dashboard-hosts.form.js
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/*************************************************
|
||||||
|
* Copyright (c) 2016 Ansible, Inc.
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*************************************************/
|
||||||
|
|
||||||
|
export default function(){
|
||||||
|
return {
|
||||||
|
editTitle: '{{host.name}}',
|
||||||
|
name: 'host',
|
||||||
|
well: true,
|
||||||
|
formLabelSize: 'col-lg-3',
|
||||||
|
formFieldSize: 'col-lg-9',
|
||||||
|
iterator: 'host',
|
||||||
|
headerFields:{
|
||||||
|
enabled: {
|
||||||
|
//flag: 'host.enabled',
|
||||||
|
class: 'Form-header-field',
|
||||||
|
ngClick: 'toggleHostEnabled()',
|
||||||
|
type: 'toggle',
|
||||||
|
editRequired: false,
|
||||||
|
awToolTip: "<p>Indicates if a host is available and should be included in running jobs.</p><p>For hosts that " +
|
||||||
|
"are part of an external inventory, this flag cannot be changed. It will be set by the inventory sync process.</p>",
|
||||||
|
dataTitle: 'Host Enabled'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fields: {
|
||||||
|
name: {
|
||||||
|
label: 'Host Name',
|
||||||
|
type: 'text',
|
||||||
|
editRequired: true,
|
||||||
|
value: '{{name}}',
|
||||||
|
awPopOver: "<p>Provide a host name, ip address, or ip address:port. Examples include:</p>" +
|
||||||
|
"<blockquote>myserver.domain.com<br/>" +
|
||||||
|
"127.0.0.1<br />" +
|
||||||
|
"10.1.0.140:25<br />" +
|
||||||
|
"server.example.com:25" +
|
||||||
|
"</blockquote>",
|
||||||
|
dataTitle: 'Host Name',
|
||||||
|
dataPlacement: 'right',
|
||||||
|
dataContainer: 'body'
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
label: 'Description',
|
||||||
|
type: 'text',
|
||||||
|
editRequired: false
|
||||||
|
},
|
||||||
|
variables: {
|
||||||
|
label: 'Variables',
|
||||||
|
type: 'textarea',
|
||||||
|
editRequired: false,
|
||||||
|
rows: 6,
|
||||||
|
class: 'modal-input-xlarge Form-textArea',
|
||||||
|
dataTitle: 'Host Variables',
|
||||||
|
dataPlacement: 'right',
|
||||||
|
dataContainer: 'body',
|
||||||
|
default: '---',
|
||||||
|
awPopOver: "<p>Enter variables using either JSON or YAML syntax. Use the radio button to toggle between the two.</p>" +
|
||||||
|
"JSON:<br />\n" +
|
||||||
|
"<blockquote>{<br />\"somevar\": \"somevalue\",<br />\"password\": \"magic\"<br /> }</blockquote>\n" +
|
||||||
|
"YAML:<br />\n" +
|
||||||
|
"<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>\n" +
|
||||||
|
'<p>View JSON examples at <a href="http://www.json.org" target="_blank">www.json.org</a></p>' +
|
||||||
|
'<p>View YAML examples at <a href="http://docs.ansible.com/YAMLSyntax.html" target="_blank">docs.ansible.com</a></p>',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
buttons: {
|
||||||
|
save: {
|
||||||
|
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||||
|
ngDisabled: "host_form.$invalid"//true //Disable when $pristine or $invalid, optional and when can_edit = false, for permission reasons
|
||||||
|
},
|
||||||
|
cancel: {
|
||||||
|
ngClick: 'formCancel()'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -1,14 +1,12 @@
|
|||||||
/*************************************************
|
/*************************************************
|
||||||
* Copyright (c) 2015 Ansible, Inc.
|
* Copyright (c) 2015 Ansible, Inc.
|
||||||
*
|
*
|
||||||
* All Rights Reserved
|
* All Rights Reserved
|
||||||
*************************************************/
|
*************************************************/
|
||||||
|
|
||||||
|
|
||||||
export default
|
export default function(){
|
||||||
angular.module('HomeHostListDefinition', [])
|
return {
|
||||||
.value('HomeHostList', {
|
|
||||||
|
|
||||||
name: 'hosts',
|
name: 'hosts',
|
||||||
iterator: 'host',
|
iterator: 'host',
|
||||||
selectTitle: 'Add Existing Hosts',
|
selectTitle: 'Add Existing Hosts',
|
||||||
@@ -20,38 +18,45 @@ export default
|
|||||||
|
|
||||||
fields: {
|
fields: {
|
||||||
status: {
|
status: {
|
||||||
label: "",
|
basePath: 'unified_jobs',
|
||||||
|
label: '',
|
||||||
iconOnly: true,
|
iconOnly: true,
|
||||||
icon: "{{ 'icon-job-' + host.active_failures }}",
|
searchable: true,
|
||||||
awToolTip: "{{ host.badgeToolTip }}",
|
searchType: 'select',
|
||||||
awTipPlacement: "right",
|
nosort: true,
|
||||||
dataPlacement: "right",
|
searchOptions: [],
|
||||||
awPopOver: "{{ host.job_status_html }}",
|
searchLabel: 'Job Status',
|
||||||
ngClick:"bob",
|
icon: 'icon-job-{{ host.active_failures }}',
|
||||||
columnClass: "List-staticColumn--smallStatus",
|
awToolTip: '{{ host.badgeToolTip }}',
|
||||||
searchable: false,
|
awTipPlacement: 'right',
|
||||||
nosort: true
|
dataPlacement: 'right',
|
||||||
|
awPopOver: '{{ host.job_status_html }}',
|
||||||
|
ngClick:'viewHost(host.id)',
|
||||||
|
columnClass: 'col-lg-1 col-md-1 col-sm-2 col-xs-2 List-staticColumn--smallStatus'
|
||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
key: true,
|
key: true,
|
||||||
label: 'Name',
|
label: 'Name',
|
||||||
columnClass: 'col-lg-5 col-md-5 col-sm-5 col-xs-8 ellipsis List-staticColumnAdjacent',
|
columnClass: 'col-lg-5 col-md-5 col-sm-5 col-xs-8 ellipsis List-staticColumnAdjacent',
|
||||||
ngClass: "{ 'host-disabled-label': !host.enabled }",
|
ngClick: 'editHost(host.id)'
|
||||||
ngClick: "editHost(host.id)"
|
|
||||||
},
|
},
|
||||||
inventory_name: {
|
inventory_name: {
|
||||||
label: 'Inventory',
|
label: 'Inventory',
|
||||||
sourceModel: 'inventory',
|
sourceModel: 'inventory',
|
||||||
sourceField: 'name',
|
sourceField: 'name',
|
||||||
columnClass: 'col-lg-5 col-md-4 col-sm-4 hidden-xs elllipsis',
|
columnClass: 'col-lg-5 col-md-4 col-sm-4 hidden-xs elllipsis',
|
||||||
linkTo: "{{ '/#/inventories/' + host.inventory }}"
|
linkTo: "{{ '/#/inventories/' + host.inventory_id }}",
|
||||||
|
searchable: false
|
||||||
},
|
},
|
||||||
enabled: {
|
enabled: {
|
||||||
label: 'Disabled?',
|
label: 'Status',
|
||||||
searchSingleValue: true,
|
columnClass: 'List-staticColumn--toggle',
|
||||||
searchType: 'boolean',
|
type: 'toggle',
|
||||||
searchValue: 'false',
|
ngClick: 'toggleHostEnabled(host)',
|
||||||
searchOnly: true
|
searchable: false,
|
||||||
|
nosort: true,
|
||||||
|
awToolTip: "<p>Indicates if a host is available and should be included in running jobs.</p><p>For hosts that are part of an external inventory, this flag cannot be changed. It will be set by the inventory sync process.</p>",
|
||||||
|
dataTitle: 'Host Enabled',
|
||||||
},
|
},
|
||||||
has_active_failures: {
|
has_active_failures: {
|
||||||
label: 'Has failed jobs?',
|
label: 'Has failed jobs?',
|
||||||
@@ -66,30 +71,15 @@ export default
|
|||||||
searchType: 'boolean',
|
searchType: 'boolean',
|
||||||
searchValue: 'true',
|
searchValue: 'true',
|
||||||
searchOnly: true
|
searchOnly: true
|
||||||
},
|
|
||||||
id: {
|
|
||||||
label: 'ID',
|
|
||||||
searchOnly: true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
fieldActions: {
|
fieldActions: {
|
||||||
|
|
||||||
columnClass: 'col-lg-2 col-md-3 col-sm-3 col-xs-4',
|
columnClass: 'col-lg-2 col-md-3 col-sm-3 col-xs-4',
|
||||||
|
|
||||||
/*active_failures: {
|
|
||||||
//label: 'Job Status',
|
|
||||||
//ngHref: "\{\{'/#/hosts/' + host.id + '/job_host_summaries/?inventory=' + inventory_id \}\}",
|
|
||||||
awPopOver: "{{ host.job_status_html }}",
|
|
||||||
dataTitle: "{{ host.job_status_title }}",
|
|
||||||
awToolTip: "{{ host.badgeToolTip }}",
|
|
||||||
awTipPlacement: 'top',
|
|
||||||
dataPlacement: 'left',
|
|
||||||
iconClass: "{{ 'fa icon-failures-' + host.has_active_failures }}"
|
|
||||||
}*/
|
|
||||||
edit: {
|
edit: {
|
||||||
label: 'Edit',
|
label: 'Edit',
|
||||||
ngClick: "editHost(host.id)",
|
ngClick: 'editHost(host.id)',
|
||||||
icon: 'icon-edit',
|
icon: 'icon-edit',
|
||||||
awToolTip: 'Edit host',
|
awToolTip: 'Edit host',
|
||||||
dataPlacement: 'top'
|
dataPlacement: 'top'
|
||||||
@@ -99,5 +89,5 @@ export default
|
|||||||
actions: {
|
actions: {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
};
|
||||||
64
awx/ui/client/src/dashboard/hosts/dashboard-hosts.route.js
Normal file
64
awx/ui/client/src/dashboard/hosts/dashboard-hosts.route.js
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/*************************************************
|
||||||
|
* Copyright (c) 2016 Ansible, Inc.
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*************************************************/
|
||||||
|
|
||||||
|
import {templateUrl} from '../../shared/template-url/template-url.factory';
|
||||||
|
import listController from './dashboard-hosts-list.controller';
|
||||||
|
import editController from './dashboard-hosts-edit.controller';
|
||||||
|
|
||||||
|
var dashboardHostsList = {
|
||||||
|
name: 'dashboardHosts',
|
||||||
|
url: '/home/hosts',
|
||||||
|
controller: listController,
|
||||||
|
templateUrl: templateUrl('dashboard/hosts/dashboard-hosts-list'),
|
||||||
|
data: {
|
||||||
|
activityStream: true,
|
||||||
|
activityStreamTarget: 'host'
|
||||||
|
},
|
||||||
|
ncyBreadcrumb: {
|
||||||
|
parent: 'dashboard',
|
||||||
|
label: "HOSTS"
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
features: ['FeaturesService', function(FeaturesService) {
|
||||||
|
return FeaturesService.get();
|
||||||
|
}],
|
||||||
|
hosts: ['Rest', 'GetBasePath', function(Rest, GetBasePath){
|
||||||
|
var defaultUrl = GetBasePath('hosts') + '?page_size=10';
|
||||||
|
Rest.setUrl(defaultUrl);
|
||||||
|
return Rest.get().then(function(res){
|
||||||
|
var results = _.map(res.data.results, function(value, key){
|
||||||
|
value.inventory_name = value.summary_fields.inventory.name;
|
||||||
|
value.inventory_id = value.summary_fields.inventory.id;
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
res.data.results = results;
|
||||||
|
return res.data
|
||||||
|
});
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var dashboardHostsEdit = {
|
||||||
|
name: 'dashboardHosts.edit',
|
||||||
|
url: '/:id',
|
||||||
|
controller: editController,
|
||||||
|
templateUrl: templateUrl('dashboard/hosts/dashboard-hosts-edit'),
|
||||||
|
ncyBreadcrumb: {
|
||||||
|
parent: 'dashboardHosts',
|
||||||
|
label: "{{host.name}}"
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
host: ['$stateParams', 'Rest', 'GetBasePath', function($stateParams, Rest, GetBasePath){
|
||||||
|
var defaultUrl = GetBasePath('hosts') + '?id=' + $stateParams.id;
|
||||||
|
Rest.setUrl(defaultUrl);
|
||||||
|
return Rest.get().then(function(res){
|
||||||
|
return res.data.results[0];
|
||||||
|
});
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export {dashboardHostsList, dashboardHostsEdit};
|
||||||
30
awx/ui/client/src/dashboard/hosts/dashboard-hosts.service.js
Normal file
30
awx/ui/client/src/dashboard/hosts/dashboard-hosts.service.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
export default
|
||||||
|
['$rootScope', 'Rest', 'GetBasePath', 'ProcessErrors', function($rootScope, Rest, GetBasePath, ProcessErrors){
|
||||||
|
return {
|
||||||
|
|
||||||
|
setHostStatus: function(host, enabled){
|
||||||
|
var url = GetBasePath('hosts') + host.id;
|
||||||
|
Rest.setUrl(url);
|
||||||
|
return Rest.put({enabled: enabled, name: host.name})
|
||||||
|
.success(function(data){
|
||||||
|
return data;
|
||||||
|
})
|
||||||
|
.error(function(data, status) {
|
||||||
|
ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
|
||||||
|
msg: 'Call to ' + url + '. GET returned: ' + status });
|
||||||
|
});
|
||||||
|
},
|
||||||
|
putHost: function(host){
|
||||||
|
var url = GetBasePath('hosts') + host.id;
|
||||||
|
Rest.setUrl(url);
|
||||||
|
return Rest.put(host)
|
||||||
|
.success(function(data){
|
||||||
|
return data;
|
||||||
|
})
|
||||||
|
.error(function(data, status) {
|
||||||
|
ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
|
||||||
|
msg: 'Call to ' + url + '. GET returned: ' + status });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}];
|
||||||
20
awx/ui/client/src/dashboard/hosts/main.js
Normal file
20
awx/ui/client/src/dashboard/hosts/main.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/*************************************************
|
||||||
|
* Copyright (c) 2016 Ansible, Inc.
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*************************************************/
|
||||||
|
|
||||||
|
import {dashboardHostsList, dashboardHostsEdit} from './dashboard-hosts.route';
|
||||||
|
import list from './dashboard-hosts.list';
|
||||||
|
import form from './dashboard-hosts.form';
|
||||||
|
import service from './dashboard-hosts.service';
|
||||||
|
|
||||||
|
export default
|
||||||
|
angular.module('dashboardHosts', [])
|
||||||
|
.service('DashboardHostService', service)
|
||||||
|
.factory('DashboardHostsList', list)
|
||||||
|
.factory('DashboardHostsForm', form)
|
||||||
|
.run(['$stateExtender', function($stateExtender){
|
||||||
|
$stateExtender.addState(dashboardHostsList);
|
||||||
|
$stateExtender.addState(dashboardHostsEdit);
|
||||||
|
}]);
|
||||||
@@ -2,7 +2,8 @@ import dashboardCounts from './counts/main';
|
|||||||
import dashboardGraphs from './graphs/main';
|
import dashboardGraphs from './graphs/main';
|
||||||
import dashboardLists from './lists/main';
|
import dashboardLists from './lists/main';
|
||||||
import dashboardDirective from './dashboard.directive';
|
import dashboardDirective from './dashboard.directive';
|
||||||
|
import dashboardHosts from './hosts/main';
|
||||||
|
|
||||||
export default
|
export default
|
||||||
angular.module('dashboard', [dashboardCounts.name, dashboardGraphs.name, dashboardLists.name])
|
angular.module('dashboard', [dashboardHosts.name, dashboardCounts.name, dashboardGraphs.name, dashboardLists.name])
|
||||||
.directive('dashboard', dashboardDirective);
|
.directive('dashboard', dashboardDirective);
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import AllJobs from "./lists/AllJobs";
|
|||||||
import Credentials from "./lists/Credentials";
|
import Credentials from "./lists/Credentials";
|
||||||
import Groups from "./lists/Groups";
|
import Groups from "./lists/Groups";
|
||||||
import HomeGroups from "./lists/HomeGroups";
|
import HomeGroups from "./lists/HomeGroups";
|
||||||
import HomeHosts from "./lists/HomeHosts";
|
|
||||||
import Hosts from "./lists/Hosts";
|
import Hosts from "./lists/Hosts";
|
||||||
import Inventories from "./lists/Inventories";
|
import Inventories from "./lists/Inventories";
|
||||||
import InventoryGroups from "./lists/InventoryGroups";
|
import InventoryGroups from "./lists/InventoryGroups";
|
||||||
@@ -39,7 +38,6 @@ export
|
|||||||
Credentials,
|
Credentials,
|
||||||
Groups,
|
Groups,
|
||||||
HomeGroups,
|
HomeGroups,
|
||||||
HomeHosts,
|
|
||||||
Hosts,
|
Hosts,
|
||||||
Inventories,
|
Inventories,
|
||||||
InventoryGroups,
|
InventoryGroups,
|
||||||
|
|||||||
@@ -1,16 +1,21 @@
|
|||||||
export default ['GetBasePath', function(GetBasePath) {
|
export default ['GetBasePath', function(GetBasePath) {
|
||||||
// given the list, return the fields that need searching
|
// given the list, return the fields that need searching
|
||||||
this.getList = function(list) {
|
this.getList = function(list) {
|
||||||
var f = _.clone(list.fields);
|
var f = _.cloneDeep(list.fields);
|
||||||
return JSON.stringify(Object
|
return JSON.stringify(Object
|
||||||
.keys(f)
|
.keys(f)
|
||||||
.filter(function(i) {
|
.filter(function(i) {
|
||||||
return (f[i]
|
return (f[i]
|
||||||
.searchable !== false);
|
.searchable !== false);
|
||||||
}).map(function(i) {
|
}).map(function(i) {
|
||||||
|
// delete any fields which might include AngularJS interpolation tags {{ }}
|
||||||
delete f[i].awToolTip;
|
delete f[i].awToolTip;
|
||||||
|
delete f[i].awPopover;
|
||||||
|
delete f[i].linkTo;
|
||||||
|
delete f[i].dataTitle;
|
||||||
delete f[i].ngClass;
|
delete f[i].ngClass;
|
||||||
delete f[i].ngClick;
|
delete f[i].ngClick;
|
||||||
|
delete f[i].icon;
|
||||||
return {[i]: f[i]};
|
return {[i]: f[i]};
|
||||||
}).reduce(function (acc, i) {
|
}).reduce(function (acc, i) {
|
||||||
var key = Object.keys(i);
|
var key = Object.keys(i);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export default ['$scope', 'Refresh', 'tagSearchService',
|
export default ['$scope', 'Refresh', 'tagSearchService',
|
||||||
function($scope, Refresh, tagSearchService) {
|
function($scope, Refresh, tagSearchService) {
|
||||||
// JSONify passed field elements that can be searched
|
// JSONify passed field elements that can be searched
|
||||||
$scope.list = JSON.parse($scope.list);
|
$scope.list = angular.fromJson($scope.list);
|
||||||
// Access config lines from list spec
|
// Access config lines from list spec
|
||||||
$scope.listConfig = $scope.$parent.list;
|
$scope.listConfig = $scope.$parent.list;
|
||||||
// Grab options for the left-dropdown of the searchbar
|
// Grab options for the left-dropdown of the searchbar
|
||||||
|
|||||||
@@ -35,8 +35,7 @@ export default ['Rest', '$q', 'GetBasePath', 'Wait', 'ProcessErrors', '$log', fu
|
|||||||
obj.value = value;
|
obj.value = value;
|
||||||
obj.label = label;
|
obj.label = label;
|
||||||
obj.type = type;
|
obj.type = type;
|
||||||
|
obj.basePath = field['basePath'] || null;
|
||||||
|
|
||||||
|
|
||||||
// return the built option
|
// return the built option
|
||||||
if (type === 'select') {
|
if (type === 'select') {
|
||||||
@@ -79,7 +78,7 @@ export default ['Rest', '$q', 'GetBasePath', 'Wait', 'ProcessErrors', '$log', fu
|
|||||||
|
|
||||||
if (needsRequest.length) {
|
if (needsRequest.length) {
|
||||||
// make the options request to reutrn the typeOptions
|
// make the options request to reutrn the typeOptions
|
||||||
Rest.setUrl(needsRequest[0].basePath ? needsRequest[0].basePath : basePath);
|
Rest.setUrl(needsRequest[0].basePath ? GetBasePath(needsRequest[0].basePath) : basePath);
|
||||||
Rest.options()
|
Rest.options()
|
||||||
.success(function (data) {
|
.success(function (data) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -230,6 +230,11 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
|
|||||||
this.scope[fld + '_field'].name = fld;
|
this.scope[fld + '_field'].name = fld;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (fld in form.headerFields){
|
||||||
|
this.scope[fld + '_field'] = form.headerFields[fld];
|
||||||
|
this.scope[fld + '_field'].name = fld;
|
||||||
|
}
|
||||||
|
|
||||||
$compile(element)(this.scope);
|
$compile(element)(this.scope);
|
||||||
|
|
||||||
if (!options.html) {
|
if (!options.html) {
|
||||||
@@ -606,9 +611,26 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
|
|||||||
return html;
|
return html;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
buildHeaderField: function(key, field, options, form){
|
||||||
|
var html = '';
|
||||||
|
// extend these blocks to include elements similarly buildField()
|
||||||
|
if (field.type === 'toggle'){
|
||||||
|
html += "<div class=\"Field-header--" + key;
|
||||||
|
html += (field['class']) ? " " + field['class'] : "";
|
||||||
|
html += " " + field.columnClass;
|
||||||
|
html += "\"><div class='ScheduleToggle' ng-class='{\"is-on\": " + form.iterator + ".";
|
||||||
|
html += (field.flag) ? field.flag : "enabled";
|
||||||
|
html += "\}' aw-tool-tip='" + field.awToolTip + "' data-placement='" + field.dataPlacement + "' data-tip-watch='" + field.dataTipWatch + "'><div ng-show='" + form.iterator + "." ;
|
||||||
|
html += (field.flag) ? field.flag : 'enabled';
|
||||||
|
html += "' class='ScheduleToggle-switch is-on' ng-click='" + field.ngClick + "'>ON</div><div ng-show='!" + form.iterator + "." ;
|
||||||
|
html += (field.flag) ? field.flag : "enabled";
|
||||||
|
html += "' class='ScheduleToggle-switch' ng-click='" + field.ngClick + "'>OFF</div></div></div>";
|
||||||
|
}
|
||||||
|
return html;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
buildField: function (fld, field, options, form) {
|
buildField: function (fld, field, options, form) {
|
||||||
|
|
||||||
var i, fldWidth, offset, html = '',
|
var i, fldWidth, offset, html = '',
|
||||||
horizontal = (this.form.horizontal) ? true : false;
|
horizontal = (this.form.horizontal) ? true : false;
|
||||||
|
|
||||||
@@ -725,6 +747,18 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
|
|||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (field.type === 'toggle'){
|
||||||
|
html += "<td class=\"List-tableCell " + fld + "-column";
|
||||||
|
html += (field['class']) ? " " + field['class'] : "";
|
||||||
|
html += " " + field.columnClass;
|
||||||
|
html += "\"><div class='ScheduleToggle' ng-class='{\"is-on\": " + form.iterator + ".";
|
||||||
|
html += (field.flag) ? field.flag : "enabled";
|
||||||
|
html += "\}' aw-tool-tip='" + field.awToolTip + "' data-placement='" + field.dataPlacement + "' data-tip-watch='" + field.dataTipWatch + "'><div ng-show='" + form.iterator + "." ;
|
||||||
|
html += (field.flag) ? field.flag : 'enabled';
|
||||||
|
html += "' class='ScheduleToggle-switch is-on' ng-click='" + field.ngClick + "'>ON</div><div ng-show='!" + form.iterator + "." ;
|
||||||
|
html += (field.flag) ? field.flag : "enabled";
|
||||||
|
html += "' class='ScheduleToggle-switch' ng-click='" + field.ngClick + "'>OFF</div></div></td>";
|
||||||
|
}
|
||||||
|
|
||||||
if (field.type === 'alertblock') {
|
if (field.type === 'alertblock') {
|
||||||
html += "<div class=\"row\">\n";
|
html += "<div class=\"row\">\n";
|
||||||
@@ -1430,17 +1464,26 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
|
|||||||
html+= "<span class=\"Form-title--is_superuser\" "+
|
html+= "<span class=\"Form-title--is_superuser\" "+
|
||||||
"ng-if=is_superuser>Admin</span>";
|
"ng-if=is_superuser>Admin</span>";
|
||||||
}
|
}
|
||||||
html += "</div>\n";
|
html += "</div>\n";
|
||||||
|
html += "<div class=\"Form-header--fields\">";
|
||||||
|
if(this.form.headerFields){
|
||||||
|
var that = this;
|
||||||
|
_.forEach(this.form.headerFields, function(value, key){
|
||||||
|
html += that.buildHeaderField(key, value, options, that.form);
|
||||||
|
});
|
||||||
|
html += "</div>\n";
|
||||||
|
}
|
||||||
|
else{ html += "</div>\n"; }
|
||||||
if(this.form.cancelButton !== undefined && this.form.cancelButton === false) {
|
if(this.form.cancelButton !== undefined && this.form.cancelButton === false) {
|
||||||
html += "<div class=\"Form-exitHolder\">";
|
html += "<div class=\"Form-exitHolder\">";
|
||||||
html += "</div>";
|
html += "</div></div>";
|
||||||
} else {
|
} else {
|
||||||
html += "<div class=\"Form-exitHolder\">";
|
html += "<div class=\"Form-exitHolder\">";
|
||||||
html += "<button class=\"Form-exit\" ng-click=\"formCancel()\">";
|
html += "<button class=\"Form-exit\" ng-click=\"formCancel()\">";
|
||||||
html += "<i class=\"fa fa-times-circle\"></i>";
|
html += "<i class=\"fa fa-times-circle\"></i>";
|
||||||
html += "</button></div>\n";
|
html += "</button></div>\n";
|
||||||
}
|
}
|
||||||
html += "</div>\n"; //end of Form-header
|
html += "</div></div>\n"; //end of Form-header
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_.isEmpty(this.form.related)) {
|
if (!_.isEmpty(this.form.related)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user