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 }}