From 434097101f9efd5f410841c22564a07867e301e1 Mon Sep 17 00:00:00 2001 From: Leigh Johnson Date: Fri, 22 Apr 2016 14:27:58 -0400 Subject: [PATCH 1/5] cloneDeep list config and add additional ignored field params --- awx/ui/client/src/app.js | 22 +--- awx/ui/client/src/controllers/Home.js | 112 +----------------- awx/ui/client/src/controllers/Projects.js | 1 - awx/ui/client/src/dashboard/main.js | 3 +- awx/ui/client/src/lists.js | 2 - awx/ui/client/src/lists/HomeHosts.js | 103 ---------------- .../src/search/getSearchHtml.service.js | 7 +- .../client/src/search/tagSearch.controller.js | 3 +- awx/ui/client/src/search/tagSearch.service.js | 5 +- 9 files changed, 14 insertions(+), 244 deletions(-) delete mode 100644 awx/ui/client/src/lists/HomeHosts.js diff --git a/awx/ui/client/src/app.js b/awx/ui/client/src/app.js index efd17c9661..6880c37411 100644 --- a/awx/ui/client/src/app.js +++ b/awx/ui/client/src/app.js @@ -20,7 +20,7 @@ import './lists'; import './widgets'; import './help'; import './filters'; -import {Home, HomeGroups, HomeHosts} from './controllers/Home'; +import {Home, HomeGroups} from './controllers/Home'; import {SocketsController} from './controllers/Sockets'; import {CredentialsAdd, CredentialsEdit, CredentialsList} from './controllers/Credentials'; import {JobsListController} from './controllers/Jobs'; @@ -175,7 +175,6 @@ var tower = angular.module('Tower', [ 'CredentialsHelper', 'StreamListDefinition', 'HomeGroupListDefinition', - 'HomeHostListDefinition', 'ActivityDetailDefinition', 'VariablesHelper', 'SchedulesListDefinition', @@ -269,25 +268,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', { url: '/jobs', templateUrl: urlPrefix + 'partials/jobs.html', diff --git a/awx/ui/client/src/controllers/Home.js b/awx/ui/client/src/controllers/Home.js index 3d8adebad2..b2fe9dbda8 100644 --- a/awx/ui/client/src/controllers/Home.js +++ b/awx/ui/client/src/controllers/Home.js @@ -1,5 +1,5 @@ /************************************************* - * Copyright (c) 2015 Ansible, Inc. + * Copyright (c) 2016 Ansible, Inc. * * 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 //scope. - var generator = GenerateList, list = HomeGroupList, defaultUrl = GetBasePath('groups'), @@ -517,112 +516,3 @@ HomeGroups.$inject = ['$rootScope', '$log', '$scope', '$filter', '$compile', '$l * @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' -]; diff --git a/awx/ui/client/src/controllers/Projects.js b/awx/ui/client/src/controllers/Projects.js index a603f69bf2..c7ca0d1ab4 100644 --- a/awx/ui/client/src/controllers/Projects.js +++ b/awx/ui/client/src/controllers/Projects.js @@ -28,7 +28,6 @@ export function ProjectsList ($scope, $rootScope, $location, $log, $stateParams, mode = (base === 'projects') ? 'edit' : 'select', url = (base === 'teams') ? GetBasePath('teams') + $stateParams.team_id + '/projects/' : defaultUrl, choiceCount = 0; - view.inject(list, { mode: mode, scope: $scope }); $rootScope.flashMessage = null; diff --git a/awx/ui/client/src/dashboard/main.js b/awx/ui/client/src/dashboard/main.js index 80f27a1ff1..bd0fd75743 100644 --- a/awx/ui/client/src/dashboard/main.js +++ b/awx/ui/client/src/dashboard/main.js @@ -2,7 +2,8 @@ import dashboardCounts from './counts/main'; import dashboardGraphs from './graphs/main'; import dashboardLists from './lists/main'; import dashboardDirective from './dashboard.directive'; +import dashboardHosts from './hosts/main'; 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); diff --git a/awx/ui/client/src/lists.js b/awx/ui/client/src/lists.js index da4aa67f7b..925f57bd65 100644 --- a/awx/ui/client/src/lists.js +++ b/awx/ui/client/src/lists.js @@ -11,7 +11,6 @@ import AllJobs from "./lists/AllJobs"; import Credentials from "./lists/Credentials"; import Groups from "./lists/Groups"; import HomeGroups from "./lists/HomeGroups"; -import HomeHosts from "./lists/HomeHosts"; import Hosts from "./lists/Hosts"; import Inventories from "./lists/Inventories"; import InventoryGroups from "./lists/InventoryGroups"; @@ -39,7 +38,6 @@ export Credentials, Groups, HomeGroups, - HomeHosts, Hosts, Inventories, InventoryGroups, diff --git a/awx/ui/client/src/lists/HomeHosts.js b/awx/ui/client/src/lists/HomeHosts.js deleted file mode 100644 index ffa5fc2d52..0000000000 --- a/awx/ui/client/src/lists/HomeHosts.js +++ /dev/null @@ -1,103 +0,0 @@ -/************************************************* - * Copyright (c) 2015 Ansible, Inc. - * - * All Rights Reserved - *************************************************/ - - -export default - angular.module('HomeHostListDefinition', []) - .value('HomeHostList', { - - name: 'hosts', - iterator: 'host', - selectTitle: 'Add Existing Hosts', - editTitle: 'Hosts', - listTitle: 'Hosts', - index: false, - hover: true, - well: true, - - fields: { - status: { - label: "", - iconOnly: true, - icon: "{{ 'icon-job-' + host.active_failures }}", - awToolTip: "{{ host.badgeToolTip }}", - awTipPlacement: "right", - dataPlacement: "right", - awPopOver: "{{ host.job_status_html }}", - ngClick:"bob", - columnClass: "List-staticColumn--smallStatus", - searchable: false, - nosort: true - }, - name: { - key: true, - label: 'Name', - 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)" - }, - inventory_name: { - label: 'Inventory', - sourceModel: 'inventory', - sourceField: 'name', - columnClass: 'col-lg-5 col-md-4 col-sm-4 hidden-xs elllipsis', - linkTo: "{{ '/#/inventories/' + host.inventory }}" - }, - enabled: { - label: 'Disabled?', - searchSingleValue: true, - searchType: 'boolean', - searchValue: 'false', - searchOnly: true - }, - has_active_failures: { - label: 'Has failed jobs?', - searchSingleValue: true, - searchType: 'boolean', - searchValue: 'true', - searchOnly: true - }, - has_inventory_sources: { - label: 'Has external source?', - searchSingleValue: true, - searchType: 'boolean', - searchValue: 'true', - searchOnly: true - }, - id: { - label: 'ID', - searchOnly: true - } - }, - - fieldActions: { - - 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: { - label: 'Edit', - ngClick: "editHost(host.id)", - icon: 'icon-edit', - awToolTip: 'Edit host', - dataPlacement: 'top' - } - }, - - actions: { - - } - - }); diff --git a/awx/ui/client/src/search/getSearchHtml.service.js b/awx/ui/client/src/search/getSearchHtml.service.js index 12b9f47da9..b7da64f702 100644 --- a/awx/ui/client/src/search/getSearchHtml.service.js +++ b/awx/ui/client/src/search/getSearchHtml.service.js @@ -1,16 +1,21 @@ export default ['GetBasePath', function(GetBasePath) { // given the list, return the fields that need searching this.getList = function(list) { - var f = _.clone(list.fields); + var f = _.cloneDeep(list.fields); return JSON.stringify(Object .keys(f) .filter(function(i) { return (f[i] .searchable !== false); }).map(function(i) { + // delete any fields which might include AngularJS interpolation tags {{ }} delete f[i].awToolTip; + delete f[i].awPopover; + delete f[i].linkTo; + delete f[i].dataTitle; delete f[i].ngClass; delete f[i].ngClick; + delete f[i].icon; return {[i]: f[i]}; }).reduce(function (acc, i) { var key = Object.keys(i); diff --git a/awx/ui/client/src/search/tagSearch.controller.js b/awx/ui/client/src/search/tagSearch.controller.js index 21121a648a..a07362bfba 100644 --- a/awx/ui/client/src/search/tagSearch.controller.js +++ b/awx/ui/client/src/search/tagSearch.controller.js @@ -1,7 +1,8 @@ export default ['$scope', 'Refresh', 'tagSearchService', function($scope, Refresh, tagSearchService) { // JSONify passed field elements that can be searched - $scope.list = JSON.parse($scope.list); + console.log($scope.list) + $scope.list = angular.fromJson($scope.list); // Access config lines from list spec $scope.listConfig = $scope.$parent.list; // Grab options for the left-dropdown of the searchbar diff --git a/awx/ui/client/src/search/tagSearch.service.js b/awx/ui/client/src/search/tagSearch.service.js index 7b53d28c8c..eb004a2e39 100644 --- a/awx/ui/client/src/search/tagSearch.service.js +++ b/awx/ui/client/src/search/tagSearch.service.js @@ -35,8 +35,7 @@ export default ['Rest', '$q', 'GetBasePath', 'Wait', 'ProcessErrors', '$log', fu obj.value = value; obj.label = label; obj.type = type; - - + obj.basePath = field['basePath'] || null; // return the built option if (type === 'select') { @@ -79,7 +78,7 @@ export default ['Rest', '$q', 'GetBasePath', 'Wait', 'ProcessErrors', '$log', fu if (needsRequest.length) { // 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() .success(function (data) { try { From baf8d9ef6f471b3ffa3f1a0dd2fb7c41c1ae9cec Mon Sep 17 00:00:00 2001 From: Leigh Johnson Date: Sun, 24 Apr 2016 19:00:16 -0400 Subject: [PATCH 2/5] create dashboard-hosts model, finish list view w/ status toggle, #1598 --- .../hosts/dashboard-hosts-edit.controller.js | 19 ++++ .../hosts/dashboard-hosts-edit.partial.html | 4 + .../hosts/dashboard-hosts-list.controller.js | 48 ++++++++++ .../hosts/dashboard-hosts-list.partial.html | 4 + .../dashboard/hosts/dashboard-hosts.form.js | 66 ++++++++++++++ .../dashboard/hosts/dashboard-hosts.list.js | 91 +++++++++++++++++++ .../dashboard/hosts/dashboard-hosts.route.js | 62 +++++++++++++ .../hosts/dashboard-hosts.service.js | 18 ++++ awx/ui/client/src/dashboard/hosts/main.js | 20 ++++ 9 files changed, 332 insertions(+) create mode 100644 awx/ui/client/src/dashboard/hosts/dashboard-hosts-edit.controller.js create mode 100644 awx/ui/client/src/dashboard/hosts/dashboard-hosts-edit.partial.html create mode 100644 awx/ui/client/src/dashboard/hosts/dashboard-hosts-list.controller.js create mode 100644 awx/ui/client/src/dashboard/hosts/dashboard-hosts-list.partial.html create mode 100644 awx/ui/client/src/dashboard/hosts/dashboard-hosts.form.js create mode 100644 awx/ui/client/src/dashboard/hosts/dashboard-hosts.list.js create mode 100644 awx/ui/client/src/dashboard/hosts/dashboard-hosts.route.js create mode 100644 awx/ui/client/src/dashboard/hosts/dashboard-hosts.service.js create mode 100644 awx/ui/client/src/dashboard/hosts/main.js diff --git a/awx/ui/client/src/dashboard/hosts/dashboard-hosts-edit.controller.js b/awx/ui/client/src/dashboard/hosts/dashboard-hosts-edit.controller.js new file mode 100644 index 0000000000..9cd09d55e5 --- /dev/null +++ b/awx/ui/client/src/dashboard/hosts/dashboard-hosts-edit.controller.js @@ -0,0 +1,19 @@ +/************************************************* + * Copyright (c) 2016 Ansible, Inc. + * + * All Rights Reserved + *************************************************/ + + export default + ['$scope', '$state', '$stateParams', 'DashboardHostsForm', 'GenerateForm', 'host', + function($scope, $state, $stateParams, DashboardHostsForm, GenerateForm, host){ + var generator = GenerateForm, + form = DashboardHostsForm; + + var init = function(){ + $scope.host = host; + GenerateForm.inject(form, {mode: 'edit', related: false, scope: $scope}); + }; + + init(); + }]; \ No newline at end of file diff --git a/awx/ui/client/src/dashboard/hosts/dashboard-hosts-edit.partial.html b/awx/ui/client/src/dashboard/hosts/dashboard-hosts-edit.partial.html new file mode 100644 index 0000000000..5db1583d13 --- /dev/null +++ b/awx/ui/client/src/dashboard/hosts/dashboard-hosts-edit.partial.html @@ -0,0 +1,4 @@ +
+
+
+
diff --git a/awx/ui/client/src/dashboard/hosts/dashboard-hosts-list.controller.js b/awx/ui/client/src/dashboard/hosts/dashboard-hosts-list.controller.js new file mode 100644 index 0000000000..7e891cd1f2 --- /dev/null +++ b/awx/ui/client/src/dashboard/hosts/dashboard-hosts-list.controller.js @@ -0,0 +1,48 @@ +/************************************************* + * Copyright (c) 2016 Ansible, Inc. + * + * All Rights Reserved + *************************************************/ + +export default + ['$scope', '$state', '$stateParams', 'Rest', 'GetBasePath', 'DashboardHostsList', + 'generateList', 'PaginateInit', 'SetStatus', 'DashboardHostsService', 'hosts', + function($scope, $state, $stateParams, Rest, GetBasePath, DashboardHostsList, GenerateList, PaginateInit, SetStatus, DashboardHostsService, hosts){ + var generator = GenerateList, + list = DashboardHostsList, + defaultUrl = GetBasePath('hosts'); + $scope.editHost = function(id){ + $state.go('dashboardHosts.edit', {id: id}); + }; + $scope.toggleHostEnabled = function(host){ + DashboardHostsService.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; + }); + }; + 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.length; + $scope.hosts = hosts; + setJobStatus(); + generator.inject(list, {mode: 'edit', scope: $scope}); + PaginateInit({ + scope: $scope, + list: list, + url: defaultUrl + }); + console.log($scope) + $scope.hostLoading = false; + }; + init(); + }]; \ No newline at end of file diff --git a/awx/ui/client/src/dashboard/hosts/dashboard-hosts-list.partial.html b/awx/ui/client/src/dashboard/hosts/dashboard-hosts-list.partial.html new file mode 100644 index 0000000000..53511acd75 --- /dev/null +++ b/awx/ui/client/src/dashboard/hosts/dashboard-hosts-list.partial.html @@ -0,0 +1,4 @@ +
+
+
+
\ No newline at end of file diff --git a/awx/ui/client/src/dashboard/hosts/dashboard-hosts.form.js b/awx/ui/client/src/dashboard/hosts/dashboard-hosts.form.js new file mode 100644 index 0000000000..78a895953d --- /dev/null +++ b/awx/ui/client/src/dashboard/hosts/dashboard-hosts.form.js @@ -0,0 +1,66 @@ +/************************************************* +* 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', + headerFields:{ + enabled: { + label: 'Enabled?', + type: 'checkbox', + editRequired: false, + 'default': true, + awPopOver: "

Indicates if a host is available and should be included in running jobs.

For hosts that " + + "are part of an external inventory, this flag cannot be changed. It will be set by the inventory sync process.

", + dataTitle: 'Host Enabled' + } + }, + fields: { + enabled: { + label: 'Status', + columnClass: 'List-staticColumn--toggle', + type: 'toggle', + ngClick: 'toggleHostEnabled(host)', + searchable: false, + nosort: true + }, + name: { + label: 'Host Name', + type: 'text', + editRequired: true, + awPopOver: "

Provide a host name, ip address, or ip address:port. Examples include:

" + + "
myserver.domain.com
" + + "127.0.0.1
" + + "10.1.0.140:25
" + + "server.example.com:25" + + "
", + }, + description: { + label: 'Description', + type: 'text', + editRequired: false + }, + variables: { + label: 'Variables', + type: 'textarea', + editRequired: false, + rows: 6, + default: '---', + awPopOver: "

Enter variables using either JSON or YAML syntax. Use the radio button to toggle between the two.

" + + "JSON:
\n" + + "
{
\"somevar\": \"somevalue\",
\"password\": \"magic\"
}
\n" + + "YAML:
\n" + + "
---
somevar: somevalue
password: magic
\n" + + '

View JSON examples at www.json.org

' + + '

View YAML examples at docs.ansible.com

', + } + } + } +}; \ No newline at end of file diff --git a/awx/ui/client/src/dashboard/hosts/dashboard-hosts.list.js b/awx/ui/client/src/dashboard/hosts/dashboard-hosts.list.js new file mode 100644 index 0000000000..aac8f8b330 --- /dev/null +++ b/awx/ui/client/src/dashboard/hosts/dashboard-hosts.list.js @@ -0,0 +1,91 @@ +/************************************************* +* Copyright (c) 2015 Ansible, Inc. +* +* All Rights Reserved +*************************************************/ + + +export default function(){ + return { + name: 'hosts', + iterator: 'host', + selectTitle: 'Add Existing Hosts', + editTitle: 'Hosts', + listTitle: 'Hosts', + index: false, + hover: true, + well: true, + + fields: { + status: { + basePath: 'unified_jobs', + label: '', + iconOnly: true, + searchable: true, + searchType: 'select', + nosort: true, + searchOptions: [], + searchLabel: 'Job Status', + icon: 'icon-job-{{ host.active_failures }}', + awToolTip: '{{ host.badgeToolTip }}', + awTipPlacement: 'right', + 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: { + key: true, + label: 'Name', + columnClass: 'col-lg-5 col-md-5 col-sm-5 col-xs-8 ellipsis List-staticColumnAdjacent', + ngClick: 'editHost(host.id)' + }, + inventory_name: { + label: 'Inventory', + sourceModel: 'inventory', + sourceField: 'name', + columnClass: 'col-lg-5 col-md-4 col-sm-4 hidden-xs elllipsis', + linkTo: "{{ '/#/inventories/' + host.inventory_id }}", + searchable: false + }, + enabled: { + label: 'Status', + columnClass: 'List-staticColumn--toggle', + type: 'toggle', + ngClick: 'toggleHostEnabled(host)', + searchable: false, + nosort: true + }, + has_active_failures: { + label: 'Has failed jobs?', + searchSingleValue: true, + searchType: 'boolean', + searchValue: 'true', + searchOnly: true + }, + has_inventory_sources: { + label: 'Has external source?', + searchSingleValue: true, + searchType: 'boolean', + searchValue: 'true', + searchOnly: true + } + }, + + fieldActions: { + + columnClass: 'col-lg-2 col-md-3 col-sm-3 col-xs-4', + edit: { + label: 'Edit', + ngClick: 'editHost(host.id)', + icon: 'icon-edit', + awToolTip: 'Edit host', + dataPlacement: 'top' + } + }, + + actions: { + + } + } +}; diff --git a/awx/ui/client/src/dashboard/hosts/dashboard-hosts.route.js b/awx/ui/client/src/dashboard/hosts/dashboard-hosts.route.js new file mode 100644 index 0000000000..ced2ebfc63 --- /dev/null +++ b/awx/ui/client/src/dashboard/hosts/dashboard-hosts.route.js @@ -0,0 +1,62 @@ +/************************************************* + * 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){ + return _.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; + }); + }); + }] + } +}; + +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}; \ No newline at end of file diff --git a/awx/ui/client/src/dashboard/hosts/dashboard-hosts.service.js b/awx/ui/client/src/dashboard/hosts/dashboard-hosts.service.js new file mode 100644 index 0000000000..f85050e060 --- /dev/null +++ b/awx/ui/client/src/dashboard/hosts/dashboard-hosts.service.js @@ -0,0 +1,18 @@ +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 }); + }); + } + }; + }]; \ No newline at end of file diff --git a/awx/ui/client/src/dashboard/hosts/main.js b/awx/ui/client/src/dashboard/hosts/main.js new file mode 100644 index 0000000000..65f0da2373 --- /dev/null +++ b/awx/ui/client/src/dashboard/hosts/main.js @@ -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('DashboardHostsService', service) + .factory('DashboardHostsList', list) + .factory('DashboardHostsForm', form) + .run(['$stateExtender', function($stateExtender){ + $stateExtender.addState(dashboardHostsList); + $stateExtender.addState(dashboardHostsEdit); + }]); From 85698213cb96c1ec61f8c53d3da758d2e420965c Mon Sep 17 00:00:00 2001 From: Leigh Johnson Date: Mon, 25 Apr 2016 13:47:04 -0400 Subject: [PATCH 3/5] finish dashboard hosts edit, resolves #1598 remove debug line --- awx/ui/client/legacy-styles/forms.less | 15 +++++- .../hosts/dashboard-hosts-edit.controller.js | 38 ++++++++++++-- .../hosts/dashboard-hosts-list.controller.js | 48 +++++++++++------ .../dashboard/hosts/dashboard-hosts.form.js | 41 +++++++++------ .../dashboard/hosts/dashboard-hosts.list.js | 4 +- .../dashboard/hosts/dashboard-hosts.route.js | 4 +- .../hosts/dashboard-hosts.service.js | 12 +++++ awx/ui/client/src/dashboard/hosts/main.js | 2 +- .../client/src/search/tagSearch.controller.js | 1 - awx/ui/client/src/shared/form-generator.js | 51 +++++++++++++++++-- 10 files changed, 172 insertions(+), 44 deletions(-) diff --git a/awx/ui/client/legacy-styles/forms.less b/awx/ui/client/legacy-styles/forms.less index 1afc218913..19cf74082c 100644 --- a/awx/ui/client/legacy-styles/forms.less +++ b/awx/ui/client/legacy-styles/forms.less @@ -15,12 +15,25 @@ 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{ display: flex; } .Form-title{ - flex: 1 0 auto; + flex: 0 1 auto; text-transform: uppercase; color: @list-header-txt; font-size: 14px; diff --git a/awx/ui/client/src/dashboard/hosts/dashboard-hosts-edit.controller.js b/awx/ui/client/src/dashboard/hosts/dashboard-hosts-edit.controller.js index 9cd09d55e5..08abb34cdd 100644 --- a/awx/ui/client/src/dashboard/hosts/dashboard-hosts-edit.controller.js +++ b/awx/ui/client/src/dashboard/hosts/dashboard-hosts-edit.controller.js @@ -5,14 +5,44 @@ *************************************************/ export default - ['$scope', '$state', '$stateParams', 'DashboardHostsForm', 'GenerateForm', 'host', - function($scope, $state, $stateParams, DashboardHostsForm, GenerateForm, host){ + ['$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 + }; + DashboardHostService.putHost(host).then(function(res){ + $state.go('^', null, {reload: true}); + }); + + }; var init = function(){ $scope.host = host; - GenerateForm.inject(form, {mode: 'edit', related: false, scope: $scope}); + $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(); diff --git a/awx/ui/client/src/dashboard/hosts/dashboard-hosts-list.controller.js b/awx/ui/client/src/dashboard/hosts/dashboard-hosts-list.controller.js index 7e891cd1f2..03398be7e9 100644 --- a/awx/ui/client/src/dashboard/hosts/dashboard-hosts-list.controller.js +++ b/awx/ui/client/src/dashboard/hosts/dashboard-hosts-list.controller.js @@ -5,12 +5,13 @@ *************************************************/ export default - ['$scope', '$state', '$stateParams', 'Rest', 'GetBasePath', 'DashboardHostsList', - 'generateList', 'PaginateInit', 'SetStatus', 'DashboardHostsService', 'hosts', - function($scope, $state, $stateParams, Rest, GetBasePath, DashboardHostsList, GenerateList, PaginateInit, SetStatus, DashboardHostsService, hosts){ + ['$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}); }; @@ -21,6 +22,14 @@ export default $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({ @@ -30,19 +39,26 @@ export default }); }; var init = function(){ - $scope.list = list; - $scope.host_active_search = false; - $scope.host_total_rows = hosts.length; - $scope.hosts = hosts; - setJobStatus(); - generator.inject(list, {mode: 'edit', scope: $scope}); - PaginateInit({ - scope: $scope, - list: list, - url: defaultUrl - }); - console.log($scope) - $scope.hostLoading = false; + $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(); }]; \ No newline at end of file diff --git a/awx/ui/client/src/dashboard/hosts/dashboard-hosts.form.js b/awx/ui/client/src/dashboard/hosts/dashboard-hosts.form.js index 78a895953d..654e76a13e 100644 --- a/awx/ui/client/src/dashboard/hosts/dashboard-hosts.form.js +++ b/awx/ui/client/src/dashboard/hosts/dashboard-hosts.form.js @@ -11,36 +11,34 @@ export default function(){ well: true, formLabelSize: 'col-lg-3', formFieldSize: 'col-lg-9', + iterator: 'host', headerFields:{ enabled: { - label: 'Enabled?', - type: 'checkbox', + //flag: 'host.enabled', + class: 'Form-header-field', + ngClick: 'toggleHostEnabled()', + type: 'toggle', editRequired: false, - 'default': true, - awPopOver: "

Indicates if a host is available and should be included in running jobs.

For hosts that " + + awToolTip: "

Indicates if a host is available and should be included in running jobs.

For hosts that " + "are part of an external inventory, this flag cannot be changed. It will be set by the inventory sync process.

", - dataTitle: 'Host Enabled' + dataTitle: 'Host Enabled' } }, fields: { - enabled: { - label: 'Status', - columnClass: 'List-staticColumn--toggle', - type: 'toggle', - ngClick: 'toggleHostEnabled(host)', - searchable: false, - nosort: true - }, name: { label: 'Host Name', type: 'text', editRequired: true, - awPopOver: "

Provide a host name, ip address, or ip address:port. Examples include:

" + + value: '{{name}}', + awPopOver: "

Provide a host name, ip address, or ip address:port. Examples include:

" + "
myserver.domain.com
" + "127.0.0.1
" + "10.1.0.140:25
" + "server.example.com:25" + "
", + dataTitle: 'Host Name', + dataPlacement: 'right', + dataContainer: 'body' }, description: { label: 'Description', @@ -52,6 +50,10 @@ export default function(){ type: 'textarea', editRequired: false, rows: 6, + class: 'modal-input-xlarge Form-textArea', + dataTitle: 'Host Variables', + dataPlacement: 'right', + dataContainer: 'body', default: '---', awPopOver: "

Enter variables using either JSON or YAML syntax. Use the radio button to toggle between the two.

" + "JSON:
\n" + @@ -61,6 +63,15 @@ export default function(){ '

View JSON examples at www.json.org

' + '

View YAML examples at docs.ansible.com

', } + }, + 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()' + } } - } + }; }; \ No newline at end of file diff --git a/awx/ui/client/src/dashboard/hosts/dashboard-hosts.list.js b/awx/ui/client/src/dashboard/hosts/dashboard-hosts.list.js index aac8f8b330..4731155cbb 100644 --- a/awx/ui/client/src/dashboard/hosts/dashboard-hosts.list.js +++ b/awx/ui/client/src/dashboard/hosts/dashboard-hosts.list.js @@ -54,7 +54,9 @@ export default function(){ type: 'toggle', ngClick: 'toggleHostEnabled(host)', searchable: false, - nosort: true + nosort: true, + awToolTip: "

Indicates if a host is available and should be included in running jobs.

For hosts that are part of an external inventory, this flag cannot be changed. It will be set by the inventory sync process.

", + dataTitle: 'Host Enabled', }, has_active_failures: { label: 'Has failed jobs?', diff --git a/awx/ui/client/src/dashboard/hosts/dashboard-hosts.route.js b/awx/ui/client/src/dashboard/hosts/dashboard-hosts.route.js index ced2ebfc63..84f31ad981 100644 --- a/awx/ui/client/src/dashboard/hosts/dashboard-hosts.route.js +++ b/awx/ui/client/src/dashboard/hosts/dashboard-hosts.route.js @@ -29,11 +29,13 @@ var dashboardHostsList = { var defaultUrl = GetBasePath('hosts') + '?page_size=10'; Rest.setUrl(defaultUrl); return Rest.get().then(function(res){ - return _.map(res.data.results, function(value, key){ + 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 }); }] } diff --git a/awx/ui/client/src/dashboard/hosts/dashboard-hosts.service.js b/awx/ui/client/src/dashboard/hosts/dashboard-hosts.service.js index f85050e060..997167b90a 100644 --- a/awx/ui/client/src/dashboard/hosts/dashboard-hosts.service.js +++ b/awx/ui/client/src/dashboard/hosts/dashboard-hosts.service.js @@ -13,6 +13,18 @@ export default 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 }); + }); } }; }]; \ No newline at end of file diff --git a/awx/ui/client/src/dashboard/hosts/main.js b/awx/ui/client/src/dashboard/hosts/main.js index 65f0da2373..7a02e597d0 100644 --- a/awx/ui/client/src/dashboard/hosts/main.js +++ b/awx/ui/client/src/dashboard/hosts/main.js @@ -11,7 +11,7 @@ import service from './dashboard-hosts.service'; export default angular.module('dashboardHosts', []) - .service('DashboardHostsService', service) + .service('DashboardHostService', service) .factory('DashboardHostsList', list) .factory('DashboardHostsForm', form) .run(['$stateExtender', function($stateExtender){ diff --git a/awx/ui/client/src/search/tagSearch.controller.js b/awx/ui/client/src/search/tagSearch.controller.js index a07362bfba..d49e294a5b 100644 --- a/awx/ui/client/src/search/tagSearch.controller.js +++ b/awx/ui/client/src/search/tagSearch.controller.js @@ -1,7 +1,6 @@ export default ['$scope', 'Refresh', 'tagSearchService', function($scope, Refresh, tagSearchService) { // JSONify passed field elements that can be searched - console.log($scope.list) $scope.list = angular.fromJson($scope.list); // Access config lines from list spec $scope.listConfig = $scope.$parent.list; diff --git a/awx/ui/client/src/shared/form-generator.js b/awx/ui/client/src/shared/form-generator.js index a446b9991e..574d4ac77c 100644 --- a/awx/ui/client/src/shared/form-generator.js +++ b/awx/ui/client/src/shared/form-generator.js @@ -230,6 +230,11 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat 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); if (!options.html) { @@ -606,9 +611,26 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat return html; }, + buildHeaderField: function(key, field, options, form){ + var html = ''; + // extend these blocks to include elements similarly buildField() + if (field.type === 'toggle'){ + html += "
ON
OFF
"; + } + return html; + }, + buildField: function (fld, field, options, form) { - var i, fldWidth, offset, html = '', horizontal = (this.form.horizontal) ? true : false; @@ -725,6 +747,18 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat return html; } + if (field.type === 'toggle'){ + html += "
ON
OFF
"; + } if (field.type === 'alertblock') { html += "
\n"; @@ -1429,17 +1463,26 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat html+= "Admin"; } - html += "
\n"; + html += "\n"; + html += "
"; + if(this.form.headerFields){ + var that = this; + _.forEach(this.form.headerFields, function(value, key){ + html += that.buildHeaderField(key, value, options, that.form); + }); + html += "
\n"; + } + else{ html += "\n"; } if(this.form.cancelButton !== undefined && this.form.cancelButton === false) { html += "
"; - html += "
"; + html += ""; } else { html += "
"; html += "
\n"; } - html += "\n"; //end of Form-header + html += "\n"; //end of Form-header } if (!_.isEmpty(this.form.related)) { From 443d54407b3c76767287dc474f861a2481def074 Mon Sep 17 00:00:00 2001 From: Leigh Johnson Date: Wed, 27 Apr 2016 09:29:16 -0400 Subject: [PATCH 4/5] fix typo in service call ##1679 --- .../src/dashboard/hosts/dashboard-hosts-list.controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awx/ui/client/src/dashboard/hosts/dashboard-hosts-list.controller.js b/awx/ui/client/src/dashboard/hosts/dashboard-hosts-list.controller.js index 03398be7e9..066ab5f9aa 100644 --- a/awx/ui/client/src/dashboard/hosts/dashboard-hosts-list.controller.js +++ b/awx/ui/client/src/dashboard/hosts/dashboard-hosts-list.controller.js @@ -16,7 +16,7 @@ export default $state.go('dashboardHosts.edit', {id: id}); }; $scope.toggleHostEnabled = function(host){ - DashboardHostsService.setHostStatus(host, !host.enabled) + 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; From 5afd8ecce41fba13bf8e1b0865b068fdca8f56f1 Mon Sep 17 00:00:00 2001 From: Leigh Johnson Date: Wed, 27 Apr 2016 09:42:23 -0400 Subject: [PATCH 5/5] pass enabled/disabled to DsahboardHostService #1679 --- .../src/dashboard/hosts/dashboard-hosts-edit.controller.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/awx/ui/client/src/dashboard/hosts/dashboard-hosts-edit.controller.js b/awx/ui/client/src/dashboard/hosts/dashboard-hosts-edit.controller.js index 08abb34cdd..8393088f4a 100644 --- a/awx/ui/client/src/dashboard/hosts/dashboard-hosts-edit.controller.js +++ b/awx/ui/client/src/dashboard/hosts/dashboard-hosts-edit.controller.js @@ -24,7 +24,8 @@ id: $scope.host.id, variables: $scope.extraVars === '---' || $scope.extraVars === '{}' ? null : $scope.extraVars, name: $scope.name, - description: $scope.description + description: $scope.description, + enabled: $scope.host.enabled }; DashboardHostService.putHost(host).then(function(res){ $state.go('^', null, {reload: true});