Added groundwork for the refstack user-interface.
Used a combination of AngularJS and Bootstrap to form a preliminary front-end website for Refstack. Most of the content text can be considered placeholders and is subject to change. Change-Id: Ide82783478d1863052fe54d02ca6ee88113c46b2
This commit is contained in:
parent
649137a0b0
commit
cfe34d9371
3
refstack-ui/.bowerrc
Normal file
3
refstack-ui/.bowerrc
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"directory": "app/assets/lib"
|
||||
}
|
9
refstack-ui/.gitignore
vendored
Normal file
9
refstack-ui/.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
.tmp
|
||||
AUTHORS
|
||||
ChangeLog
|
||||
build/
|
||||
cover/
|
||||
dist
|
||||
node_modules
|
||||
npm-debug.log
|
||||
app/assets/lib
|
36
refstack-ui/README.rst
Normal file
36
refstack-ui/README.rst
Normal file
@ -0,0 +1,36 @@
|
||||
=======================
|
||||
Refstack User Interface
|
||||
=======================
|
||||
|
||||
User interface for interacting with the Refstack API.
|
||||
|
||||
Setup
|
||||
=====
|
||||
|
||||
You can start a development server by doing the following:
|
||||
|
||||
Install NodeJS and NPM:
|
||||
|
||||
:code:`curl -sL https://deb.nodesource.com/setup | sudo bash -`
|
||||
|
||||
:code:`sudo apt-get install nodejs`
|
||||
|
||||
From the Refstack project root directory, move into the UI folder:
|
||||
|
||||
:code:`cd refstack-ui`
|
||||
|
||||
Install dependencies and start the server:
|
||||
|
||||
:code:`npm start`
|
||||
|
||||
Doing this will automatically perform :code:`npm start` and :code:`bower install`
|
||||
to get all dependencies.
|
||||
|
||||
By default, as noted in package.json, the server will use 0.0.0.0:8080.
|
||||
|
||||
Test
|
||||
====
|
||||
|
||||
To run unit tests, simply perform the following:
|
||||
|
||||
:code:`npm test`
|
30
refstack-ui/app/app.js
Normal file
30
refstack-ui/app/app.js
Normal file
@ -0,0 +1,30 @@
|
||||
'use strict';
|
||||
|
||||
/* App Module */
|
||||
|
||||
var refstackApp = angular.module('refstackApp', [
|
||||
'ui.router', 'ui.bootstrap']);
|
||||
|
||||
refstackApp.config(['$stateProvider', '$urlRouterProvider',
|
||||
function($stateProvider, $urlRouterProvider) {
|
||||
$urlRouterProvider.otherwise('/');
|
||||
$stateProvider.
|
||||
state('home', {
|
||||
url: '/',
|
||||
templateUrl: '/components/home/home.html'
|
||||
}).
|
||||
state('about', {
|
||||
url: '/about',
|
||||
templateUrl: '/components/about/about.html'
|
||||
}).
|
||||
state('capabilities', {
|
||||
url: '/capabilities',
|
||||
templateUrl: '/components/capabilities/capabilities.html',
|
||||
controller: 'capabilitiesController'
|
||||
}).
|
||||
state('results', {
|
||||
url: '/results',
|
||||
templateUrl: '/components/results/results.html'
|
||||
})
|
||||
}]);
|
||||
|
1
refstack-ui/app/assets/capabilities/2015.03.json
Symbolic link
1
refstack-ui/app/assets/capabilities/2015.03.json
Symbolic link
@ -0,0 +1 @@
|
||||
../../../../defcore/2015.03.json
|
130
refstack-ui/app/assets/css/style.css
Normal file
130
refstack-ui/app/assets/css/style.css
Normal file
@ -0,0 +1,130 @@
|
||||
body {
|
||||
background: white;
|
||||
color: black;
|
||||
font-family: 'Helvetica Neue', 'Helvetica', 'Verdana', sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.heading {
|
||||
font-size: 3em;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.heading img {
|
||||
height: 50px;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
|
||||
form {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
input.error {
|
||||
background: #FAFF78;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: 'Futura-CondensedExtraBold', 'Futura', 'Helvetica', sans-serif;
|
||||
}
|
||||
|
||||
.footer {
|
||||
background: none repeat scroll 0% 0% #333;
|
||||
}
|
||||
|
||||
.required {
|
||||
color: #1D6503;
|
||||
}
|
||||
|
||||
.advisory {
|
||||
color: #9F8501;
|
||||
}
|
||||
|
||||
.deprecated {
|
||||
color: #B03838;
|
||||
}
|
||||
|
||||
.removed {
|
||||
color: #801601;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
word-spacing: 20px;
|
||||
background: #F8F8F8;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.capabilities {
|
||||
color: #4B4B4B;
|
||||
}
|
||||
|
||||
.capabilities a, .criteria a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.capabilities .capability-list-item {
|
||||
border-bottom: 2px solid #AFAFAF;
|
||||
padding-bottom: .6em;
|
||||
}
|
||||
|
||||
.capabilities .capability-name {
|
||||
font-size: 1.3em;
|
||||
font-weight: bold;
|
||||
color: black;
|
||||
}
|
||||
|
||||
#criteria {
|
||||
color: #4B4B4B;
|
||||
}
|
||||
|
||||
.criterion-name {
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.list-inline li:before {
|
||||
content: '\00BB';
|
||||
}
|
||||
|
||||
.flagged:before {
|
||||
color: #E6A100;
|
||||
content: '\2691';
|
||||
}
|
||||
|
||||
.program-about {
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
.jumbotron .left {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.container .jumbotron {
|
||||
background: #F6F6F6;
|
||||
border-top: 2px solid #C9C9C9;
|
||||
border-bottom: 2px solid #C9C9C9;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.jumbotron .right {
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.jumbotron img {
|
||||
width: 70%;
|
||||
height: 70%;
|
||||
}
|
BIN
refstack-ui/app/assets/img/openstack-logo.png
Normal file
BIN
refstack-ui/app/assets/img/openstack-logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
refstack-ui/app/assets/img/refstack-logo.png
Executable file
BIN
refstack-ui/app/assets/img/refstack-logo.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
3
refstack-ui/app/assets/js/refstack.js
Normal file
3
refstack-ui/app/assets/js/refstack.js
Normal file
@ -0,0 +1,3 @@
|
||||
'use strict';
|
||||
|
||||
/* Miscellaneous Refstack JavaScript */
|
93
refstack-ui/app/components/about/about.html
Normal file
93
refstack-ui/app/components/about/about.html
Normal file
@ -0,0 +1,93 @@
|
||||
<p>
|
||||
<strong>Overview</strong>
|
||||
</p>
|
||||
<p>Refstack intends on being THE source of tools for interoperability testing
|
||||
of OpenStack clouds.</p>
|
||||
<p>Refstack provides users in the OpenStack community with a Tempest wrapper,
|
||||
refstack-client, that helps to verify interoperability of their cloud
|
||||
with other OpenStack clouds. It does so by validating any cloud
|
||||
implementation against the OpenStack Tempest API tests.</p>
|
||||
<p>
|
||||
<strong>Refstack and DefCore</strong> - The prototypical use case for Refstack provides
|
||||
the DefCore Committee the tools for vendors and other users to run API
|
||||
tests against their clouds to provide the DefCore committee with a reliable
|
||||
overview of what APIs and capabilities are being used in the marketplace.
|
||||
This will help to guide the DefCore-defined capabilities and help ensure
|
||||
interoperability across the entire OpenStack ecosystem. It can also
|
||||
be used to validate clouds against existing DefCore capability lists,
|
||||
giving you assurance that your cloud faithfully implements OpenStack
|
||||
standards.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Value Add for Vendors</strong> - Vendors can use Refstack to demonstrate that
|
||||
their distros, and/or their customers' installed clouds remain with OpenStack
|
||||
after their software has been incorporated into the distro or cloud.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Refstack consists of two parts:</strong>
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<dl>
|
||||
<dt>
|
||||
<strong>refstack-api</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
<p>Our API isn't just for us to collect data from private and public cloud
|
||||
vendors. It can be used by vendors in house to compare interoperability
|
||||
data over time.</p>
|
||||
<ul>
|
||||
<li>install docs:
|
||||
<a href="https://github.com/stackforge/refstack/blob/master/doc/refstack.md">doc/refstack.md</a>
|
||||
</li>
|
||||
<li>repository:
|
||||
<a href="http://git.openstack.org/cgit/stackforge/refstack">http://git.openstack.org/cgit/stackforge/refstack</a>
|
||||
</li>
|
||||
<li>storyboard:
|
||||
<a href="https://storyboard.openstack.org/#!/project/700">https://storyboard.openstack.org/#!/project/700</a>
|
||||
</li>
|
||||
<li>reviews:
|
||||
<a href="https://review.openStack.org/#q,status:open+refstack,n,z">https://review.OpenStack.org/#q,status:open+refstack,n,z</a>
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>
|
||||
<dl>
|
||||
<dt>
|
||||
<strong>refstack-client</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
<p>refstack-client contains the tools you will need to run the DefCore tests.</p>
|
||||
<ul>
|
||||
<li>repository:
|
||||
<a href="http://git.openstack.org/cgit/stackforge/refstack-client">http://git.openstack.org/cgit/stackforge/refstack-client</a>
|
||||
</li>
|
||||
<li>storyboard:
|
||||
<a href="https://storyboard.openstack.org/#!/project/703">https://storyboard.openstack.org/#!/project/703</a>
|
||||
</li>
|
||||
<li>reviews:
|
||||
<a href="https://review.openstack.org/#q,status:open+refstack-client,n,z">https://review.openstack.org/#q,status:open+refstack-client,n,z</a>
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
<strong>Get involved!</strong>
|
||||
</p>
|
||||
<ul>
|
||||
<li>Mailing List:
|
||||
<a href="mailto:fits%40OpenStack.org">fits@OpenStack.org</a>
|
||||
</li>
|
||||
<li>IRC: #refstack on Freenode</li>
|
||||
<li>Dev Meetings: Mondays @ 19:00 UTC in #openstack-meeting-alt on Freenode</li>
|
||||
<li>Web-site:
|
||||
<a href="http://refstack.net">http://refstack.net</a>
|
||||
</li>
|
||||
<li>Wiki:
|
||||
<a href="https://wiki.OpenStack.org/wiki/refstack">https://wiki.OpenStack.org/wiki/refstack</a>
|
||||
</li>
|
||||
</ul>
|
71
refstack-ui/app/components/capabilities/capabilities.html
Normal file
71
refstack-ui/app/components/capabilities/capabilities.html
Normal file
@ -0,0 +1,71 @@
|
||||
<h3>DefCore Capabilities</h3>
|
||||
<strong>Version:</strong>
|
||||
<select ng-model="version" ng-change="update()">
|
||||
<option value="2015.03">2015.03</option>
|
||||
</select>
|
||||
<br /><br />
|
||||
<strong>Target Program:</strong>
|
||||
<select ng-model="target" >
|
||||
<option value="platform">OpenStack Powered Platform</option>
|
||||
<option value="compute">OpenStack Powered Compute</option>
|
||||
<option value="object">OpenStack Powered Object Storage</option>
|
||||
</select>
|
||||
<span class="program-about"><a target="_blank" href="http://www.openstack.org/brand/interop/">About</a></span>
|
||||
<br /><br />
|
||||
|
||||
<strong>Capability Status:</strong>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="status.required" ng-true-value="'required'" ng-false-value="''">
|
||||
<span class="required">Required</span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" ng-model="status.advisory" ng-true-value="'advisory'" ng-false-value="''">
|
||||
<span class="advisory">Advisory</span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" ng-model="status.deprecated" ng-true-value="'deprecated'" ng-false-value="''">
|
||||
<span class="deprecated">Deprecated</span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" ng-model="status.removed" ng-true-value="'removed'" ng-false-value="''">
|
||||
<span class="removed">Removed</span>
|
||||
</label>
|
||||
</div>
|
||||
<p><small>Tests marked with <span class="flagged"></span> are tests flagged by DefCore.</small></p>
|
||||
|
||||
<ol class="capabilities">
|
||||
<li class="capability-list-item" ng-repeat="capability in capabilities.capabilities | arrayConverter | filter:filterProgram | filter:filterStatus">
|
||||
<span class="capability-name">{{capability.name}}</span><br />
|
||||
<em>{{capability.description}}</em><br />
|
||||
Status: <span class="{{capability.status}}">{{capability.status}}</span><br />
|
||||
<a ng-click="hideAchievements = !hideAchievements">Achievements ({{capability.achievements.length}})</a><br />
|
||||
<ol collapse="hideAchievements" 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">
|
||||
<li ng-repeat="test in capability.tests">
|
||||
<span ng-class="{'flagged': capability.flagged.indexOf(test) > -1}"> {{test}}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
<hr>
|
||||
|
||||
<div class="criteria">
|
||||
<h4><a ng-click="hideCriteria = !hideCriteria">Criteria</a></h4>
|
||||
<div collapse="hideCriteria">
|
||||
<ul>
|
||||
<li ng-repeat="(key, criterion) in capabilities.criteria">
|
||||
<span class="criterion-name">{{criterion.name}}</span><br />
|
||||
<em>{{criterion.Description}}</em><br />
|
||||
Weight: {{criterion.weight}}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<br /><br />
|
@ -0,0 +1,63 @@
|
||||
'use strict';
|
||||
|
||||
/* Refstack Capabilities Controller */
|
||||
|
||||
var refstackApp = angular.module('refstackApp');
|
||||
|
||||
refstackApp.controller('capabilitiesController', ['$scope', '$http', function($scope, $http) {
|
||||
$scope.version = '2015.03';
|
||||
$scope.hideAchievements = true;
|
||||
$scope.hideTests = true;
|
||||
$scope.target = 'platform';
|
||||
$scope.status = {
|
||||
required: 'required',
|
||||
advisory: '',
|
||||
deprecated: '',
|
||||
removed: ''
|
||||
};
|
||||
|
||||
$scope.update = function() {
|
||||
// Rate-limiting is an issue with this URL. Using a local copy for now.
|
||||
// var content_url = 'https://api.github.com/repos/openstack/defcore/contents/'.concat($scope.version, '.json');
|
||||
var content_url = 'assets/capabilities/'.concat($scope.version, '.json');
|
||||
$http.get(content_url).success(function(data) {
|
||||
//$scope.data = data;
|
||||
//$scope.capabilities = JSON.parse(atob($scope.data.content.replace(/\s/g, '')));
|
||||
$scope.capabilities = data;
|
||||
}).error(function(error) {
|
||||
console.log(error);
|
||||
$scope.capabilities = 'Error retrieving capabilities.';
|
||||
});
|
||||
}
|
||||
$scope.update()
|
||||
|
||||
$scope.filterProgram = function(capability){
|
||||
var components = $scope.capabilities.components;
|
||||
if ($scope.target === 'platform') {
|
||||
var platform_components = $scope.capabilities.platform.required;
|
||||
var cap_array = [];
|
||||
// For each component required for the platform program.
|
||||
angular.forEach(platform_components, function(component) {
|
||||
// Get each capability belonging to each status.
|
||||
angular.forEach(components[component], function(capabilities) {
|
||||
cap_array = cap_array.concat(capabilities);
|
||||
});
|
||||
});
|
||||
return (cap_array.indexOf(capability.id) > -1);
|
||||
}
|
||||
else {
|
||||
var cap_array = [];
|
||||
angular.forEach(components[$scope.target], function(capabilities) {
|
||||
cap_array = cap_array.concat(capabilities);
|
||||
});
|
||||
return (cap_array.indexOf(capability.id) > -1);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.filterStatus = function(capability){
|
||||
return capability.status === $scope.status.required ||
|
||||
capability.status === $scope.status.advisory ||
|
||||
capability.status === $scope.status.deprecated ||
|
||||
capability.status === $scope.status.removed;
|
||||
};
|
||||
}]);
|
31
refstack-ui/app/components/home/home.html
Normal file
31
refstack-ui/app/components/home/home.html
Normal file
@ -0,0 +1,31 @@
|
||||
<div class="jumbotron">
|
||||
<div class="pull-left left">
|
||||
<h1>OpenStack Interoperability</h1>
|
||||
<p>Refstack is a source of tools for OpenStack interoperability testing.</p>
|
||||
</div>
|
||||
<div class="pull-right right">
|
||||
<img src="assets/img/openstack-logo.png" alt="OpenStack">
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<h4>What is Refstack?</h4>
|
||||
<ul>
|
||||
<li>Toolset for testing interoperability between OpenStack clouds.</li>
|
||||
<li>Database backed website supporting collection and publication of
|
||||
community test results for OpenStack.</li>
|
||||
<li>User interface to display individual test run results.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<h4>OpenStack Marketing Programs</h4>
|
||||
<ul>
|
||||
<li>OpenStack Powered Platform</li>
|
||||
<li>OpenStack Powered Compute</li>
|
||||
<li>OpenStack Powered Object Storage</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
1
refstack-ui/app/components/results/results.html
Normal file
1
refstack-ui/app/components/results/results.html
Normal file
@ -0,0 +1 @@
|
||||
<p>Community results list here.</p>
|
BIN
refstack-ui/app/favicon.ico
Normal file
BIN
refstack-ui/app/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 318 B |
49
refstack-ui/app/index.html
Normal file
49
refstack-ui/app/index.html
Normal file
@ -0,0 +1,49 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Copyright (c) 2015 IBM Corp.
|
||||
|
||||
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.
|
||||
-->
|
||||
<html ng-app="refstackApp">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="description" content="Refstack">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<title>Refstack</title>
|
||||
|
||||
<link rel="shorcut icon" href="favicon.ico">
|
||||
|
||||
<link rel="stylesheet" href="assets/lib/bootstrap/dist/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="assets/css/style.css">
|
||||
|
||||
<script src="assets/lib/angular/angular.js"></script>
|
||||
<script src="assets/lib/angular-ui-router/release/angular-ui-router.js"></script>
|
||||
<script src="assets/lib/angular-bootstrap/ui-bootstrap.min.js"></script>
|
||||
<script src="app.js"></script>
|
||||
<script src="assets/js/refstack.js"></script>
|
||||
|
||||
<!-- Controllers -->
|
||||
<script src="shared/header/headerController.js"></script>
|
||||
<script src="components/capabilities/capabilitiesController.js"></script>
|
||||
|
||||
<!-- Filters -->
|
||||
<script src="shared/filters.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body class="container">
|
||||
<header ng-include src="'shared/header/header.html'"></header>
|
||||
|
||||
<div ui-view></div>
|
||||
</body>
|
||||
</html>
|
4
refstack-ui/app/robots.txt
Normal file
4
refstack-ui/app/robots.txt
Normal file
@ -0,0 +1,4 @@
|
||||
# robotstxt.org
|
||||
|
||||
User-agent: *
|
||||
|
18
refstack-ui/app/shared/filters.js
Normal file
18
refstack-ui/app/shared/filters.js
Normal file
@ -0,0 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
/* Refstack Filters */
|
||||
|
||||
var refstackApp = angular.module('refstackApp');
|
||||
|
||||
// Convert an object of objects to an array of objects to use with ng-repeat
|
||||
// filters.
|
||||
refstackApp.filter('arrayConverter', function() {
|
||||
return function(objects) {
|
||||
var array = [];
|
||||
angular.forEach(objects, function(object, key) {
|
||||
object['id'] = key;
|
||||
array.push(object);
|
||||
});
|
||||
return array;
|
||||
};
|
||||
});
|
26
refstack-ui/app/shared/header/header.html
Normal file
26
refstack-ui/app/shared/header/header.html
Normal file
@ -0,0 +1,26 @@
|
||||
<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">
|
||||
<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">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbar" collapse="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('/results')}"><a ui-sref="results">Community Results</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
18
refstack-ui/app/shared/header/headerController.js
Normal file
18
refstack-ui/app/shared/header/headerController.js
Normal file
@ -0,0 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
/* Refstack Header Controller */
|
||||
|
||||
var refstackApp = angular.module('refstackApp')
|
||||
refstackApp.controller('headerController', ['$scope', '$location', function($scope, $location) {
|
||||
$scope.navbarCollapsed = true;
|
||||
$scope.isActive = function(viewLocation) {
|
||||
var path = $location.path().substr(0, viewLocation.length);
|
||||
if (path === viewLocation) {
|
||||
// Make sure "/" only matches when viewLocation is "/".
|
||||
if (!($location.path().substr(0).length > 1 && viewLocation.length === 1 )) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}]);
|
18
refstack-ui/bower.json
Normal file
18
refstack-ui/bower.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "refstack-ui",
|
||||
"version": "0.0.1",
|
||||
"description": "Refstack user interface",
|
||||
"dependencies": {
|
||||
"angular": "1.3.15",
|
||||
"angular-ui-router": "0.2.13",
|
||||
"angular-resource": "1.3.15",
|
||||
"angular-bootstrap": "0.12.1",
|
||||
"bootstrap": "3.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"angular-mocks": "1.3.15"
|
||||
},
|
||||
"resolutions": {
|
||||
"angular": "1.3.15"
|
||||
}
|
||||
}
|
28
refstack-ui/package.json
Normal file
28
refstack-ui/package.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"name": "refstack-ui",
|
||||
"description": "A user interface for Refstack",
|
||||
"license": "Apache2",
|
||||
"devDependencies": {
|
||||
"karma": "^0.12.23",
|
||||
"karma-chrome-launcher": "^0.1.5",
|
||||
"karma-jasmine": "^0.2.2",
|
||||
"karma-firefox-launcher": "^0.1.3",
|
||||
"protractor": "~1.0.0",
|
||||
"http-server": "^0.6.1",
|
||||
"tmp": "0.0.23",
|
||||
"bower": "1.3.12",
|
||||
"shelljs": "^0.2.6"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "bower install",
|
||||
|
||||
"prestart": "npm install",
|
||||
"start": "http-server ./app -a 0.0.0.0 -p 8080",
|
||||
|
||||
"pretest": "npm install",
|
||||
"test": "node node_modules/karma/bin/karma start tests/karma.conf.js",
|
||||
"test-single-run": "node node_modules/karma/bin/karma start tests/karma.conf.js --single-run"
|
||||
}
|
||||
}
|
42
refstack-ui/tests/karma.conf.js
Normal file
42
refstack-ui/tests/karma.conf.js
Normal file
@ -0,0 +1,42 @@
|
||||
module.exports = function(config){
|
||||
config.set({
|
||||
|
||||
basePath : '../',
|
||||
|
||||
files : [
|
||||
// Angular libraries.
|
||||
'app/assets/lib/angular/angular.js',
|
||||
'app/assets/lib/angular-ui-router/release/angular-ui-router.js',
|
||||
'app/assets/lib/angular-bootstrap/ui-bootstrap.min.js',
|
||||
'app/assets/lib/angular-mocks/angular-mocks.js',
|
||||
|
||||
// JS files.
|
||||
'app/app.js',
|
||||
'app/components/**/*.js',
|
||||
'app/shared/*.js',
|
||||
'app/shared/**/*.js',
|
||||
'app/assets/js/*.js',
|
||||
|
||||
// Test Specs.
|
||||
'tests/unit/*.js'
|
||||
],
|
||||
|
||||
autoWatch : true,
|
||||
|
||||
frameworks: ['jasmine'],
|
||||
|
||||
browsers : ['Firefox'],
|
||||
|
||||
plugins : [
|
||||
'karma-chrome-launcher',
|
||||
'karma-firefox-launcher',
|
||||
'karma-jasmine',
|
||||
],
|
||||
|
||||
junitReporter : {
|
||||
outputFile: 'test_out/unit.xml',
|
||||
suite: 'unit'
|
||||
}
|
||||
|
||||
});
|
||||
};
|
94
refstack-ui/tests/unit/ControllerSpec.js
Normal file
94
refstack-ui/tests/unit/ControllerSpec.js
Normal file
@ -0,0 +1,94 @@
|
||||
'use strict';
|
||||
|
||||
/* Jasmine specs for Refstack controllers */
|
||||
describe('Refstack controllers', function() {
|
||||
|
||||
describe('headerController', function() {
|
||||
var scope, ctrl, $location;
|
||||
beforeEach(module('refstackApp'));
|
||||
|
||||
beforeEach(inject(function($rootScope, $controller, _$location_) {
|
||||
scope = $rootScope.$new();
|
||||
$location = _$location_;
|
||||
ctrl = $controller('headerController', {$scope: scope});
|
||||
}));
|
||||
|
||||
it('should set "navbarCollapsed" to true', function() {
|
||||
expect(scope.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);
|
||||
|
||||
$location.path('/results?cpid=123&foo=bar');
|
||||
expect($location.path()).toBe('/results?cpid=123&foo=bar');
|
||||
expect(scope.isActive('/results')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('capabilitiesController', function() {
|
||||
var scope, ctrl, $httpBackend;
|
||||
beforeEach(module('refstackApp'));
|
||||
|
||||
beforeEach(inject(function(_$httpBackend_, $rootScope, $controller) {
|
||||
$httpBackend = _$httpBackend_;
|
||||
scope = $rootScope.$new();
|
||||
ctrl = $controller('capabilitiesController', {$scope: scope});
|
||||
}));
|
||||
|
||||
it('should set default states', function() {
|
||||
expect(scope.hideAchievements).toBe(true);
|
||||
expect(scope.hideTests).toBe(true);
|
||||
expect(scope.version).toBe('2015.03');
|
||||
expect(scope.target).toBe('platform');
|
||||
expect(scope.status).toEqual({required: 'required', advisory: '',
|
||||
deprecated: '', removed: ''});
|
||||
|
||||
});
|
||||
|
||||
it('should fetch the selected capabilities version', function() {
|
||||
$httpBackend.expectGET('assets/capabilities/2015.03.json').respond({'foo': 'bar'});
|
||||
$httpBackend.flush();
|
||||
expect(scope.capabilities).toEqual({'foo': 'bar'});
|
||||
});
|
||||
|
||||
it('should have a function to check if a status filter is selected', function() {
|
||||
expect(scope.filterStatus({'status': 'required'})).toBe(true);
|
||||
expect(scope.filterStatus({'status': 'advisory'})).toBe(false);
|
||||
expect(scope.filterStatus({'status': 'deprecated'})).toBe(false);
|
||||
expect(scope.filterStatus({'status': 'removed'})).toBe(false);
|
||||
|
||||
scope.status = {
|
||||
required: 'required',
|
||||
advisory: 'advisory',
|
||||
deprecated: 'deprecated',
|
||||
removed: 'removed'
|
||||
};
|
||||
|
||||
expect(scope.filterStatus({'status': 'required'})).toBe(true);
|
||||
expect(scope.filterStatus({'status': 'advisory'})).toBe(true);
|
||||
expect(scope.filterStatus({'status': 'deprecated'})).toBe(true);
|
||||
expect(scope.filterStatus({'status': 'removed'})).toBe(true);
|
||||
});
|
||||
|
||||
it('should have a function to check if a capability belongs to a program', function() {
|
||||
scope.capabilities = {'platform': {'required': ['compute']},
|
||||
'components': {
|
||||
'compute': {
|
||||
'required': ['cap_id_1'],
|
||||
'advisory': ['cap_id_2'],
|
||||
'deprecated': ['cap_id_3'],
|
||||
'removed': ['cap_id_4']
|
||||
}
|
||||
}};
|
||||
expect(scope.filterProgram({'id': 'cap_id_1'})).toBe(true);
|
||||
expect(scope.filterProgram({'id': 'cap_id_2'})).toBe(true);
|
||||
expect(scope.filterProgram({'id': 'cap_id_3'})).toBe(true);
|
||||
expect(scope.filterProgram({'id': 'cap_id_4'})).toBe(true);
|
||||
expect(scope.filterProgram({'id': 'cap_id_5'})).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
20
refstack-ui/tests/unit/FilterSpec.js
Normal file
20
refstack-ui/tests/unit/FilterSpec.js
Normal file
@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
/* Jasmine specs for Refstack filters */
|
||||
describe('Refstack filters', function() {
|
||||
|
||||
describe('Filter: arrayConverter', function() {
|
||||
var $filter;
|
||||
beforeEach(module('refstackApp'));
|
||||
beforeEach(inject(function(_$filter_) {
|
||||
$filter = _$filter_('arrayConverter');
|
||||
}));
|
||||
|
||||
it('should convert dict to array of dict values', function () {
|
||||
var object = { 'id1': {'key1': 'value1'}, 'id2': {'key2': 'value2'}};
|
||||
var expected = [{'key1': 'value1', 'id': 'id1'},
|
||||
{'key2': 'value2', 'id': 'id2'}];
|
||||
expect($filter(object)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user