diff --git a/.jshintrc b/.jshintrc index 0239abbde6..e44155d984 100644 --- a/.jshintrc +++ b/.jshintrc @@ -11,6 +11,9 @@ "maxerr": 10000, "notypeof": true, "globals": { + "beforeEach": false, + "inject": false, + "module": false, "angular":false, "alert":false, "$AnsibleConfig":true, @@ -21,6 +24,7 @@ "Donut3D":false, "nv":false, "it": false, + "xit": false, "expect": false, "context": false, "describe": false, diff --git a/awx/ui/static/js/controllers/Inventories.js b/awx/ui/static/js/controllers/Inventories.js index f18d7116f4..9453902e0a 100644 --- a/awx/ui/static/js/controllers/Inventories.js +++ b/awx/ui/static/js/controllers/Inventories.js @@ -802,7 +802,7 @@ export function InventoriesManage ($log, $scope, $rootScope, $location, ViewUpdateStatus, GroupsDelete, Store, HostsEdit, HostsDelete, EditInventoryProperties, ToggleHostEnabled, Stream, ShowJobSummary, InventoryGroupsHelp, HelpDialog, ViewJob, - GroupsCopy, HostsCopy) { + GroupsCopy, HostsCopy, transitionTo) { var PreviousSearchParams, url, @@ -864,9 +864,10 @@ export function InventoriesManage ($log, $scope, $rootScope, $location, }); $scope.systemTracking = function() { - $location.path('/inventories/' + $scope.inventory.id + - '/system-tracking/' + - _.pluck($scope.hostsSelectedItems, "id").join(",")); + transitionTo('systemTracking', + { inventory: $scope.inventory, + hosts: $scope.hostsSelectedItems + }); }; // populates host patterns based on selected hosts/groups @@ -1411,5 +1412,5 @@ InventoriesManage.$inject = ['$log', '$scope', '$rootScope', '$location', 'GroupsDelete', 'Store', 'HostsEdit', 'HostsDelete', 'EditInventoryProperties', 'ToggleHostEnabled', 'Stream', 'ShowJobSummary', 'InventoryGroupsHelp', 'HelpDialog', 'ViewJob', 'GroupsCopy', - 'HostsCopy' + 'HostsCopy', 'transitionTo' ]; diff --git a/awx/ui/static/js/shared/route-extensions/route-params.decorator.js b/awx/ui/static/js/shared/route-extensions/route-params.decorator.js new file mode 100644 index 0000000000..e1b68484be --- /dev/null +++ b/awx/ui/static/js/shared/route-extensions/route-params.decorator.js @@ -0,0 +1,16 @@ +export function wrapDelegate($delegate) { + $delegate.hasModelKey = function hasModelKey(key) { + return $delegate.hasOwnProperty('model') && + $delegate.model.hasOwnProperty(key); + }; + + return $delegate; +} + +export default + [ '$provide', + function($provide) { + $provide.decorator('$routeParams', wrapDelegate); + + } + ]; diff --git a/awx/ui/static/js/shared/route-extensions/transition-to.factory.js b/awx/ui/static/js/shared/route-extensions/transition-to.factory.js index 6acee4326f..17558a8397 100644 --- a/awx/ui/static/js/shared/route-extensions/transition-to.factory.js +++ b/awx/ui/static/js/shared/route-extensions/transition-to.factory.js @@ -91,7 +91,7 @@ export default function($location, $rootScope, $route, $q) { return function(routeName, model) { var deferred = $q.defer(); - var url = lookupRouteUrl(routeName, $route.routes, model); + var url = lookupRouteUrl(routeName, $route.routes, model, true); var offRouteChangeStart = $rootScope.$on('$routeChangeStart', function(e, newRoute) { diff --git a/awx/ui/static/js/shared/text-label.less b/awx/ui/static/js/shared/text-label.less new file mode 100644 index 0000000000..66ef5f3fec --- /dev/null +++ b/awx/ui/static/js/shared/text-label.less @@ -0,0 +1,20 @@ +/* oops */ + +.include-text-label(@background-color; @color; @content) { + display: inline-block; + content: @content; + + border-radius: 3px; + background-color: @background-color; + color: @color; + text-transform: uppercase; + font-size: .7em; + font-weight: bold; + font-style: normal; + margin-left: 0.5em; + padding: 0.35em; + padding-bottom: 0.2em; + line-height: 1.1; +} + + diff --git a/awx/ui/static/js/system-tracking/compare-facts.js b/awx/ui/static/js/system-tracking/compare-facts.js new file mode 100644 index 0000000000..c7f7f85f63 --- /dev/null +++ b/awx/ui/static/js/system-tracking/compare-facts.js @@ -0,0 +1,10 @@ +import compareNestedFacts from './compare-facts/nested'; +import compareFlatFacts from './compare-facts/flat'; + +export function compareFacts(module, facts) { + if (module.displayType === 'nested') { + return compareNestedFacts(facts); + } else { + return compareFlatFacts(facts, module.nameKey, module.compareKey); + } +} diff --git a/awx/ui/static/js/system-tracking/compare-facts/flat.js b/awx/ui/static/js/system-tracking/compare-facts/flat.js new file mode 100644 index 0000000000..747def2b77 --- /dev/null +++ b/awx/ui/static/js/system-tracking/compare-facts/flat.js @@ -0,0 +1,57 @@ +export default + function flatCompare(facts, nameKey, compareKeys) { + + var leftFacts = facts[0]; + var rightFacts = facts[1]; + + return rightFacts.reduce(function(arr, rightFact) { + var searcher = {}; + searcher[nameKey] = rightFact[nameKey]; + + var isNewFactValue = false; + + var matchingFact = _.where(leftFacts, searcher); + var diffs; + + if (_.isEmpty(matchingFact)) { + isNewFactValue = true; + + diffs = + _.map(rightFact, function(value, key) { + return { keyName: key, + value1: value, + value2: '' + }; + }); + } else { + matchingFact = matchingFact[0]; + + diffs = _(compareKeys) + .map(function(key) { + var leftValue = rightFact[key]; + var rightValue = matchingFact[key]; + if (leftValue !== rightValue) { + return { + keyName: key, + value1: leftValue, + value2: rightValue + }; + } + }).compact() + .value(); + + } + + var descriptor = + { displayKeyPath: rightFact[nameKey], + isNew: isNewFactValue, + nestingLevel: 0, + facts: diffs + }; + + return arr.concat(descriptor); + }, []).filter(function(diff) { + return !_.isEmpty(diff.facts); + }); + + } diff --git a/awx/ui/static/js/system-tracking/compare-facts/nested-helpers.js b/awx/ui/static/js/system-tracking/compare-facts/nested-helpers.js new file mode 100644 index 0000000000..ba3e9c99e7 --- /dev/null +++ b/awx/ui/static/js/system-tracking/compare-facts/nested-helpers.js @@ -0,0 +1,169 @@ +export function formatFacts(diffedResults) { + + var loggingEnabled = false; + + function log(msg, obj) { + if (loggingEnabled) { + /* jshint ignore:start */ + console.log(msg, obj); + /* jshint ignore:end */ + } + return obj; + } + + function isFlatFactArray(fact) { + // Flat arrays will have the index as their + // keyName + return !_.isNaN(Number(fact.keyName)); + } + + function isNestedFactArray(fact) { + // Nested arrays will have the index as the last element + // in the keypath + return !_.isNaN(Number(_.last(fact.keyPath))); + } + function isFactArray(fact) { + return isNestedFactArray(fact) || isFlatFactArray(fact); + } + + // Explode flat results into groups based matching + // parent keypaths + var grouped = _.groupBy(diffedResults, function(obj) { + var leftKeyPathStr = obj.keyPath.join('.'); + log('obj.keyPath', obj.keyPath); + return log(' reduced key', _.reduce(diffedResults, function(result, obj2) { + log(' obj2.keyPath', obj2.keyPath); + var rightKeyPathStr = obj2.keyPath.join('.'); + if (isFactArray(obj)) { + log(' number hit!', Number(_.last(obj.keyPath))); + return obj.keyPath.slice(0,-1); + } else if (rightKeyPathStr && leftKeyPathStr !== rightKeyPathStr && log(' intersection', _.intersection(obj.keyPath, obj2.keyPath).join('.')) === rightKeyPathStr) { + log(' hit!'); + return obj2.keyPath; + } else { + log(' else hit!'); + return result; + } + }, obj.keyPath)).join('.'); + }); + + var normalized = _.mapValues(grouped, function(arr, rootKey) { + log('processing', rootKey); + var nestingLevel = 0; + var trailingLength; + return _(arr).sortBy('keyPath.length').tap(function(arr) { + // Initialize trailing length to the shortest keyPath length + // in the array (first item because we know it's sorted now) + trailingLength = arr[0].keyPath.length; + }).map(function(obj) { + var keyPathStr = obj.keyPath.join('.'); + log(' calculating displayKeyPath for', keyPathStr); + var rootKeyPath = rootKey.split('.'); + var displayKeyPath; + // var factArrayIndex; + var isFactArrayProp = isFactArray(obj); + + if (obj.keyPath.length > trailingLength) { + nestingLevel++; + trailingLength = obj.keyPath.length; + } + + if (isNestedFactArray(obj)) { + // factArrayIndex = obj.keyPath.length > 1 ? Number(_.last(obj.keyPath)) : obj.keyName; + displayKeyPath = _.initial(obj.keyPath).join('.'); + } else if (keyPathStr !== rootKey) { + displayKeyPath = _.difference(obj.keyPath, rootKeyPath).join('.'); + } else { + displayKeyPath = rootKeyPath.join('.'); + } + + + obj.displayKeyPath = displayKeyPath; + obj.nestingLevel = nestingLevel; + // obj.arrayPosition = factArrayIndex; + obj.isArrayMember = isFactArrayProp; + return obj; + }).value(); + }); + + var flattened = _.reduce(normalized, function(flat, value) { + + var groupedValues = _.groupBy(value, 'displayKeyPath'); + + var groupArr = + _.reduce(groupedValues, function(groupArr, facts, key) { + var isArray = facts[0].isArrayMember; + var nestingLevel = facts[0].nestingLevel; + + if (isArray) { + facts = _(facts) + .groupBy('arrayPosition') + .values() + .value(); + } + + var displayObj = + { keyPath: key.split('.'), + displayKeyPath: key, + facts: facts, + isFactArray: isArray, + nestingLevel: nestingLevel + }; + return groupArr.concat(displayObj); + }, []); + + return flat.concat(groupArr); + + }, []); + + return flattened; +} + +export function findFacts(factData) { + var rightData = factData[0]; + var leftData = factData[1]; + + function factObject(keyPath, key, leftValue, rightValue) { + var obj = + { keyPath: keyPath, + keyName: key, + value1: leftValue, + value2: rightValue + }; + return obj; + } + + function descend(parentValue, parentKey, parentKeys) { + if (_.isObject(parentValue)) { + return _.reduce(parentValue, function(all, value, key) { + var merged = descend(value, key, parentKeys.concat(key)); + return all.concat(merged); + }, []); + } else { + + var rightValue = + _.get(rightData, + parentKeys, + 'absent'); + + return factObject( + // TODO: Currently parentKeys is getting passed with the final key + // as the last element. Figure out how to have it passed + // in correctly, so that it's all the keys leading up to + // the value, but not the value's key itself + // In the meantime, slicing the last element off the array + parentKeys.slice(0,-1), + parentKey, + parentValue, + rightValue); + } + } + + return _.reduce(leftData, function(mergedFacts, parentValue, parentKey) { + + var merged = descend(parentValue, parentKey, [parentKey]); + + return _.flatten(mergedFacts.concat(merged)); + + }, []); +} diff --git a/awx/ui/static/js/system-tracking/compare-facts/nested.js b/awx/ui/static/js/system-tracking/compare-facts/nested.js new file mode 100644 index 0000000000..7c5955e48b --- /dev/null +++ b/awx/ui/static/js/system-tracking/compare-facts/nested.js @@ -0,0 +1,63 @@ +import {formatFacts, findFacts} from './nested-helpers'; + +export default function nestedCompare(factsList) { + + factsList = findFacts(factsList); + factsList = compareFacts(factsList); + return formatFacts(factsList); + + function compareFacts(factsList) { + + function serializedFactKey(fact) { + return fact.keyPath.join('.'); + } + + var groupedByParent = + _.groupBy(factsList, function(fact) { + return serializedFactKey(fact); + }); + + + var diffed = _.mapValues(groupedByParent, function(facts) { + return facts.filter(function(fact) { + return fact.value1 !== fact.value2; + }).map(function(fact) { + // TODO: Can we determine a "compare order" and be able say + // which property is actually divergent? + return _.merge({}, fact, { isDivergent: true }); + }); + }); + + var itemsWithDiffs = + _.filter(factsList, function(facts) { + var groupedData = diffed[serializedFactKey(facts)]; + return !_.isEmpty(groupedData); + }); + + var keysWithDiffs = + _.reduce(diffed, function(diffs, facts, key) { + diffs[key] = + facts.reduce(function(diffKeys, fact) { + if (fact.isDivergent) { + return diffKeys.concat(fact.keyName); + } + return diffKeys; + }, []); + return diffs; + }, {}); + + var factsWithDivergence = + _.mapValues(itemsWithDiffs, function(fact) { + var divergentKeys = keysWithDiffs[serializedFactKey(fact)]; + if (divergentKeys) { + var isDivergent = _.include(divergentKeys, fact.keyName); + return _.merge({}, fact, { isDivergent: isDivergent }); + } else { + return _.merge({}, fact, { isDivergent: false }); + } + }); + + return factsWithDivergence; + + } +} diff --git a/awx/ui/static/js/system-tracking/compare-hosts.factory.js b/awx/ui/static/js/system-tracking/compare-hosts.factory.js deleted file mode 100644 index e9eb8972dd..0000000000 --- a/awx/ui/static/js/system-tracking/compare-hosts.factory.js +++ /dev/null @@ -1,7 +0,0 @@ -export default - ['xorObjects', 'formatResults', function(xorObjects, formatResults) { - return function compareHosts(module, factData1, factData2) { - var diffed = xorObjects('name', factData1, factData2); - return formatResults('name', 'version', diffed); - }; - }]; diff --git a/awx/ui/static/js/system-tracking/single-host-data.service.js b/awx/ui/static/js/system-tracking/data-services/fact-scan-data.service.js similarity index 64% rename from awx/ui/static/js/system-tracking/single-host-data.service.js rename to awx/ui/static/js/system-tracking/data-services/fact-scan-data.service.js index c83672ce11..018f3d098b 100644 --- a/awx/ui/static/js/system-tracking/single-host-data.service.js +++ b/awx/ui/static/js/system-tracking/data-services/fact-scan-data.service.js @@ -1,7 +1,22 @@ -export default ['Rest', 'GetBasePath', 'ProcessErrors', -function (Rest, GetBasePath, ProcessErrors) { +export default ['Rest', 'GetBasePath', 'ProcessErrors', 'lodashAsPromised', +function (Rest, GetBasePath, ProcessErrors, _) { return { - getFacts: function(version){ + getHostFacts: function(host, moduleName, date, fetchScanNumber) { + + var version =this.getVersion(host, moduleName, date.from, date.to, fetchScanNumber); + var getFacts = this.getFacts; + + return version + .then(function(versionData) { + if (_.isEmpty(versionData)) { + return []; + } else { + return getFacts(versionData); + } + }); + + }, + getFacts: function(version) { var promise; Rest.setUrl(version.related.fact_view); promise = Rest.get(); @@ -16,15 +31,18 @@ function (Rest, GetBasePath, ProcessErrors) { }); }, - getVersion: function(host_id, module, startDate, endDate){ + getVersion: function(host_id, module, startDate, endDate, fetchScanNumber){ //move the build url into getVersion and have the // parameters passed into this var promise, url = this.buildUrl(host_id, module, startDate, endDate); + + fetchScanNumber = fetchScanNumber || 0; + Rest.setUrl(url); promise = Rest.get(); return promise.then(function(data) { - return data.data.results[0]; + return data.data.results[fetchScanNumber]; }).catch(function (response) { ProcessErrors(null, response.data, response.status, null, { hdr: 'Error!', @@ -36,7 +54,7 @@ function (Rest, GetBasePath, ProcessErrors) { buildUrl: function(host_id, module, startDate, endDate){ var url = GetBasePath('hosts') + host_id + '/fact_versions/', - params= [["module", module] , ['startDate', startDate.format()], ['endDate', endDate.format()]]; + params= [["module", module] , ['from', startDate.format()], ['to', endDate.format()]]; params = params.filter(function(p){ return !_.isEmpty(p[1]); 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 new file mode 100644 index 0000000000..e6f0cb2ec9 --- /dev/null +++ b/awx/ui/static/js/system-tracking/data-services/get-data-for-comparison.factory.js @@ -0,0 +1,42 @@ +export default + [ 'factScanDataService', + 'lodashAsPromised', + function(factScanDataService, _) { + return function(hostIds, moduleName, leftDate, rightDate) { + + if (hostIds.length === 1) { + hostIds = hostIds.concat(hostIds[0]); + } + + return _(hostIds) + .promise() + .thenMap(function(hostId, index) { + var date = leftDate; + var fetchScanNumber; + + if (index === 1) { + date = rightDate; + } else { + if (rightDate.from.isSame(leftDate.from, 'day')) { + fetchScanNumber = 1; + } + } + + var params = + [ hostId, + moduleName, + date, + fetchScanNumber + ]; + + return params; + }).thenMap(function(params) { + var getHostFacts = + _.spread(factScanDataService.getHostFacts) + .bind(factScanDataService); + + return getHostFacts(params); + }); + }; + } + ]; diff --git a/awx/ui/static/js/system-tracking/date-picker/date-picker.block.less b/awx/ui/static/js/system-tracking/date-picker/date-picker.block.less new file mode 100644 index 0000000000..01aa490d73 --- /dev/null +++ b/awx/ui/static/js/system-tracking/date-picker/date-picker.block.less @@ -0,0 +1,38 @@ +/** @define DatePicker */ + +.DatePicker { + flex: 1; + display: flex; + + &-icon { + flex: initial; + padding: 6px 12px; + font-size: 14px; + border-radius: 4px 0 0 4px; + border: 1px solid #ccc; + border-right: 0; + background-color: #fff; + } + + &-icon:hover { + background-color: #e8e8e8; + } + + &-icon:focus, + &-icon:active { + background-color: #ccc; + } + + &-input { + flex: 1; + border-radius: 0 4px 4px 0; + border: 1px solid #ccc; + padding: 6px 12px; + } + + &-input:focus, + &-input:active { + outline-offset: 0; + outline: 0; + } +} diff --git a/awx/ui/static/js/system-tracking/date-picker/date-picker.directive.js b/awx/ui/static/js/system-tracking/date-picker/date-picker.directive.js new file mode 100644 index 0000000000..c7820b50b7 --- /dev/null +++ b/awx/ui/static/js/system-tracking/date-picker/date-picker.directive.js @@ -0,0 +1,44 @@ +/* jshint unused: vars */ + +export default + [ '$rootScope', + function() { + return { + restrict: 'E', + scope: { + date: '=' + }, + templateUrl: '/static/js/system-tracking/date-picker/date-picker.partial.html', + link: function(scope, element, attrs) { + + // We need to make sure this _never_ recurses, which sometimes happens + // with two-way binding. + var mustUpdateValue = true; + + scope.$watch('date', function(newValue) { + if (newValue) { + mustUpdateValue = false; + scope.dateValue = newValue.format('L'); + } + }, true); + + scope.$watch('dateValue', function(newValue) { + var newDate = moment(newValue); + + if (newValue && !newDate.isValid()) { + scope.error = "That is not a valid date."; + } else if (newValue) { + scope.date = newDate; + } + mustUpdateValue = true; + }); + + element.find(".DatePicker").addClass("input-prepend date"); + element.find(".DatePicker").find(".DatePicker-icon").addClass("add-on"); + $(".date").systemTrackingDP({ + autoclose: true + }); + } + }; + } + ]; diff --git a/awx/ui/static/js/system-tracking/date-picker/date-picker.partial.html b/awx/ui/static/js/system-tracking/date-picker/date-picker.partial.html new file mode 100644 index 0000000000..46b2a0d5de --- /dev/null +++ b/awx/ui/static/js/system-tracking/date-picker/date-picker.partial.html @@ -0,0 +1,9 @@ +
+ + +

{{error}}

+
diff --git a/awx/ui/static/js/system-tracking/date-picker/main.js b/awx/ui/static/js/system-tracking/date-picker/main.js new file mode 100644 index 0000000000..f2d536cdd3 --- /dev/null +++ b/awx/ui/static/js/system-tracking/date-picker/main.js @@ -0,0 +1,7 @@ +import datePicker from './date-picker.directive'; + +export default + angular.module('systemTracking.datePicker', + []) + .directive('datePicker', datePicker); + diff --git a/awx/ui/static/js/system-tracking/fact-data-group.block.less b/awx/ui/static/js/system-tracking/fact-data-group.block.less new file mode 100644 index 0000000000..9d62b689ef --- /dev/null +++ b/awx/ui/static/js/system-tracking/fact-data-group.block.less @@ -0,0 +1,16 @@ +/** @define FactDataGroup */ + +@import 'shared/text-label.less'; + +.FactDataGroup { + &-header { + display: flex; + &--new { + &:after { + .include-text-label(#676767; white; "new"); + align-self: center; + font-size: 1rem; + } + } + } +} diff --git a/awx/ui/static/js/system-tracking/fact-data-service.factory.js b/awx/ui/static/js/system-tracking/fact-data-service.factory.js deleted file mode 100644 index 6ccf6aafa4..0000000000 --- a/awx/ui/static/js/system-tracking/fact-data-service.factory.js +++ /dev/null @@ -1,63 +0,0 @@ -import fakeData from './fake-data'; - -function getComparisonData(module) { - - var valueName, leftValue, rightValue; - - switch(module) { - case 'packages': - valueName = 'bash'; - leftValue = '5.2.3'; - rightValue = '5.2.4'; - break; - case 'services': - valueName = 'httpd'; - leftValue = 'started'; - rightValue = 'absent'; - break; - case 'files': - valueName = '/etc/sudoers'; - leftValue = 'some string'; - rightValue = 'some other string'; - break; - case 'ansible': - valueName = 'ansible_ipv4_address'; - leftValue = '192.168.0.1'; - rightValue = '192.168.0.2'; - break; - } - - return [{ module: module, - valueName: valueName, - leftValue: leftValue, - rightValue: rightValue - }]; -} - -export default - ['$q', 'compareHosts', function factDataServiceFactory($q, compareHosts) { - return function(type) { - if (type === 'multiHost') { - return { get: function(inventoryId, module, host1, host2) { - var result = {}; - result.leftFilterValue = host1; - result.rightFilterValue = host2; - - result.factComparisonData = compareHosts(module, fakeData.host1, fakeData.host2); - - return result; - } - }; - } else if (type === 'singleHost') { - return { get: function(inventoryId, module, startDate, endDate) { - var result = {}; - result.leftFilterValue = startDate; - result.rightFilterValue = endDate; - - result.factComparisonData = getComparisonData(module); - return result; - } - }; - } - }; - }] diff --git a/awx/ui/static/js/system-tracking/fact-data-table.block.less b/awx/ui/static/js/system-tracking/fact-data-table.block.less new file mode 100644 index 0000000000..910acc2ccc --- /dev/null +++ b/awx/ui/static/js/system-tracking/fact-data-table.block.less @@ -0,0 +1,13 @@ +/** @define FactDataTable */ + +.FactDataTable { + &-row { + display: flex; + } + &-column { + flex: 1; + &--offsetLeft { + padding-left: 33%; + } + } +} diff --git a/awx/ui/static/js/system-tracking/fact-data-table.partial.html b/awx/ui/static/js/system-tracking/fact-data-table.partial.html new file mode 100644 index 0000000000..22e17b1d4b --- /dev/null +++ b/awx/ui/static/js/system-tracking/fact-data-table.partial.html @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + +
{{comparisonLeftHeader|stringOrDate:'L'}}{{comparisonRightHeader|stringOrDate:'L'}}
+

{{group.displayKeyPath}}

+
+

{{group.displayKeyPath}}

+
+

{{group.displayKeyPath}}

+
+
{{group.displayKeyPath}}
+
{{fact.keyName}} +

+ {{fact.value1}} +

+
+

+ {{fact.value2}} +

+
diff --git a/awx/ui/static/js/system-tracking/fact-datum.block.less b/awx/ui/static/js/system-tracking/fact-datum.block.less new file mode 100644 index 0000000000..a12ab5aa80 --- /dev/null +++ b/awx/ui/static/js/system-tracking/fact-datum.block.less @@ -0,0 +1,7 @@ +/** @define FactDatum */ + +.FactDatum { + &--divergent { + font-style: italic; + } +} diff --git a/awx/ui/static/js/system-tracking/fact-module-pickers.block.less b/awx/ui/static/js/system-tracking/fact-module-pickers.block.less index 5aa588bd4a..f40d580164 100644 --- a/awx/ui/static/js/system-tracking/fact-module-pickers.block.less +++ b/awx/ui/static/js/system-tracking/fact-module-pickers.block.less @@ -5,65 +5,23 @@ display: flex; margin-bottom: 15px; - &-dateSpacer { - flex: initial; - width: 0px; - } - &-dateContainer { flex: 1; display: flex; - flex-wrap: wrap; + flex-direction: column } - &-date { - flex: 1; - // flex-wrap: wrap; - display: flex; - } - - &-date--right, - &-label--right { - margin-left: 7px; - } - - &-date--left { + &-dateContainer--left { margin-right: 7px; } + &-dateContainer--right { + margin-left: 7px; + } + &-label { - flex: initial; - width: 100%; + flex: 1; font-weight: 700; padding-bottom: 5px; } - - &-dateIcon { - flex: initial; - padding: 6px 12px; - font-size: 14px; - border-radius: 4px 0 0 4px; - border: 1px solid #ccc; - border-right: 0; - background-color: #fff; - } - - &-dateIcon:hover, - &-dateIcon:focus, - &-dateIcon:active { - background-color: #ccc; - } - - &-dateInput { - flex: 1; - border-radius: 0 4px 4px 0; - border: 1px solid #ccc; - padding: 6px 12px; - } - - &-dateInput:focus, - &-dateInput:active { - outline-offset: 0; - outline: 0; - } } diff --git a/awx/ui/static/js/system-tracking/fake-data.js b/awx/ui/static/js/system-tracking/fake-data.js deleted file mode 100644 index 6c76e4ef6e..0000000000 --- a/awx/ui/static/js/system-tracking/fake-data.js +++ /dev/null @@ -1,2514 +0,0 @@ -export default -{ - host1: [ - { - "source": "apt", - "version": "1:4.9.1-0ubuntu1", - "architecture": "amd64", - "name": "libgcc1" - }, - { - "source": "apt", - "version": "2.0.21-stable-1ubuntu1.14.04.1", - "architecture": "amd64", - "name": "libevent-2.0-5" - }, - { - "source": "apt", - "version": "0.11-3ubuntu1.2", - "architecture": "amd64", - "name": "libjson0" - }, - { - "source": "apt", - "version": "6.3-4ubuntu2", - "architecture": "amd64", - "name": "libreadline6" - }, - { - "source": "apt", - "version": "1:1.9.1-1ubuntu0.1", - "architecture": "all", - "name": "git-man" - }, - { - "source": "apt", - "version": "1.6~git20131207+dfsg-1ubuntu1.1", - "architecture": "amd64", - "name": "libgssapi3-heimdal" - }, - { - "source": "apt", - "version": "2.53", - "architecture": "amd64", - "name": "mountall" - }, - { - "source": "apt", - "version": "2.7.2-2", - "architecture": "all", - "name": "python-jinja2" - }, - { - "source": "apt", - "version": "3.4.0-2ubuntu1", - "architecture": "amd64", - "name": "python3.4-minimal" - }, - { - "source": "apt", - "version": "8.6.0+6ubuntu3", - "architecture": "amd64", - "name": "tk" - }, - { - "source": "apt", - "version": "4.8.2-19ubuntu1", - "architecture": "amd64", - "name": "gcc-4.8-base" - }, - { - "source": "apt", - "version": "1.0.1-1ubuntu1", - "architecture": "amd64", - "name": "libmpc3" - }, - { - "source": "apt", - "version": "2.3.1-93ubuntu1", - "architecture": "all", - "name": "makedev" - }, - { - "source": "apt", - "version": "1.10-2ubuntu1", - "architecture": "amd64", - "name": "libxcb-present0" - }, - { - "source": "apt", - "version": "3.3-1ubuntu2", - "architecture": "all", - "name": "python-setuptools" - }, - { - "source": "apt", - "version": "1:1.0.7-1ubuntu1", - "architecture": "amd64", - "name": "xauth" - }, - { - "source": "apt", - "version": "5.1.1alpha+20120614-2ubuntu2", - "architecture": "amd64", - "name": "liblzma5" - }, - { - "source": "apt", - "version": "1:0.4.4-1", - "architecture": "amd64", - "name": "libxcomposite1" - }, - { - "source": "apt", - "version": "0.19.6-1", - "architecture": "amd64", - "name": "libfribidi0" - }, - { - "source": "apt", - "version": "1.5.4-1ubuntu1", - "architecture": "all", - "name": "python-pip" - }, - { - "source": "apt", - "version": "2.8.2-1ubuntu1", - "architecture": "amd64", - "name": "mercurial" - }, - { - "source": "apt", - "version": "1.16-8ubuntu1", - "architecture": "amd64", - "name": "libpopt0" - }, - { - "source": "apt", - "version": "2.2.4-15ubuntu1", - "architecture": "amd64", - "name": "libslang2" - }, - { - "source": "apt", - "version": "0.1.4-3ubuntu3.1", - "architecture": "amd64", - "name": "libyaml-0-2" - }, - { - "source": "apt", - "version": "1.12+dfsg-2ubuntu5.1", - "architecture": "amd64", - "name": "libk5crypto3" - }, - { - "source": "apt", - "version": "204-5ubuntu20.7", - "architecture": "amd64", - "name": "libudev1" - }, - { - "source": "apt", - "version": "3.0pl1-124ubuntu2", - "architecture": "amd64", - "name": "cron" - }, - { - "source": "apt", - "version": "0.92.37.3", - "architecture": "all", - "name": "software-properties-common" - }, - { - "source": "apt", - "version": "2:1.4.2-1", - "architecture": "amd64", - "name": "libxrandr2" - }, - { - "source": "apt", - "version": "1.1.8-1ubuntu2", - "architecture": "all", - "name": "libpam-runtime" - }, - { - "source": "apt", - "version": "1:2.24-0ubuntu2", - "architecture": "amd64", - "name": "libcap2" - }, - { - "source": "apt", - "version": "2.7.6-8", - "architecture": "amd64", - "name": "python2.7" - }, - { - "source": "apt", - "version": "5.1.118-1~dfsg-0.1ubuntu3", - "architecture": "amd64", - "name": "libpgm-5.1-0" - }, - { - "source": "apt", - "version": "0.100.0-16", - "architecture": "amd64", - "name": "ureadahead" - }, - { - "source": "apt", - "version": "14.5.0-1chl1~trusty1", - "architecture": "amd64", - "name": "python-zmq" - }, - { - "source": "apt", - "version": "2.7.5-5ubuntu3", - "architecture": "amd64", - "name": "python-minimal" - }, - { - "source": "apt", - "version": "1.3.3-17ubuntu2", - "architecture": "amd64", - "name": "mawk" - }, - { - "source": "apt", - "version": "3.54-1ubuntu1", - "architecture": "all", - "name": "manpages-dev" - }, - { - "source": "apt", - "version": "4.8.2-19ubuntu1", - "architecture": "amd64", - "name": "libgcc-4.8-dev" - }, - { - "source": "apt", - "version": "0.20.2-2ubuntu2", - "architecture": "amd64", - "name": "libp11-kit0" - }, - { - "source": "apt", - "version": "1.0.33", - "architecture": "all", - "name": "ssl-cert" - }, - { - "source": "apt", - "version": "1.5.0-1", - "architecture": "amd64", - "name": "libapr1" - }, - { - "source": "apt", - "version": "2:1.1.3-1", - "architecture": "amd64", - "name": "libxinerama1" - }, - { - "source": "apt", - "version": "2:1.3.2-1ubuntu0.0.14.04.1", - "architecture": "amd64", - "name": "libxext6" - }, - { - "source": "apt", - "version": "1.8-5", - "architecture": "amd64", - "name": "tmux" - }, - { - "source": "apt", - "version": "3.3-1ubuntu2", - "architecture": "all", - "name": "python-pkg-resources" - }, - { - "source": "apt", - "version": "5.1.1alpha+20120614-2ubuntu2", - "architecture": "amd64", - "name": "xz-utils" - }, - { - "source": "apt", - "version": "1.2-0ubuntu3", - "architecture": "amd64", - "name": "shared-mime-info" - }, - { - "source": "apt", - "version": "1.14", - "architecture": "all", - "name": "init-system-helpers" - }, - { - "source": "apt", - "version": "2.4.31-1+nmu2ubuntu8", - "architecture": "amd64", - "name": "libldap-2.4-2" - }, - { - "source": "apt", - "version": "1.5.51ubuntu2", - "architecture": "all", - "name": "debconf-i18n" - }, - { - "source": "apt", - "version": "5.18.2-2ubuntu1", - "architecture": "amd64", - "name": "perl" - }, - { - "source": "apt", - "version": "2014i-0ubuntu0.14.04", - "architecture": "all", - "name": "tzdata" - }, - { - "source": "apt", - "version": "3.4-3ubuntu2", - "architecture": "all", - "name": "python-ply" - }, - { - "source": "apt", - "version": "2.10.1-1ubuntu1", - "architecture": "all", - "name": "xkb-data" - }, - { - "source": "apt", - "version": "1.0.1ubuntu2.5", - "architecture": "amd64", - "name": "libapt-pkg4.12" - }, - { - "source": "apt", - "version": "4.8.2-19ubuntu1", - "architecture": "amd64", - "name": "gcc-4.8" - }, - { - "source": "apt", - "version": "0.158-0ubuntu5.2", - "architecture": "amd64", - "name": "libelf1" - }, - { - "source": "apt", - "version": "0.70-1", - "architecture": "all", - "name": "libarchive-extract-perl" - }, - { - "source": "apt", - "version": "3.4-3ubuntu0.1", - "architecture": "amd64", - "name": "libtasn1-6" - }, - { - "source": "apt", - "version": "1.27.1-1", - "architecture": "amd64", - "name": "tar" - }, - { - "source": "apt", - "version": "10.1.3-0ubuntu0.4", - "architecture": "amd64", - "name": "libgl1-mesa-glx" - }, - { - "source": "apt", - "version": "1.09-6ubuntu1", - "architecture": "amd64", - "name": "liblockfile-bin" - }, - { - "source": "apt", - "version": "1.8.9p5-1ubuntu1", - "architecture": "amd64", - "name": "sudo" - }, - { - "source": "apt", - "version": "1.6~git20131207+dfsg-1ubuntu1.1", - "architecture": "amd64", - "name": "libwind0-heimdal" - }, - { - "source": "apt", - "version": "1.7-5build2", - "architecture": "amd64", - "name": "libtext-iconv-perl" - }, - { - "source": "apt", - "version": "3.8.7-1ubuntu1", - "architecture": "amd64", - "name": "logrotate" - }, - { - "source": "apt", - "version": "1:3.3.9-1ubuntu2", - "architecture": "amd64", - "name": "libprocps3" - }, - { - "source": "apt", - "version": "7.2ubuntu5.1", - "architecture": "amd64", - "name": "base-files" - }, - { - "source": "apt", - "version": "4:4.8.2-1ubuntu6", - "architecture": "amd64", - "name": "gcc" - }, - { - "source": "apt", - "version": "5.9+20140118-1ubuntu1", - "architecture": "amd64", - "name": "libtinfo5" - }, - { - "source": "apt", - "version": "0~git20131104-1.1", - "architecture": "amd64", - "name": "libtxc-dxtn-s2tc0" - }, - { - "source": "apt", - "version": "9.3.6-0ubuntu0.14.04", - "architecture": "amd64", - "name": "postgresql-client-9.3" - }, - { - "source": "apt", - "version": "1:2.3.2-2ubuntu1", - "architecture": "amd64", - "name": "libaudit1" - }, - { - "source": "apt", - "version": "0.8.8-0ubuntu17", - "architecture": "amd64", - "name": "libplymouth2" - }, - { - "source": "apt", - "version": "2.10+dfsg-1ubuntu2", - "architecture": "all", - "name": "python-pycparser" - }, - { - "source": "apt", - "version": "0.4.2-1build1", - "architecture": "amd64", - "name": "python-greenlet" - }, - { - "source": "apt", - "version": "1.14.0-5ubuntu2", - "architecture": "amd64", - "name": "insserv" - }, - { - "source": "apt", - "version": "2.19-0ubuntu6.3", - "architecture": "amd64", - "name": "multiarch-support" - }, - { - "source": "apt", - "version": "2.0.3-0ubuntu1", - "architecture": "amd64", - "name": "klibc-utils" - }, - { - "source": "apt", - "version": "2.3.1-2", - "architecture": "amd64", - "name": "libxft2" - }, - { - "source": "apt", - "version": "2.7.6-8", - "architecture": "amd64", - "name": "libpython2.7-dev" - }, - { - "source": "apt", - "version": "2.1.0-4ubuntu1", - "architecture": "amd64", - "name": "libexpat1" - }, - { - "source": "apt", - "version": "2.6.1-4build1", - "architecture": "amd64", - "name": "python-crypto" - }, - { - "source": "apt", - "version": "1.1-2", - "architecture": "amd64", - "name": "libxshmfence1" - }, - { - "source": "apt", - "version": "0.92.37.3", - "architecture": "all", - "name": "python-software-properties" - }, - { - "source": "apt", - "version": "4.1+Debian11ubuntu6", - "architecture": "all", - "name": "lsb-base" - }, - { - "source": "apt", - "version": "1.15.5-1ubuntu1", - "architecture": "amd64", - "name": "kbd" - }, - { - "source": "apt", - "version": "2.34-1ubuntu1", - "architecture": "all", - "name": "fonts-dejavu-core" - }, - { - "source": "apt", - "version": "1.6~git20131207+dfsg-1ubuntu1.1", - "architecture": "amd64", - "name": "libroken18-heimdal" - }, - { - "source": "apt", - "version": "3.0.2", - "architecture": "amd64", - "name": "mongodb-org-tools" - }, - { - "source": "apt", - "version": "0.0.9", - "architecture": "all", - "name": "sensible-utils" - }, - { - "source": "apt", - "version": "2:0.1.12-23.3ubuntu1", - "architecture": "amd64", - "name": "libusb-0.1-4" - }, - { - "source": "apt", - "version": "2.7.6-8", - "architecture": "amd64", - "name": "libpython2.7-minimal" - }, - { - "source": "apt", - "version": "5.9+20140118-1ubuntu1", - "architecture": "amd64", - "name": "libncursesw5" - }, - { - "source": "apt", - "version": "1:3.5.10-1", - "architecture": "amd64", - "name": "libxpm4" - }, - { - "source": "apt", - "version": "0.52.15-2ubuntu5", - "architecture": "amd64", - "name": "whiptail" - }, - { - "source": "apt", - "version": "2:1.6.2-1ubuntu2", - "architecture": "amd64", - "name": "libx11-xcb1" - }, - { - "source": "apt", - "version": "3.4.0-0ubuntu2", - "architecture": "amd64", - "name": "libpython3-stdlib" - }, - { - "source": "apt", - "version": "1.05-7build3", - "architecture": "amd64", - "name": "liblocale-gettext-perl" - }, - { - "source": "apt", - "version": "2.4.60-2~ubuntu14.04.1", - "architecture": "amd64", - "name": "libdrm-nouveau2" - }, - { - "source": "apt", - "version": "1.70ubuntu8", - "architecture": "all", - "name": "console-setup" - }, - { - "source": "apt", - "version": "1:5.0.1-1ubuntu1.1", - "architecture": "amd64", - "name": "libxfixes3" - }, - { - "source": "apt", - "version": "2.7.5-5ubuntu3", - "architecture": "amd64", - "name": "python" - }, - { - "source": "apt", - "version": "0.100.2-1", - "architecture": "amd64", - "name": "libdbus-glib-1-2" - }, - { - "source": "apt", - "version": "2.2.52-1", - "architecture": "amd64", - "name": "libacl1" - }, - { - "source": "apt", - "version": "3.2.7-1build1", - "architecture": "amd64", - "name": "python-egenix-mxdatetime" - }, - { - "source": "apt", - "version": "1.1.8-1ubuntu2", - "architecture": "amd64", - "name": "libpam0g" - }, - { - "source": "apt", - "version": "9.3.6-0ubuntu0.14.04", - "architecture": "amd64", - "name": "postgresql-9.3" - }, - { - "source": "apt", - "version": "1.6~git20131207+dfsg-1ubuntu1.1", - "architecture": "amd64", - "name": "libkrb5-26-heimdal" - }, - { - "source": "apt", - "version": "2:1.02.77-6ubuntu2", - "architecture": "amd64", - "name": "dmsetup" - }, - { - "source": "apt", - "version": "2.11.0-0ubuntu4.1", - "architecture": "amd64", - "name": "libfontconfig1" - }, - { - "source": "apt", - "version": "2.40.2-0ubuntu1", - "architecture": "amd64", - "name": "libglib2.0-0" - }, - { - "source": "apt", - "version": "1.1.8-1ubuntu2", - "architecture": "amd64", - "name": "libpam-modules-bin" - }, - { - "source": "apt", - "version": "3.113+nmu3ubuntu3", - "architecture": "all", - "name": "adduser" - }, - { - "source": "apt", - "version": "3.13.0-52.85", - "architecture": "amd64", - "name": "linux-libc-dev" - }, - { - "source": "apt", - "version": "0.82.1ubuntu2.2", - "architecture": "all", - "name": "unattended-upgrades" - }, - { - "source": "apt", - "version": "2:1.0.12-1", - "architecture": "amd64", - "name": "libxaw7" - }, - { - "source": "apt", - "version": "1.1.5-4build1", - "architecture": "amd64", - "name": "libutempter0" - }, - { - "source": "apt", - "version": "1.10.1-1git1build1", - "architecture": "all", - "name": "python-paramiko" - }, - { - "source": "apt", - "version": "2.4.60-2~ubuntu14.04.1", - "architecture": "amd64", - "name": "libdrm-intel1" - }, - { - "source": "apt", - "version": "1:8.31-2ubuntu2", - "architecture": "amd64", - "name": "libpcre3" - }, - { - "source": "apt", - "version": "2.20.1-5.1ubuntu20.2", - "architecture": "amd64", - "name": "libmount1" - }, - { - "source": "apt", - "version": "3.1-20130712-2", - "architecture": "amd64", - "name": "libedit2" - }, - { - "source": "apt", - "version": "1.0.6-5", - "architecture": "amd64", - "name": "libbz2-1.0" - }, - { - "source": "apt", - "version": "2.7.5-5ubuntu3", - "architecture": "amd64", - "name": "libpython-stdlib" - }, - { - "source": "apt", - "version": "4.3-7ubuntu1.5", - "architecture": "amd64", - "name": "bash" - }, - { - "source": "apt", - "version": "3:3.0.0-1chl1~trusty1", - "architecture": "amd64", - "name": "redis-tools" - }, - { - "source": "apt", - "version": "1.0.1f-1ubuntu2.11", - "architecture": "amd64", - "name": "openssl" - }, - { - "source": "apt", - "version": "2.11.0-0ubuntu4.1", - "architecture": "all", - "name": "fontconfig-config" - }, - { - "source": "apt", - "version": "2.0.3-0ubuntu1", - "architecture": "amd64", - "name": "libklibc" - }, - { - "source": "apt", - "version": "2.40.2-0ubuntu1", - "architecture": "all", - "name": "libglib2.0-data" - }, - { - "source": "apt", - "version": "1.4.16-1ubuntu2.1", - "architecture": "amd64", - "name": "gpgv" - }, - { - "source": "apt", - "version": "0.08-2", - "architecture": "all", - "name": "libalgorithm-merge-perl" - }, - { - "source": "apt", - "version": "4.8.2-19ubuntu1", - "architecture": "amd64", - "name": "cpp-4.8" - }, - { - "source": "apt", - "version": "0.1.8-1ubuntu1", - "architecture": "all", - "name": "python-distlib" - }, - { - "source": "apt", - "version": "2.19-0ubuntu6.3", - "architecture": "amd64", - "name": "libc-bin" - }, - { - "source": "apt", - "version": "0.04-2build4", - "architecture": "amd64", - "name": "libalgorithm-diff-xs-perl" - }, - { - "source": "apt", - "version": "1.28-1ubuntu2", - "architecture": "amd64", - "name": "libidn11" - }, - { - "source": "apt", - "version": "1:4.2.6.p5+dfsg-3ubuntu2", - "architecture": "amd64", - "name": "ntpdate" - }, - { - "source": "apt", - "version": "3.1~rc1+r3.0.13-12", - "architecture": "amd64", - "name": "libffi6" - }, - { - "source": "apt", - "version": "0.06-7", - "architecture": "all", - "name": "libtext-wrapi18n-perl" - }, - { - "source": "apt", - "version": "2:5.1.3+dfsg-1ubuntu1", - "architecture": "amd64", - "name": "libgmp10" - }, - { - "source": "apt", - "version": "2:1.1.1-1", - "architecture": "amd64", - "name": "libxmuu1" - }, - { - "source": "apt", - "version": "5.1-1", - "architecture": "all", - "name": "libmodule-pluggable-perl" - }, - { - "source": "apt", - "version": "1:2.20.1-5.1ubuntu20.2", - "architecture": "amd64", - "name": "bsdutils" - }, - { - "source": "apt", - "version": "0.10-1", - "architecture": "all", - "name": "liblog-message-simple-perl" - }, - { - "source": "apt", - "version": "1.6~git20131207+dfsg-1ubuntu1.1", - "architecture": "amd64", - "name": "libheimntlm0-heimdal" - }, - { - "source": "apt", - "version": "5.9+20140118-1ubuntu1", - "architecture": "all", - "name": "ncurses-base" - }, - { - "source": "apt", - "version": "1.17.5ubuntu5.3", - "architecture": "amd64", - "name": "dpkg" - }, - { - "source": "apt", - "version": "3:20121221-4ubuntu1.1", - "architecture": "amd64", - "name": "iputils-ping" - }, - { - "source": "apt", - "version": "7.35.0-1ubuntu2.5", - "architecture": "amd64", - "name": "libcurl3-gnutls" - }, - { - "source": "apt", - "version": "2.16-1", - "architecture": "amd64", - "name": "grep" - }, - { - "source": "apt", - "version": "3.52-1", - "architecture": "all", - "name": "iso-codes" - }, - { - "source": "apt", - "version": "5.3.28-3ubuntu3", - "architecture": "amd64", - "name": "libdb5.3" - }, - { - "source": "apt", - "version": "1.4.16-1ubuntu2.1", - "architecture": "amd64", - "name": "gnupg" - }, - { - "source": "apt", - "version": "2.0.1-2build2", - "architecture": "all", - "name": "python-chardet" - }, - { - "source": "apt", - "version": "2.5.2-1ubuntu2.4", - "architecture": "amd64", - "name": "libfreetype6" - }, - { - "source": "apt", - "version": "0.5.7-4ubuntu1", - "architecture": "amd64", - "name": "dash" - }, - { - "source": "apt", - "version": "1.20-3ubuntu2", - "architecture": "amd64", - "name": "libfakeroot" - }, - { - "source": "apt", - "version": "8.6.1-3ubuntu2", - "architecture": "amd64", - "name": "tk8.6" - }, - { - "source": "apt", - "version": "1.5.3-1", - "architecture": "amd64", - "name": "libaprutil1" - }, - { - "source": "apt", - "version": "2.7.6-8", - "architecture": "amd64", - "name": "libpython2.7" - }, - { - "source": "apt", - "version": "1.6~git20131207+dfsg-1ubuntu1.1", - "architecture": "amd64", - "name": "libasn1-8-heimdal" - }, - { - "source": "apt", - "version": "0.2.5-0.1ubuntu2", - "architecture": "all", - "name": "python-colorama" - }, - { - "source": "apt", - "version": "2.1.25.dfsg1-17build1", - "architecture": "amd64", - "name": "libsasl2-modules" - }, - { - "source": "apt", - "version": "1.40.0-1ubuntu0.2", - "architecture": "amd64", - "name": "libgirepository-1.0-1" - }, - { - "source": "apt", - "version": "1.0-1ubuntu1", - "architecture": "amd64", - "name": "python-gevent" - }, - { - "source": "apt", - "version": "1.10-2ubuntu1", - "architecture": "amd64", - "name": "libxcb-shape0" - }, - { - "source": "apt", - "version": "1:4.1.5.1-1ubuntu9", - "architecture": "amd64", - "name": "passwd" - }, - { - "source": "apt", - "version": "0.24.0-1~ubuntu1", - "architecture": "all", - "name": "python-wheel" - }, - { - "source": "apt", - "version": "1.12+dfsg-2ubuntu5.1", - "architecture": "all", - "name": "krb5-locales" - }, - { - "source": "apt", - "version": "1.0.4-3ubuntu2", - "architecture": "amd64", - "name": "libustr-1.0-1" - }, - { - "source": "apt", - "version": "1:1.1.3-1", - "architecture": "amd64", - "name": "libxxf86vm1" - }, - { - "source": "apt", - "version": "0.9.3.5ubuntu1", - "architecture": "all", - "name": "python-apt-common" - }, - { - "source": "apt", - "version": "4.2.4-7ubuntu12", - "architecture": "amd64", - "name": "isc-dhcp-client" - }, - { - "source": "apt", - "version": "1.20-3ubuntu2", - "architecture": "amd64", - "name": "fakeroot" - }, - { - "source": "apt", - "version": "2.1.0-4ubuntu1", - "architecture": "amd64", - "name": "libexpat1-dev" - }, - { - "source": "apt", - "version": "2:7.4.052-1ubuntu3", - "architecture": "amd64", - "name": "vim-tiny" - }, - { - "source": "apt", - "version": "2.20.1-5.1ubuntu20.2", - "architecture": "amd64", - "name": "libuuid1" - }, - { - "source": "apt", - "version": "4.9.1-0ubuntu1", - "architecture": "amd64", - "name": "gcc-4.9-base" - }, - { - "source": "apt", - "version": "1:0.9.8-1build0.14.04.1", - "architecture": "amd64", - "name": "libxrender1" - }, - { - "source": "apt", - "version": "10.1.3-0ubuntu0.4", - "architecture": "amd64", - "name": "libglapi-mesa" - }, - { - "source": "apt", - "version": "4.4.2-7", - "architecture": "amd64", - "name": "findutils" - }, - { - "source": "apt", - "version": "0.42-1", - "architecture": "all", - "name": "libterm-ui-perl" - }, - { - "source": "apt", - "version": "2.4.5-1build5", - "architecture": "amd64", - "name": "python-psycopg2" - }, - { - "source": "apt", - "version": "2.2-1", - "architecture": "all", - "name": "libsemanage-common" - }, - { - "source": "apt", - "version": "2.4.10-1build1", - "architecture": "amd64", - "name": "python-ldap" - }, - { - "source": "apt", - "version": "0.17-1.1", - "architecture": "all", - "name": "liberror-perl" - }, - { - "source": "apt", - "version": "0.04-7build3", - "architecture": "amd64", - "name": "libtext-charwidth-perl" - }, - { - "source": "apt", - "version": "0.18.2-1", - "architecture": "amd64", - "name": "libcloog-isl4" - }, - { - "source": "apt", - "version": "2.88dsf-41ubuntu6", - "architecture": "all", - "name": "sysv-rc" - }, - { - "source": "apt", - "version": "1.12+dfsg-2ubuntu5.1", - "architecture": "amd64", - "name": "libgssapi-krb5-2" - }, - { - "source": "apt", - "version": "3.2.7-1build1", - "architecture": "amd64", - "name": "python-egenix-mxtools" - }, - { - "source": "apt", - "version": "1.5.6-1", - "architecture": "amd64", - "name": "libkeyutils1" - }, - { - "source": "apt", - "version": "1.2.0-2build2", - "architecture": "amd64", - "name": "python3-dbus" - }, - { - "source": "apt", - "version": "1.3.3-1ubuntu0.1", - "architecture": "amd64", - "name": "libserf-1-1" - }, - { - "source": "apt", - "version": "2.11+dfsg-1ubuntu1", - "architecture": "amd64", - "name": "cpio" - }, - { - "source": "apt", - "version": "5.9+20140118-1ubuntu1", - "architecture": "amd64", - "name": "libncurses5" - }, - { - "source": "apt", - "version": "0.9.3.5ubuntu1", - "architecture": "amd64", - "name": "python3-apt" - }, - { - "source": "apt", - "version": "2.20.1-5.1ubuntu20.2", - "architecture": "amd64", - "name": "util-linux" - }, - { - "source": "apt", - "version": "3.0.2", - "architecture": "amd64", - "name": "mongodb-org-shell" - }, - { - "source": "apt", - "version": "2.7.6-8", - "architecture": "amd64", - "name": "python2.7-dev" - }, - { - "source": "apt", - "version": "2.2.1-1ubuntu0.3", - "architecture": "all", - "name": "python-requests" - }, - { - "source": "apt", - "version": "2.7.1-4ubuntu2", - "architecture": "amd64", - "name": "patch" - }, - { - "source": "apt", - "version": "1.42.9-3ubuntu1", - "architecture": "amd64", - "name": "e2fslibs" - }, - { - "source": "apt", - "version": "1.60-25ubuntu2.1", - "architecture": "amd64", - "name": "net-tools" - }, - { - "source": "apt", - "version": "0.9.3.5ubuntu1", - "architecture": "amd64", - "name": "python-apt" - }, - { - "source": "apt", - "version": "1.5.51ubuntu2", - "architecture": "all", - "name": "debconf" - }, - { - "source": "apt", - "version": "1.2.50-1ubuntu2", - "architecture": "amd64", - "name": "libpng12-0" - }, - { - "source": "apt", - "version": "1:2.24-0ubuntu2", - "architecture": "amd64", - "name": "libpam-cap" - }, - { - "source": "apt", - "version": "4.2.2-4ubuntu1", - "architecture": "amd64", - "name": "sed" - }, - { - "source": "apt", - "version": "15-0ubuntu6", - "architecture": "amd64", - "name": "kmod" - }, - { - "source": "apt", - "version": "2.4.0-6", - "architecture": "amd64", - "name": "libmpdec2" - }, - { - "source": "apt", - "version": "4.2.4-7ubuntu12", - "architecture": "amd64", - "name": "isc-dhcp-common" - }, - { - "source": "apt", - "version": "4:4.8.2-1ubuntu6", - "architecture": "amd64", - "name": "g++" - }, - { - "source": "apt", - "version": "1.26+nmu4ubuntu1", - "architecture": "all", - "name": "sgml-base" - }, - { - "source": "apt", - "version": "1.325", - "architecture": "amd64", - "name": "ubuntu-minimal" - }, - { - "source": "apt", - "version": "0.187ubuntu1", - "architecture": "amd64", - "name": "libdebconfclient0" - }, - { - "source": "apt", - "version": "1.7.1-1ubuntu3", - "architecture": "all", - "name": "python-urllib3" - }, - { - "source": "apt", - "version": "1:2.4.47-1ubuntu1", - "architecture": "amd64", - "name": "libattr1" - }, - { - "source": "apt", - "version": "3.54ubuntu1", - "architecture": "all", - "name": "mime-support" - }, - { - "source": "apt", - "version": "0.8.6-2chl1~trusty1", - "architecture": "amd64", - "name": "python-cffi" - }, - { - "source": "apt", - "version": "4.0.5-1chl1~trusty1", - "architecture": "amd64", - "name": "libzmq3" - }, - { - "source": "apt", - "version": "0.37-5", - "architecture": "amd64", - "name": "rlwrap" - }, - { - "source": "apt", - "version": "1:4.1.5.1-1ubuntu9", - "architecture": "amd64", - "name": "login" - }, - { - "source": "apt", - "version": "2.24-5ubuntu3.1", - "architecture": "amd64", - "name": "binutils" - }, - { - "source": "apt", - "version": "11.6ubuntu6", - "architecture": "amd64", - "name": "build-essential" - }, - { - "source": "apt", - "version": "2:1.02.77-6ubuntu2", - "architecture": "amd64", - "name": "libdevmapper1.02.1" - }, - { - "source": "apt", - "version": "1.6~git20131207+dfsg-1ubuntu1.1", - "architecture": "amd64", - "name": "libhcrypto4-heimdal" - }, - { - "source": "apt", - "version": "1.40.0-1ubuntu0.2", - "architecture": "amd64", - "name": "gir1.2-glib-2.0" - }, - { - "source": "apt", - "version": "3.0027+nmu1", - "architecture": "all", - "name": "ucf" - }, - { - "source": "apt", - "version": "4.1+Debian11ubuntu6", - "architecture": "all", - "name": "lsb-release" - }, - { - "source": "apt", - "version": "2.8.2-1ubuntu1", - "architecture": "all", - "name": "mercurial-common" - }, - { - "source": "apt", - "version": "2:1.6.2-1ubuntu2", - "architecture": "all", - "name": "libx11-data" - }, - { - "source": "apt", - "version": "0.7.47.2ubuntu4.1", - "architecture": "amd64", - "name": "ifupdown" - }, - { - "source": "apt", - "version": "1:1.1.4-1ubuntu1", - "architecture": "amd64", - "name": "libxdamage1" - }, - { - "source": "apt", - "version": "0.52.15-2ubuntu5", - "architecture": "amd64", - "name": "libnewt0.52" - }, - { - "source": "apt", - "version": "0.14-2build1", - "architecture": "amd64", - "name": "libfile-fcntllock-perl" - }, - { - "source": "apt", - "version": "5.2", - "architecture": "all", - "name": "netbase" - }, - { - "source": "apt", - "version": "1:2.3.2-2ubuntu1", - "architecture": "all", - "name": "libaudit-common" - }, - { - "source": "apt", - "version": "1:3.4-1ubuntu3", - "architecture": "amd64", - "name": "libllvm3.4" - }, - { - "source": "apt", - "version": "8.6.1-4ubuntu1", - "architecture": "amd64", - "name": "libtcl8.6" - }, - { - "source": "apt", - "version": "0.61-1", - "architecture": "all", - "name": "libpod-latex-perl" - }, - { - "source": "apt", - "version": "2.2-1", - "architecture": "amd64", - "name": "libsepol1" - }, - { - "source": "apt", - "version": "2.2-1", - "architecture": "amd64", - "name": "libsemanage1" - }, - { - "source": "apt", - "version": "1.12.1-0ubuntu4.2", - "architecture": "amd64", - "name": "upstart" - }, - { - "source": "apt", - "version": "3.4.0-2ubuntu1", - "architecture": "amd64", - "name": "python3.4" - }, - { - "source": "apt", - "version": "2.13+git20120306-12.1", - "architecture": "all", - "name": "locales" - }, - { - "source": "apt", - "version": "1.0.1ubuntu2.5", - "architecture": "amd64", - "name": "apt-utils" - }, - { - "source": "apt", - "version": "2.20.1-5.1ubuntu20.2", - "architecture": "amd64", - "name": "mount" - }, - { - "source": "apt", - "version": "0.12.2-1", - "architecture": "amd64", - "name": "libisl10" - }, - { - "source": "apt", - "version": "1.8.8-1ubuntu3.1", - "architecture": "amd64", - "name": "libsvn1" - }, - { - "source": "apt", - "version": "1.69ubuntu1.1", - "architecture": "all", - "name": "resolvconf" - }, - { - "source": "apt", - "version": "2.12.23-12ubuntu2.1", - "architecture": "amd64", - "name": "libgnutls26" - }, - { - "source": "apt", - "version": "3.4.0-2ubuntu1", - "architecture": "amd64", - "name": "libpython3.4-minimal" - }, - { - "source": "apt", - "version": "1:1.1.2-1", - "architecture": "amd64", - "name": "libfontenc1" - }, - { - "source": "apt", - "version": "1:3.3.9-1ubuntu2", - "architecture": "amd64", - "name": "procps" - }, - { - "source": "apt", - "version": "0.10.37-1chl1~trusty1", - "architecture": "amd64", - "name": "nodejs" - }, - { - "source": "apt", - "version": "2.9.1+dfsg1-3ubuntu4.4", - "architecture": "amd64", - "name": "libxml2" - }, - { - "source": "apt", - "version": "2.7.5-5ubuntu3", - "architecture": "amd64", - "name": "libpython-dev" - }, - { - "source": "apt", - "version": "2:1.0.8-2", - "architecture": "amd64", - "name": "libice6" - }, - { - "source": "apt", - "version": "154ubuntu1", - "architecture": "all", - "name": "postgresql-client-common" - }, - { - "source": "apt", - "version": "0.103ubuntu4.2", - "architecture": "all", - "name": "initramfs-tools" - }, - { - "source": "apt", - "version": "2.1.25.dfsg1-17build1", - "architecture": "amd64", - "name": "libsasl2-2" - }, - { - "source": "apt", - "version": "3.81-8.2ubuntu3", - "architecture": "amd64", - "name": "make" - }, - { - "source": "apt", - "version": "3.15ubuntu1", - "architecture": "amd64", - "name": "hostname" - }, - { - "source": "apt", - "version": "8.21-1ubuntu5", - "architecture": "amd64", - "name": "coreutils" - }, - { - "source": "apt", - "version": "4.8.2-19ubuntu1", - "architecture": "amd64", - "name": "libstdc++6" - }, - { - "source": "apt", - "version": "3.0.2", - "architecture": "amd64", - "name": "mongodb-org" - }, - { - "source": "apt", - "version": "0.999-3~ubuntu1", - "architecture": "all", - "name": "python-html5lib" - }, - { - "source": "apt", - "version": "3.4.0-2ubuntu1", - "architecture": "amd64", - "name": "libpython3.4-stdlib" - }, - { - "source": "apt", - "version": "3.12.0-2", - "architecture": "amd64", - "name": "iproute2" - }, - { - "source": "apt", - "version": "4.8.2-19ubuntu1", - "architecture": "amd64", - "name": "libasan0" - }, - { - "source": "apt", - "version": "5.18.2-2ubuntu1", - "architecture": "all", - "name": "perl-modules" - }, - { - "source": "apt", - "version": "3.54-1ubuntu1", - "architecture": "all", - "name": "manpages" - }, - { - "source": "apt", - "version": "1:1.2.8.dfsg-1ubuntu1", - "architecture": "amd64", - "name": "zlib1g" - }, - { - "source": "apt", - "version": "2:1.1.1-1", - "architecture": "amd64", - "name": "libxmu6" - }, - { - "source": "apt", - "version": "2.19-0ubuntu6.6", - "architecture": "amd64", - "name": "libc6" - }, - { - "source": "apt", - "version": "1.10-2ubuntu1", - "architecture": "amd64", - "name": "libxcb-dri3-0" - }, - { - "source": "apt", - "version": "3.4-1build1", - "architecture": "amd64", - "name": "libtext-soundex-perl" - }, - { - "source": "apt", - "version": "2.7.6-8", - "architecture": "amd64", - "name": "python2.7-minimal" - }, - { - "source": "apt", - "version": "15-0ubuntu6", - "architecture": "all", - "name": "module-init-tools" - }, - { - "source": "apt", - "version": "1.6~git20131207+dfsg-1ubuntu1.1", - "architecture": "amd64", - "name": "libhx509-5-heimdal" - }, - { - "source": "apt", - "version": "0.8-3build1", - "architecture": "amd64", - "name": "python-netifaces" - }, - { - "source": "apt", - "version": "1.6-3ubuntu1", - "architecture": "amd64", - "name": "gzip" - }, - { - "source": "apt", - "version": "2.20.1-5.1ubuntu20.2", - "architecture": "amd64", - "name": "libblkid1" - }, - { - "source": "apt", - "version": "2:7.4.052-1ubuntu3", - "architecture": "amd64", - "name": "vim-common" - }, - { - "source": "apt", - "version": "458-2", - "architecture": "amd64", - "name": "less" - }, - { - "source": "apt", - "version": "8.6.0+6ubuntu3", - "architecture": "amd64", - "name": "tcl" - }, - { - "source": "apt", - "version": "3.0.2", - "architecture": "amd64", - "name": "mongodb-org-mongos" - }, - { - "source": "apt", - "version": "1.8.8-1ubuntu3.1", - "architecture": "amd64", - "name": "subversion" - }, - { - "source": "apt", - "version": "4.8.2-19ubuntu1", - "architecture": "amd64", - "name": "libquadmath0" - }, - { - "source": "apt", - "version": "1.0.3-4ubuntu25", - "architecture": "amd64", - "name": "libnih1" - }, - { - "source": "apt", - "version": "1:1.0.8-1", - "architecture": "amd64", - "name": "libxau6" - }, - { - "source": "apt", - "version": "2.12.23-12ubuntu2.1", - "architecture": "amd64", - "name": "libgnutls-openssl27" - }, - { - "source": "apt", - "version": "1.1.8-1ubuntu2", - "architecture": "amd64", - "name": "libpam-modules" - }, - { - "source": "apt", - "version": "297-1ubuntu1", - "architecture": "amd64", - "name": "xterm" - }, - { - "source": "apt", - "version": "1.10-2ubuntu1", - "architecture": "amd64", - "name": "libxcb-sync1" - }, - { - "source": "apt", - "version": "3.4.0-0ubuntu2", - "architecture": "amd64", - "name": "python3-minimal" - }, - { - "source": "apt", - "version": "2.3000-1", - "architecture": "all", - "name": "libtimedate-perl" - }, - { - "source": "apt", - "version": "20141019ubuntu0.14.04.1", - "architecture": "all", - "name": "ca-certificates" - }, - { - "source": "apt", - "version": "1:1.1.4-1", - "architecture": "amd64", - "name": "libxt6" - }, - { - "source": "apt", - "version": "1.0.1ubuntu2.5", - "architecture": "amd64", - "name": "apt" - }, - { - "source": "apt", - "version": "6.3-4ubuntu2", - "architecture": "all", - "name": "readline-common" - }, - { - "source": "apt", - "version": "1.12-0.2ubuntu1", - "architecture": "amd64", - "name": "libgpg-error0" - }, - { - "source": "apt", - "version": "8.6.1-4ubuntu1", - "architecture": "amd64", - "name": "tcl8.6" - }, - { - "source": "apt", - "version": "3.4.0-0ubuntu2", - "architecture": "amd64", - "name": "python3" - }, - { - "source": "apt", - "version": "0.18-1build2", - "architecture": "amd64", - "name": "python-markupsafe" - }, - { - "source": "apt", - "version": "1.0.1ubuntu2.5", - "architecture": "amd64", - "name": "libapt-inst1.5" - }, - { - "source": "apt", - "version": "0.92.37.3", - "architecture": "all", - "name": "python3-software-properties" - }, - { - "source": "apt", - "version": "1:1.21.0-1ubuntu1", - "architecture": "amd64", - "name": "busybox-initramfs" - }, - { - "source": "apt", - "version": "4.8.2-19ubuntu1", - "architecture": "amd64", - "name": "g++-4.8" - }, - { - "source": "apt", - "version": "1.1.1-2", - "architecture": "all", - "name": "xbitmaps" - }, - { - "source": "apt", - "version": "8.6.1-3ubuntu2", - "architecture": "amd64", - "name": "libtk8.6" - }, - { - "source": "apt", - "version": "1.0.1f-1ubuntu2.7", - "architecture": "amd64", - "name": "libssl1.0.0" - }, - { - "source": "apt", - "version": "2.88dsf-41ubuntu6", - "architecture": "amd64", - "name": "sysvinit-utils" - }, - { - "source": "apt", - "version": "204-5ubuntu20.7", - "architecture": "amd64", - "name": "udev" - }, - { - "source": "apt", - "version": "0.1.17", - "architecture": "amd64", - "name": "lockfile-progs" - }, - { - "source": "apt", - "version": "4.8.2-19ubuntu1", - "architecture": "amd64", - "name": "libatomic1" - }, - { - "source": "apt", - "version": "3.1.0-2ubuntu0.1", - "architecture": "amd64", - "name": "rsync" - }, - { - "source": "apt", - "version": "1:6.6p1-2ubuntu2", - "architecture": "amd64", - "name": "openssh-client" - }, - { - "source": "apt", - "version": "0.24-0ubuntu7", - "architecture": "amd64", - "name": "libcgmanager0" - }, - { - "source": "apt", - "version": "2.2.2-1ubuntu0.1", - "architecture": "amd64", - "name": "libselinux1" - }, - { - "source": "apt", - "version": "4.8.2-19ubuntu1", - "architecture": "amd64", - "name": "libitm1" - }, - { - "source": "apt", - "version": "5.9+20140118-1ubuntu1", - "architecture": "amd64", - "name": "ncurses-bin" - }, - { - "source": "apt", - "version": "3.8.2-1ubuntu2", - "architecture": "amd64", - "name": "libsqlite3-0" - }, - { - "source": "apt", - "version": "1.12+dfsg-2ubuntu5.1", - "architecture": "amd64", - "name": "libkrb5-3" - }, - { - "source": "apt", - "version": "7.19.3-0ubuntu3", - "architecture": "amd64", - "name": "python3-pycurl" - }, - { - "source": "apt", - "version": "1.42.9-3ubuntu1", - "architecture": "amd64", - "name": "libss2" - }, - { - "source": "apt", - "version": "1:5.14-2ubuntu3.2", - "architecture": "amd64", - "name": "libmagic1" - }, - { - "source": "apt", - "version": "4.8.2-19ubuntu1", - "architecture": "amd64", - "name": "libtsan0" - }, - { - "source": "apt", - "version": "1.42.9-3ubuntu1", - "architecture": "amd64", - "name": "libcomerr2" - }, - { - "source": "apt", - "version": "3.12.0-1ubuntu1", - "architecture": "amd64", - "name": "python3-gi" - }, - { - "source": "apt", - "version": "1.105-7ubuntu1", - "architecture": "amd64", - "name": "netcat-openbsd" - }, - { - "source": "apt", - "version": "1.10-2ubuntu1", - "architecture": "amd64", - "name": "libxcb-glx0" - }, - { - "source": "apt", - "version": "9.3+154ubuntu1", - "architecture": "all", - "name": "postgresql" - }, - { - "source": "apt", - "version": "2.19-0ubuntu6.6", - "architecture": "amd64", - "name": "libc6-dev" - }, - { - "source": "apt", - "version": "2:1.0.10-1", - "architecture": "amd64", - "name": "libxv1" - }, - { - "source": "apt", - "version": "0.1.9-0ubuntu2", - "architecture": "amd64", - "name": "libestr0" - }, - { - "source": "apt", - "version": "0.6.0-2ubuntu1", - "architecture": "amd64", - "name": "libbsd0" - }, - { - "source": "apt", - "version": "2:1.2.2-1", - "architecture": "amd64", - "name": "libxtst6" - }, - { - "source": "apt", - "version": "1.09-6ubuntu1", - "architecture": "amd64", - "name": "liblockfile1" - }, - { - "source": "apt", - "version": "1.10-2ubuntu1", - "architecture": "amd64", - "name": "libxcb1" - }, - { - "source": "apt", - "version": "4.8.2-19ubuntu1", - "architecture": "amd64", - "name": "libgomp1" - }, - { - "source": "apt", - "version": "2.4+20121230.gitdf6c518-1", - "architecture": "amd64", - "name": "librtmp0" - }, - { - "source": "apt", - "version": "0.13+nmu2", - "architecture": "all", - "name": "xml-core" - }, - { - "source": "apt", - "version": "1.5.3-2ubuntu4.1", - "architecture": "amd64", - "name": "libgcrypt11" - }, - { - "source": "apt", - "version": "3.10-4ubuntu0.1", - "architecture": "amd64", - "name": "python-yaml" - }, - { - "source": "apt", - "version": "1:1.9.1-1ubuntu0.1", - "architecture": "amd64", - "name": "git" - }, - { - "source": "apt", - "version": "0.13.2-1", - "architecture": "amd64", - "name": "libpciaccess0" - }, - { - "source": "apt", - "version": "7.19.3-0ubuntu3", - "architecture": "amd64", - "name": "python-pycurl" - }, - { - "source": "apt", - "version": "2:1.7.1.901-1ubuntu1.1", - "architecture": "amd64", - "name": "libxi6" - }, - { - "source": "apt", - "version": "3.0.2", - "architecture": "amd64", - "name": "mongodb-org-server" - }, - { - "source": "apt", - "version": "1:7.7+1ubuntu8.1", - "architecture": "all", - "name": "x11-common" - }, - { - "source": "apt", - "version": "154ubuntu1", - "architecture": "all", - "name": "postgresql-common" - }, - { - "source": "apt", - "version": "0.103ubuntu4.2", - "architecture": "amd64", - "name": "initramfs-tools-bin" - }, - { - "source": "apt", - "version": "10.1.3-0ubuntu0.4", - "architecture": "amd64", - "name": "libgl1-mesa-dri" - }, - { - "source": "apt", - "version": "1:2.24-0ubuntu2", - "architecture": "amd64", - "name": "libcap2-bin" - }, - { - "source": "apt", - "version": "9.3.6-0ubuntu0.14.04", - "architecture": "amd64", - "name": "libpq5" - }, - { - "source": "apt", - "version": "4.4", - "architecture": "amd64", - "name": "debianutils" - }, - { - "source": "apt", - "version": "3:3.0.0-1chl1~trusty1", - "architecture": "amd64", - "name": "redis-server" - }, - { - "source": "apt", - "version": "2:1.1.4-1", - "architecture": "amd64", - "name": "libxxf86dga1" - }, - { - "source": "apt", - "version": "1.10-2ubuntu1", - "architecture": "amd64", - "name": "libxcb-dri2-0" - }, - { - "source": "apt", - "version": "2.1.5+deb1+cvs20081104-13.1", - "architecture": "amd64", - "name": "eject" - }, - { - "source": "apt", - "version": "2.88dsf-41ubuntu6", - "architecture": "amd64", - "name": "initscripts" - }, - { - "source": "apt", - "version": "0.8.8-0ubuntu17", - "architecture": "amd64", - "name": "plymouth" - }, - { - "source": "apt", - "version": "0.1.4-3ubuntu3.1", - "architecture": "amd64", - "name": "libyaml-dev" - }, - { - "source": "apt", - "version": "1.19.02-3", - "architecture": "all", - "name": "libalgorithm-diff-perl" - }, - { - "source": "apt", - "version": "1:1.1.1-1", - "architecture": "amd64", - "name": "libxdmcp6" - }, - { - "source": "apt", - "version": "7.7+1", - "architecture": "amd64", - "name": "x11-utils" - }, - { - "source": "apt", - "version": "0.11-3ubuntu1.2", - "architecture": "amd64", - "name": "libjson-c2" - }, - { - "source": "apt", - "version": "1:1.2.2-1", - "architecture": "amd64", - "name": "libxss1" - }, - { - "source": "apt", - "version": "3.1.2-1", - "architecture": "amd64", - "name": "libmpfr4" - }, - { - "source": "apt", - "version": "2.4.60-2~ubuntu14.04.1", - "architecture": "amd64", - "name": "libdrm-radeon1" - }, - { - "source": "apt", - "version": "1:5.14-2ubuntu3.2", - "architecture": "amd64", - "name": "file" - }, - { - "source": "apt", - "version": "7.4.4-1ubuntu2.3", - "architecture": "amd64", - "name": "rsyslog" - }, - { - "source": "apt", - "version": "2:1.2.1-2", - "architecture": "amd64", - "name": "libsm6" - }, - { - "source": "apt", - "version": "2.7.6-8", - "architecture": "amd64", - "name": "libpython2.7-stdlib" - }, - { - "source": "apt", - "version": "1.12+dfsg-2ubuntu5.1", - "architecture": "amd64", - "name": "libkrb5support0" - }, - { - "source": "apt", - "version": "2.7.5-5ubuntu3", - "architecture": "amd64", - "name": "python-dev" - }, - { - "source": "apt", - "version": "1.0.6-5", - "architecture": "amd64", - "name": "bzip2" - }, - { - "source": "apt", - "version": "1.5.2-1ubuntu1", - "architecture": "all", - "name": "python-six" - }, - { - "source": "apt", - "version": "1.0.3-4ubuntu25", - "architecture": "amd64", - "name": "libnih-dbus1" - }, - { - "source": "apt", - "version": "1.8.3-12build1", - "architecture": "amd64", - "name": "libgdbm3" - }, - { - "source": "apt", - "version": "3.6.0-1chl1~trusty1", - "architecture": "amd64", - "name": "libjemalloc1" - }, - { - "source": "apt", - "version": "1.17.5ubuntu5.4", - "architecture": "all", - "name": "dpkg-dev" - }, - { - "source": "apt", - "version": "15-0ubuntu6", - "architecture": "amd64", - "name": "libkmod2" - }, - { - "source": "apt", - "version": "2:1.6.2-1ubuntu2", - "architecture": "amd64", - "name": "libx11-6" - }, - { - "source": "apt", - "version": "1.17.5ubuntu5.4", - "architecture": "all", - "name": "libdpkg-perl" - }, - { - "source": "apt", - "version": "2012.05.19", - "architecture": "all", - "name": "ubuntu-keyring" - }, - { - "source": "apt", - "version": "1:3.3-1", - "architecture": "amd64", - "name": "diffutils" - }, - { - "source": "apt", - "version": "1.42.9-3ubuntu1", - "architecture": "amd64", - "name": "e2fsprogs" - }, - { - "source": "apt", - "version": "4.8.2-19ubuntu1", - "architecture": "amd64", - "name": "libstdc++-4.8-dev" - }, - { - "source": "apt", - "version": "5.18.2-2ubuntu1", - "architecture": "amd64", - "name": "perl-base" - }, - { - "source": "apt", - "version": "2.1.25.dfsg1-17build1", - "architecture": "amd64", - "name": "libsasl2-modules-db" - }, - { - "source": "apt", - "version": "2.19-0ubuntu6.6", - "architecture": "amd64", - "name": "libc-dev-bin" - }, - { - "source": "apt", - "version": "4:4.8.2-1ubuntu6", - "architecture": "amd64", - "name": "cpp" - }, - { - "source": "apt", - "version": "1.6.18-0ubuntu4.2", - "architecture": "amd64", - "name": "libdbus-1-3" - }, - { - "source": "apt", - "version": "3.5.33", - "architecture": "amd64", - "name": "base-passwd" - }, - { - "source": "apt", - "version": "1.20140128-1ubuntu8", - "architecture": "all", - "name": "dh-python" - } - ], - host2: - [{ - "source": "apt", - "version": "1:4.9.1-0ubuntu1", - "architecture": "amd64", - "name": "libgcc1" - }, - { - "source": "apt", - "version": "2.0.21-stable-1ubuntu1.14.04.1", - "architecture": "amd64", - "name": "libevent-2.0-5" - }, - { - "source": "apt", - "version": "0.11-3ubuntu1.2", - "architecture": "amd64", - "name": "libjson0" - }, - { - "source": "apt", - "version": "6.3-4ubuntu2", - "architecture": "amd64", - "name": "libreadline6" - }, - { - "source": "apt", - "version": "1:1.9.1-1ubuntu0.1", - "architecture": "all", - "name": "git-man" - }, - { - "source": "apt", - "version": "1.6~git20131207+dfsg-1ubuntu1.1", - "architecture": "amd64", - "name": "libgssapi3-heimdal" - }, - { - "source": "apt", - "version": "2.53", - "architecture": "amd64", - "name": "mountall" - }, - { - "source": "apt", - "version": "2.7.2-2", - "architecture": "all", - "name": "python-jinja2" - }, - { - "source": "apt", - "version": "3.4.0-2ubuntu1", - "architecture": "amd64", - "name": "python3.4-minimal" - }, - { - "source": "apt", - "version": "8.6.0+6ubuntu3", - "architecture": "amd64", - "name": "tk" - }, - { - "source": "apt", - "version": "4.8.2-19ubuntu1", - "architecture": "amd64", - "name": "gcc-4.8-base" - }, - { - "source": "apt", - "version": "1.0.1-1ubuntu1", - "architecture": "amd64", - "name": "libmpc3" - }, - { - "source": "apt", - "version": "2.3.1-93ubuntu1", - "architecture": "all", - "name": "makedev" - }, - { - "source": "apt", - "version": "1.10-2ubuntu1", - "architecture": "amd64", - "name": "libxcb-present0" - }, - { - "source": "apt", - "version": "2.4.52-1", - "architecture": "amd64", - "name": "libdrm2" - }, - { - "source": "apt", - "version": "1.70ubuntu8", - "architecture": "all", - "name": "keyboard-configuration" - }, - { - "source": "apt", - "version": "1.6~git20131207+dfsg-1ubuntu1.1", - "architecture": "amd64", - "name": "libheimbase1-heimdal" - }] -}; diff --git a/awx/ui/static/js/system-tracking/format-results.factory.js b/awx/ui/static/js/system-tracking/format-results.factory.js deleted file mode 100644 index 2789950c43..0000000000 --- a/awx/ui/static/js/system-tracking/format-results.factory.js +++ /dev/null @@ -1,13 +0,0 @@ -export default - function() { - return function formatResults(compareKey, displayKey, results) { - return results.reduce(function(arr, value) { - var obj = - { keyName: value[compareKey], - value1: value.position === 0 ? value[displayKey] : 'absent', - value2: value.position === 1 ? value[displayKey] : 'absent' - }; - return arr.concat(obj); - }, []); - }; - } diff --git a/awx/ui/static/js/system-tracking/main.js b/awx/ui/static/js/system-tracking/main.js index df92fd86f4..0361ab502c 100644 --- a/awx/ui/static/js/system-tracking/main.js +++ b/awx/ui/static/js/system-tracking/main.js @@ -1,21 +1,21 @@ import route from './system-tracking.route'; -import singleHostDataService from './single-host-data.service'; -import factDataServiceFactory from './fact-data-service.factory'; +import factScanDataService from './data-services/fact-scan-data.service'; +import getDataForComparison from './data-services/get-data-for-comparison.factory'; import controller from './system-tracking.controller'; import stringOrDateFilter from './string-or-date.filter'; -import xorObjects from './xor-objects.factory'; -import formatResults from './format-results.factory'; -import compareHosts from './compare-hosts.factory'; +import shared from 'tower/shared/main'; +import utilities from 'tower/shared/Utilities'; +import datePicker from './date-picker/main'; export default angular.module('systemTracking', - [ 'angularMoment' + [ 'angularMoment', + utilities.name, + shared.name, + datePicker.name ]) - .factory('factDataServiceFactory', factDataServiceFactory) - .service('singleHostDataService', singleHostDataService) - .factory('xorObjects', xorObjects) - .factory('formatResults', formatResults) - .factory('compareHosts', compareHosts) + .service('factScanDataService', factScanDataService) + .factory('getDataForComparison', getDataForComparison) .filter('stringOrDate', stringOrDateFilter) .controller('systemTracking', controller) .config(['$routeProvider', function($routeProvider) { @@ -23,6 +23,3 @@ export default delete route.route; $routeProvider.when(url, route); }]); - - - diff --git a/awx/ui/static/js/system-tracking/nested-facts.md b/awx/ui/static/js/system-tracking/nested-facts.md deleted file mode 100644 index e74b38bf3d..0000000000 --- a/awx/ui/static/js/system-tracking/nested-facts.md +++ /dev/null @@ -1,168 +0,0 @@ -## How I will do it - -1. Find all facts from results -2. Filter out all "same facts" -3. Transform for display - -### Finding facts from results - -Iterate over fact collection. Check if a thing is a fact or not (it is a fact when all of its key's values are comparable (not an object or array). If it's a fact, then transform it to an object that contains the nested key and value from each candidate. If it's not a fact, then recurse passing in the parent keys & value until we find a fact. - -To accomplish this we'll reduce over the values in the fact collection to create a new array. For each key, we'll check the type of its value. If it's an object or an array, we'll append the key to an array of parent keys and pass that and the value into a recursive call. If it's not an object or array, we'll record the parent key path as an array & both left & right values. We'll return the accumulator array with that object concatenated to it. - -End result example (FactComparison): - -[{ keyPath: ['sda', 'partitions', 'sda1'], - key: 'sectors', - leftValue: '39843840', - rightValue: '13254121' - }, - { keyPath: ['sda', partitions', 'sda1'], - key: 'model', - leftValue: 'VMware Virtual S", - rightValue: '' - }]; - -### Filtering out "same" facts - -This needs to look at all of the facts by parent key and remove any of those that have one or more differences. This will leave plenty of context for the user to determine exactly what is different here. For example, given the facts: - -#### Left Host - -```json -{ "ansible_mounts": - [{ - "device": "/dev/sda1", - "fstype": "ext4", - "mount": "/", - "options": "rw,errors=remount-ro", - "size_available": 15032406016, - "size_total": 20079898624 - }] -} -``` - -#### Right Host - -```json -{ "ansible_mounts": - [{ - "device": "/dev/sda1", - "fstype": "btrfs", - "mount": "/", - "options": "rw,errors=remount-ro", - "size_available": 153985231054, - "size_total": 53056978564321 - }] -} -``` - -If all the user could see was that the `fstype` fields were different, this would leave them wondering "what device is that on? where did that come from?" We are solving this problem by displaying all sibling properties of a fact regardless of whether they are different when at least one of those properties contains a difference. - -Therefore, to compare facts we need to first group them by their keys. Once we do that, we'll have a structure like: - -```json -{ 'sda.partitions.sda1': - [{ keyPath: ['sda', 'partitions', 'sda1'], - key: 'sectors', - leftValue: '39843840', - rightValue: '13254121' - }, - { keyPath: ['sda', partitions', 'sda1'], - key: 'model', - leftValue: 'VMware Virtual S", - rightValue: '' - }] -} -``` - -The simplest way to handle this would be to map over each key in this grouped object and return a filtered array of only objects with differences. Then we could iterate over the resulting object and filter out any keys whose value is an empty array, leaving us with only the keys that contain at least a single difference. Finally, we iterate over the original collection keeping only those values whose `keyPath` is in the previous collection of keys and return that result. - -### Transforming for display - -Given fact comparisons of: - -[{ keyPath: ['ansible_devices', 'sda'], - key: 'host', - leftValue: 'SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)', - rightValue: '' - - }, - { keyPath: ['ansible_devices', 'sda'], - key: 'model', - leftValue: 'VMWare Virtual S', - rightValue: 'APPLE SSD SM256C' - }, - { keyPath: ['ansible_devices', 'sda', 'partitions', 'sda1'], - key: 'sectors', - leftValue: '39843840', - rightValue: '13254121' - }, - { keyPath: ['ansible_devices', 'sda', partitions', 'sda1'], - key: 'sectorsize', - leftValue: '512', - rightValue: '512' - }, - { keyPath: ['ansible_mounts', '0'], - key: 'device', - leftValue: '/dev/sda5', - rightValue: '/dev/sda1' - }, - { keyPath: ['ansible_mounts', '0'], - key: 'fstype', - leftValue: 'ext4', - rightValue: 'btrfs' - }, - { keyPath: ['ansible_mounts', '1'], - key: 'device', - leftValue: 'absent', - rightValue: '/dev/sda5' - }]; - -We need to transform that to something like: - -[{ keyPath: ['ansible_devices', 'sda'], - displayKeyPath: 'ansible_devices.sda', - nestingLevel: 1, - facts: - [{ keyPath: ['ansible_devices', 'sda'], - key: 'host', - value1: 'SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)', - value2: '' - - }, - { keyPath: ['ansible_devices', 'sda'], - keyName: 'model', - value1: 'VMWare Virtual S', - value2: 'APPLE SSD SM256C' - }], - }, - { keyPath: ['ansible_devices', 'sda', 'partitions', 'sda1'], - displayKeyPath: 'partitions.sda1', - nestingLevel: 2, - facts: - // ... - }, - { keyPath: ['ansible_mounts'], - displayKeyPath: 'ansible_mounts', - nestingLevel: 1, - isArray: true, - facts: - [ [{ keyPath: ['ansible_mounts', '0'], - key: 'device', - leftValue: '/dev/sda5', - rightValue: '/dev/sda1' - }, - { keyPath: ['ansible_mounts', '0'], - key: 'fstype', - leftValue: 'ext4', - rightValue: 'btrfs' - }], - [{ keyPath: ['ansible_mounts', '1'], - key: 'device', - leftValue: 'absent', - rightValue: '/dev/sda5' - }] - ] - }] -``` diff --git a/awx/ui/static/js/system-tracking/search-date-range.js b/awx/ui/static/js/system-tracking/search-date-range.js new file mode 100644 index 0000000000..ed2a36e0e4 --- /dev/null +++ b/awx/ui/static/js/system-tracking/search-date-range.js @@ -0,0 +1,6 @@ +export function searchDateRange(date) { + return { + from: moment(date).startOf('day'), + to: moment(date).endOf('day') + }; +} diff --git a/awx/ui/static/js/system-tracking/string-or-date.filter.js b/awx/ui/static/js/system-tracking/string-or-date.filter.js index 275994a769..487af2190b 100644 --- a/awx/ui/static/js/system-tracking/string-or-date.filter.js +++ b/awx/ui/static/js/system-tracking/string-or-date.filter.js @@ -9,4 +9,4 @@ export default } }; } - ] + ]; 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 817e5a4551..9cb44062ef 100644 --- a/awx/ui/static/js/system-tracking/system-tracking.controller.js +++ b/awx/ui/static/js/system-tracking/system-tracking.controller.js @@ -1,37 +1,41 @@ -function controller($rootScope, $scope, $routeParams, $location, $q, factDataServiceFactory, moment) { +import {searchDateRange} from './search-date-range'; +import {compareFacts} from './compare-facts'; - var service; - var inventoryId = $routeParams.id; +function controller($rootScope, + $scope, + $routeParams, + $location, + $q, + initialFactData, + getDataForComparison, + waitIndicator, + + _) { + // var inventoryId = $routeParams.id; var hostIds = $routeParams.hosts.split(','); - var moduleParam = $location.search().module || 'packages'; - var configReadyOff = - $rootScope.$on('ConfigReady', function() { - $(".date").systemTrackingDP({ - autoclose: true - }); - configReadyOff(); - }); - - $scope.leftFilterValue = hostIds[0]; - $scope.rightFilterValue = hostIds[1]; - - $scope.factModulePickersLabelLeft = "Fact collection date for host " + $scope.leftFilterValue; - $scope.factModulePickersLabelRight = "Fact collection date for host " + $scope.rightFilterValue; + $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' }, @@ -45,25 +49,57 @@ function controller($rootScope, $scope, $routeParams, $location, $q, factDataSer // Use this to determine how to orchestrate the services var viewType = hostIds.length > 1 ? 'multiHost' : 'singleHost'; - if (viewType === 'singleHost') { - var startDate = moment(); - $scope.leftFilterValue = startDate; - $scope.rightFilterValue = startDate.clone().subtract(1, 'days'); + var searchConfig = + { leftDate: initialFactData.leftDate, + rightDate: initialFactData.rightDate + }; + + $scope.leftDate = initialFactData.leftDate.from; + $scope.rightDate = initialFactData.rightDate.from; + + function setHeaderValues(viewType) { + if (viewType === 'singleHost') { + $scope.comparisonLeftHeader = $scope.leftDate; + $scope.comparisonRightHeader = $scope.rightDate; + } else { + $scope.comparisonLeftHeader = hostIds[0]; + $scope.comparisonRightHeader = hostIds[1]; + } } - service = factDataServiceFactory(viewType); + function reloadData(params, initialData) { + searchConfig = _.merge({}, searchConfig, params); - function reloadData(activeModule) { - activeModule.then(function(module) { - $scope.factData = - service.get(inventoryId, - module.name, - $scope.leftFilterValue, - $scope.rightFilterValue); - }); + var factData = initialData; + var leftDate = searchConfig.leftDate; + var rightDate = searchConfig.rightDate; + var activeModule = searchConfig.module; + + if (!factData) { + factData = getDataForComparison( + hostIds, + activeModule.name, + leftDate, + rightDate); + } + + waitIndicator('start'); + + _(factData) + .thenAll(_.partial(compareFacts, activeModule)) + .then(function(info) { + + $scope.factData = info; + + setHeaderValues(viewType); + + }).finally(function() { + waitIndicator('stop'); + }) + .value(); } - $scope.setActiveModule = function(newModuleName) { + $scope.setActiveModule = function(newModuleName, initialData) { var newModule = _.find($scope.modules, function(module) { return module.name === newModuleName; @@ -74,14 +110,40 @@ function controller($rootScope, $scope, $routeParams, $location, $q, factDataSer }); newModule.isActive = true; + + $location.replace(); $location.search('module', newModuleName); - reloadData($q.when(newModule)); - + reloadData( + { module: newModule + }, initialData); }; + function dateWatcher(dateProperty) { + return function(newValue, oldValue) { + // passing in `true` for the 3rd param to $watch should make + // angular use `angular.equals` for comparing these values; + // the watcher should not fire, but it still is. Therefore, + // using `moment.isSame` to keep from reloading data when the + // dates did not actually change + if (newValue.isSame(oldValue)) { + return; + } - $scope.setActiveModule(moduleParam); + var newDate = searchDateRange(newValue); + + var params = {}; + params[dateProperty] = newDate; + + reloadData(params); + }; + } + + $scope.$watch('leftDate', dateWatcher('leftDate'), true); + + $scope.$watch('rightDate', dateWatcher('rightDate'), true); + + $scope.setActiveModule(initialFactData.moduleName, initialFactData); } export default @@ -90,7 +152,9 @@ export default '$routeParams', '$location', '$q', - 'factDataServiceFactory', - 'moment', + 'factScanData', + 'getDataForComparison', + 'Wait', + 'lodashAsPromised', controller ]; 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 bb51f07ac6..a05967ef5d 100644 --- a/awx/ui/static/js/system-tracking/system-tracking.partial.html +++ b/awx/ui/static/js/system-tracking/system-tracking.partial.html @@ -1,21 +1,11 @@
-
-
-
+
{{ factModulePickersLabelLeft }} -
- - -
+
-
- - {{ factModulePickersLabelRight }} - -
- - -
+
+ {{ factModulePickersLabelRight }} +
@@ -33,19 +23,57 @@ - - - - - - - - - - - - - - - -
{{factData.leftFilterValue|stringOrDate:'L'}}{{factData.rightFilterValue|stringOrDate:'L'}}
{{fact.keyName}}{{fact.value1}}{{fact.value2}}
+
+

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

+

{{comparisonRightHeader|stringOrDate:'L'}}

+
+
+
+

+ {{group.displayKeyPath}} +

+

+ {{group.displayKeyPath}} +

+

+ {{group.displayKeyPath}} +

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

+ {{fact.keyName}} +

+

+ {{fact.value1}} +

+

+ {{fact.value2}} +

+
+
+
+

+ {{fact.keyName}} +

+

+ {{fact.value1}} +

+

+ {{fact.value2}} +

+
+
+
+ +
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 02f231fc84..cb3eb0f5a6 100644 --- a/awx/ui/static/js/system-tracking/system-tracking.route.js +++ b/awx/ui/static/js/system-tracking/system-tracking.route.js @@ -1,5 +1,88 @@ +import {searchDateRange} from './search-date-range'; + export default { - route: '/inventories/:id/system-tracking/:hosts', + name: 'systemTracking', + route: '/inventories/:inventory/system-tracking/:hosts', controller: 'systemTracking', - templateUrl: '/static/js/system-tracking/system-tracking.partial.html' + templateUrl: '/static/js/system-tracking/system-tracking.partial.html', + resolve: { + factScanData: + [ 'getDataForComparison', + 'lodashAsPromised', + '$route', + '$location', + function(getDataForComparison, _, $route, $location) { + 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'); + + if (hostIds.length === 1) { + hostIds = hostIds.concat(hostIds[0]); + } + + var data = + getDataForComparison(hostIds, moduleParam, leftDate, rightDate). + thenThru(function(factData) { + factData.leftDate = leftDate; + factData.rightDate = rightDate; + factData.moduleName = moduleParam; + return factData; + }) + .value(); + + return data; + + } + ], + inventory: + [ '$route', + '$q', + 'Rest', + 'GetBasePath', + function($route, $q, rest, getBasePath) { + if ($route.current.params.inventory) { + return $q.when(true); + } + + var inventoryId = $route.current.params.inventory; + + var url = getBasePath('inventory') + inventoryId + '/'; + rest.setUrl(url); + return rest.get() + .then(function(data) { + return data.data; + }); + } + ], + filters: + [ '$route', + '$q', + 'Rest', + 'GetBasePath', + function($route, $q, rest, getBasePath) { + if ($route.current.params.hosts) { + return $q.when(true); + } + + var hostIds = $route.current.params.filters.split(','); + + var hosts = + hostIds.map(function(hostId) { + var url = getBasePath('hosts') + + hostId + '/'; + + rest.setUrl(url); + return rest.get() + .then(function(data) { + return data.data; + }); + }); + + return $q.all(hosts); + } + + ] + } }; diff --git a/awx/ui/static/js/system-tracking/xor-objects.factory.js b/awx/ui/static/js/system-tracking/xor-objects.factory.js deleted file mode 100644 index a56d169abc..0000000000 --- a/awx/ui/static/js/system-tracking/xor-objects.factory.js +++ /dev/null @@ -1,28 +0,0 @@ -export default - function() { - return function xorObjects(key, thing1, thing2) { - var values1 = _.pluck(thing1, key); - var values2 = _.pluck(thing2, key); - - var valuesDiff = _.xor(values1, values2); - - return valuesDiff.reduce(function(arr, value) { - var searcher = {}; - searcher[key] = value; - - var valuePosition1 = _.find(thing1, searcher); - - if (valuePosition1) { - valuePosition1.position = 0; - } - - var valuePosition2 = _.find(thing2, searcher); - - if (valuePosition2) { - valuePosition2.position = 1; - } - - return _.compact(arr.concat(valuePosition1).concat(valuePosition2)); - }, []); - }; - } diff --git a/awx/ui/static/less/text-label.less b/awx/ui/static/less/text-label.less index cb3c6898a9..bb6bbd8242 100644 --- a/awx/ui/static/less/text-label.less +++ b/awx/ui/static/less/text-label.less @@ -1,19 +1,4 @@ -.include-text-label(@background-color; @color; @content) { - display: inline-block; - content: @content; - - border-radius: 3px; - background-color: @background-color; - color: @color; - text-transform: uppercase; - font-size: .7em; - font-weight: bold; - font-style: normal; - margin-left: 0.5em; - padding: 0.35em; - padding-bottom: 0.2em; - line-height: 1.1; -} +@import "../js/shared/text-label.less"; .host-disabled-label { &:after { 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 322eaab9e3..7e9f88c626 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 @@ -2,7 +2,7 @@ import systemTracking from 'tower/system-tracking/main'; import {describeModule} from '../describe-module'; describeModule(systemTracking.name) - .testService('singleHostDataService', function(test, restStub) { + .testService('factScanDataService', function(test, restStub) { var service;