Update eslint and update angular style to match
With an updated eslint version and the addition of eslint-config-openstack and eslint-plugin-angular, there are several more stylistic guidelines to follow. However, this is what other OpenStack angular projects follow such as Horizon. Some notable changes are: * Wrapped javascript content in anonymous functions. This is a safeguard to keep the code from conflicting with other variables with the same name in other scripts on the same page. * Explicitly inject dependencies and have controllers, factories, etc as explicitly declared functions. * Use angular "controller as" syntax instead of assigning variables to $scope. * Added eslint rule that requires JSDoc for every function declaration. Note these are mainly stylistic changes and all the functionality of RefStack should remain the same. Change-Id: I044b1f473d589681a2ae9d2704700dd85687cbb6
This commit is contained in:
parent
8f730eb46f
commit
d23adad7f6
15
.eslintrc
15
.eslintrc
@ -32,6 +32,8 @@
|
||||
"shelljs": false
|
||||
},
|
||||
|
||||
"extends": "openstack",
|
||||
|
||||
"globals": {
|
||||
"require": false,
|
||||
"exports": false,
|
||||
@ -43,16 +45,25 @@
|
||||
"browser": false
|
||||
},
|
||||
|
||||
"plugins": [
|
||||
"angular"
|
||||
],
|
||||
|
||||
"rules": {
|
||||
"quotes": [2, "single"],
|
||||
"eol-last": 2,
|
||||
"no-trailing-spaces": 2,
|
||||
"camelcase": 0,
|
||||
"no-extra-boolean-cast": 0,
|
||||
"operator-linebreak": 0,
|
||||
"require-jsdoc": 2,
|
||||
|
||||
// Stylistic
|
||||
"indent": [2, 4],
|
||||
"indent": [2, 4, {SwitchCase: 1}],
|
||||
"max-len": [2, 80],
|
||||
"no-undefined": 2
|
||||
"no-undefined": 2,
|
||||
|
||||
// Angular Plugin
|
||||
"angular/controller-as-vm": [1, "ctrl"]
|
||||
}
|
||||
}
|
10
package.json
10
package.json
@ -2,11 +2,13 @@
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"name": "refstack-ui",
|
||||
"description": "A user interface for Refstack",
|
||||
"description": "A user interface for RefStack",
|
||||
"license": "Apache2",
|
||||
"devDependencies": {
|
||||
"bower": "1.3.12",
|
||||
"eslint": "^0.21.2",
|
||||
"eslint": "1.5.1",
|
||||
"eslint-config-openstack": "1.2.1",
|
||||
"eslint-plugin-angular": "0.12.0",
|
||||
"http-server": "^0.6.1",
|
||||
"karma": "^0.12.23",
|
||||
"karma-chrome-launcher": "^0.1.5",
|
||||
@ -15,9 +17,7 @@
|
||||
"karma-jasmine": "^0.2.2",
|
||||
"karma-phantomjs-launcher": "0.2.0",
|
||||
"phantomjs": "1.9.17",
|
||||
"protractor": "~1.0.0",
|
||||
"shelljs": "^0.2.6",
|
||||
"tmp": "0.0.23"
|
||||
"protractor": "~1.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "bower install --config.interactive=false",
|
||||
|
@ -1,16 +1,38 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/** Main app module where application dependencies are listed. */
|
||||
var refstackApp = angular.module('refstackApp', [
|
||||
'ui.router', 'ui.bootstrap', 'cgBusy', 'ngResource', 'angular-confirm']);
|
||||
angular
|
||||
.module('refstackApp', [
|
||||
'ui.router','ui.bootstrap', 'cgBusy',
|
||||
'ngResource', 'angular-confirm'
|
||||
]);
|
||||
|
||||
angular
|
||||
.module('refstackApp')
|
||||
.config(configureRoutes);
|
||||
|
||||
configureRoutes.$inject = ['$stateProvider', '$urlRouterProvider'];
|
||||
|
||||
/**
|
||||
* Handle application routing. Specific templates and controllers will be
|
||||
* used based on the URL route.
|
||||
*/
|
||||
refstackApp.config([
|
||||
'$stateProvider', '$urlRouterProvider',
|
||||
function ($stateProvider, $urlRouterProvider) {
|
||||
'use strict';
|
||||
|
||||
function configureRoutes($stateProvider, $urlRouterProvider) {
|
||||
$urlRouterProvider.otherwise('/');
|
||||
$stateProvider.
|
||||
state('home', {
|
||||
@ -24,70 +46,80 @@ refstackApp.config([
|
||||
state('capabilities', {
|
||||
url: '/capabilities',
|
||||
templateUrl: '/components/capabilities/capabilities.html',
|
||||
controller: 'capabilitiesController'
|
||||
controller: 'CapabilitiesController as ctrl'
|
||||
}).
|
||||
state('communityResults', {
|
||||
url: '/community_results',
|
||||
templateUrl: '/components/results/results.html',
|
||||
controller: 'resultsController'
|
||||
controller: 'ResultsController as ctrl'
|
||||
}).
|
||||
state('userResults', {
|
||||
url: '/user_results',
|
||||
templateUrl: '/components/results/results.html',
|
||||
controller: 'resultsController'
|
||||
controller: 'ResultsController as ctrl'
|
||||
}).
|
||||
state('resultsDetail', {
|
||||
url: '/results/:testID',
|
||||
templateUrl: '/components/results-report/resultsReport.html',
|
||||
controller: 'resultsReportController'
|
||||
templateUrl: '/components/results-report' +
|
||||
'/resultsReport.html',
|
||||
controller: 'ResultsReportController as ctrl'
|
||||
}).
|
||||
state('profile', {
|
||||
url: '/profile',
|
||||
templateUrl: '/components/profile/profile.html',
|
||||
controller: 'profileController'
|
||||
controller: 'ProfileController as ctrl'
|
||||
}).
|
||||
state('authFailure', {
|
||||
url: '/auth_failure/:message',
|
||||
templateUrl: '/components/home/home.html',
|
||||
controller: 'authFailureController'
|
||||
controller: 'AuthFailureController as ctrl'
|
||||
});
|
||||
}
|
||||
]);
|
||||
|
||||
angular
|
||||
.module('refstackApp')
|
||||
.run(setup);
|
||||
|
||||
setup.$inject = [
|
||||
'$http', '$rootScope', '$window', '$state', 'refstackApiUrl'
|
||||
];
|
||||
|
||||
/**
|
||||
* Injections in $rootscope
|
||||
* Set up the app with injections into $rootscope. This is mainly for auth
|
||||
* functions.
|
||||
*/
|
||||
|
||||
refstackApp.run(['$http', '$rootScope', '$window', '$state', 'refstackApiUrl',
|
||||
function($http, $rootScope, $window, $state, refstackApiUrl) {
|
||||
'use strict';
|
||||
function setup($http, $rootScope, $window, $state, refstackApiUrl) {
|
||||
|
||||
/**
|
||||
* This function injects sign in function in all scopes
|
||||
*/
|
||||
|
||||
$rootScope.auth = {};
|
||||
$rootScope.auth.doSignIn = doSignIn;
|
||||
$rootScope.auth.doSignOut = doSignOut;
|
||||
$rootScope.auth.doSignCheck = doSignCheck;
|
||||
|
||||
var sign_in_url = refstackApiUrl + '/auth/signin';
|
||||
$rootScope.auth.doSignIn = function () {
|
||||
$window.location.href = sign_in_url;
|
||||
};
|
||||
|
||||
/**
|
||||
* This function injects sign out function in all scopes
|
||||
*/
|
||||
var sign_out_url = refstackApiUrl + '/auth/signout';
|
||||
$rootScope.auth.doSignOut = function () {
|
||||
var profile_url = refstackApiUrl + '/profile';
|
||||
|
||||
/** This function initiates a sign in. */
|
||||
function doSignIn() {
|
||||
$window.location.href = sign_in_url;
|
||||
}
|
||||
|
||||
/** This function will initate a sign out. */
|
||||
function doSignOut() {
|
||||
$rootScope.currentUser = null;
|
||||
$rootScope.isAuthenticated = false;
|
||||
$window.location.href = sign_out_url;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This block tries to authenticate user
|
||||
* This function checks to see if a user is logged in and
|
||||
* authenticated.
|
||||
*/
|
||||
var profile_url = refstackApiUrl + '/profile';
|
||||
$rootScope.auth.doSignCheck = function () {
|
||||
function doSignCheck() {
|
||||
return $http.get(profile_url, {withCredentials: true}).
|
||||
success(function (data) {
|
||||
$rootScope.auth.currentUser = data;
|
||||
@ -97,24 +129,31 @@ refstackApp.run(['$http', '$rootScope', '$window', '$state', 'refstackApiUrl',
|
||||
$rootScope.auth.currentUser = null;
|
||||
$rootScope.auth.isAuthenticated = false;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
$rootScope.auth.doSignCheck();
|
||||
}
|
||||
]);
|
||||
|
||||
angular
|
||||
.element(document)
|
||||
.ready(loadConfig);
|
||||
|
||||
/**
|
||||
* Load config and start up the angular application.
|
||||
*/
|
||||
angular.element(document).ready(function () {
|
||||
'use strict';
|
||||
function loadConfig() {
|
||||
|
||||
var $http = angular.injector(['ng']).get('$http');
|
||||
|
||||
/**
|
||||
* Store config variables as constants, and start the app.
|
||||
*/
|
||||
function startApp(config) {
|
||||
// Add config options as constants.
|
||||
for (var key in config) {
|
||||
angular.module('refstackApp').constant(key, config[key]);
|
||||
}
|
||||
angular.forEach(config, function(value, key) {
|
||||
angular.module('refstackApp').constant(key, value);
|
||||
});
|
||||
|
||||
angular.bootstrap(document, ['refstackApp']);
|
||||
}
|
||||
|
||||
@ -123,4 +162,5 @@ angular.element(document).ready(function () {
|
||||
}).error(function () {
|
||||
startApp({});
|
||||
});
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
@ -1,17 +1,31 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('refstackApp')
|
||||
.controller('AuthFailureController', AuthFailureController);
|
||||
|
||||
AuthFailureController.$inject = ['$stateParams', '$state', 'raiseAlert'];
|
||||
/**
|
||||
* Refstack Auth Failure Controller
|
||||
* This controller handles messages from Refstack API if user auth fails.
|
||||
*/
|
||||
|
||||
var refstackApp = angular.module('refstackApp');
|
||||
|
||||
refstackApp.controller('authFailureController',
|
||||
[
|
||||
'$stateParams', '$state', 'raiseAlert',
|
||||
function($stateParams, $state, raiseAlert) {
|
||||
'use strict';
|
||||
raiseAlert('danger', 'Authentication Failure:',
|
||||
$stateParams.message);
|
||||
function AuthFailureController($stateParams, $state, raiseAlert) {
|
||||
raiseAlert('danger', 'Authentication Failure:', $stateParams.message);
|
||||
$state.go('home');
|
||||
}
|
||||
]);
|
||||
})();
|
||||
|
@ -4,15 +4,15 @@
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<strong>Version:</strong>
|
||||
<select ng-model="version" ng-change="update()" class="form-control">
|
||||
<select ng-model="ctrl.version" ng-change="ctrl.update()" class="form-control">
|
||||
<!-- Slicing the version file name here gets rid of the '.json' file extension. -->
|
||||
<option ng-repeat="versionFile in versionList" value="{{versionFile}}">{{versionFile.slice(0, -5)}}</option>
|
||||
<option ng-repeat="versionFile in ctrl.versionList" value="{{versionFile}}">{{versionFile.slice(0, -5)}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<strong>Target Program:</strong>
|
||||
<span class="program-about"><a target="_blank" href="http://www.openstack.org/brand/interop/">About</a></span>
|
||||
<select ng-model="target" class="form-control" ng-change="updateTargetCapabilities()">
|
||||
<select ng-model="ctrl.target" class="form-control" ng-change="ctrl.updateTargetCapabilities()">
|
||||
<option value="platform">OpenStack Powered Platform</option>
|
||||
<option value="compute">OpenStack Powered Compute</option>
|
||||
<option value="object">OpenStack Powered Object Storage</option>
|
||||
@ -21,10 +21,10 @@
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<div ng-show="capabilities">
|
||||
<div ng-show="ctrl.capabilities">
|
||||
<strong>Corresponding OpenStack Releases:</strong>
|
||||
<ul class="list-inline">
|
||||
<li ng-repeat="release in capabilities.releases">
|
||||
<li ng-repeat="release in ctrl.capabilities.releases">
|
||||
{{release | capitalize}}
|
||||
</li>
|
||||
</ul>
|
||||
@ -33,19 +33,19 @@
|
||||
<strong>Capability Status:</strong>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="status.required">
|
||||
<input type="checkbox" ng-model="ctrl.status.required">
|
||||
<span class="required">Required</span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" ng-model="status.advisory">
|
||||
<input type="checkbox" ng-model="ctrl.status.advisory">
|
||||
<span class="advisory">Advisory</span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" ng-model="status.deprecated">
|
||||
<input type="checkbox" ng-model="ctrl.status.deprecated">
|
||||
<span class="deprecated">Deprecated</span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" ng-model="status.removed">
|
||||
<input type="checkbox" ng-model="ctrl.status.removed">
|
||||
<span class="removed">Removed</span>
|
||||
</label>
|
||||
</div>
|
||||
@ -54,14 +54,14 @@
|
||||
<p><small>Tests marked with <span class="glyphicon glyphicon-flag text-warning"></span> are tests flagged by DefCore.</small></p>
|
||||
|
||||
<!-- Loading animation divs -->
|
||||
<div cg-busy="{promise:versionsRequest,message:'Loading versions'}"></div>
|
||||
<div cg-busy="{promise:capsRequest,message:'Loading capabilities'}"></div>
|
||||
<div cg-busy="{promise:ctrl.versionsRequest,message:'Loading versions'}"></div>
|
||||
<div cg-busy="{promise:ctrl.capsRequest,message:'Loading capabilities'}"></div>
|
||||
|
||||
<!-- Get the version-specific template -->
|
||||
<div ng-include src="detailsTemplate"></div>
|
||||
<div ng-include src="ctrl.detailsTemplate"></div>
|
||||
|
||||
<div ng-show="showError" class="alert alert-danger" role="alert">
|
||||
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
|
||||
<span class="sr-only">Error:</span>
|
||||
{{error}}
|
||||
{{ctrl.error}}
|
||||
</div>
|
||||
|
@ -1,26 +1,45 @@
|
||||
var refstackApp = angular.module('refstackApp');
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('refstackApp')
|
||||
.controller('CapabilitiesController', CapabilitiesController);
|
||||
|
||||
CapabilitiesController.$inject = ['$http', 'refstackApiUrl'];
|
||||
|
||||
/**
|
||||
* Refstack Capabilities Controller
|
||||
* RefStack Capabilities Controller
|
||||
* This controller is for the '/capabilities' page where a user can browse
|
||||
* through tests belonging to DefCore-defined capabilities.
|
||||
*/
|
||||
refstackApp.controller('capabilitiesController',
|
||||
['$scope', '$http', 'refstackApiUrl',
|
||||
function ($scope, $http, refstackApiUrl) {
|
||||
'use strict';
|
||||
function CapabilitiesController($http, refstackApiUrl) {
|
||||
var ctrl = this;
|
||||
|
||||
/** Whether to hide/collapse the achievements for each capability. */
|
||||
$scope.hideAchievements = true;
|
||||
|
||||
/** Whether to hide/collapse the tests for each capability. */
|
||||
$scope.hideTests = true;
|
||||
ctrl.getVersionList = getVersionList;
|
||||
ctrl.update = update;
|
||||
ctrl.updateTargetCapabilities = updateTargetCapabilities;
|
||||
ctrl.filterStatus = filterStatus;
|
||||
ctrl.getObjectLength = getObjectLength;
|
||||
|
||||
/** The target OpenStack marketing program to show capabilities for. */
|
||||
$scope.target = 'platform';
|
||||
ctrl.target = 'platform';
|
||||
|
||||
/** The various possible capability statuses. */
|
||||
$scope.status = {
|
||||
ctrl.status = {
|
||||
required: true,
|
||||
advisory: false,
|
||||
deprecated: false,
|
||||
@ -31,7 +50,7 @@ refstackApp.controller('capabilitiesController',
|
||||
* The template to load for displaying capability details. The value
|
||||
* of this depends on the schema version of the capabilities file.
|
||||
*/
|
||||
$scope.detailsTemplate = null;
|
||||
ctrl.detailsTemplate = null;
|
||||
|
||||
/**
|
||||
* Retrieve an array of available capability files from the Refstack
|
||||
@ -41,42 +60,42 @@ refstackApp.controller('capabilitiesController',
|
||||
* call, the function to update the capabilities is called.
|
||||
* Sample API return array: ["2015.03.json", "2015.04.json"]
|
||||
*/
|
||||
$scope.getVersionList = function () {
|
||||
function getVersionList() {
|
||||
var content_url = refstackApiUrl + '/capabilities';
|
||||
$scope.versionsRequest =
|
||||
ctrl.versionsRequest =
|
||||
$http.get(content_url).success(function (data) {
|
||||
$scope.versionList = data.sort().reverse();
|
||||
$scope.version = $scope.versionList[0];
|
||||
$scope.update();
|
||||
ctrl.versionList = data.sort().reverse();
|
||||
ctrl.version = ctrl.versionList[0];
|
||||
ctrl.update();
|
||||
}).error(function (error) {
|
||||
$scope.showError = true;
|
||||
$scope.error = 'Error retrieving version list: ' +
|
||||
JSON.stringify(error);
|
||||
ctrl.showError = true;
|
||||
ctrl.error = 'Error retrieving version list: ' +
|
||||
angular.toJson(error);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This will contact the Refstack API server to retrieve the JSON
|
||||
* content of the capability file corresponding to the selected
|
||||
* version.
|
||||
*/
|
||||
$scope.update = function () {
|
||||
function update() {
|
||||
var content_url = refstackApiUrl + '/capabilities/' +
|
||||
$scope.version;
|
||||
$scope.capsRequest =
|
||||
ctrl.version;
|
||||
ctrl.capsRequest =
|
||||
$http.get(content_url).success(function (data) {
|
||||
$scope.capabilities = data;
|
||||
$scope.detailsTemplate = 'components/capabilities/' +
|
||||
ctrl.capabilities = data;
|
||||
ctrl.detailsTemplate = 'components/capabilities/' +
|
||||
'partials/capabilityDetailsV' +
|
||||
data.schema + '.html';
|
||||
$scope.updateTargetCapabilities();
|
||||
ctrl.updateTargetCapabilities();
|
||||
}).error(function (error) {
|
||||
$scope.showError = true;
|
||||
$scope.capabilities = null;
|
||||
$scope.error = 'Error retrieving capabilities: ' +
|
||||
JSON.stringify(error);
|
||||
ctrl.showError = true;
|
||||
ctrl.capabilities = null;
|
||||
ctrl.error = 'Error retrieving capabilities: ' +
|
||||
angular.toJson(error);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This will update the scope's 'targetCapabilities' object with
|
||||
@ -84,17 +103,16 @@ refstackApp.controller('capabilitiesController',
|
||||
* (programs typically correspond to 'components' in the DefCore
|
||||
* schema). Each capability will have its status mapped to it.
|
||||
*/
|
||||
$scope.updateTargetCapabilities = function () {
|
||||
$scope.targetCapabilities = {};
|
||||
var components = $scope.capabilities.components;
|
||||
var targetCaps = $scope.targetCapabilities;
|
||||
function updateTargetCapabilities() {
|
||||
ctrl.targetCapabilities = {};
|
||||
var components = ctrl.capabilities.components;
|
||||
var targetCaps = ctrl.targetCapabilities;
|
||||
|
||||
// The 'platform' target is comprised of multiple components, so
|
||||
// we need to get the capabilities belonging to each of its
|
||||
// components.
|
||||
if ($scope.target === 'platform') {
|
||||
var platform_components =
|
||||
$scope.capabilities.platform.required;
|
||||
if (ctrl.target === 'platform') {
|
||||
var platform_components = ctrl.capabilities.platform.required;
|
||||
|
||||
// This will contain status priority values, where lower
|
||||
// values mean higher priorities.
|
||||
@ -130,16 +148,14 @@ refstackApp.controller('capabilitiesController',
|
||||
});
|
||||
}
|
||||
else {
|
||||
angular.forEach(components[$scope.target],
|
||||
angular.forEach(components[ctrl.target],
|
||||
function (caps, status) {
|
||||
angular.forEach(caps, function(cap) {
|
||||
targetCaps[cap] = status;
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.getVersionList();
|
||||
}
|
||||
|
||||
/**
|
||||
* This filter will check if a capability's status corresponds
|
||||
@ -148,17 +164,17 @@ refstackApp.controller('capabilitiesController',
|
||||
* @param {Object} capability
|
||||
* @returns {Boolean} True if capability's status is selected
|
||||
*/
|
||||
$scope.filterStatus = function (capability) {
|
||||
var caps = $scope.targetCapabilities;
|
||||
return ($scope.status.required &&
|
||||
function filterStatus(capability) {
|
||||
var caps = ctrl.targetCapabilities;
|
||||
return (ctrl.status.required &&
|
||||
caps[capability.id] === 'required') ||
|
||||
($scope.status.advisory &&
|
||||
(ctrl.status.advisory &&
|
||||
caps[capability.id] === 'advisory') ||
|
||||
($scope.status.deprecated &&
|
||||
(ctrl.status.deprecated &&
|
||||
caps[capability.id] === 'deprecated') ||
|
||||
($scope.status.removed &&
|
||||
(ctrl.status.removed &&
|
||||
caps[capability.id] === 'removed');
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will get the length of an Object/dict based on
|
||||
@ -166,7 +182,10 @@ refstackApp.controller('capabilitiesController',
|
||||
* @param {Object} object
|
||||
* @returns {Number} length of object
|
||||
*/
|
||||
$scope.getObjectLength = function (object) {
|
||||
function getObjectLength(object) {
|
||||
return Object.keys(object).length;
|
||||
};
|
||||
}]);
|
||||
}
|
||||
|
||||
ctrl.getVersionList();
|
||||
}
|
||||
})();
|
||||
|
@ -4,20 +4,20 @@ This expects the JSON data of the capability file to be stored in scope
|
||||
variable 'capabilities'.
|
||||
-->
|
||||
|
||||
<ol ng-show="capabilities" class="capabilities">
|
||||
<li class="capability-list-item" ng-repeat="capability in capabilities.capabilities | arrayConverter | filter:filterStatus">
|
||||
<ol ng-show="ctrl.capabilities" class="capabilities">
|
||||
<li class="capability-list-item" ng-repeat="capability in ctrl.capabilities.capabilities | arrayConverter | filter:ctrl.filterStatus | orderBy:'id'">
|
||||
<span class="capability-name">{{capability.id}}</span><br />
|
||||
<em>{{capability.description}}</em><br />
|
||||
Status: <span class="{{targetCapabilities[capability.id]}}">{{targetCapabilities[capability.id]}}</span><br />
|
||||
<a ng-click="hideAchievements = !hideAchievements">Achievements ({{capability.achievements.length}})</a><br />
|
||||
<ol collapse="hideAchievements" class="list-inline">
|
||||
Status: <span class="{{ctrl.targetCapabilities[capability.id]}}">{{ctrl.targetCapabilities[capability.id]}}</span><br />
|
||||
<a ng-click="showAchievements = !showAchievements">Achievements ({{capability.achievements.length}})</a><br />
|
||||
<ol collapse="!showAchievements" class="list-inline">
|
||||
<li ng-repeat="achievement in capability.achievements">
|
||||
{{achievement}}
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<a ng-click="hideTests = !hideTests">Tests ({{capability.tests.length}})</a>
|
||||
<ul collapse="hideTests">
|
||||
<a ng-click="showTests = !showTests">Tests ({{capability.tests.length}})</a>
|
||||
<ul collapse="!showTests">
|
||||
<li ng-repeat="test in capability.tests">
|
||||
<span ng-class="{'glyphicon glyphicon-flag text-warning': capability.flagged.indexOf(test) > -1}"></span>
|
||||
{{test}}
|
||||
@ -26,12 +26,12 @@ variable 'capabilities'.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<div ng-show="capabilities" class="criteria">
|
||||
<div ng-show="ctrl.capabilities" class="criteria">
|
||||
<hr>
|
||||
<h4><a ng-click="hideCriteria = !hideCriteria">Criteria</a></h4>
|
||||
<div collapse="hideCriteria">
|
||||
<h4><a ng-click="showCriteria = !showCriteria">Criteria</a></h4>
|
||||
<div collapse="showCriteria">
|
||||
<ul>
|
||||
<li ng-repeat="(key, criterion) in capabilities.criteria">
|
||||
<li ng-repeat="(key, criterion) in ctrl.capabilities.criteria">
|
||||
<span class="criterion-name">{{criterion.name}}</span><br />
|
||||
<em>{{criterion.Description}}</em><br />
|
||||
Weight: {{criterion.weight}}
|
||||
|
@ -4,21 +4,21 @@ This expects the JSON data of the capability file to be stored in scope
|
||||
variable 'capabilities'.
|
||||
-->
|
||||
|
||||
<ol ng-show="capabilities" class="capabilities">
|
||||
<li class="capability-list-item" ng-repeat="capability in capabilities.capabilities | arrayConverter | filter:filterStatus">
|
||||
<ol ng-show="ctrl.capabilities" class="capabilities">
|
||||
<li class="capability-list-item" ng-repeat="capability in ctrl.capabilities.capabilities | arrayConverter | filter:ctrl.filterStatus | orderBy:'id'">
|
||||
<span class="capability-name">{{capability.id}}</span><br />
|
||||
<em>{{capability.description}}</em><br />
|
||||
Status: <span class="{{targetCapabilities[capability.id]}}">{{targetCapabilities[capability.id]}}</span><br />
|
||||
Status: <span class="{{ctrl.targetCapabilities[capability.id]}}">{{ctrl.targetCapabilities[capability.id]}}</span><br />
|
||||
Project: {{capability.project | capitalize}}<br />
|
||||
<a ng-click="hideAchievements = !hideAchievements">Achievements ({{capability.achievements.length}})</a><br />
|
||||
<ol collapse="hideAchievements" class="list-inline">
|
||||
<a ng-click="showAchievements = !hshowAchievements">Achievements ({{capability.achievements.length}})</a><br />
|
||||
<ol collapse="!showAchievements" class="list-inline">
|
||||
<li ng-repeat="achievement in capability.achievements">
|
||||
{{achievement}}
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<a ng-click="hideTests = !hideTests">Tests ({{getObjectLength(capability.tests)}})</a>
|
||||
<ul collapse="hideTests">
|
||||
<a ng-click="showTests = !showTests">Tests ({{ctrl.getObjectLength(capability.tests)}})</a>
|
||||
<ul collapse="!showTests">
|
||||
<li ng-repeat="(testName, testDetails) in capability.tests">
|
||||
<span ng-class="{'glyphicon glyphicon-flag text-warning': testDetails.flagged}" title="{{testDetails.flagged.reason}}"></span>
|
||||
{{testName}}
|
||||
@ -27,12 +27,12 @@ variable 'capabilities'.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<div ng-show="capabilities" class="criteria">
|
||||
<div ng-show="ctrl.capabilities" class="criteria">
|
||||
<hr>
|
||||
<h4><a ng-click="hideCriteria = !hideCriteria">Criteria</a></h4>
|
||||
<div collapse="hideCriteria">
|
||||
<h4><a ng-click="showCriteria = !showCriteria">Criteria</a></h4>
|
||||
<div collapse="showCriteria">
|
||||
<ul>
|
||||
<li ng-repeat="(key, criterion) in capabilities.criteria">
|
||||
<li ng-repeat="(key, criterion) in ctrl.capabilities.criteria">
|
||||
<span class="criterion-name">{{criterion.name}}</span><br />
|
||||
<em>{{criterion.Description}}</em><br />
|
||||
Weight: {{criterion.weight}}
|
||||
|
@ -1,21 +1,21 @@
|
||||
<div class="modal-header">
|
||||
<h4>Import public key</h4>
|
||||
<h4>Import Public Key</h4>
|
||||
</div>
|
||||
<div class="modal-body container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-2">Public key</div>
|
||||
<div class="col-md-2">Public Key</div>
|
||||
<div class="col-md-9 pull-right">
|
||||
<textarea type="text" rows="11" cols="42" ng-model="raw_key" required></textarea>
|
||||
<textarea type="text" rows="11" cols="42" ng-model="modal.raw_key" required></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-2">Signature</div>
|
||||
<div class="col-md-9 pull-right">
|
||||
<textarea type="text" rows="11" cols="42" ng-model="self_signature" required></textarea>
|
||||
<textarea type="text" rows="11" cols="42" ng-model="modal.self_signature" required></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
|
||||
<button type="button" class="btn btn-default btn-sm" ng-click="importPubKey()">Import public key</button>
|
||||
<button class="btn btn-warning" ng-click="modal.cancel()">Cancel</button>
|
||||
<button type="button" class="btn btn-default btn-sm" ng-click="modal.importPubKey()">Import Public Key</button>
|
||||
</div>
|
||||
</div>
|
@ -1,5 +1,5 @@
|
||||
<h3>User profile</h3>
|
||||
<div cg-busy="{promise:authRequest,message:'Loading'}"></div>
|
||||
<div cg-busy="{promise:ctrl.authRequest,message:'Loading'}"></div>
|
||||
<div>
|
||||
<table class="table table-striped table-hover">
|
||||
<tbody>
|
||||
@ -9,15 +9,15 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div ng-show="pubkeys">
|
||||
<div ng-show="ctrl.pubkeys">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<h4>User public keys</h4>
|
||||
<h4>User Public Keys</h4>
|
||||
</div>
|
||||
<div class="col-md-2 pull-right">
|
||||
<button type="button" class="btn btn-default btn-sm" ng-click="openImportPubKeyModal()">
|
||||
<span class="glyphicon glyphicon-plus"></span> Import public key
|
||||
<button type="button" class="btn btn-default btn-sm" ng-click="ctrl.openImportPubKeyModal()">
|
||||
<span class="glyphicon glyphicon-plus"></span> Import Public Key
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -26,7 +26,7 @@
|
||||
<div>
|
||||
<table class="table table-striped table-hover">
|
||||
<tbody>
|
||||
<tr ng-repeat="pubKey in pubkeys" ng-click="openShowPubKeyModal(pubKey)">
|
||||
<tr ng-repeat="pubKey in ctrl.pubkeys" ng-click="ctrl.openShowPubKeyModal(pubKey)">
|
||||
<td>{{pubKey.format}}</td>
|
||||
<td>{{pubKey.shortKey}}</td>
|
||||
<td>{{pubKey.comment}}</td>
|
||||
|
@ -1,34 +1,71 @@
|
||||
/*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('refstackApp')
|
||||
.factory('PubKeys', PubKeys);
|
||||
|
||||
PubKeys.$inject = ['$resource', 'refstackApiUrl'];
|
||||
|
||||
/**
|
||||
* Refstack User Profile Controller
|
||||
* This is a provider for the user's uploaded public keys.
|
||||
*/
|
||||
function PubKeys($resource, refstackApiUrl) {
|
||||
return $resource(refstackApiUrl + '/profile/pubkeys/:id', null, null);
|
||||
}
|
||||
|
||||
angular
|
||||
.module('refstackApp')
|
||||
.controller('ProfileController', ProfileController);
|
||||
|
||||
ProfileController.$inject = [
|
||||
'$scope', '$http', 'refstackApiUrl', 'PubKeys',
|
||||
'$modal', 'raiseAlert', '$state'
|
||||
];
|
||||
|
||||
/**
|
||||
* RefStack Profile Controller
|
||||
* This controller handles user's profile page, where a user can view
|
||||
* account-specific information.
|
||||
*/
|
||||
|
||||
var refstackApp = angular.module('refstackApp');
|
||||
|
||||
refstackApp.factory('PubKeys',
|
||||
['$resource', 'refstackApiUrl', function($resource, refstackApiUrl) {
|
||||
'use strict';
|
||||
return $resource(refstackApiUrl + '/profile/pubkeys/:id', null, null);
|
||||
}]);
|
||||
|
||||
refstackApp.controller('profileController',
|
||||
[
|
||||
'$scope', '$http', 'refstackApiUrl', 'PubKeys',
|
||||
'$modal', 'raiseAlert', '$state',
|
||||
function($scope, $http, refstackApiUrl,
|
||||
function ProfileController($scope, $http, refstackApiUrl,
|
||||
PubKeys, $modal, raiseAlert, $state) {
|
||||
'use strict';
|
||||
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.updatePubKeys = updatePubKeys;
|
||||
ctrl.openImportPubKeyModal = openImportPubKeyModal;
|
||||
ctrl.openShowPubKeyModal = openShowPubKeyModal;
|
||||
|
||||
// Must be authenticated to view this page.
|
||||
if (!$scope.auth.isAuthenticated) {
|
||||
$state.go('home');
|
||||
}
|
||||
|
||||
$scope.updatePubKeys = function (){
|
||||
/**
|
||||
* This function will fetch all the user's public keys from the
|
||||
* server and store them in an array.
|
||||
*/
|
||||
function updatePubKeys() {
|
||||
var keys = PubKeys.query(function() {
|
||||
$scope.pubkeys = [];
|
||||
ctrl.pubkeys = [];
|
||||
angular.forEach(keys, function (key) {
|
||||
$scope.pubkeys.push({
|
||||
ctrl.pubkeys.push({
|
||||
'resource': key,
|
||||
'format': key.format,
|
||||
'shortKey': [
|
||||
@ -41,93 +78,140 @@ refstackApp.controller('profileController',
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
$scope.openImportPubKeyModal = function () {
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will open the modal that will give the user a form
|
||||
* for importing a public key.
|
||||
*/
|
||||
function openImportPubKeyModal() {
|
||||
$modal.open({
|
||||
templateUrl: '/components/profile/importPubKeyModal.html',
|
||||
backdrop: true,
|
||||
windowClass: 'modal',
|
||||
controller: 'importPubKeyModalController'
|
||||
controller: 'ImportPubKeyModalController as modal'
|
||||
}).result.finally(function() {
|
||||
$scope.updatePubKeys();
|
||||
ctrl.updatePubKeys();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
$scope.openShowPubKeyModal = function (pubKey) {
|
||||
/**
|
||||
* This function will open the modal that will give the full
|
||||
* information regarding a specific public key.
|
||||
* @param {Object} pubKey resource
|
||||
*/
|
||||
function openShowPubKeyModal(pubKey) {
|
||||
$modal.open({
|
||||
templateUrl: '/components/profile/showPubKeyModal.html',
|
||||
backdrop: true,
|
||||
windowClass: 'modal',
|
||||
controller: 'showPubKeyModalController',
|
||||
controller: 'ShowPubKeyModalController as modal',
|
||||
resolve: {
|
||||
pubKey: function() {
|
||||
return pubKey;
|
||||
}
|
||||
}
|
||||
}).result.finally(function() {
|
||||
$scope.updatePubKeys();
|
||||
ctrl.updatePubKeys();
|
||||
});
|
||||
};
|
||||
$scope.showRes = function(pubKey){
|
||||
raiseAlert('success', '', pubKey.pubkey);
|
||||
};
|
||||
$scope.authRequest = $scope.auth.doSignCheck()
|
||||
.then($scope.updatePubKeys);
|
||||
}
|
||||
]);
|
||||
|
||||
refstackApp.controller('importPubKeyModalController',
|
||||
['$scope', '$modalInstance', 'PubKeys', 'raiseAlert',
|
||||
function ($scope, $modalInstance, PubKeys, raiseAlert) {
|
||||
'use strict';
|
||||
$scope.importPubKey = function () {
|
||||
ctrl.authRequest = $scope.auth.doSignCheck().then(ctrl.updatePubKeys);
|
||||
}
|
||||
|
||||
angular
|
||||
.module('refstackApp')
|
||||
.controller('ImportPubKeyModalController', ImportPubKeyModalController);
|
||||
|
||||
ImportPubKeyModalController.$inject = [
|
||||
'$modalInstance', 'PubKeys', 'raiseAlert'
|
||||
];
|
||||
|
||||
/**
|
||||
* Import Pub Key Modal Controller
|
||||
* This controller is for the modal that appears if a user wants to import
|
||||
* a public key.
|
||||
*/
|
||||
function ImportPubKeyModalController($modalInstance, PubKeys, raiseAlert) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.importPubKey = importPubKey;
|
||||
ctrl.cancel = cancel;
|
||||
|
||||
/**
|
||||
* This function will save a new public key resource to the API server.
|
||||
*/
|
||||
function importPubKey() {
|
||||
var newPubKey = new PubKeys(
|
||||
{raw_key: $scope.raw_key,
|
||||
self_signature: $scope.self_signature}
|
||||
{raw_key: ctrl.raw_key, self_signature: ctrl.self_signature}
|
||||
);
|
||||
newPubKey.$save(function(newPubKey_){
|
||||
raiseAlert('success',
|
||||
'', 'Public key saved successfully');
|
||||
newPubKey.$save(
|
||||
function(newPubKey_) {
|
||||
raiseAlert('success', '', 'Public key saved successfully');
|
||||
$modalInstance.close(newPubKey_);
|
||||
},
|
||||
function(httpResp) {
|
||||
raiseAlert('danger',
|
||||
httpResp.statusText, httpResp.data.title);
|
||||
$scope.cancel();
|
||||
ctrl.cancel();
|
||||
}
|
||||
);
|
||||
};
|
||||
$scope.cancel = function () {
|
||||
$modalInstance.dismiss('cancel');
|
||||
};
|
||||
}
|
||||
]);
|
||||
|
||||
refstackApp.controller('showPubKeyModalController',
|
||||
['$scope', '$modalInstance', 'raiseAlert', 'pubKey',
|
||||
function ($scope, $modalInstance, raiseAlert, pubKey) {
|
||||
'use strict';
|
||||
$scope.pubKey = pubKey.resource;
|
||||
$scope.rawKey = [pubKey.format,
|
||||
pubKey.pubkey, pubKey.comment].join('\n');
|
||||
$scope.deletePubKey = function () {
|
||||
$scope.pubKey.$remove(
|
||||
{id: $scope.pubKey.id},
|
||||
/**
|
||||
* This function will dismiss the modal.
|
||||
*/
|
||||
function cancel() {
|
||||
$modalInstance.dismiss('cancel');
|
||||
}
|
||||
}
|
||||
|
||||
angular
|
||||
.module('refstackApp')
|
||||
.controller('ShowPubKeyModalController', ShowPubKeyModalController);
|
||||
|
||||
ShowPubKeyModalController.$inject = [
|
||||
'$modalInstance', 'raiseAlert', 'pubKey'
|
||||
];
|
||||
|
||||
/**
|
||||
* Show Pub Key Modal Controller
|
||||
* This controller is for the modal that appears if a user wants to see the
|
||||
* full details of one of their public keys.
|
||||
*/
|
||||
function ShowPubKeyModalController($modalInstance, raiseAlert, pubKey) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.deletePubKey = deletePubKey;
|
||||
ctrl.cancel = cancel;
|
||||
|
||||
ctrl.pubKey = pubKey.resource;
|
||||
ctrl.rawKey = [pubKey.format, pubKey.pubkey, pubKey.comment].join('\n');
|
||||
|
||||
/**
|
||||
* This function will delete a public key resource.
|
||||
*/
|
||||
function deletePubKey() {
|
||||
ctrl.pubKey.$remove(
|
||||
{id: ctrl.pubKey.id},
|
||||
function() {
|
||||
raiseAlert('success',
|
||||
'', 'Public key deleted successfully');
|
||||
$modalInstance.close($scope.pubKey.id);
|
||||
$modalInstance.close(ctrl.pubKey.id);
|
||||
},
|
||||
function(httpResp) {
|
||||
raiseAlert('danger',
|
||||
httpResp.statusText, httpResp.data.title);
|
||||
$scope.cancel();
|
||||
ctrl.cancel();
|
||||
}
|
||||
);
|
||||
};
|
||||
$scope.cancel = function () {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will dismiss the modal.
|
||||
*/
|
||||
function cancel() {
|
||||
$modalInstance.dismiss('cancel');
|
||||
};
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
})();
|
||||
|
@ -1,11 +1,11 @@
|
||||
<div class="modal-header">
|
||||
<h4>Public key</h4>
|
||||
<h4>Public Key</h4>
|
||||
</div>
|
||||
<div class="modal-body container-fluid">
|
||||
<textarea type="text" rows="10" cols="67" readonly="readonly">{{::rawKey}}</textarea>
|
||||
<textarea type="text" rows="10" cols="67" readonly="readonly">{{modal.rawKey}}</textarea>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
|
||||
<button type="button" class="btn btn-danger btn-sm" ng-click="deletePubKey() "
|
||||
<button class="btn btn-warning" ng-click="modal.cancel()">Cancel</button>
|
||||
<button type="button" class="btn btn-danger btn-sm" ng-click="modal.deletePubKey() "
|
||||
confirm="Are you sure you want to delete this public key? You will lose management access to any test results signed with this key.">Delete</button>
|
||||
</div>
|
||||
</div>
|
@ -1,13 +1,13 @@
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4>All Passed Tests ({{tests.length}})</h4>
|
||||
<h4>All Passed Tests ({{modal.tests.length}})</h4>
|
||||
</div>
|
||||
<div class="modal-body tests-modal-content">
|
||||
<div class="form-group">
|
||||
<textarea class="form-control" rows="20" id="tests" wrap="off">{{getTestListString()}}</textarea>
|
||||
<textarea class="form-control" rows="20" id="tests" wrap="off">{{modal.getTestListString()}}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary" type="button" ng-click="close()">Close</button>
|
||||
<button class="btn btn-primary" type="button" ng-click="modal.close()">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3,13 +3,13 @@ HTML for each accordion group that separates the status types on the results
|
||||
report page.
|
||||
-->
|
||||
|
||||
<accordion-group is-open="isOpen" is-disabled="caps[status].caps.length == 0">
|
||||
<accordion-group is-open="isOpen" is-disabled="ctrl.caps[status].caps.length == 0">
|
||||
<accordion-heading>
|
||||
{{status | capitalize}}
|
||||
<small>
|
||||
(<strong>Total:</strong> {{caps[status].caps.length}} capabilities, {{caps[status].count}} tests)
|
||||
<span ng-if="testStatus !== 'total'">
|
||||
(<strong>{{testStatus | capitalize}}:</strong> {{getStatusTestCount(status)}} tests)
|
||||
(<strong>Total:</strong> {{ctrl.caps[status].caps.length}} capabilities, {{ctrl.caps[status].count}} tests)
|
||||
<span ng-if="ctrl.testStatus !== 'total'">
|
||||
(<strong>{{ctrl.testStatus | capitalize}}:</strong> {{ctrl.getStatusTestCount(status)}} tests)
|
||||
</span>
|
||||
</small>
|
||||
<i class="pull-right glyphicon"
|
||||
@ -17,18 +17,18 @@ report page.
|
||||
</i>
|
||||
</accordion-heading>
|
||||
<ol class="capabilities">
|
||||
<li ng-repeat="capability in caps[status].caps | orderBy:'id'"
|
||||
ng-if="isCapabilityShown(capability)">
|
||||
<li ng-repeat="capability in ctrl.caps[status].caps | orderBy:'id'"
|
||||
ng-if="ctrl.isCapabilityShown(capability)">
|
||||
|
||||
<a ng-click="hideTests = !hideTests"
|
||||
title="{{capabilityData.capabilities[capability.id].description}}">
|
||||
<a ng-click="ctrl.hideTests = !ctrl.hideTests"
|
||||
title="{{ctrl.capabilityData.capabilities[capability.id].description}}">
|
||||
{{capability.id}}
|
||||
</a>
|
||||
<span ng-class="{'text-success': testStatus === 'passed',
|
||||
'text-danger': testStatus === 'not passed',
|
||||
'text-warning': testStatus === 'flagged'}"
|
||||
ng-if="testStatus !== 'total'">
|
||||
[{{getCapabilityTestCount(capability)}}]
|
||||
<span ng-class="{'text-success': ctrl.testStatus === 'passed',
|
||||
'text-danger': ctrl.testStatus === 'not passed',
|
||||
'text-warning': ctrl.testStatus === 'flagged'}"
|
||||
ng-if="ctrl.testStatus !== 'total'">
|
||||
[{{ctrl.getCapabilityTestCount(capability)}}]
|
||||
</span>
|
||||
<span ng-class="{'text-success': (capability.passedTests.length > 0 &&
|
||||
capability.notPassedTests.length == 0),
|
||||
@ -36,31 +36,31 @@ report page.
|
||||
capability.notPassedTests.length > 0),
|
||||
'text-warning': (capability.passedTests.length > 0 &&
|
||||
capability.notPassedTests.length > 0)}"
|
||||
ng-if="testStatus === 'total'">
|
||||
ng-if="ctrl.testStatus === 'total'">
|
||||
[{{capability.passedTests.length}}/{{capability.passedTests.length +
|
||||
capability.notPassedTests.length}}]
|
||||
</span>
|
||||
|
||||
<ul class="list-unstyled" collapse="hideTests">
|
||||
<ul class="list-unstyled" collapse="ctrl.hideTests">
|
||||
<li ng-repeat="test in capability.passedTests | orderBy:'toString()'"
|
||||
ng-if="isTestShown(test, capability)">
|
||||
ng-if="ctrl.isTestShown(test, capability)">
|
||||
|
||||
<span class="glyphicon glyphicon-ok text-success"
|
||||
aria-hidden="true">
|
||||
</span>
|
||||
<span ng-class="{'glyphicon glyphicon-flag text-warning':
|
||||
isTestFlagged(test, capabilityData.capabilities[capability.id])}"
|
||||
title="{{getFlaggedReason(test, capabilityData.capabilities[capability.id])}}">
|
||||
ctrl.isTestFlagged(test, ctrl.capabilityData.capabilities[capability.id])}"
|
||||
title="{{ctrl.getFlaggedReason(test, ctrl.capabilityData.capabilities[capability.id])}}">
|
||||
</span>
|
||||
{{test}}
|
||||
</li>
|
||||
<li ng-repeat="test in capability.notPassedTests | orderBy:'toString()'"
|
||||
ng-if="isTestShown(test, capability)">
|
||||
ng-if="ctrl.isTestShown(test, capability)">
|
||||
|
||||
<span class="glyphicon glyphicon-remove text-danger" aria-hidden="true"></span>
|
||||
<span ng-class="{'glyphicon glyphicon-flag text-warning':
|
||||
isTestFlagged(test, capabilityData.capabilities[capability.id])}"
|
||||
title="{{getFlaggedReason(test, capabilityData.capabilities[capability.id])}}">
|
||||
ctrl.isTestFlagged(test, ctrl.capabilityData.capabilities[capability.id])}"
|
||||
title="{{ctrl.getFlaggedReason(test, ctrl.capabilityData.capabilities[capability.id])}}">
|
||||
</span>
|
||||
{{test}}
|
||||
</li>
|
||||
|
@ -1,31 +1,31 @@
|
||||
<h3>Test Run Results</h3>
|
||||
|
||||
<div ng-show="resultsData" class="container-fluid">
|
||||
<div ng-show="ctrl.resultsData" class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="pull-left">
|
||||
<div class="test-report">
|
||||
<strong>Test ID:</strong> {{testId}}<br />
|
||||
<div ng-if="isEditingAllowed()"><strong>Cloud ID:</strong> {{resultsData.cpid}}<br /></div>
|
||||
<strong>Upload Date:</strong> {{resultsData.created_at}} UTC<br />
|
||||
<strong>Duration:</strong> {{resultsData.duration_seconds}} seconds<br />
|
||||
<strong>Test ID:</strong> {{ctrl.testId}}<br />
|
||||
<div ng-if="ctrl.isEditingAllowed()"><strong>Cloud ID:</strong> {{ctrl.resultsData.cpid}}<br /></div>
|
||||
<strong>Upload Date:</strong> {{ctrl.resultsData.created_at}} UTC<br />
|
||||
<strong>Duration:</strong> {{ctrl.resultsData.duration_seconds}} seconds<br />
|
||||
<strong>Total Number of Passed Tests:</strong>
|
||||
<a title="See all passed tests" ng-click="openFullTestListModal()">
|
||||
{{resultsData.results.length}}
|
||||
<a title="See all passed tests" ng-click="ctrl.openFullTestListModal()">
|
||||
{{ctrl.resultsData.results.length}}
|
||||
</a><br />
|
||||
<hr>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pull-right">
|
||||
<div ng-show="isEditingAllowed()">
|
||||
<button class="btn btn-warning" ng-hide="isShared()" ng-click="shareTestRun(true)" confirm="Are you sure you want to share these test run results with the community?">Share</button>
|
||||
<button class="btn btn-success" ng-show="isShared()" ng-click="shareTestRun(false)">Unshare</button>
|
||||
<button type="button" class="btn btn-danger" ng-click="deleteTestRun()" confirm="Are you sure you want to delete these test run results?">Delete</button>
|
||||
<div ng-show="ctrl.isEditingAllowed()">
|
||||
<button class="btn btn-warning" ng-hide="ctrl.isShared()" ng-click="ctrl.shareTestRun(true)" confirm="Are you sure you want to share these test run results with the community?">Share</button>
|
||||
<button class="btn btn-success" ng-show="ctrl.isShared()" ng-click="ctrl.shareTestRun(false)">Unshare</button>
|
||||
<button type="button" class="btn btn-danger" ng-click="ctrl.deleteTestRun()" confirm="Are you sure you want to delete these test run results?">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-show="resultsData">
|
||||
<div ng-show="ctrl.resultsData">
|
||||
<p>See how these results stack up against DefCore capabilities and OpenStack
|
||||
<a target="_blank" href="http://www.openstack.org/brand/interop/">target marketing programs.</a>
|
||||
</p>
|
||||
@ -34,14 +34,14 @@
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<strong>Capabilities Version:</strong>
|
||||
<select ng-model="version" ng-change="updateCapabilities()" class="form-control">
|
||||
<select ng-model="ctrl.version" ng-change="ctrl.updateCapabilities()" class="form-control">
|
||||
<!-- Slicing the version file name here gets rid of the '.json' file extension -->
|
||||
<option ng-repeat="versionFile in versionList" value="{{versionFile}}">{{versionFile.slice(0, -5)}}</option>
|
||||
<option ng-repeat="versionFile in ctrl.versionList" value="{{versionFile}}">{{versionFile.slice(0, -5)}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<strong>Target Program:</strong>
|
||||
<select ng-model="target" class="form-control" ng-change="buildCapabilitiesObject()">
|
||||
<select ng-model="ctrl.target" class="form-control" ng-change="ctrl.buildCapabilitiesObject()">
|
||||
<option value="platform">OpenStack Powered Platform</option>
|
||||
<option value="compute">OpenStack Powered Compute</option>
|
||||
<option value="object">OpenStack Powered Object Storage</option>
|
||||
@ -53,28 +53,28 @@
|
||||
<br />
|
||||
<strong>Corresponding OpenStack Releases:</strong>
|
||||
<ul class="list-inline">
|
||||
<li ng-repeat="release in capabilityData.releases">
|
||||
<li ng-repeat="release in ctrl.capabilityData.releases">
|
||||
{{release | capitalize}}
|
||||
</li>
|
||||
</ul>
|
||||
<hr >
|
||||
|
||||
<div ng-show="capabilityData">
|
||||
<div ng-show="ctrl.capabilityData">
|
||||
<strong>Status:</strong>
|
||||
<p>This cloud passes <strong>{{requiredPassPercent | number:1}}% </strong>
|
||||
({{caps.required.passedCount}}/{{caps.required.count}})
|
||||
of the tests in the <strong>{{version.slice(0, -5)}}</strong> <em>required</em> capabilities for the
|
||||
<strong>{{targetMappings[target]}}</strong> program. <br />
|
||||
<p>This cloud passes <strong>{{ctrl.requiredPassPercent | number:1}}% </strong>
|
||||
({{ctrl.caps.required.passedCount}}/{{ctrl.caps.required.count}})
|
||||
of the tests in the <strong>{{ctrl.version.slice(0, -5)}}</strong> <em>required</em> capabilities for the
|
||||
<strong>{{ctrl.targetMappings[target]}}</strong> program. <br />
|
||||
Excluding flagged tests, this cloud passes
|
||||
<strong>{{nonFlagRequiredPassPercent | number:1}}%</strong>
|
||||
({{nonFlagPassCount}}/{{totalNonFlagCount}})
|
||||
<strong>{{ctrl.nonFlagRequiredPassPercent | number:1}}%</strong>
|
||||
({{ctrl.nonFlagPassCount}}/{{ctrl.totalNonFlagCount}})
|
||||
of the <em>required</em> tests.
|
||||
</p>
|
||||
|
||||
<p>Compliance with <strong>{{version.slice(0, -5)}}</strong>:
|
||||
<p>Compliance with <strong>{{ctrl.version.slice(0, -5)}}</strong>:
|
||||
<strong>
|
||||
<span ng-if="nonFlagPassCount === totalNonFlagCount" class="yes">YES</span>
|
||||
<span ng-if="nonFlagPassCount !== totalNonFlagCount" class="no">NO</span>
|
||||
<span ng-if="ctrl.nonFlagPassCount === ctrl.totalNonFlagCount" class="yes">YES</span>
|
||||
<span ng-if="ctrl.nonFlagPassCount !== ctrl.totalNonFlagCount" class="no">NO</span>
|
||||
</strong>
|
||||
</p>
|
||||
|
||||
@ -83,20 +83,20 @@
|
||||
|
||||
Test Filters:<br />
|
||||
<div class="btn-group button-margin" data-toggle="buttons">
|
||||
<label class="btn btn-default" ng-class="{'active': testStatus === 'total'}">
|
||||
<input type="radio" ng-model="testStatus" value="total">
|
||||
<label class="btn btn-default" ng-class="{'active': ctrl.testStatus === 'total'}">
|
||||
<input type="radio" ng-model="ctrl.testStatus" value="total">
|
||||
<span class="text-primary">All</span>
|
||||
</label>
|
||||
<label class="btn btn-default" ng-class="{'active': testStatus === 'passed'}">
|
||||
<input type="radio" ng-model="testStatus" value="passed">
|
||||
<label class="btn btn-default" ng-class="{'active': ctrl.testStatus === 'passed'}">
|
||||
<input type="radio" ng-model="ctrl.testStatus" value="passed">
|
||||
<span class="text-success">Passed</span>
|
||||
</label>
|
||||
<label class="btn btn-default" ng-class="{'active': testStatus === 'not passed'}">
|
||||
<input type="radio" ng-model="testStatus" value="not passed">
|
||||
<label class="btn btn-default" ng-class="{'active': ctrl.testStatus === 'not passed'}">
|
||||
<input type="radio" ng-model="ctrl.testStatus" value="not passed">
|
||||
<span class="text-danger">Not Passed</span>
|
||||
</label>
|
||||
<label class="btn btn-default" ng-class="{'active': testStatus === 'flagged'}">
|
||||
<input type="radio" ng-model="testStatus" value="flagged">
|
||||
<label class="btn btn-default" ng-class="{'active': ctrl.testStatus === 'flagged'}">
|
||||
<input type="radio" ng-model="ctrl.testStatus" value="flagged">
|
||||
<span class="text-warning">Flagged</span>
|
||||
</label>
|
||||
</div>
|
||||
@ -105,23 +105,23 @@
|
||||
<!-- The ng-repeat is used to pass in a local variable to the template. -->
|
||||
<ng-include
|
||||
ng-repeat="status in ['required']"
|
||||
src="detailsTemplate"
|
||||
src="ctrl.detailsTemplate"
|
||||
onload="isOpen = true">
|
||||
</ng-include>
|
||||
<br />
|
||||
<ng-include
|
||||
ng-repeat="status in ['advisory']"
|
||||
src="detailsTemplate">
|
||||
src="ctrl.detailsTemplate">
|
||||
</ng-include>
|
||||
<br />
|
||||
<ng-include
|
||||
ng-repeat="status in ['deprecated']"
|
||||
src="detailsTemplate">
|
||||
src="ctrl.detailsTemplate">
|
||||
</ng-include>
|
||||
<br />
|
||||
<ng-include
|
||||
ng-repeat="status in ['removed']"
|
||||
src="detailsTemplate">
|
||||
src="ctrl.detailsTemplate">
|
||||
</ng-include>
|
||||
</accordion>
|
||||
</div>
|
||||
|
@ -1,41 +1,82 @@
|
||||
var refstackApp = angular.module('refstackApp');
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('refstackApp')
|
||||
.controller('ResultsReportController', ResultsReportController);
|
||||
|
||||
ResultsReportController.$inject = [
|
||||
'$http', '$stateParams', '$window',
|
||||
'$modal', 'refstackApiUrl', 'raiseAlert'
|
||||
];
|
||||
|
||||
/**
|
||||
* Refstack Results Report Controller
|
||||
* RefStack Results Report Controller
|
||||
* This controller is for the '/results/<test run ID>' page where a user can
|
||||
* view details for a specific test run.
|
||||
*/
|
||||
refstackApp.controller('resultsReportController',
|
||||
['$scope', '$http', '$stateParams',
|
||||
'$window', '$modal', 'refstackApiUrl', 'raiseAlert',
|
||||
function ($scope, $http, $stateParams, $window, $modal,
|
||||
refstackApiUrl, raiseAlert) {
|
||||
'use strict';
|
||||
function ResultsReportController($http, $stateParams, $window,
|
||||
$modal, refstackApiUrl, raiseAlert) {
|
||||
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.getVersionList = getVersionList;
|
||||
ctrl.getResults = getResults;
|
||||
ctrl.isEditingAllowed = isEditingAllowed;
|
||||
ctrl.isShared = isShared;
|
||||
ctrl.shareTestRun = shareTestRun;
|
||||
ctrl.deleteTestRun = deleteTestRun;
|
||||
ctrl.updateCapabilities = updateCapabilities;
|
||||
ctrl.getTargetCapabilities = getTargetCapabilities;
|
||||
ctrl.buildCapabilityV1_2 = buildCapabilityV1_2;
|
||||
ctrl.buildCapabilityV1_3 = buildCapabilityV1_3;
|
||||
ctrl.buildCapabilitiesObject = buildCapabilitiesObject;
|
||||
ctrl.isTestFlagged = isTestFlagged;
|
||||
ctrl.getFlaggedReason = getFlaggedReason;
|
||||
ctrl.isCapabilityShown = isCapabilityShown;
|
||||
ctrl.isTestShown = isTestShown;
|
||||
ctrl.getCapabilityTestCount = getCapabilityTestCount;
|
||||
ctrl.getStatusTestCount = getStatusTestCount;
|
||||
ctrl.openFullTestListModal = openFullTestListModal;
|
||||
|
||||
/** The testID extracted from the URL route. */
|
||||
$scope.testId = $stateParams.testID;
|
||||
ctrl.testId = $stateParams.testID;
|
||||
|
||||
/** Whether to hide tests on start.*/
|
||||
$scope.hideTests = true;
|
||||
ctrl.hideTests = true;
|
||||
|
||||
/** The target OpenStack marketing program to compare against. */
|
||||
$scope.target = 'platform';
|
||||
ctrl.target = 'platform';
|
||||
|
||||
/** Mappings of DefCore components to marketing program names. */
|
||||
$scope.targetMappings = {
|
||||
ctrl.targetMappings = {
|
||||
'platform': 'Openstack Powered Platform',
|
||||
'compute': 'OpenStack Powered Compute',
|
||||
'object': 'OpenStack Powered Object Storage'
|
||||
};
|
||||
|
||||
/** The schema version of the currently selected capabilities data. */
|
||||
$scope.schemaVersion = null;
|
||||
ctrl.schemaVersion = null;
|
||||
|
||||
/** The selected test status used for test filtering. */
|
||||
$scope.testStatus = 'total';
|
||||
ctrl.testStatus = 'total';
|
||||
|
||||
/** The HTML template that all accordian groups will use. */
|
||||
$scope.detailsTemplate = 'components/results-report/partials/' +
|
||||
ctrl.detailsTemplate = 'components/results-report/partials/' +
|
||||
'reportDetails.html';
|
||||
|
||||
/**
|
||||
@ -46,19 +87,19 @@ refstackApp.controller('resultsReportController',
|
||||
* call, the function to update the capabilities is called.
|
||||
* Sample API return array: ["2015.03.json", "2015.04.json"]
|
||||
*/
|
||||
var getVersionList = function () {
|
||||
function getVersionList() {
|
||||
var content_url = refstackApiUrl + '/capabilities';
|
||||
$scope.versionsRequest =
|
||||
ctrl.versionsRequest =
|
||||
$http.get(content_url).success(function (data) {
|
||||
$scope.versionList = data.sort().reverse();
|
||||
$scope.version = $scope.versionList[0];
|
||||
$scope.updateCapabilities();
|
||||
ctrl.versionList = data.sort().reverse();
|
||||
ctrl.version = ctrl.versionList[0];
|
||||
ctrl.updateCapabilities();
|
||||
}).error(function (error) {
|
||||
$scope.showError = true;
|
||||
$scope.error = 'Error retrieving version list: ' +
|
||||
JSON.stringify(error);
|
||||
ctrl.showError = true;
|
||||
ctrl.error = 'Error retrieving version list: ' +
|
||||
angular.toJson(error);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve results from the Refstack API server based on the test
|
||||
@ -66,68 +107,82 @@ refstackApp.controller('resultsReportController',
|
||||
* be called from the controller. Upon successful retrieval of results,
|
||||
* the function that gets the version list will be called.
|
||||
*/
|
||||
var getResults = function () {
|
||||
var content_url = refstackApiUrl + '/results/' + $scope.testId;
|
||||
$scope.resultsRequest =
|
||||
function getResults() {
|
||||
var content_url = refstackApiUrl + '/results/' + ctrl.testId;
|
||||
ctrl.resultsRequest =
|
||||
$http.get(content_url).success(function (data) {
|
||||
$scope.resultsData = data;
|
||||
ctrl.resultsData = data;
|
||||
getVersionList();
|
||||
}).error(function (error) {
|
||||
$scope.showError = true;
|
||||
$scope.resultsData = null;
|
||||
$scope.error = 'Error retrieving results from server: ' +
|
||||
JSON.stringify(error);
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
$scope.isEditingAllowed = function () {
|
||||
return Boolean($scope.resultsData &&
|
||||
$scope.resultsData.user_role === 'owner');
|
||||
};
|
||||
|
||||
$scope.isShared = function () {
|
||||
return Boolean($scope.resultsData &&
|
||||
'shared' in $scope.resultsData.meta);
|
||||
};
|
||||
|
||||
$scope.shareTestRun = function (shareState) {
|
||||
var content_url = [
|
||||
refstackApiUrl, '/results/', $scope.testId, '/meta/shared'
|
||||
].join('');
|
||||
if (shareState) {
|
||||
$scope.shareRequest =
|
||||
$http.post(content_url, 'true').success(function () {
|
||||
$scope.resultsData.meta.shared = 'true';
|
||||
raiseAlert('success', '', 'Test run shared!');
|
||||
}).error(function (error) {
|
||||
raiseAlert('danger',
|
||||
error.title, error.detail);
|
||||
});
|
||||
} else {
|
||||
$scope.shareRequest =
|
||||
$http.delete(content_url).success(function () {
|
||||
delete $scope.resultsData.meta.shared;
|
||||
raiseAlert('success', '', 'Test run unshared!');
|
||||
}).error(function (error) {
|
||||
raiseAlert('danger',
|
||||
error.title, error.detail);
|
||||
ctrl.showError = true;
|
||||
ctrl.resultsData = null;
|
||||
ctrl.error = 'Error retrieving results from server: ' +
|
||||
angular.toJson(error);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.deleteTestRun = function () {
|
||||
/**
|
||||
* This tells you whether the current results can be edited/managed
|
||||
* based on if the current user is the owner of the results set.
|
||||
* @returns {Boolean} true if editing is allowed
|
||||
*/
|
||||
function isEditingAllowed() {
|
||||
return Boolean(ctrl.resultsData &&
|
||||
ctrl.resultsData.user_role === 'owner');
|
||||
}
|
||||
/**
|
||||
* This tells you whether the current results are shared with the
|
||||
* community or not.
|
||||
* @returns {Boolean} true if the results are shared
|
||||
*/
|
||||
function isShared() {
|
||||
return Boolean(ctrl.resultsData &&
|
||||
'shared' in ctrl.resultsData.meta);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will send an API request in order to share or unshare the
|
||||
* current results based on the passed in shareState.
|
||||
* @param {Boolean} shareState - Whether to share or unshare results.
|
||||
*/
|
||||
function shareTestRun(shareState) {
|
||||
var content_url = [
|
||||
refstackApiUrl, '/results/', $scope.testId
|
||||
refstackApiUrl, '/results/', ctrl.testId, '/meta/shared'
|
||||
].join('');
|
||||
$scope.deleteRequest =
|
||||
if (shareState) {
|
||||
ctrl.shareRequest =
|
||||
$http.post(content_url, 'true').success(function () {
|
||||
ctrl.resultsData.meta.shared = 'true';
|
||||
raiseAlert('success', '', 'Test run shared!');
|
||||
}).error(function (error) {
|
||||
raiseAlert('danger', error.title, error.detail);
|
||||
});
|
||||
} else {
|
||||
ctrl.shareRequest =
|
||||
$http.delete(content_url).success(function () {
|
||||
delete ctrl.resultsData.meta.shared;
|
||||
raiseAlert('success', '', 'Test run unshared!');
|
||||
}).error(function (error) {
|
||||
raiseAlert('danger', error.title, error.detail);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This will send a request to the API to delete the current
|
||||
* test results set.
|
||||
*/
|
||||
function deleteTestRun() {
|
||||
var content_url = [
|
||||
refstackApiUrl, '/results/', ctrl.testId
|
||||
].join('');
|
||||
ctrl.deleteRequest =
|
||||
$http.delete(content_url).success(function () {
|
||||
$window.history.back();
|
||||
}).error(function (error) {
|
||||
raiseAlert('danger',
|
||||
error.title, error.detail);
|
||||
raiseAlert('danger', error.title, error.detail);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This will contact the Refstack API server to retrieve the JSON
|
||||
@ -135,39 +190,39 @@ refstackApp.controller('resultsReportController',
|
||||
* version. A function to construct an object from the capability
|
||||
* date will be called upon successful retrieval.
|
||||
*/
|
||||
$scope.updateCapabilities = function () {
|
||||
$scope.capabilityData = null;
|
||||
$scope.showError = false;
|
||||
function updateCapabilities() {
|
||||
ctrl.capabilityData = null;
|
||||
ctrl.showError = false;
|
||||
var content_url = refstackApiUrl + '/capabilities/' +
|
||||
$scope.version;
|
||||
$scope.capsRequest =
|
||||
ctrl.version;
|
||||
ctrl.capsRequest =
|
||||
$http.get(content_url).success(function (data) {
|
||||
$scope.capabilityData = data;
|
||||
$scope.schemaVersion = data.schema;
|
||||
$scope.buildCapabilitiesObject();
|
||||
ctrl.capabilityData = data;
|
||||
ctrl.schemaVersion = data.schema;
|
||||
ctrl.buildCapabilitiesObject();
|
||||
}).error(function (error) {
|
||||
$scope.showError = true;
|
||||
$scope.capabilityData = null;
|
||||
$scope.error = 'Error retrieving capabilities: ' +
|
||||
JSON.stringify(error);
|
||||
ctrl.showError = true;
|
||||
ctrl.capabilityData = null;
|
||||
ctrl.error = 'Error retrieving capabilities: ' +
|
||||
angular.toJson(error);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This will get all the capabilities relevant to the target and
|
||||
* their corresponding statuses.
|
||||
* @returns {Object} Object containing each capability and their status
|
||||
*/
|
||||
$scope.getTargetCapabilities = function () {
|
||||
var components = $scope.capabilityData.components;
|
||||
function getTargetCapabilities() {
|
||||
var components = ctrl.capabilityData.components;
|
||||
var targetCaps = {};
|
||||
|
||||
// The 'platform' target is comprised of multiple components, so
|
||||
// we need to get the capabilities belonging to each of its
|
||||
// components.
|
||||
if ($scope.target === 'platform') {
|
||||
if (ctrl.target === 'platform') {
|
||||
var platform_components =
|
||||
$scope.capabilityData.platform.required;
|
||||
ctrl.capabilityData.platform.required;
|
||||
|
||||
// This will contain status priority values, where lower
|
||||
// values mean higher priorities.
|
||||
@ -203,7 +258,7 @@ refstackApp.controller('resultsReportController',
|
||||
});
|
||||
}
|
||||
else {
|
||||
angular.forEach(components[$scope.target],
|
||||
angular.forEach(components[ctrl.target],
|
||||
function (caps, status) {
|
||||
angular.forEach(caps, function(cap) {
|
||||
targetCaps[cap] = status;
|
||||
@ -211,7 +266,7 @@ refstackApp.controller('resultsReportController',
|
||||
});
|
||||
}
|
||||
return targetCaps;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This will build the a capability object for schema version 1.2.
|
||||
@ -219,7 +274,7 @@ refstackApp.controller('resultsReportController',
|
||||
* the HTML template.
|
||||
* @param {String} capId capability ID
|
||||
*/
|
||||
$scope.buildCapabilityV1_2 = function (capId) {
|
||||
function buildCapabilityV1_2(capId) {
|
||||
var cap = {
|
||||
'id': capId,
|
||||
'passedTests': [],
|
||||
@ -227,13 +282,13 @@ refstackApp.controller('resultsReportController',
|
||||
'passedFlagged': [],
|
||||
'notPassedFlagged': []
|
||||
};
|
||||
var capDetails = $scope.capabilityData.capabilities[capId];
|
||||
var capDetails = ctrl.capabilityData.capabilities[capId];
|
||||
// Loop through each test belonging to the capability.
|
||||
angular.forEach(capDetails.tests,
|
||||
function (testId) {
|
||||
// If the test ID is in the results' test list, add
|
||||
// it to the passedTests array.
|
||||
if ($scope.resultsData.results.indexOf(testId) > -1) {
|
||||
if (ctrl.resultsData.results.indexOf(testId) > -1) {
|
||||
cap.passedTests.push(testId);
|
||||
if (capDetails.flagged.indexOf(testId) > -1) {
|
||||
cap.passedFlagged.push(testId);
|
||||
@ -247,7 +302,7 @@ refstackApp.controller('resultsReportController',
|
||||
}
|
||||
});
|
||||
return cap;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This will build the a capability object for schema version 1.3.
|
||||
@ -255,7 +310,7 @@ refstackApp.controller('resultsReportController',
|
||||
* the HTML template.
|
||||
* @param {String} capId capability ID
|
||||
*/
|
||||
$scope.buildCapabilityV1_3 = function (capId) {
|
||||
function buildCapabilityV1_3(capId) {
|
||||
var cap = {
|
||||
'id': capId,
|
||||
'passedTests': [],
|
||||
@ -264,11 +319,11 @@ refstackApp.controller('resultsReportController',
|
||||
'notPassedFlagged': []
|
||||
};
|
||||
// Loop through each test belonging to the capability.
|
||||
angular.forEach($scope.capabilityData.capabilities[capId].tests,
|
||||
angular.forEach(ctrl.capabilityData.capabilities[capId].tests,
|
||||
function (details, testId) {
|
||||
// If the test ID is in the results' test list, add
|
||||
// it to the passedTests array.
|
||||
if ($scope.resultsData.results.indexOf(testId) > -1) {
|
||||
if (ctrl.resultsData.results.indexOf(testId) > -1) {
|
||||
cap.passedTests.push(testId);
|
||||
if ('flagged' in details) {
|
||||
cap.passedFlagged.push(testId);
|
||||
@ -282,19 +337,19 @@ refstackApp.controller('resultsReportController',
|
||||
}
|
||||
});
|
||||
return cap;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This will check the schema version of the current capabilities file,
|
||||
* and will call the correct method to build an object based on the
|
||||
* capability data retrieved from the Refstack API server.
|
||||
*/
|
||||
$scope.buildCapabilitiesObject = function () {
|
||||
function buildCapabilitiesObject() {
|
||||
// This is the object template where 'count' is the number of
|
||||
// total tests that fall under the given status, and 'passedCount'
|
||||
// is the number of tests passed. The 'caps' array will contain
|
||||
// objects with details regarding each capability.
|
||||
$scope.caps = {
|
||||
ctrl.caps = {
|
||||
'required': {'caps': [], 'count': 0, 'passedCount': 0,
|
||||
'flagFailCount': 0, 'flagPassCount': 0},
|
||||
'advisory': {'caps': [], 'count': 0, 'passedCount': 0,
|
||||
@ -305,7 +360,7 @@ refstackApp.controller('resultsReportController',
|
||||
'flagFailCount': 0, 'flagPassCount': 0}
|
||||
};
|
||||
|
||||
switch ($scope.schemaVersion) {
|
||||
switch (ctrl.schemaVersion) {
|
||||
case '1.2':
|
||||
var capMethod = 'buildCapabilityV1_2';
|
||||
break;
|
||||
@ -313,45 +368,45 @@ refstackApp.controller('resultsReportController',
|
||||
capMethod = 'buildCapabilityV1_3';
|
||||
break;
|
||||
default:
|
||||
$scope.showError = true;
|
||||
$scope.capabilityData = null;
|
||||
$scope.error = 'The schema version for the capabilities ' +
|
||||
'file selected (' + $scope.schemaVersion +
|
||||
ctrl.showError = true;
|
||||
ctrl.capabilityData = null;
|
||||
ctrl.error = 'The schema version for the capabilities ' +
|
||||
'file selected (' + ctrl.schemaVersion +
|
||||
') is currently not supported.';
|
||||
return;
|
||||
}
|
||||
|
||||
// Get test details for each relevant capability and store
|
||||
// them in the scope's 'caps' object.
|
||||
var targetCaps = $scope.getTargetCapabilities();
|
||||
var targetCaps = ctrl.getTargetCapabilities();
|
||||
angular.forEach(targetCaps, function(status, capId) {
|
||||
var cap = $scope[capMethod](capId);
|
||||
$scope.caps[status].count +=
|
||||
var cap = ctrl[capMethod](capId);
|
||||
ctrl.caps[status].count +=
|
||||
cap.passedTests.length + cap.notPassedTests.length;
|
||||
$scope.caps[status].passedCount += cap.passedTests.length;
|
||||
$scope.caps[status].flagPassCount += cap.passedFlagged.length;
|
||||
$scope.caps[status].flagFailCount +=
|
||||
ctrl.caps[status].passedCount += cap.passedTests.length;
|
||||
ctrl.caps[status].flagPassCount += cap.passedFlagged.length;
|
||||
ctrl.caps[status].flagFailCount +=
|
||||
cap.notPassedFlagged.length;
|
||||
$scope.caps[status].caps.push(cap);
|
||||
ctrl.caps[status].caps.push(cap);
|
||||
});
|
||||
|
||||
$scope.requiredPassPercent = ($scope.caps.required.passedCount *
|
||||
100 / $scope.caps.required.count);
|
||||
ctrl.requiredPassPercent = (ctrl.caps.required.passedCount *
|
||||
100 / ctrl.caps.required.count);
|
||||
|
||||
$scope.totalRequiredFailCount = $scope.caps.required.count -
|
||||
$scope.caps.required.passedCount;
|
||||
$scope.totalRequiredFlagCount =
|
||||
$scope.caps.required.flagFailCount +
|
||||
$scope.caps.required.flagPassCount;
|
||||
$scope.totalNonFlagCount = $scope.caps.required.count -
|
||||
$scope.totalRequiredFlagCount;
|
||||
$scope.nonFlagPassCount = $scope.totalNonFlagCount -
|
||||
($scope.totalRequiredFailCount -
|
||||
$scope.caps.required.flagFailCount);
|
||||
ctrl.totalRequiredFailCount = ctrl.caps.required.count -
|
||||
ctrl.caps.required.passedCount;
|
||||
ctrl.totalRequiredFlagCount =
|
||||
ctrl.caps.required.flagFailCount +
|
||||
ctrl.caps.required.flagPassCount;
|
||||
ctrl.totalNonFlagCount = ctrl.caps.required.count -
|
||||
ctrl.totalRequiredFlagCount;
|
||||
ctrl.nonFlagPassCount = ctrl.totalNonFlagCount -
|
||||
(ctrl.totalRequiredFailCount -
|
||||
ctrl.caps.required.flagFailCount);
|
||||
|
||||
$scope.nonFlagRequiredPassPercent = ($scope.nonFlagPassCount *
|
||||
100 / $scope.totalNonFlagCount);
|
||||
};
|
||||
ctrl.nonFlagRequiredPassPercent = (ctrl.nonFlagPassCount *
|
||||
100 / ctrl.totalNonFlagCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will check if a given test is flagged.
|
||||
@ -359,15 +414,15 @@ refstackApp.controller('resultsReportController',
|
||||
* @param {Object} capObj capability that test is under
|
||||
* @returns {Boolean} truthy value if test is flagged
|
||||
*/
|
||||
$scope.isTestFlagged = function (test, capObj) {
|
||||
function isTestFlagged(test, capObj) {
|
||||
if (!capObj) {
|
||||
return false;
|
||||
}
|
||||
return ((($scope.schemaVersion === '1.2') &&
|
||||
return (((ctrl.schemaVersion === '1.2') &&
|
||||
(capObj.flagged.indexOf(test) > -1)) ||
|
||||
(($scope.schemaVersion === '1.3') &&
|
||||
((ctrl.schemaVersion === '1.3') &&
|
||||
(capObj.tests[test].flagged)));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This will return the reason a test is flagged. An empty string
|
||||
@ -376,23 +431,23 @@ refstackApp.controller('resultsReportController',
|
||||
* @param {String} capObj capability that test is under
|
||||
* @returns {String} reason
|
||||
*/
|
||||
$scope.getFlaggedReason = function (test, capObj) {
|
||||
if (($scope.schemaVersion === '1.2') &&
|
||||
($scope.isTestFlagged(test, capObj))){
|
||||
function getFlaggedReason(test, capObj) {
|
||||
if ((ctrl.schemaVersion === '1.2') &&
|
||||
(ctrl.isTestFlagged(test, capObj))) {
|
||||
|
||||
// Return a generic message since schema 1.2 does not
|
||||
// provide flag reasons.
|
||||
return 'DefCore has flagged this test.';
|
||||
}
|
||||
else if (($scope.schemaVersion === '1.3') &&
|
||||
($scope.isTestFlagged(test, capObj))){
|
||||
else if ((ctrl.schemaVersion === '1.3') &&
|
||||
(ctrl.isTestFlagged(test, capObj))) {
|
||||
|
||||
return capObj.tests[test].flagged.reason;
|
||||
}
|
||||
else {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This will check the if a capability should be shown based on the
|
||||
@ -401,16 +456,16 @@ refstackApp.controller('resultsReportController',
|
||||
* @param {Object} capability Built object for capability
|
||||
* @returns {Boolean} true if capability should be shown
|
||||
*/
|
||||
$scope.isCapabilityShown = function (capability) {
|
||||
return (($scope.testStatus === 'total') ||
|
||||
($scope.testStatus === 'passed' &&
|
||||
function isCapabilityShown(capability) {
|
||||
return ((ctrl.testStatus === 'total') ||
|
||||
(ctrl.testStatus === 'passed' &&
|
||||
capability.passedTests.length > 0) ||
|
||||
($scope.testStatus === 'not passed' &&
|
||||
(ctrl.testStatus === 'not passed' &&
|
||||
capability.notPassedTests.length > 0) ||
|
||||
($scope.testStatus === 'flagged' &&
|
||||
(ctrl.testStatus === 'flagged' &&
|
||||
(capability.passedFlagged.length +
|
||||
capability.notPassedFlagged.length > 0)));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This will check the if a test should be shown based on the test
|
||||
@ -419,16 +474,16 @@ refstackApp.controller('resultsReportController',
|
||||
* @param {Object} capability Built object for capability
|
||||
* @return {Boolean} true if test should be shown
|
||||
*/
|
||||
$scope.isTestShown = function (test, capability) {
|
||||
return (($scope.testStatus === 'total') ||
|
||||
($scope.testStatus === 'passed' &&
|
||||
function isTestShown(test, capability) {
|
||||
return ((ctrl.testStatus === 'total') ||
|
||||
(ctrl.testStatus === 'passed' &&
|
||||
capability.passedTests.indexOf(test) > -1) ||
|
||||
($scope.testStatus === 'not passed' &&
|
||||
(ctrl.testStatus === 'not passed' &&
|
||||
capability.notPassedTests.indexOf(test) > -1) ||
|
||||
($scope.testStatus === 'flagged' &&
|
||||
(ctrl.testStatus === 'flagged' &&
|
||||
(capability.passedFlagged.indexOf(test) > -1 ||
|
||||
capability.notPassedFlagged.indexOf(test) > -1)));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This will give the number of tests belonging under the selected
|
||||
@ -436,25 +491,25 @@ refstackApp.controller('resultsReportController',
|
||||
* @param {Object} capability Built object for capability
|
||||
* @returns {Number} number of tests under filter
|
||||
*/
|
||||
$scope.getCapabilityTestCount = function (capability) {
|
||||
if ($scope.testStatus === 'total') {
|
||||
function getCapabilityTestCount(capability) {
|
||||
if (ctrl.testStatus === 'total') {
|
||||
return capability.passedTests.length +
|
||||
capability.notPassedTests.length;
|
||||
}
|
||||
else if ($scope.testStatus === 'passed') {
|
||||
else if (ctrl.testStatus === 'passed') {
|
||||
return capability.passedTests.length;
|
||||
}
|
||||
else if ($scope.testStatus === 'not passed') {
|
||||
else if (ctrl.testStatus === 'not passed') {
|
||||
return capability.notPassedTests.length;
|
||||
}
|
||||
else if ($scope.testStatus === 'flagged') {
|
||||
else if (ctrl.testStatus === 'flagged') {
|
||||
return capability.passedFlagged.length +
|
||||
capability.notPassedFlagged.length;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This will give the number of tests belonging under the selected
|
||||
@ -462,68 +517,73 @@ refstackApp.controller('resultsReportController',
|
||||
* @param {String} capability status
|
||||
* @returns {Number} number of tests for status under filter
|
||||
*/
|
||||
$scope.getStatusTestCount = function (status) {
|
||||
if (!$scope.caps) {
|
||||
function getStatusTestCount(status) {
|
||||
if (!ctrl.caps) {
|
||||
return -1;
|
||||
}
|
||||
else if ($scope.testStatus === 'total') {
|
||||
return $scope.caps[status].count;
|
||||
else if (ctrl.testStatus === 'total') {
|
||||
return ctrl.caps[status].count;
|
||||
}
|
||||
else if ($scope.testStatus === 'passed') {
|
||||
return $scope.caps[status].passedCount;
|
||||
else if (ctrl.testStatus === 'passed') {
|
||||
return ctrl.caps[status].passedCount;
|
||||
}
|
||||
else if ($scope.testStatus === 'not passed') {
|
||||
return $scope.caps[status].count -
|
||||
$scope.caps[status].passedCount;
|
||||
else if (ctrl.testStatus === 'not passed') {
|
||||
return ctrl.caps[status].count -
|
||||
ctrl.caps[status].passedCount;
|
||||
}
|
||||
else if ($scope.testStatus === 'flagged') {
|
||||
return $scope.caps[status].flagFailCount +
|
||||
$scope.caps[status].flagPassCount;
|
||||
else if (ctrl.testStatus === 'flagged') {
|
||||
return ctrl.caps[status].flagFailCount +
|
||||
ctrl.caps[status].flagPassCount;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
$scope.openFullTestListModal = function () {
|
||||
/**
|
||||
* This will open the modal that will show the full list of passed
|
||||
* tests for the current results.
|
||||
*/
|
||||
function openFullTestListModal() {
|
||||
$modal.open({
|
||||
templateUrl: '/components/results-report/partials' +
|
||||
'/fullTestListModal.html',
|
||||
backdrop: true,
|
||||
windowClass: 'modal',
|
||||
animation: true,
|
||||
controller: 'fullTestListModalController',
|
||||
controller: 'FullTestListModalController as modal',
|
||||
size: 'lg',
|
||||
resolve: {
|
||||
tests: function () {
|
||||
return $scope.resultsData.results;
|
||||
return ctrl.resultsData.results;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
getResults();
|
||||
}
|
||||
]
|
||||
);
|
||||
|
||||
angular
|
||||
.module('refstackApp')
|
||||
.controller('FullTestListModalController', FullTestListModalController);
|
||||
|
||||
FullTestListModalController.$inject = ['$modalInstance', 'tests'];
|
||||
|
||||
/**
|
||||
* Full Test List Modal Controller
|
||||
* This controller is for the modal that appears if a user wants to see the
|
||||
* full list of passed tests on a report page.
|
||||
*/
|
||||
refstackApp.controller('fullTestListModalController',
|
||||
['$scope', '$modalInstance', 'tests',
|
||||
function ($scope, $modalInstance, tests) {
|
||||
'use strict';
|
||||
function FullTestListModalController($modalInstance, tests) {
|
||||
var ctrl = this;
|
||||
|
||||
$scope.tests = tests;
|
||||
ctrl.tests = tests;
|
||||
|
||||
/**
|
||||
* This function will close/dismiss the modal.
|
||||
*/
|
||||
$scope.close = function () {
|
||||
ctrl.close = function () {
|
||||
$modalInstance.dismiss('exit');
|
||||
};
|
||||
|
||||
@ -531,8 +591,8 @@ refstackApp.controller('fullTestListModalController',
|
||||
* This function will return a string representing the sorted
|
||||
* tests list separated by newlines.
|
||||
*/
|
||||
$scope.getTestListString = function () {
|
||||
return $scope.tests.sort().join('\n');
|
||||
ctrl.getTestListString = function () {
|
||||
return ctrl.tests.sort().join('\n');
|
||||
};
|
||||
}]
|
||||
);
|
||||
}
|
||||
})();
|
||||
|
@ -1,4 +1,4 @@
|
||||
<h3>{{pageHeader}}</h3>
|
||||
<h3>{{ctrl.pageHeader}}</h3>
|
||||
<p>The most recently uploaded community test results are listed here.</p>
|
||||
|
||||
<div class="result-filters">
|
||||
@ -8,12 +8,11 @@
|
||||
<label for="cpid">Start Date</label>
|
||||
<p class="input-group">
|
||||
<input type="text" class="form-control"
|
||||
datepicker-popup="{{format}}"
|
||||
ng-model="startDate" is-open="startOpen"
|
||||
datepicker-options="dateOptions"
|
||||
datepicker-popup="{{ctrl.format}}"
|
||||
ng-model="ctrl.startDate" is-open="ctrl.startOpen"
|
||||
close-text="Close" />
|
||||
<span class="input-group-btn">
|
||||
<button type="button" class="btn btn-default" ng-click="open($event, 'startOpen')">
|
||||
<button type="button" class="btn btn-default" ng-click="ctrl.open($event, 'startOpen')">
|
||||
<i class="glyphicon glyphicon-calendar"></i>
|
||||
</button>
|
||||
</span>
|
||||
@ -23,62 +22,61 @@
|
||||
<label for="cpid">End Date</label>
|
||||
<p class="input-group">
|
||||
<input type="text" class="form-control"
|
||||
datepicker-popup="{{format}}"
|
||||
ng-model="endDate" is-open="endOpen"
|
||||
datepicker-options="dateOptions"
|
||||
datepicker-popup="{{ctrl.format}}"
|
||||
ng-model="ctrl.endDate" is-open="ctrl.endOpen"
|
||||
close-text="Close" />
|
||||
<span class="input-group-btn">
|
||||
<button type="button" class="btn btn-default" ng-click="open($event, 'endOpen')">
|
||||
<button type="button" class="btn btn-default" ng-click="ctrl.open($event, 'endOpen')">
|
||||
<i class="glyphicon glyphicon-calendar"></i>
|
||||
</button>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-3"style="margin-top:24px;">
|
||||
<button type="submit" class="btn btn-primary" ng-click="update()">Filter</button>
|
||||
<button type="submit" class="btn btn-primary btn-danger" ng-click="clearFilters()">Clear</button>
|
||||
<button type="submit" class="btn btn-primary" ng-click="ctrl.update()">Filter</button>
|
||||
<button type="submit" class="btn btn-primary btn-danger" ng-click="ctrl.clearFilters()">Clear</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div cg-busy="{promise:authRequest,message:'Loading'}"></div>
|
||||
<div cg-busy="{promise:resultsRequest,message:'Loading'}"></div>
|
||||
<div ng-show="data" class="results-table">
|
||||
<table ng-show="data" class="table table-striped table-hover">
|
||||
<div cg-busy="{promise:ctrl.authRequest,message:'Loading'}"></div>
|
||||
<div cg-busy="{promise:ctrl.resultsRequest,message:'Loading'}"></div>
|
||||
<div ng-show="ctrl.data" class="results-table">
|
||||
<table ng-show="ctrl.data" class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Upload Date</th>
|
||||
<th>Test Run ID</th>
|
||||
<th ng-if="::isUserResults">Shared</th>
|
||||
<th ng-if="ctrl.isUserResults">Shared</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr ng-repeat="result in data.results">
|
||||
<tr ng-repeat="result in ctrl.data.results">
|
||||
<td>{{result.created_at}}</td>
|
||||
<td><a ui-sref="resultsDetail({testID: result.id})">{{result.id}}</a></td>
|
||||
<td ng-if="::isUserResults"><span ng-show="result.meta.shared" class="glyphicon glyphicon-share"></span></td>
|
||||
<td ng-if="ctrl.isUserResults"><span ng-show="result.meta.shared" class="glyphicon glyphicon-share"></span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="pages">
|
||||
<pagination
|
||||
total-items="totalItems"
|
||||
ng-model="currentPage"
|
||||
items-per-page="itemsPerPage"
|
||||
max-size="maxSize"
|
||||
total-items="ctrl.totalItems"
|
||||
ng-model="ctrl.currentPage"
|
||||
items-per-page="ctrl.itemsPerPage"
|
||||
max-size="ctrl.maxSize"
|
||||
class="pagination-sm"
|
||||
boundary-links="true"
|
||||
rotate="false"
|
||||
num-pages="numPages"
|
||||
ng-change="update()">
|
||||
num-pages="ctrl.numPages"
|
||||
ng-change="ctrl.update()">
|
||||
</pagination>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-show="showError" class="alert alert-danger" role="alert">
|
||||
<div ng-show="ctrl.showError" class="alert alert-danger" role="alert">
|
||||
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
|
||||
<span class="sr-only">Error:</span>
|
||||
{{error}}
|
||||
{{ctrl.error}}
|
||||
</div>
|
||||
|
||||
|
@ -1,17 +1,42 @@
|
||||
var refstackApp = angular.module('refstackApp');
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('refstackApp')
|
||||
.controller('ResultsController', ResultsController);
|
||||
|
||||
ResultsController.$inject = [
|
||||
'$scope', '$http', '$filter', '$state', 'refstackApiUrl'
|
||||
];
|
||||
|
||||
/**
|
||||
* Refstack Results Controller
|
||||
* RefStack Results Controller
|
||||
* This controller is for the '/results' page where a user can browse
|
||||
* a listing of community uploaded results.
|
||||
*/
|
||||
refstackApp.controller('resultsController',
|
||||
['$scope', '$http', '$filter', '$state', 'refstackApiUrl',
|
||||
function ($scope, $http, $filter, $state, refstackApiUrl) {
|
||||
'use strict';
|
||||
function ResultsController($scope, $http, $filter, $state, refstackApiUrl) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.update = update;
|
||||
ctrl.open = open;
|
||||
ctrl.clearFilters = clearFilters;
|
||||
|
||||
/** Initial page to be on. */
|
||||
$scope.currentPage = 1;
|
||||
ctrl.currentPage = 1;
|
||||
|
||||
/**
|
||||
* How many results should display on each page. Since pagination
|
||||
@ -19,67 +44,76 @@ refstackApp.controller('resultsController',
|
||||
* 'results_per_page' configuration of the Refstack server which
|
||||
* defaults to 20.
|
||||
*/
|
||||
$scope.itemsPerPage = 20;
|
||||
ctrl.itemsPerPage = 20;
|
||||
|
||||
/**
|
||||
* How many page buttons should be displayed at max before adding
|
||||
* the '...' button.
|
||||
*/
|
||||
$scope.maxSize = 5;
|
||||
ctrl.maxSize = 5;
|
||||
|
||||
/** The upload date lower limit to be used in filtering results. */
|
||||
$scope.startDate = '';
|
||||
ctrl.startDate = '';
|
||||
|
||||
/** The upload date upper limit to be used in filtering results. */
|
||||
$scope.endDate = '';
|
||||
ctrl.endDate = '';
|
||||
|
||||
$scope.isUserResults = $state.current.name === 'userResults';
|
||||
if ($scope.isUserResults && !$scope.auth.isAuthenticated) {
|
||||
/** The date format for the date picker. */
|
||||
ctrl.format = 'yyyy-MM-dd';
|
||||
|
||||
/** Check to see if this page should display user-specific results. */
|
||||
ctrl.isUserResults = $state.current.name === 'userResults';
|
||||
|
||||
// Should only be on user-results-page if authenticated.
|
||||
if (ctrl.isUserResults && !$scope.auth.isAuthenticated) {
|
||||
$state.go('home');
|
||||
}
|
||||
$scope.pageHeader = $scope.isUserResults ?
|
||||
|
||||
ctrl.pageHeader = ctrl.isUserResults ?
|
||||
'Private test results' : 'Community test results';
|
||||
|
||||
if (ctrl.isUserResults) {
|
||||
ctrl.authRequest = $scope.auth.doSignCheck()
|
||||
.then(ctrl.update);
|
||||
} else {
|
||||
ctrl.update();
|
||||
}
|
||||
|
||||
/**
|
||||
* This will contact the Refstack API to get a listing of test run
|
||||
* results.
|
||||
*/
|
||||
$scope.update = function () {
|
||||
$scope.showError = false;
|
||||
function update() {
|
||||
ctrl.showError = false;
|
||||
// Construct the API URL based on user-specified filters.
|
||||
var content_url = refstackApiUrl + '/results?page=' +
|
||||
$scope.currentPage;
|
||||
var start = $filter('date')($scope.startDate, 'yyyy-MM-dd');
|
||||
var content_url = refstackApiUrl + '/results' +
|
||||
'?page=' + ctrl.currentPage;
|
||||
var start = $filter('date')(ctrl.startDate, 'yyyy-MM-dd');
|
||||
if (start) {
|
||||
content_url =
|
||||
content_url + '&start_date=' + start + ' 00:00:00';
|
||||
}
|
||||
var end = $filter('date')($scope.endDate, 'yyyy-MM-dd');
|
||||
var end = $filter('date')(ctrl.endDate, 'yyyy-MM-dd');
|
||||
if (end) {
|
||||
content_url = content_url + '&end_date=' + end + ' 23:59:59';
|
||||
}
|
||||
if ($scope.isUserResults) {
|
||||
if (ctrl.isUserResults) {
|
||||
content_url = content_url + '&signed';
|
||||
}
|
||||
$scope.resultsRequest =
|
||||
ctrl.resultsRequest =
|
||||
$http.get(content_url).success(function (data) {
|
||||
$scope.data = data;
|
||||
$scope.totalItems = $scope.data.pagination.total_pages *
|
||||
$scope.itemsPerPage;
|
||||
$scope.currentPage = $scope.data.pagination.current_page;
|
||||
ctrl.data = data;
|
||||
ctrl.totalItems = ctrl.data.pagination.total_pages *
|
||||
ctrl.itemsPerPage;
|
||||
ctrl.currentPage = ctrl.data.pagination.current_page;
|
||||
}).error(function (error) {
|
||||
$scope.data = null;
|
||||
$scope.totalItems = 0;
|
||||
$scope.showError = true;
|
||||
$scope.error =
|
||||
ctrl.data = null;
|
||||
ctrl.totalItems = 0;
|
||||
ctrl.showError = true;
|
||||
ctrl.error =
|
||||
'Error retrieving results listing from server: ' +
|
||||
JSON.stringify(error);
|
||||
angular.toJson(error);
|
||||
});
|
||||
};
|
||||
if ($scope.isUserResults) {
|
||||
$scope.authRequest = $scope.auth.doSignCheck()
|
||||
.then($scope.update);
|
||||
} else {
|
||||
$scope.update();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -89,19 +123,20 @@ refstackApp.controller('resultsController',
|
||||
* @param {Object} $event - The Event object
|
||||
* @param {String} openVar - Tells which calendar was opened
|
||||
*/
|
||||
$scope.open = function ($event, openVar) {
|
||||
function open($event, openVar) {
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
$scope[openVar] = true;
|
||||
};
|
||||
ctrl[openVar] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will clear all filters and update the results
|
||||
* listing.
|
||||
*/
|
||||
$scope.clearFilters = function () {
|
||||
$scope.startDate = null;
|
||||
$scope.endDate = null;
|
||||
$scope.update();
|
||||
};
|
||||
}]);
|
||||
function clearFilters() {
|
||||
ctrl.startDate = null;
|
||||
ctrl.endDate = null;
|
||||
ctrl.update();
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
@ -1,8 +1,8 @@
|
||||
<div class="modal-body" style="padding:0px">
|
||||
<div class="alert alert-{{::data.mode}}" style="margin-bottom:0px">
|
||||
<button type="button" class="close" data-ng-click="close()" >
|
||||
<div class="alert alert-{{alert.data.mode}}" style="margin-bottom:0px">
|
||||
<button type="button" class="close" data-ng-click="alert.close()" >
|
||||
<span class="glyphicon glyphicon-remove-circle"></span>
|
||||
</button>
|
||||
<strong>{{::data.title}}</strong> {{::data.text}}
|
||||
<strong>{{alert.data.title}}</strong> {{alert.data.text}}
|
||||
</div>
|
||||
</div>
|
@ -1,12 +1,35 @@
|
||||
var refstackApp = angular.module('refstackApp');
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
refstackApp.factory('raiseAlert',
|
||||
['$modal', function($modal) {
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('refstackApp')
|
||||
.factory('raiseAlert', raiseAlert);
|
||||
|
||||
raiseAlert.$inject = ['$modal'];
|
||||
|
||||
/**
|
||||
* This allows alert pop-ups to be raised. Just inject it as a dependency
|
||||
* in the calling controller.
|
||||
*/
|
||||
function raiseAlert($modal) {
|
||||
return function(mode, title, text) {
|
||||
$modal.open({
|
||||
templateUrl: '/shared/alerts/alertModal.html',
|
||||
controller: 'raiseAlertModalController',
|
||||
controller: 'RaiseAlertModalController as alert',
|
||||
backdrop: true,
|
||||
keyboard: true,
|
||||
backdropClick: true,
|
||||
@ -22,20 +45,30 @@ refstackApp.factory('raiseAlert',
|
||||
}
|
||||
});
|
||||
};
|
||||
}]
|
||||
);
|
||||
|
||||
|
||||
refstackApp.controller('raiseAlertModalController',
|
||||
['$scope', '$modalInstance', 'data',
|
||||
function ($scope, $modalInstance, data) {
|
||||
'use strict';
|
||||
$scope.data = data;
|
||||
|
||||
//wait for users click to close the pop up window.
|
||||
$scope.close = function() {
|
||||
$modalInstance.close();
|
||||
};
|
||||
}
|
||||
]
|
||||
);
|
||||
|
||||
angular
|
||||
.module('refstackApp')
|
||||
.controller('RaiseAlertModalController', RaiseAlertModalController);
|
||||
|
||||
RaiseAlertModalController.$inject = ['$modalInstance', 'data'];
|
||||
|
||||
/**
|
||||
* This is the controller for the alert pop-up.
|
||||
*/
|
||||
function RaiseAlertModalController($modalInstance, data) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.close = close;
|
||||
ctrl.data = data;
|
||||
|
||||
/**
|
||||
* This method will close the alert modal. The modal will close
|
||||
* when the user clicks the close button or clicks outside of the
|
||||
* modal.
|
||||
*/
|
||||
function close() {
|
||||
$modalInstance.close();
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
@ -1,14 +1,33 @@
|
||||
var refstackApp = angular.module('refstackApp');
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** Refstack AngularJS Filters */
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Convert an object of objects to an array of objects to use with ng-repeat
|
||||
* filters.
|
||||
*/
|
||||
refstackApp.filter('arrayConverter', function () {
|
||||
'use strict';
|
||||
angular
|
||||
.module('refstackApp')
|
||||
.filter('arrayConverter', arrayConverter);
|
||||
|
||||
/**
|
||||
* Convert an object of objects to an array of objects to use with ng-repeat
|
||||
* filters.
|
||||
*/
|
||||
function arrayConverter() {
|
||||
return function (objects) {
|
||||
var array = [];
|
||||
angular.forEach(objects, function (object, key) {
|
||||
@ -17,15 +36,18 @@ refstackApp.filter('arrayConverter', function () {
|
||||
});
|
||||
return array;
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
angular
|
||||
.module('refstackApp')
|
||||
.filter('capitalize', capitalize);
|
||||
|
||||
/**
|
||||
* Angular filter that will capitalize the first letter of a string.
|
||||
*/
|
||||
refstackApp.filter('capitalize', function() {
|
||||
'use strict';
|
||||
|
||||
function capitalize() {
|
||||
return function (string) {
|
||||
return string.substring(0, 1).toUpperCase() + string.substring(1);
|
||||
};
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
@ -1,11 +1,11 @@
|
||||
<div class="heading"><a ui-sref="home"><img src="assets/img/refstack-logo.png" alt="RefStack"></a>
|
||||
RefStack
|
||||
</div>
|
||||
<nav class="navbar navbar-default" role="navigation" ng-controller="headerController">
|
||||
<nav class="navbar navbar-default" role="navigation" ng-controller="HeaderController as header">
|
||||
<div class="container-fluid">
|
||||
<!-- Brand and toggle get grouped for better mobile display -->
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" ng-click="navbarCollapsed = !navbarCollapsed">
|
||||
<button type="button" class="navbar-toggle collapsed" ng-click="header.navbarCollapsed = !header.navbarCollapsed">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
@ -13,12 +13,12 @@ RefStack
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbar" collapse="navbarCollapsed">
|
||||
<div class="collapse navbar-collapse" id="navbar" collapse="header.navbarCollapsed">
|
||||
<ul class="nav navbar-nav">
|
||||
<li ng-class="{ active: isActive('/')}"><a ui-sref="home">Home</a></li>
|
||||
<li ng-class="{ active: isActive('/about')}"><a ui-sref="about">About</a></li>
|
||||
<li ng-class="{ active: isActive('/capabilities')}"><a ui-sref="capabilities">DefCore Capabilities</a></li>
|
||||
<li ng-class="{ active: isActive('/community_results')}"><a ui-sref="communityResults">Community Results</a></li>
|
||||
<li ng-class="{ active: header.isActive('/')}"><a ui-sref="home">Home</a></li>
|
||||
<li ng-class="{ active: header.isActive('/about')}"><a ui-sref="about">About</a></li>
|
||||
<li ng-class="{ active: header.isActive('/capabilities')}"><a ui-sref="capabilities">DefCore Capabilities</a></li>
|
||||
<li ng-class="{ active: header.isActive('/community_results')}"><a ui-sref="communityResults">Community Results</a></li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li ng-class="{ active: isActive('/user_results')}" ng-if="auth.isAuthenticated"><a ui-sref="userResults">My Results</a></li>
|
||||
|
@ -1,22 +1,44 @@
|
||||
var refstackApp = angular.module('refstackApp');
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('refstackApp')
|
||||
.controller('HeaderController', HeaderController);
|
||||
|
||||
HeaderController.$inject = ['$location'];
|
||||
|
||||
/**
|
||||
* Refstack Header Controller
|
||||
* This controller is for the header template which contains the site
|
||||
* navigation.
|
||||
*/
|
||||
refstackApp.controller('headerController',
|
||||
['$scope', '$location', function ($scope, $location) {
|
||||
'use strict';
|
||||
function HeaderController($location) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.isActive = isActive;
|
||||
|
||||
/** Whether the Navbar is collapsed for small displays. */
|
||||
$scope.navbarCollapsed = true;
|
||||
ctrl.navbarCollapsed = true;
|
||||
|
||||
/**
|
||||
* This determines whether a button should be in the active state based
|
||||
* on the URL.
|
||||
*/
|
||||
$scope.isActive = function (viewLocation) {
|
||||
function isActive(viewLocation) {
|
||||
var path = $location.path().substr(0, viewLocation.length);
|
||||
if (path === viewLocation) {
|
||||
// Make sure "/" only matches when viewLocation is "/".
|
||||
@ -26,5 +48,6 @@ refstackApp.controller('headerController',
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}]);
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
@ -17,45 +17,41 @@ describe('Refstack controllers', function () {
|
||||
.respond('<div>mock template</div>');
|
||||
});
|
||||
|
||||
describe('headerController', function () {
|
||||
var scope, $location;
|
||||
describe('HeaderController', function () {
|
||||
var $location, ctrl;
|
||||
|
||||
beforeEach(inject(function ($rootScope, $controller, _$location_) {
|
||||
scope = $rootScope.$new();
|
||||
beforeEach(inject(function ($controller, _$location_) {
|
||||
$location = _$location_;
|
||||
$controller('headerController', {$scope: scope});
|
||||
ctrl = $controller('HeaderController', {});
|
||||
}));
|
||||
|
||||
it('should set "navbarCollapsed" to true', function () {
|
||||
expect(scope.navbarCollapsed).toBe(true);
|
||||
expect(ctrl.navbarCollapsed).toBe(true);
|
||||
});
|
||||
|
||||
it('should have a function to check if the URL path is active',
|
||||
function () {
|
||||
$location.path('/');
|
||||
expect($location.path()).toBe('/');
|
||||
expect(scope.isActive('/')).toBe(true);
|
||||
expect(scope.isActive('/about')).toBe(false);
|
||||
expect(ctrl.isActive('/')).toBe(true);
|
||||
expect(ctrl.isActive('/about')).toBe(false);
|
||||
|
||||
$location.path('/results?cpid=123&foo=bar');
|
||||
expect($location.path()).toBe('/results?cpid=123&foo=bar');
|
||||
expect(scope.isActive('/results')).toBe(true);
|
||||
expect(ctrl.isActive('/results')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('capabilitiesController', function () {
|
||||
var scope;
|
||||
describe('CapabilitiesController', function () {
|
||||
var ctrl;
|
||||
|
||||
beforeEach(inject(function ($rootScope, $controller) {
|
||||
scope = $rootScope.$new();
|
||||
$controller('capabilitiesController', {$scope: scope});
|
||||
beforeEach(inject(function ($controller) {
|
||||
ctrl = $controller('CapabilitiesController', {});
|
||||
}));
|
||||
|
||||
it('should set default states', function () {
|
||||
expect(scope.hideAchievements).toBe(true);
|
||||
expect(scope.hideTests).toBe(true);
|
||||
expect(scope.target).toBe('platform');
|
||||
expect(scope.status).toEqual({
|
||||
expect(ctrl.target).toBe('platform');
|
||||
expect(ctrl.status).toEqual({
|
||||
required: true, advisory: false,
|
||||
deprecated: false, removed: false
|
||||
});
|
||||
@ -84,24 +80,24 @@ describe('Refstack controllers', function () {
|
||||
'/capabilities/2015.04.json').respond(fakeCaps);
|
||||
$httpBackend.flush();
|
||||
// The version list should be sorted latest first.
|
||||
expect(scope.versionList).toEqual(['2015.04.json',
|
||||
expect(ctrl.versionList).toEqual(['2015.04.json',
|
||||
'2015.03.json']);
|
||||
expect(scope.capabilities).toEqual(fakeCaps);
|
||||
expect(ctrl.capabilities).toEqual(fakeCaps);
|
||||
var expectedTemplate = 'components/capabilities/partials/' +
|
||||
'capabilityDetailsV1.3.html';
|
||||
expect(scope.detailsTemplate).toEqual(expectedTemplate);
|
||||
expect(ctrl.detailsTemplate).toEqual(expectedTemplate);
|
||||
var expectedTargetCaps = {
|
||||
'cap_id_1': 'required',
|
||||
'cap_id_2': 'advisory',
|
||||
'cap_id_3': 'deprecated',
|
||||
'cap_id_4': 'removed'
|
||||
};
|
||||
expect(scope.targetCapabilities).toEqual(expectedTargetCaps);
|
||||
expect(ctrl.targetCapabilities).toEqual(expectedTargetCaps);
|
||||
});
|
||||
|
||||
it('should have a function to check if a capability status is selected',
|
||||
function () {
|
||||
scope.targetCapabilities = {
|
||||
ctrl.targetCapabilities = {
|
||||
'cap_id_1': 'required',
|
||||
'cap_id_2': 'advisory',
|
||||
'cap_id_3': 'deprecated',
|
||||
@ -109,12 +105,12 @@ describe('Refstack controllers', function () {
|
||||
};
|
||||
|
||||
// Expect only the required capability to return true.
|
||||
expect(scope.filterStatus({'id': 'cap_id_1'})).toBe(true);
|
||||
expect(scope.filterStatus({'id': 'cap_id_2'})).toBe(false);
|
||||
expect(scope.filterStatus({'id': 'cap_id_3'})).toBe(false);
|
||||
expect(scope.filterStatus({'id': 'cap_id_4'})).toBe(false);
|
||||
expect(ctrl.filterStatus({'id': 'cap_id_1'})).toBe(true);
|
||||
expect(ctrl.filterStatus({'id': 'cap_id_2'})).toBe(false);
|
||||
expect(ctrl.filterStatus({'id': 'cap_id_3'})).toBe(false);
|
||||
expect(ctrl.filterStatus({'id': 'cap_id_4'})).toBe(false);
|
||||
|
||||
scope.status = {
|
||||
ctrl.status = {
|
||||
required: true,
|
||||
advisory: true,
|
||||
deprecated: true,
|
||||
@ -122,10 +118,10 @@ describe('Refstack controllers', function () {
|
||||
};
|
||||
|
||||
// Every capability should return true now.
|
||||
expect(scope.filterStatus({'id': 'cap_id_1'})).toBe(true);
|
||||
expect(scope.filterStatus({'id': 'cap_id_2'})).toBe(true);
|
||||
expect(scope.filterStatus({'id': 'cap_id_3'})).toBe(true);
|
||||
expect(scope.filterStatus({'id': 'cap_id_4'})).toBe(true);
|
||||
expect(ctrl.filterStatus({'id': 'cap_id_1'})).toBe(true);
|
||||
expect(ctrl.filterStatus({'id': 'cap_id_2'})).toBe(true);
|
||||
expect(ctrl.filterStatus({'id': 'cap_id_3'})).toBe(true);
|
||||
expect(ctrl.filterStatus({'id': 'cap_id_4'})).toBe(true);
|
||||
});
|
||||
|
||||
it('should have a function to get the length of an object/dict',
|
||||
@ -138,12 +134,12 @@ describe('Refstack controllers', function () {
|
||||
'idempotent_id': 'id-5678'
|
||||
}
|
||||
};
|
||||
expect(scope.getObjectLength(testObject)).toBe(2);
|
||||
expect(ctrl.getObjectLength(testObject)).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('resultsController', function () {
|
||||
var scope;
|
||||
var scope, ctrl;
|
||||
var fakeResponse = {
|
||||
'pagination': {'current_page': 1, 'total_pages': 2},
|
||||
'results': [{
|
||||
@ -155,7 +151,7 @@ describe('Refstack controllers', function () {
|
||||
|
||||
beforeEach(inject(function ($rootScope, $controller) {
|
||||
scope = $rootScope.$new();
|
||||
$controller('resultsController', {$scope: scope});
|
||||
ctrl = $controller('ResultsController', {$scope: scope});
|
||||
}));
|
||||
|
||||
it('should fetch the first page of results with proper URL args',
|
||||
@ -164,46 +160,46 @@ describe('Refstack controllers', function () {
|
||||
$httpBackend.expectGET(fakeApiUrl + '/results?page=1')
|
||||
.respond(fakeResponse);
|
||||
$httpBackend.flush();
|
||||
expect(scope.data).toEqual(fakeResponse);
|
||||
expect(scope.currentPage).toBe(1);
|
||||
expect(ctrl.data).toEqual(fakeResponse);
|
||||
expect(ctrl.currentPage).toBe(1);
|
||||
|
||||
// Simulate the user adding date filters.
|
||||
scope.startDate = new Date('2015-03-10T11:51:00');
|
||||
scope.endDate = new Date('2015-04-10T11:51:00');
|
||||
scope.update();
|
||||
ctrl.startDate = new Date('2015-03-10T11:51:00');
|
||||
ctrl.endDate = new Date('2015-04-10T11:51:00');
|
||||
ctrl.update();
|
||||
$httpBackend.expectGET(fakeApiUrl +
|
||||
'/results?page=1' +
|
||||
'&start_date=2015-03-10 00:00:00' +
|
||||
'&end_date=2015-04-10 23:59:59')
|
||||
.respond(fakeResponse);
|
||||
$httpBackend.flush();
|
||||
expect(scope.data).toEqual(fakeResponse);
|
||||
expect(scope.currentPage).toBe(1);
|
||||
expect(ctrl.data).toEqual(fakeResponse);
|
||||
expect(ctrl.currentPage).toBe(1);
|
||||
});
|
||||
|
||||
it('should set an error when results cannot be retrieved', function () {
|
||||
$httpBackend.expectGET(fakeApiUrl + '/results?page=1').respond(404,
|
||||
{'detail': 'Not Found'});
|
||||
$httpBackend.flush();
|
||||
expect(scope.data).toBe(null);
|
||||
expect(scope.error).toEqual('Error retrieving results listing ' +
|
||||
expect(ctrl.data).toBe(null);
|
||||
expect(ctrl.error).toEqual('Error retrieving results listing ' +
|
||||
'from server: {"detail":"Not Found"}');
|
||||
expect(scope.totalItems).toBe(0);
|
||||
expect(scope.showError).toBe(true);
|
||||
expect(ctrl.totalItems).toBe(0);
|
||||
expect(ctrl.showError).toBe(true);
|
||||
});
|
||||
|
||||
it('should have an function to clear filters and update the view',
|
||||
function () {
|
||||
scope.startDate = 'some date';
|
||||
scope.endDate = 'some other date';
|
||||
scope.clearFilters();
|
||||
expect(scope.startDate).toBe(null);
|
||||
expect(scope.endDate).toBe(null);
|
||||
ctrl.startDate = 'some date';
|
||||
ctrl.endDate = 'some other date';
|
||||
ctrl.clearFilters();
|
||||
expect(ctrl.startDate).toBe(null);
|
||||
expect(ctrl.endDate).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('resultsReportController', function () {
|
||||
var scope, stateparams;
|
||||
describe('ResultsReportController', function () {
|
||||
var stateparams, ctrl;
|
||||
var fakeResultResponse = {'results': ['test_id_1']};
|
||||
var fakeCapabilityResponse = {
|
||||
'platform': {'required': ['compute']},
|
||||
@ -224,11 +220,11 @@ describe('Refstack controllers', function () {
|
||||
}
|
||||
};
|
||||
|
||||
beforeEach(inject(function ($rootScope, $controller) {
|
||||
beforeEach(inject(function ($controller) {
|
||||
stateparams = {testID: 1234};
|
||||
scope = $rootScope.$new();
|
||||
$controller('resultsReportController',
|
||||
{$scope: scope, $stateParams: stateparams});
|
||||
ctrl = $controller('ResultsReportController',
|
||||
{$stateParams: stateparams}
|
||||
);
|
||||
}));
|
||||
|
||||
it('should make all necessary API requests to get results ' +
|
||||
@ -242,18 +238,18 @@ describe('Refstack controllers', function () {
|
||||
$httpBackend.expectGET(fakeApiUrl +
|
||||
'/capabilities/2015.04.json').respond(fakeCapabilityResponse);
|
||||
$httpBackend.flush();
|
||||
expect(scope.resultsData).toEqual(fakeResultResponse);
|
||||
expect(ctrl.resultsData).toEqual(fakeResultResponse);
|
||||
// The version list should be sorted latest first.
|
||||
expect(scope.versionList).toEqual(['2015.04.json',
|
||||
expect(ctrl.versionList).toEqual(['2015.04.json',
|
||||
'2015.03.json']);
|
||||
expect(scope.capabilityData).toEqual(fakeCapabilityResponse);
|
||||
expect(scope.schemaVersion).toEqual('1.2');
|
||||
expect(ctrl.capabilityData).toEqual(fakeCapabilityResponse);
|
||||
expect(ctrl.schemaVersion).toEqual('1.2');
|
||||
});
|
||||
|
||||
it('should have a method that creates an object containing each ' +
|
||||
'relevant capability and its highest priority status',
|
||||
function () {
|
||||
scope.capabilityData = {
|
||||
ctrl.capabilityData = {
|
||||
'schema': '1.3',
|
||||
'platform': {'required': ['compute', 'object']},
|
||||
'components': {
|
||||
@ -276,16 +272,16 @@ describe('Refstack controllers', function () {
|
||||
'cap_id_2': 'required',
|
||||
'cap_id_3': 'advisory'
|
||||
};
|
||||
expect(scope.getTargetCapabilities()).toEqual(expected);
|
||||
expect(ctrl.getTargetCapabilities()).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should be able to sort the results into a capability object for ' +
|
||||
'schema version 1.2',
|
||||
function () {
|
||||
scope.resultsData = fakeResultResponse;
|
||||
scope.capabilityData = fakeCapabilityResponse;
|
||||
scope.schemaVersion = '1.2';
|
||||
scope.buildCapabilitiesObject();
|
||||
ctrl.resultsData = fakeResultResponse;
|
||||
ctrl.capabilityData = fakeCapabilityResponse;
|
||||
ctrl.schemaVersion = '1.2';
|
||||
ctrl.buildCapabilitiesObject();
|
||||
var expectedCapsObject = {
|
||||
'required': {
|
||||
'caps': [{
|
||||
@ -305,16 +301,16 @@ describe('Refstack controllers', function () {
|
||||
'removed': {'caps': [], 'count': 0, 'passedCount': 0,
|
||||
'flagFailCount': 0, 'flagPassCount': 0}
|
||||
};
|
||||
expect(scope.caps).toEqual(expectedCapsObject);
|
||||
expect(scope.requiredPassPercent).toEqual(50);
|
||||
expect(scope.nonFlagPassCount).toEqual(0);
|
||||
expect(ctrl.caps).toEqual(expectedCapsObject);
|
||||
expect(ctrl.requiredPassPercent).toEqual(50);
|
||||
expect(ctrl.nonFlagPassCount).toEqual(0);
|
||||
});
|
||||
|
||||
it('should be able to sort the results into a capability object for ' +
|
||||
'schema version 1.3',
|
||||
function () {
|
||||
scope.resultsData = fakeResultResponse;
|
||||
scope.capabilityData = {
|
||||
ctrl.resultsData = fakeResultResponse;
|
||||
ctrl.capabilityData = {
|
||||
'platform': {'required': ['compute']},
|
||||
'schema': '1.3',
|
||||
'components': {
|
||||
@ -343,8 +339,8 @@ describe('Refstack controllers', function () {
|
||||
}
|
||||
}
|
||||
};
|
||||
scope.schemaVersion = '1.3';
|
||||
scope.buildCapabilitiesObject();
|
||||
ctrl.schemaVersion = '1.3';
|
||||
ctrl.buildCapabilitiesObject();
|
||||
var expectedCapsObject = {
|
||||
'required': {
|
||||
'caps': [{
|
||||
@ -364,9 +360,9 @@ describe('Refstack controllers', function () {
|
||||
'removed': {'caps': [], 'count': 0, 'passedCount': 0,
|
||||
'flagFailCount': 0, 'flagPassCount': 0}
|
||||
};
|
||||
expect(scope.caps).toEqual(expectedCapsObject);
|
||||
expect(scope.requiredPassPercent).toEqual(50);
|
||||
expect(scope.nonFlagPassCount).toEqual(0);
|
||||
expect(ctrl.caps).toEqual(expectedCapsObject);
|
||||
expect(ctrl.requiredPassPercent).toEqual(50);
|
||||
expect(ctrl.nonFlagPassCount).toEqual(0);
|
||||
});
|
||||
|
||||
it('should have a method to determine if a test is flagged',
|
||||
@ -374,11 +370,12 @@ describe('Refstack controllers', function () {
|
||||
var capObj = {'flagged': [ 'test1'],
|
||||
'tests': ['test1', 'test2']};
|
||||
|
||||
scope.schemaVersion = '1.2';
|
||||
expect(scope.isTestFlagged('test1', capObj)).toEqual(true);
|
||||
expect(scope.isTestFlagged('test2', capObj)).toEqual(false);
|
||||
ctrl.schemaVersion = '1.2';
|
||||
expect(ctrl.isTestFlagged('test1', capObj)).toEqual(true);
|
||||
expect(ctrl.isTestFlagged('test2', capObj)).toEqual(false);
|
||||
|
||||
capObj = {'tests': {
|
||||
capObj = {
|
||||
'tests': {
|
||||
'test1': {
|
||||
'flagged': {
|
||||
'action': 'foo',
|
||||
@ -393,11 +390,11 @@ describe('Refstack controllers', function () {
|
||||
}
|
||||
};
|
||||
|
||||
scope.schemaVersion = '1.3';
|
||||
expect(scope.isTestFlagged('test1', capObj)).toBeTruthy();
|
||||
expect(scope.isTestFlagged('test2', capObj)).toBeFalsy();
|
||||
ctrl.schemaVersion = '1.3';
|
||||
expect(ctrl.isTestFlagged('test1', capObj)).toBeTruthy();
|
||||
expect(ctrl.isTestFlagged('test2', capObj)).toBeFalsy();
|
||||
|
||||
expect(scope.isTestFlagged('test2', null)).toEqual(false);
|
||||
expect(ctrl.isTestFlagged('test2', null)).toEqual(false);
|
||||
});
|
||||
|
||||
it('should have a method to get the reason a flagged test is flagged',
|
||||
@ -405,14 +402,15 @@ describe('Refstack controllers', function () {
|
||||
var capObj = {'flagged': [ 'test1'],
|
||||
'tests': ['test1', 'test2']};
|
||||
|
||||
scope.schemaVersion = '1.2';
|
||||
expect(scope.getFlaggedReason('test1', capObj)).toEqual(
|
||||
ctrl.schemaVersion = '1.2';
|
||||
expect(ctrl.getFlaggedReason('test1', capObj)).toEqual(
|
||||
'DefCore has flagged this test.');
|
||||
|
||||
// Check that non-flagged test returns empty string.
|
||||
expect(scope.getFlaggedReason('test2', capObj)).toEqual('');
|
||||
expect(ctrl.getFlaggedReason('test2', capObj)).toEqual('');
|
||||
|
||||
capObj = {'tests': {
|
||||
capObj = {
|
||||
'tests': {
|
||||
'test1': {
|
||||
'flagged': {
|
||||
'action': 'foo',
|
||||
@ -424,8 +422,8 @@ describe('Refstack controllers', function () {
|
||||
}
|
||||
};
|
||||
|
||||
scope.schemaVersion = '1.3';
|
||||
expect(scope.getFlaggedReason('test1', capObj)).toEqual('bar');
|
||||
ctrl.schemaVersion = '1.3';
|
||||
expect(ctrl.getFlaggedReason('test1', capObj)).toEqual('bar');
|
||||
});
|
||||
|
||||
it('should have a method to determine whether a capability should ' +
|
||||
@ -445,23 +443,23 @@ describe('Refstack controllers', function () {
|
||||
}];
|
||||
|
||||
// Check that all capabilities are shown by default.
|
||||
expect(scope.isCapabilityShown(caps[0])).toEqual(true);
|
||||
expect(scope.isCapabilityShown(caps[1])).toEqual(true);
|
||||
expect(ctrl.isCapabilityShown(caps[0])).toEqual(true);
|
||||
expect(ctrl.isCapabilityShown(caps[1])).toEqual(true);
|
||||
|
||||
// Check that only capabilities with passed tests are shown.
|
||||
scope.testStatus = 'passed';
|
||||
expect(scope.isCapabilityShown(caps[0])).toEqual(true);
|
||||
expect(scope.isCapabilityShown(caps[1])).toEqual(false);
|
||||
ctrl.testStatus = 'passed';
|
||||
expect(ctrl.isCapabilityShown(caps[0])).toEqual(true);
|
||||
expect(ctrl.isCapabilityShown(caps[1])).toEqual(false);
|
||||
|
||||
// Check that only capabilities with passed tests are shown.
|
||||
scope.testStatus = 'not passed';
|
||||
expect(scope.isCapabilityShown(caps[0])).toEqual(false);
|
||||
expect(scope.isCapabilityShown(caps[1])).toEqual(true);
|
||||
ctrl.testStatus = 'not passed';
|
||||
expect(ctrl.isCapabilityShown(caps[0])).toEqual(false);
|
||||
expect(ctrl.isCapabilityShown(caps[1])).toEqual(true);
|
||||
|
||||
// Check that only capabilities with flagged tests are shown.
|
||||
scope.testStatus = 'flagged';
|
||||
expect(scope.isCapabilityShown(caps[0])).toEqual(true);
|
||||
expect(scope.isCapabilityShown(caps[1])).toEqual(false);
|
||||
ctrl.testStatus = 'flagged';
|
||||
expect(ctrl.isCapabilityShown(caps[0])).toEqual(true);
|
||||
expect(ctrl.isCapabilityShown(caps[1])).toEqual(false);
|
||||
});
|
||||
|
||||
it('should have a method to determine whether a test should be shown',
|
||||
@ -473,13 +471,13 @@ describe('Refstack controllers', function () {
|
||||
'notPassedFlagged': []
|
||||
};
|
||||
|
||||
expect(scope.isTestShown('test_id_1', cap)).toEqual(true);
|
||||
scope.testStatus = 'passed';
|
||||
expect(scope.isTestShown('test_id_1', cap)).toEqual(true);
|
||||
scope.testStatus = 'not passed';
|
||||
expect(scope.isTestShown('test_id_1', cap)).toEqual(false);
|
||||
scope.testStatus = 'flagged';
|
||||
expect(scope.isTestShown('test_id_1', cap)).toEqual(true);
|
||||
expect(ctrl.isTestShown('test_id_1', cap)).toEqual(true);
|
||||
ctrl.testStatus = 'passed';
|
||||
expect(ctrl.isTestShown('test_id_1', cap)).toEqual(true);
|
||||
ctrl.testStatus = 'not passed';
|
||||
expect(ctrl.isTestShown('test_id_1', cap)).toEqual(false);
|
||||
ctrl.testStatus = 'flagged';
|
||||
expect(ctrl.isTestShown('test_id_1', cap)).toEqual(true);
|
||||
});
|
||||
|
||||
it('should have a method to determine how many tests in a ' +
|
||||
@ -493,48 +491,48 @@ describe('Refstack controllers', function () {
|
||||
};
|
||||
|
||||
// Should return the count of all tests.
|
||||
expect(scope.getCapabilityTestCount(cap)).toEqual(7);
|
||||
expect(ctrl.getCapabilityTestCount(cap)).toEqual(7);
|
||||
|
||||
// Should return the count of passed tests.
|
||||
scope.testStatus = 'passed';
|
||||
expect(scope.getCapabilityTestCount(cap)).toEqual(3);
|
||||
ctrl.testStatus = 'passed';
|
||||
expect(ctrl.getCapabilityTestCount(cap)).toEqual(3);
|
||||
|
||||
// Should return the count of failed tests.
|
||||
scope.testStatus = 'not passed';
|
||||
expect(scope.getCapabilityTestCount(cap)).toEqual(4);
|
||||
ctrl.testStatus = 'not passed';
|
||||
expect(ctrl.getCapabilityTestCount(cap)).toEqual(4);
|
||||
|
||||
// Should return the count of flagged tests.
|
||||
scope.testStatus = 'flagged';
|
||||
expect(scope.getCapabilityTestCount(cap)).toEqual(3);
|
||||
ctrl.testStatus = 'flagged';
|
||||
expect(ctrl.getCapabilityTestCount(cap)).toEqual(3);
|
||||
});
|
||||
|
||||
it('should have a method to determine how many tests in a status ' +
|
||||
'belong under the current test filter',
|
||||
function () {
|
||||
scope.caps = {'required': {'caps': [], 'count': 10,
|
||||
ctrl.caps = {'required': {'caps': [], 'count': 10,
|
||||
'passedCount': 6, 'flagFailCount': 3,
|
||||
'flagPassCount': 2}};
|
||||
|
||||
// Should return the count of all tests (count).
|
||||
expect(scope.getStatusTestCount('required')).toEqual(10);
|
||||
expect(ctrl.getStatusTestCount('required')).toEqual(10);
|
||||
|
||||
// Should return the count of passed tests (passedCount).
|
||||
scope.testStatus = 'passed';
|
||||
expect(scope.getStatusTestCount('required')).toEqual(6);
|
||||
ctrl.testStatus = 'passed';
|
||||
expect(ctrl.getStatusTestCount('required')).toEqual(6);
|
||||
|
||||
// Should return the count of failed tests
|
||||
// (count - passedCount).
|
||||
scope.testStatus = 'not passed';
|
||||
expect(scope.getStatusTestCount('required')).toEqual(4);
|
||||
ctrl.testStatus = 'not passed';
|
||||
expect(ctrl.getStatusTestCount('required')).toEqual(4);
|
||||
|
||||
// Should return the count of flagged tests
|
||||
// (flagFailCount + flagPassCount).
|
||||
scope.testStatus = 'flagged';
|
||||
expect(scope.getStatusTestCount('required')).toEqual(5);
|
||||
ctrl.testStatus = 'flagged';
|
||||
expect(ctrl.getStatusTestCount('required')).toEqual(5);
|
||||
|
||||
// Test when caps has not been set yet.
|
||||
scope.caps = null;
|
||||
expect(scope.getStatusTestCount('required')).toEqual(-1);
|
||||
ctrl.caps = null;
|
||||
expect(ctrl.getStatusTestCount('required')).toEqual(-1);
|
||||
});
|
||||
|
||||
it('should have a method to open a modal for the full passed test list',
|
||||
@ -544,48 +542,43 @@ describe('Refstack controllers', function () {
|
||||
modal = $modal;
|
||||
});
|
||||
spyOn(modal, 'open');
|
||||
scope.openFullTestListModal();
|
||||
ctrl.openFullTestListModal();
|
||||
expect(modal.open).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('fullTestListModalController', function () {
|
||||
var scope;
|
||||
var modalInstance;
|
||||
describe('FullTestListModalController', function () {
|
||||
var modalInstance, ctrl;
|
||||
|
||||
beforeEach(inject(function ($rootScope, $controller) {
|
||||
scope = $rootScope.$new();
|
||||
beforeEach(inject(function ($controller) {
|
||||
modalInstance = {
|
||||
dismiss: jasmine.createSpy('modalInstance.dismiss')
|
||||
};
|
||||
$controller('fullTestListModalController', {
|
||||
$scope: scope,
|
||||
$modalInstance: modalInstance,
|
||||
tests: ['t1', 't2']
|
||||
});
|
||||
ctrl = $controller('FullTestListModalController',
|
||||
{$modalInstance: modalInstance, tests: ['t1', 't2']}
|
||||
);
|
||||
}));
|
||||
|
||||
it('should set a scope variable to the passed in tests', function () {
|
||||
expect(scope.tests).toEqual(['t1', 't2']);
|
||||
expect(ctrl.tests).toEqual(['t1', 't2']);
|
||||
});
|
||||
|
||||
it('should have a method to close the modal',
|
||||
function () {
|
||||
scope.close();
|
||||
ctrl.close();
|
||||
expect(modalInstance.dismiss).toHaveBeenCalledWith('exit');
|
||||
});
|
||||
|
||||
it('should have a method to convert the tests to a string',
|
||||
function () {
|
||||
scope.tests = ['t2', 't1', 't3'];
|
||||
ctrl.tests = ['t2', 't1', 't3'];
|
||||
var expectedString = 't1\nt2\nt3';
|
||||
expect(scope.getTestListString()).toEqual(expectedString);
|
||||
expect(ctrl.getTestListString()).toEqual(expectedString);
|
||||
});
|
||||
});
|
||||
|
||||
describe('testRaiseAlertModalController', function() {
|
||||
var data;
|
||||
var scope, modalInstance;
|
||||
describe('TestRaiseAlertModalController', function() {
|
||||
var data, modalInstance, ctrl;
|
||||
|
||||
data = {
|
||||
mode: 'success',
|
||||
@ -593,22 +586,19 @@ describe('Refstack controllers', function () {
|
||||
text: 'operation successful'
|
||||
};
|
||||
|
||||
beforeEach(inject(function ($rootScope, $controller) {
|
||||
scope = $rootScope.$new();
|
||||
beforeEach(inject(function ($controller) {
|
||||
modalInstance = {
|
||||
dismiss: jasmine.createSpy('modalInstance.dismiss'),
|
||||
close: jasmine.createSpy('modalInstance.close')
|
||||
};
|
||||
$controller('raiseAlertModalController', {
|
||||
$scope: scope,
|
||||
$modalInstance: modalInstance,
|
||||
data: data
|
||||
});
|
||||
ctrl = $controller('RaiseAlertModalController',
|
||||
{$modalInstance: modalInstance, data: data}
|
||||
);
|
||||
}));
|
||||
|
||||
it('should close',
|
||||
function () {
|
||||
scope.close();
|
||||
ctrl.close();
|
||||
expect(modalInstance.close).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user