From 657b41510c57fa7173b3cec0d251e2dab4f8c30c Mon Sep 17 00:00:00 2001 From: Joe Fiorini Date: Thu, 28 May 2015 09:42:01 -0400 Subject: [PATCH 01/10] Add breadcrumbs to system tracking page --- .../js/shared/breadcrumbs/breadcrumbs.controller.js | 5 +++-- .../shared/route-extensions/model-listener.config.js | 6 ++++++ .../js/system-tracking/system-tracking.controller.js | 8 ++++++-- .../js/system-tracking/system-tracking.partial.html | 6 ++++++ .../js/system-tracking/system-tracking.route.js | 12 ++++++------ 5 files changed, 27 insertions(+), 10 deletions(-) diff --git a/awx/ui/static/js/shared/breadcrumbs/breadcrumbs.controller.js b/awx/ui/static/js/shared/breadcrumbs/breadcrumbs.controller.js index 62e892b8e3..bc6bd7e661 100644 --- a/awx/ui/static/js/shared/breadcrumbs/breadcrumbs.controller.js +++ b/awx/ui/static/js/shared/breadcrumbs/breadcrumbs.controller.js @@ -11,10 +11,11 @@ export default $scope.breadcrumbs = []; - this.addBreadcrumb = function(title, path) { + this.addBreadcrumb = function(title, path, isCurrent) { var breadcrumb = { title: title, - path: path + path: path, + isCurrent: isCurrent }; if ($rootScope.enteredPath === path) { diff --git a/awx/ui/static/js/shared/route-extensions/model-listener.config.js b/awx/ui/static/js/shared/route-extensions/model-listener.config.js index 78feebb8f9..bf4bb5feba 100644 --- a/awx/ui/static/js/shared/route-extensions/model-listener.config.js +++ b/awx/ui/static/js/shared/route-extensions/model-listener.config.js @@ -4,10 +4,16 @@ * All Rights Reserved *************************************************/ +import {wrapDelegate} from './route-params.decorator'; + export default [ '$rootScope', '$routeParams', function($rootScope, $routeParams) { + $rootScope.$on('$routeChangeStart', function(e, newRoute) { + wrapDelegate(newRoute.params); + }); + $rootScope.$on('$routeChangeSuccess', function(e, newRoute) { if (angular.isUndefined(newRoute.model)) { var keys = Object.keys(newRoute.params); diff --git a/awx/ui/static/js/system-tracking/system-tracking.controller.js b/awx/ui/static/js/system-tracking/system-tracking.controller.js index 493bdc5118..8244874bbf 100644 --- a/awx/ui/static/js/system-tracking/system-tracking.controller.js +++ b/awx/ui/static/js/system-tracking/system-tracking.controller.js @@ -19,6 +19,10 @@ function controller($rootScope, _) { // var inventoryId = $routeParams.id; var hostIds = $routeParams.hosts.split(','); + var hosts = $routeParams.model.hosts; + + $scope.hostIds = $routeParams.hosts; + $scope.inventory = $routeParams.model.inventory; $scope.factModulePickersLabelLeft = "Compare facts collected on"; $scope.factModulePickersLabelRight = "To facts collected on"; @@ -68,8 +72,8 @@ function controller($rootScope, $scope.comparisonLeftHeader = $scope.leftDate; $scope.comparisonRightHeader = $scope.rightDate; } else { - $scope.comparisonLeftHeader = hostIds[0]; - $scope.comparisonRightHeader = hostIds[1]; + $scope.comparisonLeftHeader = hosts[0].name; + $scope.comparisonRightHeader = hosts[1].name; } } diff --git a/awx/ui/static/js/system-tracking/system-tracking.partial.html b/awx/ui/static/js/system-tracking/system-tracking.partial.html index a05967ef5d..cfa2ff6d7b 100644 --- a/awx/ui/static/js/system-tracking/system-tracking.partial.html +++ b/awx/ui/static/js/system-tracking/system-tracking.partial.html @@ -1,3 +1,9 @@ + + + + + +
{{ factModulePickersLabelLeft }} diff --git a/awx/ui/static/js/system-tracking/system-tracking.route.js b/awx/ui/static/js/system-tracking/system-tracking.route.js index ca78ed6b61..fa4fa07d47 100644 --- a/awx/ui/static/js/system-tracking/system-tracking.route.js +++ b/awx/ui/static/js/system-tracking/system-tracking.route.js @@ -48,8 +48,8 @@ export default { 'Rest', 'GetBasePath', function($route, $q, rest, getBasePath) { - if ($route.current.params.inventory) { - return $q.when(true); + if ($route.current.params.hasModelKey('inventory')) { + return $q.when($route.current.params.model.inventory); } var inventoryId = $route.current.params.inventory; @@ -62,17 +62,17 @@ export default { }); } ], - filters: + hosts: [ '$route', '$q', 'Rest', 'GetBasePath', function($route, $q, rest, getBasePath) { - if ($route.current.params.hosts) { - return $q.when(true); + if ($route.current.params.hasModelKey('hosts')) { + return $q.when($route.current.params.model.hosts); } - var hostIds = $route.current.params.filters.split(','); + var hostIds = $route.current.params.hosts.split(','); var hosts = hostIds.map(function(hostId) { From caf7c30de7102f1d7b0ac1a947bffb8be6baa823 Mon Sep 17 00:00:00 2001 From: Joe Fiorini Date: Thu, 28 May 2015 11:26:43 -0400 Subject: [PATCH 02/10] Get available modules from OPTIONS endpoint --- .../get-data-for-comparison.factory.js | 18 ++++-- .../get-module-options.factory.js | 56 +++++++++++++++++++ awx/ui/static/js/system-tracking/main.js | 2 + .../system-tracking.controller.js | 29 +--------- 4 files changed, 73 insertions(+), 32 deletions(-) create mode 100644 awx/ui/static/js/system-tracking/data-services/get-module-options.factory.js diff --git a/awx/ui/static/js/system-tracking/data-services/get-data-for-comparison.factory.js b/awx/ui/static/js/system-tracking/data-services/get-data-for-comparison.factory.js index 1eea1edc54..8865d62bea 100644 --- a/awx/ui/static/js/system-tracking/data-services/get-data-for-comparison.factory.js +++ b/awx/ui/static/js/system-tracking/data-services/get-data-for-comparison.factory.js @@ -6,17 +6,24 @@ export default [ 'factScanDataService', + 'getModuleOptions', 'lodashAsPromised', - function(factScanDataService, _) { + function(factScanDataService, getModuleOptions, _) { return function(hostIds, moduleName, leftDate, rightDate) { + var moduleOptions; + if (hostIds.length === 1) { hostIds = hostIds.concat(hostIds[0]); } - return _(hostIds) - .promise() - .thenMap(function(hostId, index) { + return getModuleOptions(hostIds[0]) + .then(function(modules) { + moduleOptions = modules; + return modules; + }).then(function() { + return hostIds; + }).thenMap(function(hostId, index) { var date = leftDate; var fetchScanNumber; @@ -42,6 +49,9 @@ export default .bind(factScanDataService); return getHostFacts(params); + }).then(function(hostFacts) { + hostFacts.moduleOptions = moduleOptions; + return hostFacts; }); }; } diff --git a/awx/ui/static/js/system-tracking/data-services/get-module-options.factory.js b/awx/ui/static/js/system-tracking/data-services/get-module-options.factory.js new file mode 100644 index 0000000000..031396da9d --- /dev/null +++ b/awx/ui/static/js/system-tracking/data-services/get-module-options.factory.js @@ -0,0 +1,56 @@ +var moduleConfig = + { 'packages': + { compareKey: ['release', 'version'], + nameKey: 'name', + displayType: 'flat' + }, + 'services': + { compareKey: ['state', 'source'], + nameKey: 'name', + displayType: 'flat' + }, + 'files': + { compareKey: ['size', 'mode', 'md5', 'mtime', 'gid', 'uid'], + nameKey: 'path', + displayType: 'flat' + }, + 'custom': + { displayType: 'nested' + } + }; + +function makeModule(option) { + var name = option[0]; + var displayName = option[1]; + var config = moduleConfig.hasOwnProperty(name) ? + moduleConfig[name] : moduleConfig.custom; + + return { + name: name, + displayName: displayName, + compareKey: config.compareKey, + nameKey: config.nameKey, + displayType: config.displayType + }; +} + +function factory(hostId, rest, getBasePath, _) { + var url = [ getBasePath('hosts') + hostId, + 'fact_versions' + ].join('/'); + + rest.setUrl(url); + return _(rest.options()) + .then(function(response) { + return response.data.actions.GET.module.choices; + }).thenMap(makeModule); +} + +export default + [ 'Rest', + 'GetBasePath', + 'lodashAsPromised', + function(rest, getBasePath, lodash) { + return _.partialRight(factory, rest, getBasePath, lodash); + } + ]; diff --git a/awx/ui/static/js/system-tracking/main.js b/awx/ui/static/js/system-tracking/main.js index 7f20e86d89..be08358455 100644 --- a/awx/ui/static/js/system-tracking/main.js +++ b/awx/ui/static/js/system-tracking/main.js @@ -7,6 +7,7 @@ import route from './system-tracking.route'; import factScanDataService from './data-services/fact-scan-data.service'; import getDataForComparison from './data-services/get-data-for-comparison.factory'; +import getModuleOptions from './data-services/get-module-options.factory'; import controller from './system-tracking.controller'; import stringOrDateFilter from './string-or-date.filter'; import shared from 'tower/shared/main'; @@ -22,6 +23,7 @@ export default ]) .service('factScanDataService', factScanDataService) .factory('getDataForComparison', getDataForComparison) + .factory('getModuleOptions', getModuleOptions) .filter('stringOrDate', stringOrDateFilter) .controller('systemTracking', controller) .config(['$routeProvider', function($routeProvider) { diff --git a/awx/ui/static/js/system-tracking/system-tracking.controller.js b/awx/ui/static/js/system-tracking/system-tracking.controller.js index 8244874bbf..f3dc587ca5 100644 --- a/awx/ui/static/js/system-tracking/system-tracking.controller.js +++ b/awx/ui/static/js/system-tracking/system-tracking.controller.js @@ -27,34 +27,7 @@ function controller($rootScope, $scope.factModulePickersLabelLeft = "Compare facts collected on"; $scope.factModulePickersLabelRight = "To facts collected on"; - $scope.modules = - [{ name: 'packages', - displayName: 'Packages', - compareKey: ['release', 'version'], - nameKey: 'name', - isActive: true, - displayType: 'flat' - }, - { name: 'services', - compareKey: ['state', 'source'], - nameKey: 'name', - displayName: 'Services', - isActive: false, - displayType: 'flat' - }, - { name: 'files', - displayName: 'Files', - nameKey: 'path', - compareKey: ['size', 'mode', 'md5', 'mtime', 'gid', 'uid'], - isActive: false, - displayType: 'flat' - }, - { name: 'ansible', - displayName: 'Ansible', - isActive: false, - displayType: 'nested' - } - ]; + $scope.modules = initialFactData.moduleOptions; // Use this to determine how to orchestrate the services var viewType = hostIds.length > 1 ? 'multiHost' : 'singleHost'; From 579ee6d7217c24087462223a1f5352f9557e7ae8 Mon Sep 17 00:00:00 2001 From: Joe Fiorini Date: Thu, 28 May 2015 12:20:43 -0400 Subject: [PATCH 03/10] Display custom fact plugins in module options --- .../data-services/get-module-options.factory.js | 11 ++++------- .../js/system-tracking/fact-module-filter.block.less | 6 +++++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/awx/ui/static/js/system-tracking/data-services/get-module-options.factory.js b/awx/ui/static/js/system-tracking/data-services/get-module-options.factory.js index 031396da9d..961ef718ac 100644 --- a/awx/ui/static/js/system-tracking/data-services/get-module-options.factory.js +++ b/awx/ui/static/js/system-tracking/data-services/get-module-options.factory.js @@ -25,13 +25,10 @@ function makeModule(option) { var config = moduleConfig.hasOwnProperty(name) ? moduleConfig[name] : moduleConfig.custom; - return { - name: name, - displayName: displayName, - compareKey: config.compareKey, - nameKey: config.nameKey, - displayType: config.displayType - }; + config.name = name; + config.displayName = displayName; + + return config; } function factory(hostId, rest, getBasePath, _) { diff --git a/awx/ui/static/js/system-tracking/fact-module-filter.block.less b/awx/ui/static/js/system-tracking/fact-module-filter.block.less index b8cef91cdc..6545cf4245 100644 --- a/awx/ui/static/js/system-tracking/fact-module-filter.block.less +++ b/awx/ui/static/js/system-tracking/fact-module-filter.block.less @@ -3,9 +3,13 @@ .FactModuleFilter { width: 100%; display: flex; + flex-flow: row wrap; margin-bottom: 2.8rem; &-module { - flex: 1; + flex: 1 1 20%; + @media screen and (max-width: 750px) { + flex-basis: 50%; + } &--isActive { // copied from bootstrap's .btn:focus background-color: #ebebeb; From 5f902a55febf0f35ac194553a6b1c8d7e944e221 Mon Sep 17 00:00:00 2001 From: Joe Fiorini Date: Thu, 28 May 2015 12:46:08 -0400 Subject: [PATCH 04/10] Sort modules by built-in then custom --- .../get-module-options.factory.js | 27 +++++++++++++++---- .../system-tracking.partial.html | 2 +- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/awx/ui/static/js/system-tracking/data-services/get-module-options.factory.js b/awx/ui/static/js/system-tracking/data-services/get-module-options.factory.js index 961ef718ac..5ea39f2480 100644 --- a/awx/ui/static/js/system-tracking/data-services/get-module-options.factory.js +++ b/awx/ui/static/js/system-tracking/data-services/get-module-options.factory.js @@ -2,32 +2,48 @@ var moduleConfig = { 'packages': { compareKey: ['release', 'version'], nameKey: 'name', - displayType: 'flat' + displayType: 'flat', + sortKey: 1 }, 'services': { compareKey: ['state', 'source'], nameKey: 'name', - displayType: 'flat' + displayType: 'flat', + sortKey: 2 }, 'files': { compareKey: ['size', 'mode', 'md5', 'mtime', 'gid', 'uid'], nameKey: 'path', - displayType: 'flat' + displayType: 'flat', + sortKey: 3 + }, + 'ansible': + { displayType: 'nested', + sortKey: 4 }, 'custom': { displayType: 'nested' } }; -function makeModule(option) { +function makeModule(option, index) { var name = option[0]; var displayName = option[1]; var config = moduleConfig.hasOwnProperty(name) ? moduleConfig[name] : moduleConfig.custom; + var modulesCount = _.keys(moduleConfig).length - 1; config.name = name; config.displayName = displayName; + // Use index to sort custom modules, + // offset by built-in modules since + // they have a hardcoded sort key + // + if (_.isUndefined(config.sortKey)) { + config.sortKey = (index - 1) + modulesCount; + } + return config; } @@ -39,7 +55,8 @@ function factory(hostId, rest, getBasePath, _) { rest.setUrl(url); return _(rest.options()) .then(function(response) { - return response.data.actions.GET.module.choices; + var choices = response.data.actions.GET.module.choices; + return _.sortBy(choices, '1'); }).thenMap(makeModule); } diff --git a/awx/ui/static/js/system-tracking/system-tracking.partial.html b/awx/ui/static/js/system-tracking/system-tracking.partial.html index cfa2ff6d7b..6b45cbec9e 100644 --- a/awx/ui/static/js/system-tracking/system-tracking.partial.html +++ b/awx/ui/static/js/system-tracking/system-tracking.partial.html @@ -24,7 +24,7 @@ 'FactModuleFilter-module--isActive': module.isActive, }" ng-click="setActiveModule(module.name)" - ng-repeat="module in modules"> + ng-repeat="module in modules | orderBy: 'sortKey'"> {{module.displayName}} From da67aba2d43b8f810f78a6e206b3bf5ba72c5cd0 Mon Sep 17 00:00:00 2001 From: Joe Fiorini Date: Fri, 29 May 2015 09:37:07 -0400 Subject: [PATCH 05/10] Default dates to today and yesterday --- .../js/system-tracking/search-date-range.js | 20 ++++++++++++++++--- .../system-tracking/system-tracking.route.js | 4 ++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/awx/ui/static/js/system-tracking/search-date-range.js b/awx/ui/static/js/system-tracking/search-date-range.js index 6fe497b18b..40acdb3efb 100644 --- a/awx/ui/static/js/system-tracking/search-date-range.js +++ b/awx/ui/static/js/system-tracking/search-date-range.js @@ -4,9 +4,23 @@ * All Rights Reserved *************************************************/ -export function searchDateRange(date) { +export function searchDateRange(dateString) { + var date; + + switch(dateString) { + case 'yesterday': + date = moment().subtract(1, 'day'); + break; + case 'tomorrow': + date = moment().add(1, 'day'); + break; + default: + date = moment(dateString); + } + + return { - from: moment(date).startOf('day'), - to: moment(date).endOf('day') + from: date.startOf('day'), + to: date.endOf('day') }; } diff --git a/awx/ui/static/js/system-tracking/system-tracking.route.js b/awx/ui/static/js/system-tracking/system-tracking.route.js index fa4fa07d47..372012ca3a 100644 --- a/awx/ui/static/js/system-tracking/system-tracking.route.js +++ b/awx/ui/static/js/system-tracking/system-tracking.route.js @@ -21,8 +21,8 @@ export default { var hostIds = $route.current.params.hosts.split(','); var moduleParam = $location.search().module || 'packages'; - var leftDate = searchDateRange('2015-05-26'); - var rightDate = searchDateRange('2015-05-26'); + var leftDate = searchDateRange('yesterday'); + var rightDate = searchDateRange(); if (hostIds.length === 1) { hostIds = hostIds.concat(hostIds[0]); From 8d1e2e1c0c7a0b47854698e706d0e3119c15f101 Mon Sep 17 00:00:00 2001 From: Joe Fiorini Date: Fri, 29 May 2015 09:37:20 -0400 Subject: [PATCH 06/10] Fix styling after nav refresh merge --- awx/ui/static/js/system-tracking/system-tracking.partial.html | 1 - 1 file changed, 1 deletion(-) diff --git a/awx/ui/static/js/system-tracking/system-tracking.partial.html b/awx/ui/static/js/system-tracking/system-tracking.partial.html index 6b45cbec9e..f6828ffba1 100644 --- a/awx/ui/static/js/system-tracking/system-tracking.partial.html +++ b/awx/ui/static/js/system-tracking/system-tracking.partial.html @@ -19,7 +19,6 @@ - - -
-

- There were no facts collected for that module in the selected date range. Please pick a different range or module and try again. -

-
-
-
-

{{comparisonLeftHeader|stringOrDate:'L LT'}}

-

{{comparisonRightHeader|stringOrDate:'L LT'}}

-
-
-
-

- {{group.displayKeyPath}} -

-

- {{group.displayKeyPath}} -

-

- {{group.displayKeyPath}} -

-
- {{group.displayKeyPath}} -
+
+
+ {{ factModulePickersLabelLeft }} +
-
-
-
-

+

+ {{ factModulePickersLabelRight }} + +
+
+ + + +
+

+ There were no facts collected on the dates you selected ({{error.dateValues.leftDate|amDateFormat:'L'}} and {{error.dateValues.rightDate|amDateFormat:'L'}}). Please pick a different range or module and try again. +

+

+ There were no facts collected on one of the dates you selected ({{error.dateValue|amDateFormat:'L'}}). Please select a different date and try again. +

+

+ To setup or run scan jobs, edit the "{{inventory.name}}" inventory and select "Scan Jobs Templates". +

+
+
+
+

{{comparisonLeftHeader|stringOrDate:'L LT'}}

+

{{comparisonRightHeader|stringOrDate:'L LT'}}

+
+
+
+

+ {{group.displayKeyPath}} +

+

+ {{group.displayKeyPath}} +

+

+ {{group.displayKeyPath}} +

+
+ {{group.displayKeyPath}} +
+
+
+
+
+

+ {{fact.keyName}} +

+

+ {{fact.value1}} +

+

+ {{fact.value2}} +

+
+
+
+

{{fact.keyName}}

-

+

{{fact.value1}}

-

+

{{fact.value2}}

-
-

- {{fact.keyName}} -

-

- {{fact.value1}} -

-

- {{fact.value2}} -

-
-
+
From c804409ed3746c56e426da057554b99e9f25a5d5 Mon Sep 17 00:00:00 2001 From: Joe Fiorini Date: Mon, 1 Jun 2015 09:30:06 -0400 Subject: [PATCH 10/10] Fix tests --- .../unit/system-tracking/single-host-data.service-test.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/awx/ui/tests/unit/system-tracking/single-host-data.service-test.js b/awx/ui/tests/unit/system-tracking/single-host-data.service-test.js index 7e9f88c626..fd054c2b38 100644 --- a/awx/ui/tests/unit/system-tracking/single-host-data.service-test.js +++ b/awx/ui/tests/unit/system-tracking/single-host-data.service-test.js @@ -37,7 +37,7 @@ describeModule(systemTracking.name) "module" : "package", "timestamp": '2015-05-07T14:57:37', "related" : { - "fact_view" : "/api/v1/hosts/1/fact_view/?module=packages&datetime=2015-05-07T14%3A57%3A37Z" + "fact_view" : "/hosts/1/fact_versions/?module=packages&from=2015-05-05T00:00:00-04:00&to=2015-05-06T00:00:00-04:00" } }, result = { @@ -46,7 +46,10 @@ describeModule(systemTracking.name) } }; - var actual = service.getFacts(version); + var actual = service.getFacts(version) + .then(function(response) { + return response.fact; + }); restStub.succeedAt(version.related.fact_view, result); restStub.flush();