diff --git a/awx/ui/static/js/system-tracking/data-services/dedupe-versions.js b/awx/ui/static/js/system-tracking/data-services/dedupe-versions.js new file mode 100644 index 0000000000..789d1cd61e --- /dev/null +++ b/awx/ui/static/js/system-tracking/data-services/dedupe-versions.js @@ -0,0 +1,36 @@ +export default + function dedupeVersions(nonEmptyResults) { + + if (_.any(nonEmptyResults, 'versions.length', 0)) { + return _.pluck(nonEmptyResults, 'versions[0]'); + } + + var firstTimestamp = nonEmptyResults[0].versions[0].timestamp; + + var hostIdsWithDupes = + _(nonEmptyResults) + .pluck('versions[0]') + .filter('timestamp', firstTimestamp) + .map(function(version, index) { + return nonEmptyResults[index].hostId; + }) + .value(); + + if (hostIdsWithDupes.length === 1) { + return _.pluck(nonEmptyResults, 'versions[0]'); + } + + var bestScanResults = _.max(nonEmptyResults, "versions.length"); + + return nonEmptyResults.map(function(scan, index) { + var hasDupe = + _.include(hostIdsWithDupes, scan.hostId); + + if (hasDupe && index === 1) { + return bestScanResults.versions[0]; + } else { + return bestScanResults.versions[1]; + } + }); + + } diff --git a/awx/ui/static/js/system-tracking/data-services/fact-scan-data.service.js b/awx/ui/static/js/system-tracking/data-services/fact-scan-data.service.js index 6caa558aab..9805dfdf2d 100644 --- a/awx/ui/static/js/system-tracking/data-services/fact-scan-data.service.js +++ b/awx/ui/static/js/system-tracking/data-services/fact-scan-data.service.js @@ -51,7 +51,8 @@ function (Rest, GetBasePath, ProcessErrors, _) { Rest.setUrl(url); promise = Rest.get(); return promise.then(function(response) { - return response.data.results; + versionParams.versions = response.data.results; + return versionParams; }).catch(function (response) { ProcessErrors(null, response.data, response.status, null, { hdr: 'Error!', 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 a45249d483..0e6e47ac45 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 @@ -4,15 +4,20 @@ * All Rights Reserved *************************************************/ +import dedupeVersions from './dedupe-versions'; + export default [ 'factScanDataService', 'getModuleOptions', - 'resolveVersions', + 'resolveEmptyVersions', 'lodashAsPromised', - function(factScanDataService, getModuleOptions, resolveVersions, _) { + function(factScanDataService, getModuleOptions, resolveEmptyVersions, _) { return function(hostIds, moduleName, leftDate, rightDate) { + var singleHostMode = false; + if (hostIds.length === 1) { + singleHostMode = true; hostIds = hostIds.concat(hostIds[0]); } @@ -27,26 +32,36 @@ export default } ]; - return _(hostVersionParams) - .map(function(versionParam) { - var versionWithRequest = - [ versionParam, - factScanDataService. - getVersion(versionParam) - ]; + return _(factScanDataService.getVersion(hostVersionParams[1])) + .then(function(result) { + return resolveEmptyVersions(result); + }).thenAll(function(firstResult) { - return versionWithRequest; - }).thenAll(function(versions) { - return resolveVersions(versions); - }, true) - .thenMap(function(versionData) { + return factScanDataService.getVersion(hostVersionParams[0]) + .then(function(secondResult) { + if (_.isEmpty(secondResult.versions)) { + secondResult = resolveEmptyVersions(secondResult); + } + + return [firstResult, secondResult]; + }); + }).thenAll(function(results) { + var finalSet; + + if (singleHostMode) { + finalSet = dedupeVersions(results.reverse()); + } else { + finalSet = _.pluck(results, 'versions[0]').reverse(); + } + + return finalSet; + }).thenMap(function(versionData) { if (versionData) { return factScanDataService.getFacts(versionData); } else { return { fact: [] }; } - }) - .thenAll(function(hostFacts) { + }).thenAll(function(hostFacts) { return hostFacts; }); }; diff --git a/awx/ui/static/js/system-tracking/data-services/resolve-empty-versions.factory.js b/awx/ui/static/js/system-tracking/data-services/resolve-empty-versions.factory.js new file mode 100644 index 0000000000..127e80af41 --- /dev/null +++ b/awx/ui/static/js/system-tracking/data-services/resolve-empty-versions.factory.js @@ -0,0 +1,31 @@ +import moment from 'tower/shared/moment/moment'; + +function resolveEmptyVersions(service, _, candidate, previousResult) { + + candidate = _.merge({}, candidate); + + if (_.isEmpty(candidate.versions)) { + var originalStartDate = candidate.dateRange.from.clone(); + + if (!_.isUndefined(previousResult)) { + candidate.dateRange.from = moment(previousResult.versions[0].timestamp); + } else { + candidate.dateRange.from = originalStartDate.clone().subtract(1, 'year'); + } + + candidate.dateRange.to = originalStartDate; + + return service.getVersion(candidate); + } + + return _.promise(candidate); + +} + +export default + [ 'factScanDataService', + 'lodashAsPromised', + function(factScanDataService, lodash) { + return _.partial(resolveEmptyVersions, factScanDataService, lodash); + } + ]; diff --git a/awx/ui/static/js/system-tracking/data-services/resolve-versions.factory.js b/awx/ui/static/js/system-tracking/data-services/resolve-versions.factory.js deleted file mode 100644 index e2a21e791e..0000000000 --- a/awx/ui/static/js/system-tracking/data-services/resolve-versions.factory.js +++ /dev/null @@ -1,86 +0,0 @@ -function resolveVersions(service, _, results) { - - function transformToObjects(versionArray) { - - var converted = versionArray[0]; - converted.versions = versionArray[1]; - - return converted; - - } - - function resolveEmpties(result) { - - var newResult = _.merge({}, result); - - if (_.isEmpty(newResult.versions)) { - var originalStartDate = result.dateRange.from.clone(); - - newResult.dateRange.from = originalStartDate.clone().subtract(1, 'year'); - newResult.dateRange.to = originalStartDate; - - return [newResult, service.getVersion(newResult)]; - } - - return [newResult, _.promise(newResult.versions)]; - - } - - function resolveDuplicates(nonEmptyResults) { - var allSameHost = - _.every(nonEmptyResults, { 'hostId': nonEmptyResults[0].hostId }); - - if (allSameHost) { - - if (_.any(nonEmptyResults, 'versions.length', 0)) { - return _.pluck(nonEmptyResults, 'versions[0]'); - } - - var firstTimestamp = nonEmptyResults[0].versions[0].timestamp; - - var hostIdsWithDupes = - _(nonEmptyResults) - .pluck('versions[0]') - .filter('timestamp', firstTimestamp) - .map(function(version, index) { - return nonEmptyResults[index].hostId; - }) - .value(); - - if (hostIdsWithDupes.length === 1) { - return _.pluck(nonEmptyResults, 'versions[0]'); - } - - return nonEmptyResults.map(function(scan, index) { - var hasDupe = - _.include(hostIdsWithDupes, scan.hostId); - - if (hasDupe && index === 1) { - return scan.versions[1]; - } else { - return scan.versions[0]; - } - }); - - } else { - return _.pluck(nonEmptyResults, 'versions[0]'); - } - } - - return _(results) - .map(transformToObjects) - .map(resolveEmpties) - .thenAll(function(resolved) { - var versionObjects = resolved.map(transformToObjects); - return resolveDuplicates(versionObjects); - }, true) - .value(); -} - -export default - [ 'factScanDataService', - 'lodashAsPromised', - function(factScanDataService, lodash) { - return _.partial(resolveVersions, factScanDataService, lodash); - } - ]; diff --git a/awx/ui/static/js/system-tracking/main.js b/awx/ui/static/js/system-tracking/main.js index c1e94bd617..956b80be8d 100644 --- a/awx/ui/static/js/system-tracking/main.js +++ b/awx/ui/static/js/system-tracking/main.js @@ -8,7 +8,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 resolveVersions from './data-services/resolve-versions.factory'; +import resolveEmptyVersions from './data-services/resolve-empty-versions.factory'; import controller from './system-tracking.controller'; import stringOrDateFilter from './string-or-date.filter'; import shared from 'tower/shared/main'; @@ -24,7 +24,7 @@ export default .service('factScanDataService', factScanDataService) .factory('getDataForComparison', getDataForComparison) .factory('getModuleOptions', getModuleOptions) - .factory('resolveVersions', resolveVersions) + .factory('resolveEmptyVersions', resolveEmptyVersions) .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 0ca55b9346..9536148a17 100644 --- a/awx/ui/static/js/system-tracking/system-tracking.controller.js +++ b/awx/ui/static/js/system-tracking/system-tracking.controller.js @@ -23,11 +23,17 @@ function controller($rootScope, var hosts = $routeParams.model.hosts; var moduleParam = $routeParams.module || 'packages'; + $scope.compareMode = + hostIds.length === 1 ? 'single-host' : 'host-to-host'; $scope.hostIds = $routeParams.hosts; $scope.inventory = $routeParams.model.inventory; - $scope.factModulePickersLabelLeft = "Compare latest facts collected on or before"; - $scope.factModulePickersLabelRight = "To latest facts collected on or before"; + if ($scope.compareMode === 'host-to-host') { + $scope.factModulePickersLabelLeft = "Compare latest facts collected across both hosts on or before"; + } else { + $scope.factModulePickersLabelLeft = "Compare latest facts collected on or before"; + $scope.factModulePickersLabelRight = "To latest facts collected on or before"; + } $scope.modules = moduleOptions; @@ -53,6 +59,9 @@ function controller($rootScope, var rightRange = searchConfig.rightRange; var activeModule = searchConfig.module; + if ($scope.compareMode === 'host-to-host') { + rightRange = searchConfig.leftRange; + } waitIndicator('start'); 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 3e75fd7a12..fa4c45c4ca 100644 --- a/awx/ui/static/js/system-tracking/system-tracking.partial.html +++ b/awx/ui/static/js/system-tracking/system-tracking.partial.html @@ -10,7 +10,7 @@ {{ factModulePickersLabelLeft }} -
+
{{ factModulePickersLabelRight }}