summaryrefslogtreecommitdiffstats
path: root/testapi/opnfv_testapi/ui
diff options
context:
space:
mode:
Diffstat (limited to 'testapi/opnfv_testapi/ui')
-rw-r--r--testapi/opnfv_testapi/ui/Gruntfile.js162
-rw-r--r--testapi/opnfv_testapi/ui/app.js260
-rw-r--r--testapi/opnfv_testapi/ui/components/about/about.html (renamed from testapi/opnfv_testapi/ui/about/about.html)0
-rw-r--r--testapi/opnfv_testapi/ui/components/auth-failure/authFailureController.js (renamed from testapi/opnfv_testapi/ui/auth-failure/authFailureController.js)0
-rw-r--r--testapi/opnfv_testapi/ui/components/home/home.html (renamed from testapi/opnfv_testapi/ui/home/home.html)0
-rw-r--r--testapi/opnfv_testapi/ui/components/logout/logout.html (renamed from testapi/opnfv_testapi/ui/logout/logout.html)0
-rw-r--r--testapi/opnfv_testapi/ui/components/logout/logoutController.js (renamed from testapi/opnfv_testapi/ui/logout/logoutController.js)0
-rw-r--r--testapi/opnfv_testapi/ui/components/pods/pods.html (renamed from testapi/opnfv_testapi/ui/pods/pods.html)0
-rw-r--r--testapi/opnfv_testapi/ui/components/pods/podsController.js (renamed from testapi/opnfv_testapi/ui/pods/podsController.js)0
-rw-r--r--testapi/opnfv_testapi/ui/components/profile/importPubKeyModal.html (renamed from testapi/opnfv_testapi/ui/profile/importPubKeyModal.html)0
-rw-r--r--testapi/opnfv_testapi/ui/components/profile/profile.html (renamed from testapi/opnfv_testapi/ui/profile/profile.html)0
-rw-r--r--testapi/opnfv_testapi/ui/components/profile/profileController.js (renamed from testapi/opnfv_testapi/ui/profile/profileController.js)0
-rw-r--r--testapi/opnfv_testapi/ui/components/profile/showPubKeyModal.html (renamed from testapi/opnfv_testapi/ui/profile/showPubKeyModal.html)0
-rw-r--r--testapi/opnfv_testapi/ui/components/projects/project/project.html (renamed from testapi/opnfv_testapi/ui/projects/project/project.html)0
-rw-r--r--testapi/opnfv_testapi/ui/components/projects/project/projectController.js (renamed from testapi/opnfv_testapi/ui/projects/project/projectController.js)0
-rw-r--r--testapi/opnfv_testapi/ui/components/projects/project/updateModal.html (renamed from testapi/opnfv_testapi/ui/projects/project/updateModal.html)0
-rw-r--r--testapi/opnfv_testapi/ui/components/projects/projects.html (renamed from testapi/opnfv_testapi/ui/projects/projects.html)0
-rw-r--r--testapi/opnfv_testapi/ui/components/projects/projectsController.js (renamed from testapi/opnfv_testapi/ui/projects/projectsController.js)0
-rw-r--r--testapi/opnfv_testapi/ui/components/results-report/partials/editTestModal.html (renamed from testapi/opnfv_testapi/ui/results-report/partials/editTestModal.html)0
-rw-r--r--testapi/opnfv_testapi/ui/components/results-report/partials/fullTestListModal.html (renamed from testapi/opnfv_testapi/ui/results-report/partials/fullTestListModal.html)0
-rw-r--r--testapi/opnfv_testapi/ui/components/results-report/partials/reportDetails.html (renamed from testapi/opnfv_testapi/ui/results-report/partials/reportDetails.html)0
-rw-r--r--testapi/opnfv_testapi/ui/components/results-report/resultsReport.html (renamed from testapi/opnfv_testapi/ui/results-report/resultsReport.html)0
-rw-r--r--testapi/opnfv_testapi/ui/components/results-report/resultsReportController.js (renamed from testapi/opnfv_testapi/ui/results-report/resultsReportController.js)0
-rw-r--r--testapi/opnfv_testapi/ui/components/results/results.html (renamed from testapi/opnfv_testapi/ui/results/results.html)0
-rw-r--r--testapi/opnfv_testapi/ui/components/results/resultsController.js (renamed from testapi/opnfv_testapi/ui/results/resultsController.js)0
-rw-r--r--testapi/opnfv_testapi/ui/config.json1
-rwxr-xr-xtestapi/opnfv_testapi/ui/favicon-16x16.pngbin0 -> 638 bytes
-rwxr-xr-xtestapi/opnfv_testapi/ui/favicon-32x32.pngbin0 -> 1540 bytes
-rw-r--r--testapi/opnfv_testapi/ui/favicon.icobin0 -> 318 bytes
-rw-r--r--testapi/opnfv_testapi/ui/index.html62
-rw-r--r--testapi/opnfv_testapi/ui/package.json18
-rw-r--r--testapi/opnfv_testapi/ui/robots.txt4
-rw-r--r--testapi/opnfv_testapi/ui/shared/alerts/alertModal.html8
-rw-r--r--testapi/opnfv_testapi/ui/shared/alerts/alertModalFactory.js74
-rw-r--r--testapi/opnfv_testapi/ui/shared/alerts/confirmModal.html23
-rw-r--r--testapi/opnfv_testapi/ui/shared/alerts/confirmModalFactory.js67
-rw-r--r--testapi/opnfv_testapi/ui/shared/filters.js55
-rw-r--r--testapi/opnfv_testapi/ui/shared/header/header.html55
-rw-r--r--testapi/opnfv_testapi/ui/shared/header/headerController.js63
39 files changed, 852 insertions, 0 deletions
diff --git a/testapi/opnfv_testapi/ui/Gruntfile.js b/testapi/opnfv_testapi/ui/Gruntfile.js
new file mode 100644
index 0000000..13f484f
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/Gruntfile.js
@@ -0,0 +1,162 @@
+
+module.exports = function (grunt) {
+ require('load-grunt-tasks')(grunt);
+ require('grunt-protractor-coverage')(grunt);
+ grunt.loadNpmTasks('grunt-shell-spawn');
+ grunt.loadNpmTasks('grunt-wait');
+ grunt.loadNpmTasks('grunt-contrib-copy');
+ grunt.loadNpmTasks('grunt-contrib-connect');
+ grunt.initConfig({
+ connect: {
+ server: {
+ options: {
+ port: 8000,
+ base: './',
+ middleware: function(connect, options, middlewares) {
+ middlewares.unshift(function(req, res, next) {
+ if (req.method.toUpperCase() == 'POST' || req.method.toUpperCase() == "PUT"){
+ req.method='GET';
+ }
+ return next();
+ });
+ return middlewares;
+ }
+ }
+ }
+ },
+ copy: {
+ assets: {
+ expand: true,
+ cwd: 'assets',
+ src: '**',
+ dest: 'testapi-ui/assets',
+ },
+ components: {
+ expand: true,
+ cwd: '../../../opnfv_testapi/ui',
+ src: '**',
+ dest: 'components',
+ },
+ copyComponents: {
+ expand: true,
+ cwd: 'components',
+ src: '**',
+ dest: 'testapi-ui/components',
+ },
+ shared: {
+ expand: true,
+ cwd: 'shared',
+ src: '**',
+ dest: 'testapi-ui/shared',
+ },
+ filesPng: {
+ expand: true,
+ src: '*.png',
+ dest: 'testapi-ui/',
+ },
+ filesIco: {
+ expand: true,
+ src: '*.ico',
+ dest: 'testapi-ui/',
+ },
+ filesJs: {
+ expand: true,
+ src: 'app.js',
+ dest: 'testapi-ui/',
+ },
+ filesJson: {
+ expand: true,
+ src: 'config.json',
+ dest: 'testapi-ui/',
+ }
+ },
+ wait: {
+ default: {
+ options: {
+ delay: 3000
+ }
+ }
+ },
+ shell: {
+ updateSelenium: {
+ command: 'node_modules/protractor/bin/webdriver-manager update',
+ options: {
+ async: false
+ }
+ },
+ startSelenium: {
+ command: 'node_modules/protractor/bin/webdriver-manager start',
+ options: {
+ async: true
+ }
+ },
+ deleteFiles: {
+ command: 'rm -r testapi-ui && rm -r components',
+ options: {
+ async: false
+ }
+ },
+ options: {
+ stdout: false,
+ stderr: false
+ }
+ },
+ instrument: {
+ files: ['components/**/*.js'],
+ options: {
+ lazy: false,
+ basePath: "./testapi-ui/"
+ }
+ },
+ karma: {
+ unit: {
+ configFile: '../../../opnfv_testapi/tests/UI/karma.conf.js'
+ }
+ },
+ protractor_coverage: {
+ options: {
+ keepAlive: true,
+ noColor: false,
+ coverageDir: '../../../opnfv_testapi/tests/UI/coverage',
+ args: {
+ specs: ['../../../opnfv_testapi/tests/UI/e2e/podsControllerSpec.js',
+ '../../../opnfv_testapi/tests/UI/e2e/projectsControllerSpec.js',
+ '../../../opnfv_testapi/tests/UI/e2e/projectControllerSpec.js']
+ }
+ },
+ local: {
+ options: {
+ configFile: '../../../opnfv_testapi/tests/UI/protractor-conf.js'
+ }
+ }
+ },
+ makeReport: {
+ src: '../../../opnfv_testapi/tests/UI/coverage/*.json',
+ options: {
+ print: 'detail'
+ }
+ }
+ });
+ grunt.registerTask('test', [
+ 'karma:unit'
+ ]);
+ grunt.registerTask('e2e', [
+ 'copy:assets',
+ 'copy:components',
+ 'copy:copyComponents',
+ 'copy:shared',
+ 'copy:filesPng',
+ 'copy:filesIco',
+ 'copy:filesJs',
+ 'copy:filesJson',
+ 'instrument',
+ 'connect',
+ 'shell:updateSelenium',
+ 'shell:startSelenium',
+ 'wait:default',
+ 'protractor_coverage',
+ 'makeReport',
+ 'shell:deleteFiles'
+
+ ]);
+}
diff --git a/testapi/opnfv_testapi/ui/app.js b/testapi/opnfv_testapi/ui/app.js
new file mode 100644
index 0000000..dbb56a6
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/app.js
@@ -0,0 +1,260 @@
+/*
+ * 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. */
+ angular
+ .module('testapiApp', [
+ 'ui.router','ui.bootstrap', 'cgBusy',
+ 'ngResource', 'angular-confirm'
+ ]);
+
+ angular
+ .module('testapiApp')
+ .config(configureRoutes);
+
+ angular
+ .module('testapiApp')
+ .directive('dynamicModel', ['$compile', '$parse', function ($compile, $parse) {
+ return {
+ restrict: 'A',
+ terminal: true,
+ priority: 100000,
+ link: function (scope, elem) {
+ var name = $parse(elem.attr('dynamic-model'))(scope);
+ elem.removeAttr('dynamic-model');
+ elem.attr('ng-model', name);
+ $compile(elem)(scope);
+ }
+ };
+ }]);
+
+ configureRoutes.$inject = ['$stateProvider', '$urlRouterProvider'];
+
+ /**
+ * Handle application routing. Specific templates and controllers will be
+ * used based on the URL route.
+ */
+ function configureRoutes($stateProvider, $urlRouterProvider) {
+ $urlRouterProvider.otherwise('/');
+ $stateProvider.
+ state('home', {
+ url: '/',
+ templateUrl: 'testapi-ui/components/home/home.html'
+ }).
+ state('about', {
+ url: '/about',
+ templateUrl: 'testapi-ui/components/about/about.html'
+ }).
+ state('pods', {
+ url: '/pods',
+ templateUrl: 'testapi-ui/components/pods/pods.html',
+ controller: 'PodsController as ctrl'
+ }).
+ state('projects', {
+ url: '/projects',
+ templateUrl: 'testapi-ui/components/projects/projects.html',
+ controller: 'ProjectsController as ctrl'
+ }).
+ state('project', {
+ url: '/projects/:name',
+ templateUrl: 'testapi-ui/components/projects/project/project.html',
+ controller: 'ProjectController as ctrl'
+ }).
+ state('communityResults', {
+ url: '/community_results',
+ templateUrl: 'testapi-ui/components/results/results.html',
+ controller: 'ResultsController as ctrl'
+ }).
+ state('userResults', {
+ url: '/user_results',
+ templateUrl: 'testapi-ui/components/results/results.html',
+ controller: 'ResultsController as ctrl'
+ }).
+ state('resultsDetail', {
+ url: '/results/:testID',
+ templateUrl: 'testapi-ui/components/results-report' +
+ '/resultsReport.html',
+ controller: 'ResultsReportController as ctrl'
+ }).
+ state('profile', {
+ url: '/profile',
+ templateUrl: 'testapi-ui/components/profile/profile.html',
+ controller: 'ProfileController as ctrl'
+ }).
+ state('authFailure', {
+ url: '/auth_failure',
+ templateUrl: 'testapi-ui/components/home/home.html',
+ controller: 'AuthFailureController as ctrl'
+ }).
+ state('logout', {
+ url: '/logout',
+ templateUrl: 'testapi-ui/components/logout/logout.html',
+ controller: 'LogoutController as ctrl'
+ }).
+ state('userVendors', {
+ url: '/user_vendors',
+ templateUrl: '/testapi-ui/components/vendors/vendors.html',
+ controller: 'VendorsController as ctrl'
+ }).
+ state('publicVendors', {
+ url: '/public_vendors',
+ templateUrl: '/testapi-ui/components/vendors/vendors.html',
+ controller: 'VendorsController as ctrl'
+ }).
+ state('vendor', {
+ url: '/vendor/:vendorID',
+ templateUrl: '/swagger/testapi-ui/components/vendors/vendor.html',
+ controller: 'VendorController as ctrl'
+ }).
+ state('userProducts', {
+ url: '/user_products',
+ templateUrl: '/testapi-ui/components/products/products.html',
+ controller: 'ProductsController as ctrl'
+ }).
+ state('publicProducts', {
+ url: '/public_products',
+ templateUrl: '/testapi-ui/components/products/products.html',
+ controller: 'ProductsController as ctrl'
+ }).
+ state('cloud', {
+ url: '/cloud/:id',
+ templateUrl: '/testapi-ui/components/products/cloud.html',
+ controller: 'ProductController as ctrl'
+ }).
+ state('distro', {
+ url: '/distro/:id',
+ templateUrl: '/testapi-ui/components/products/distro.html',
+ controller: 'ProductController as ctrl'
+ });
+ }
+
+ angular
+ .module('testapiApp')
+ .config(disableHttpCache);
+
+ disableHttpCache.$inject = ['$httpProvider'];
+
+ /**
+ * Disable caching in $http requests. This is primarily for IE, as it
+ * tends to cache Angular IE requests.
+ */
+ function disableHttpCache($httpProvider) {
+ if (!$httpProvider.defaults.headers.get) {
+ $httpProvider.defaults.headers.get = {};
+ }
+ $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache';
+ $httpProvider.defaults.headers.get.Pragma = 'no-cache';
+ }
+
+ angular
+ .module('testapiApp')
+ .run(setup);
+
+ setup.$inject = [
+ '$http', '$rootScope', '$window', '$state', 'testapiApiUrl'
+ ];
+
+ /**
+ * Set up the app with injections into $rootscope. This is mainly for auth
+ * functions.
+ */
+ function setup($http, $rootScope, $window, $state, testapiApiUrl) {
+
+ $rootScope.auth = {};
+ $rootScope.auth.doSignIn = doSignIn;
+ $rootScope.auth.doSignOut = doSignOut;
+ $rootScope.auth.doSignCheck = doSignCheck;
+ $rootScope.auth.doSubmitterCheck = doSubmitterCheck;
+
+ var sign_in_url = testapiApiUrl + '/auth/signin';
+ var sign_out_url = testapiApiUrl + '/auth/signout';
+ var profile_url = testapiApiUrl + '/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.auth.currentUser = null;
+ $rootScope.auth.isAuthenticated = false;
+ $rootScope.auth.projectNames = [];
+ $window.location.href = sign_out_url;
+ }
+
+ /**
+ * This function checks to see if a user is logged in and
+ * authenticated.
+ */
+ function doSignCheck() {
+ return $http.get(profile_url, {withCredentials: true}).
+ success(function (data) {
+ $rootScope.auth.currentUser = data;
+ $rootScope.auth.isAuthenticated = true;
+ $rootScope.auth.projectNames = $rootScope.auth.doSubmitterCheck(data.groups);
+ }).
+ error(function () {
+ $rootScope.auth.currentUser = null;
+ $rootScope.auth.isAuthenticated = false;
+ $rootScope.auth.projectNames = [];
+ });
+ }
+
+ function doSubmitterCheck(groups){
+ var projectNames = []
+ for(var index=0;index<groups.length; index++){
+ if(groups[index].indexOf('-submitters')>=0){
+ projectNames.push(groups[index].split('-')[2])
+ }
+ }
+ return projectNames;
+ }
+
+ $rootScope.auth.doSignCheck();
+ }
+
+ angular
+ .element(document)
+ .ready(loadConfig);
+
+ /**
+ * Load config and start up the angular application.
+ */
+ 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.
+ angular.forEach(config, function(value, key) {
+ angular.module('testapiApp').constant(key, value);
+ });
+
+ angular.bootstrap(document, ['testapiApp']);
+ }
+
+ $http.get('testapi-ui/config.json').success(function (data) {
+ startApp(data);
+ }).error(function () {
+ startApp({});
+ });
+ }
+})();
diff --git a/testapi/opnfv_testapi/ui/about/about.html b/testapi/opnfv_testapi/ui/components/about/about.html
index 65860a8..65860a8 100644
--- a/testapi/opnfv_testapi/ui/about/about.html
+++ b/testapi/opnfv_testapi/ui/components/about/about.html
diff --git a/testapi/opnfv_testapi/ui/auth-failure/authFailureController.js b/testapi/opnfv_testapi/ui/components/auth-failure/authFailureController.js
index 29d1d70..29d1d70 100644
--- a/testapi/opnfv_testapi/ui/auth-failure/authFailureController.js
+++ b/testapi/opnfv_testapi/ui/components/auth-failure/authFailureController.js
diff --git a/testapi/opnfv_testapi/ui/home/home.html b/testapi/opnfv_testapi/ui/components/home/home.html
index 47d747f..47d747f 100644
--- a/testapi/opnfv_testapi/ui/home/home.html
+++ b/testapi/opnfv_testapi/ui/components/home/home.html
diff --git a/testapi/opnfv_testapi/ui/logout/logout.html b/testapi/opnfv_testapi/ui/components/logout/logout.html
index 38a5c36..38a5c36 100644
--- a/testapi/opnfv_testapi/ui/logout/logout.html
+++ b/testapi/opnfv_testapi/ui/components/logout/logout.html
diff --git a/testapi/opnfv_testapi/ui/logout/logoutController.js b/testapi/opnfv_testapi/ui/components/logout/logoutController.js
index 1b6d78c..1b6d78c 100644
--- a/testapi/opnfv_testapi/ui/logout/logoutController.js
+++ b/testapi/opnfv_testapi/ui/components/logout/logoutController.js
diff --git a/testapi/opnfv_testapi/ui/pods/pods.html b/testapi/opnfv_testapi/ui/components/pods/pods.html
index 22f2934..22f2934 100644
--- a/testapi/opnfv_testapi/ui/pods/pods.html
+++ b/testapi/opnfv_testapi/ui/components/pods/pods.html
diff --git a/testapi/opnfv_testapi/ui/pods/podsController.js b/testapi/opnfv_testapi/ui/components/pods/podsController.js
index 489fa8a..489fa8a 100644
--- a/testapi/opnfv_testapi/ui/pods/podsController.js
+++ b/testapi/opnfv_testapi/ui/components/pods/podsController.js
diff --git a/testapi/opnfv_testapi/ui/profile/importPubKeyModal.html b/testapi/opnfv_testapi/ui/components/profile/importPubKeyModal.html
index 0f55c27..0f55c27 100644
--- a/testapi/opnfv_testapi/ui/profile/importPubKeyModal.html
+++ b/testapi/opnfv_testapi/ui/components/profile/importPubKeyModal.html
diff --git a/testapi/opnfv_testapi/ui/profile/profile.html b/testapi/opnfv_testapi/ui/components/profile/profile.html
index 763f5d1..763f5d1 100644
--- a/testapi/opnfv_testapi/ui/profile/profile.html
+++ b/testapi/opnfv_testapi/ui/components/profile/profile.html
diff --git a/testapi/opnfv_testapi/ui/profile/profileController.js b/testapi/opnfv_testapi/ui/components/profile/profileController.js
index 5dbdf7b..5dbdf7b 100644
--- a/testapi/opnfv_testapi/ui/profile/profileController.js
+++ b/testapi/opnfv_testapi/ui/components/profile/profileController.js
diff --git a/testapi/opnfv_testapi/ui/profile/showPubKeyModal.html b/testapi/opnfv_testapi/ui/components/profile/showPubKeyModal.html
index 5f63a5e..5f63a5e 100644
--- a/testapi/opnfv_testapi/ui/profile/showPubKeyModal.html
+++ b/testapi/opnfv_testapi/ui/components/profile/showPubKeyModal.html
diff --git a/testapi/opnfv_testapi/ui/projects/project/project.html b/testapi/opnfv_testapi/ui/components/projects/project/project.html
index 9d46364..9d46364 100644
--- a/testapi/opnfv_testapi/ui/projects/project/project.html
+++ b/testapi/opnfv_testapi/ui/components/projects/project/project.html
diff --git a/testapi/opnfv_testapi/ui/projects/project/projectController.js b/testapi/opnfv_testapi/ui/components/projects/project/projectController.js
index 8f4bd20..8f4bd20 100644
--- a/testapi/opnfv_testapi/ui/projects/project/projectController.js
+++ b/testapi/opnfv_testapi/ui/components/projects/project/projectController.js
diff --git a/testapi/opnfv_testapi/ui/projects/project/updateModal.html b/testapi/opnfv_testapi/ui/components/projects/project/updateModal.html
index ab8d64e..ab8d64e 100644
--- a/testapi/opnfv_testapi/ui/projects/project/updateModal.html
+++ b/testapi/opnfv_testapi/ui/components/projects/project/updateModal.html
diff --git a/testapi/opnfv_testapi/ui/projects/projects.html b/testapi/opnfv_testapi/ui/components/projects/projects.html
index 55f8683..55f8683 100644
--- a/testapi/opnfv_testapi/ui/projects/projects.html
+++ b/testapi/opnfv_testapi/ui/components/projects/projects.html
diff --git a/testapi/opnfv_testapi/ui/projects/projectsController.js b/testapi/opnfv_testapi/ui/components/projects/projectsController.js
index 16002f6..16002f6 100644
--- a/testapi/opnfv_testapi/ui/projects/projectsController.js
+++ b/testapi/opnfv_testapi/ui/components/projects/projectsController.js
diff --git a/testapi/opnfv_testapi/ui/results-report/partials/editTestModal.html b/testapi/opnfv_testapi/ui/components/results-report/partials/editTestModal.html
index 583c9b9..583c9b9 100644
--- a/testapi/opnfv_testapi/ui/results-report/partials/editTestModal.html
+++ b/testapi/opnfv_testapi/ui/components/results-report/partials/editTestModal.html
diff --git a/testapi/opnfv_testapi/ui/results-report/partials/fullTestListModal.html b/testapi/opnfv_testapi/ui/components/results-report/partials/fullTestListModal.html
index 6db198b..6db198b 100644
--- a/testapi/opnfv_testapi/ui/results-report/partials/fullTestListModal.html
+++ b/testapi/opnfv_testapi/ui/components/results-report/partials/fullTestListModal.html
diff --git a/testapi/opnfv_testapi/ui/results-report/partials/reportDetails.html b/testapi/opnfv_testapi/ui/components/results-report/partials/reportDetails.html
index 517e569..517e569 100644
--- a/testapi/opnfv_testapi/ui/results-report/partials/reportDetails.html
+++ b/testapi/opnfv_testapi/ui/components/results-report/partials/reportDetails.html
diff --git a/testapi/opnfv_testapi/ui/results-report/resultsReport.html b/testapi/opnfv_testapi/ui/components/results-report/resultsReport.html
index 5527121..5527121 100644
--- a/testapi/opnfv_testapi/ui/results-report/resultsReport.html
+++ b/testapi/opnfv_testapi/ui/components/results-report/resultsReport.html
diff --git a/testapi/opnfv_testapi/ui/results-report/resultsReportController.js b/testapi/opnfv_testapi/ui/components/results-report/resultsReportController.js
index 591ad40..591ad40 100644
--- a/testapi/opnfv_testapi/ui/results-report/resultsReportController.js
+++ b/testapi/opnfv_testapi/ui/components/results-report/resultsReportController.js
diff --git a/testapi/opnfv_testapi/ui/results/results.html b/testapi/opnfv_testapi/ui/components/results/results.html
index 2ae5339..2ae5339 100644
--- a/testapi/opnfv_testapi/ui/results/results.html
+++ b/testapi/opnfv_testapi/ui/components/results/results.html
diff --git a/testapi/opnfv_testapi/ui/results/resultsController.js b/testapi/opnfv_testapi/ui/components/results/resultsController.js
index cc6cc0b..cc6cc0b 100644
--- a/testapi/opnfv_testapi/ui/results/resultsController.js
+++ b/testapi/opnfv_testapi/ui/components/results/resultsController.js
diff --git a/testapi/opnfv_testapi/ui/config.json b/testapi/opnfv_testapi/ui/config.json
new file mode 100644
index 0000000..5d48c7b
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/config.json
@@ -0,0 +1 @@
+{"testapiApiUrl": "http://localhost:8000/api/v1"}
diff --git a/testapi/opnfv_testapi/ui/favicon-16x16.png b/testapi/opnfv_testapi/ui/favicon-16x16.png
new file mode 100755
index 0000000..e08c8a1
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/favicon-16x16.png
Binary files differ
diff --git a/testapi/opnfv_testapi/ui/favicon-32x32.png b/testapi/opnfv_testapi/ui/favicon-32x32.png
new file mode 100755
index 0000000..7bf57e2
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/favicon-32x32.png
Binary files differ
diff --git a/testapi/opnfv_testapi/ui/favicon.ico b/testapi/opnfv_testapi/ui/favicon.ico
new file mode 100644
index 0000000..156019a
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/favicon.ico
Binary files differ
diff --git a/testapi/opnfv_testapi/ui/index.html b/testapi/opnfv_testapi/ui/index.html
new file mode 100644
index 0000000..ac29aca
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/index.html
@@ -0,0 +1,62 @@
+<!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 id="ng-app">
+ <head>
+ <meta charset="utf-8">
+ <meta name="description" content="TestAPI">
+ <meta name="viewport" content="width=device-width">
+ <title>TestAPI</title>
+
+ <link rel="icon" type="image/png" href="testapi-ui/favicon-16x16.png" sizes="16x16" />
+ <link rel="icon" type="image/png" href="testapi-ui/favicon-32x32.png" sizes="32x32" />
+
+ <link rel="stylesheet" href="testapi-ui/assets/lib/bootstrap/dist/css/bootstrap.min.css">
+ <link rel="stylesheet" href="testapi-ui/assets/lib/angular-busy/dist/angular-busy.min.css">
+ <link rel="stylesheet" href="testapi-ui/assets/css/style.css">
+
+ <script src="testapi-ui/assets/lib/angular/angular.min.js"></script>
+ <script src="testapi-ui/assets/lib/angular-ui-router/release/angular-ui-router.min.js"></script>
+ <script src="testapi-ui/assets/lib/angular-resource/angular-resource.min.js"></script>
+ <script src="testapi-ui/assets/lib/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
+ <script src="testapi-ui/assets/lib/angular-busy/dist/angular-busy.min.js"></script>
+ <script src="testapi-ui/assets/lib/angular-confirm-modal/angular-confirm.js"></script>
+ <script src="testapi-ui/app.js"></script>
+
+ <!-- Controllers -->
+ <script src="testapi-ui/shared/header/headerController.js"></script>
+ <script src="testapi-ui/shared/alerts/alertModalFactory.js"></script>
+ <script src="testapi-ui/shared/alerts/confirmModalFactory.js"></script>
+ <script src="testapi-ui/components/pods/podsController.js"></script>
+ <script src="testapi-ui/components/results/resultsController.js"></script>
+ <script src="testapi-ui/components/results-report/resultsReportController.js"></script>
+ <script src="testapi-ui/components/profile/profileController.js"></script>
+ <script src="testapi-ui/components/auth-failure/authFailureController.js"></script>
+ <script src="testapi-ui/components/logout/logoutController.js"></script>
+ <script src="testapi-ui/components/projects/projectsController.js"></script>
+ <script src="testapi-ui/components/projects/project/projectController.js"></script>
+
+ <!-- Filters -->
+ <script src="testapi-ui/shared/filters.js"></script>
+
+ </head>
+
+ <body class="container">
+ <header ng-include src="'testapi-ui/shared/header/header.html'"></header>
+
+ <div ui-view></div>
+ </body>
+</html>
diff --git a/testapi/opnfv_testapi/ui/package.json b/testapi/opnfv_testapi/ui/package.json
new file mode 100644
index 0000000..dc99239
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/package.json
@@ -0,0 +1,18 @@
+{
+ "devDependencies": {
+ "grunt": "~1.0.1",
+ "grunt-contrib-connect": "^1.0.2",
+ "grunt-contrib-copy": "^1.0.0",
+ "grunt-karma": "~2.0.0",
+ "grunt-protractor-coverage": "^0.2.18",
+ "grunt-protractor-runner": "~5.0.0",
+ "grunt-shell-spawn": "~0.3.10",
+ "grunt-wait": "~0.1.0",
+ "karma": "~1.7.1",
+ "karma-chrome-launcher": "~2.2.0",
+ "karma-coverage": "~1.1.1",
+ "karma-jasmine": "~1.1.0",
+ "load-grunt-tasks": "~3.5.2",
+ "protractor-http-mock": "^0.10.0"
+ }
+}
diff --git a/testapi/opnfv_testapi/ui/robots.txt b/testapi/opnfv_testapi/ui/robots.txt
new file mode 100644
index 0000000..93c4420
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/robots.txt
@@ -0,0 +1,4 @@
+# robotstxt.org
+
+User-agent: *
+
diff --git a/testapi/opnfv_testapi/ui/shared/alerts/alertModal.html b/testapi/opnfv_testapi/ui/shared/alerts/alertModal.html
new file mode 100644
index 0000000..59fd500
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/shared/alerts/alertModal.html
@@ -0,0 +1,8 @@
+<div class="modal-body" style="padding:0px">
+ <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>{{alert.data.title}}</strong> {{alert.data.text}}
+ </div>
+</div>
diff --git a/testapi/opnfv_testapi/ui/shared/alerts/alertModalFactory.js b/testapi/opnfv_testapi/ui/shared/alerts/alertModalFactory.js
new file mode 100644
index 0000000..929f543
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/shared/alerts/alertModalFactory.js
@@ -0,0 +1,74 @@
+/*
+ * 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('testapiApp')
+ .factory('raiseAlert', raiseAlert);
+
+ raiseAlert.$inject = ['$uibModal'];
+
+ /**
+ * This allows alert pop-ups to be raised. Just inject it as a dependency
+ * in the calling controller.
+ */
+ function raiseAlert($uibModal) {
+ return function(mode, title, text) {
+ $uibModal.open({
+ templateUrl: 'testapi-ui/shared/alerts/alertModal.html',
+ controller: 'RaiseAlertModalController as alert',
+ backdrop: true,
+ keyboard: true,
+ backdropClick: true,
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ mode: mode,
+ title: title,
+ text: text
+ };
+ }
+ }
+ });
+ };
+ }
+
+ angular
+ .module('testapiApp')
+ .controller('RaiseAlertModalController', RaiseAlertModalController);
+
+ RaiseAlertModalController.$inject = ['$uibModalInstance', 'data'];
+
+ /**
+ * This is the controller for the alert pop-up.
+ */
+ function RaiseAlertModalController($uibModalInstance, 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() {
+ $uibModalInstance.close();
+ }
+ }
+})();
diff --git a/testapi/opnfv_testapi/ui/shared/alerts/confirmModal.html b/testapi/opnfv_testapi/ui/shared/alerts/confirmModal.html
new file mode 100644
index 0000000..e5397e0
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/shared/alerts/confirmModal.html
@@ -0,0 +1,23 @@
+<div class="modal-header"><h3 class="modal-title">Confirm</h3></div>
+<div class="modal-body">
+ <div class="confirm" ng-class="{ 'hidden': confirmModal.data.text=='Delete' }">
+ <div class="form-group">
+ <label for="confirmText">{{confirmModal.data.text}}:</label>
+ <textarea type="text" class="form-control"
+ rows="5" ng-model="confirmModal.inputText" id="confirmText">
+ </textarea>
+ </div>
+ </div>
+ <div class="Delete" ng-class="{ 'hidden': confirmModal.data.text!='Delete' }">
+ <div class="form-group">
+ <label for="confirmText"> You are about to delete.</label>
+ <br>
+ Do you want to proceed?
+ </div>
+ </div>
+
+</div>
+<div class="modal-footer">
+ <button class="btn btn-primary" ng-click="confirmModal.confirm()">Ok</button>
+ <button class="btn btn-default" ng-click="confirmModal.cancel()">Cancel</button>
+</div>
diff --git a/testapi/opnfv_testapi/ui/shared/alerts/confirmModalFactory.js b/testapi/opnfv_testapi/ui/shared/alerts/confirmModalFactory.js
new file mode 100644
index 0000000..aba205e
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/shared/alerts/confirmModalFactory.js
@@ -0,0 +1,67 @@
+(function () {
+ 'use strict';
+
+ angular
+ .module('testapiApp')
+ .factory('confirmModal', confirmModal);
+
+ confirmModal.$inject = ['$uibModal'];
+
+ /**
+ * Opens confirm modal dialog with input textbox
+ */
+ function confirmModal($uibModal) {
+ return function(text, successHandler) {
+ $uibModal.open({
+ templateUrl: '/testapi-ui/shared/alerts/confirmModal.html',
+ controller: 'CustomConfirmModalController as confirmModal',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: text,
+ successHandler: successHandler
+ };
+ }
+ }
+ });
+ };
+ }
+
+ angular
+ .module('testapiApp')
+ .controller('CustomConfirmModalController',
+ CustomConfirmModalController);
+
+ CustomConfirmModalController.$inject = ['$uibModalInstance', 'data'];
+
+ /**
+ * This is the controller for the alert pop-up.
+ */
+ function CustomConfirmModalController($uibModalInstance, data) {
+ var ctrl = this;
+
+ ctrl.confirm = confirm;
+ ctrl.cancel = cancel;
+
+ ctrl.data = angular.copy(data);
+
+ /**
+ * Initiate confirmation and call the success handler with the
+ * input text.
+ */
+ function confirm() {
+ $uibModalInstance.close();
+ if (angular.isDefined(ctrl.data.successHandler)) {
+ ctrl.data.successHandler(ctrl.inputText);
+ }
+ }
+
+ /**
+ * Close the confirm modal without initiating changes.
+ */
+ function cancel() {
+ $uibModalInstance.dismiss('cancel');
+ }
+ }
+})();
diff --git a/testapi/opnfv_testapi/ui/shared/filters.js b/testapi/opnfv_testapi/ui/shared/filters.js
new file mode 100644
index 0000000..4a4b7bd
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/shared/filters.js
@@ -0,0 +1,55 @@
+/*
+ * 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';
+
+ /**
+ * Convert an object of objects to an array of objects to use with ng-repeat
+ * filters.
+ */
+ angular
+ .module('testapiApp')
+ .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) {
+ if (!('id' in object)) {
+ object.id = key;
+ }
+ array.push(object);
+ });
+ return array;
+ };
+ }
+
+ angular
+ .module('testapiApp')
+ .filter('capitalize', capitalize);
+
+ /**
+ * Angular filter that will capitalize the first letter of a string.
+ */
+ function capitalize() {
+ return function (string) {
+ return string.substring(0, 1).toUpperCase() + string.substring(1);
+ };
+ }
+})();
diff --git a/testapi/opnfv_testapi/ui/shared/header/header.html b/testapi/opnfv_testapi/ui/shared/header/header.html
new file mode 100644
index 0000000..4b3f8dd
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/shared/header/header.html
@@ -0,0 +1,55 @@
+<div class="heading"><a ui-sref="home"><img src="testapi-ui/assets/img/testapi-logo.png" alt="TestAPI"></a>
+TestAPI
+</div>
+<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="header.navbarCollapsed = !header.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" uib-collapse="header.navbarCollapsed">
+ <ul class="nav navbar-nav">
+ <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('/pods')}"><a ui-sref="pods">Pods</a></li>
+ <li ng-class="{ active: header.isActive('/community_results')}"><a ui-sref="communityResults">Community Results</a></li>
+ <li ng-class="{ active: header.isActive('/projects')}"><a ui-sref="projects">Projects</a></li>
+ <!--
+ <li ng-class="{ active: header.isCatalogActive('public')}" class="dropdown" uib-dropdown>
+ <a role="button" class="dropdown-toggle" uib-dropdown-toggle>
+ Catalog <strong class="caret"></strong>
+ </a>
+ <ul class="dropdown-menu">
+ <li><a ui-sref="publicVendors">Vendors</a></li>
+ <li><a ui-sref="publicProducts">Products</a></li>
+ </ul>
+ </li>
+ -->
+ </ul>
+ <ul class="nav navbar-nav navbar-right">
+ <li ng-class="{ active: header.isActive('/user_results')}" ng-if="auth.isAuthenticated"><a ui-sref="userResults">My Results</a></li>
+ <!--
+ <li ng-if="auth.isAuthenticated" ng-class="{ active: header.isCatalogActive('user')}" class="dropdown" uib-dropdown>
+ <a role="button" class="dropdown-toggle" uib-dropdown-toggle>
+ My Catalog <strong class="caret"></strong>
+ </a>
+ <ul class="dropdown-menu">
+ <li><a ui-sref="userVendors">My Vendors</a></li>
+ <li><a ui-sref="userProducts">My Products</a></li>
+ </ul>
+ </li>
+ -->
+ <li ng-class="{ active: header.isActive('/profile')}" ng-if="auth.isAuthenticated"><a ui-sref="profile">Profile</a></li>
+ <li ng-if="auth.isAuthenticated"><a href="" ng-click="auth.doSignOut()">Sign Out</a></li>
+ <li ng-if="!auth.isAuthenticated"><a href="" ng-click="auth.doSignIn()">Sign In / Sign Up</a></li>
+ </ul>
+ </div>
+ </div>
+</nav>
+
diff --git a/testapi/opnfv_testapi/ui/shared/header/headerController.js b/testapi/opnfv_testapi/ui/shared/header/headerController.js
new file mode 100644
index 0000000..0a14a41
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/shared/header/headerController.js
@@ -0,0 +1,63 @@
+/*
+ * 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('testapiApp')
+ .controller('HeaderController', HeaderController);
+
+ HeaderController.$inject = ['$location'];
+
+ /**
+ * TestAPI Header Controller
+ * This controller is for the header template which contains the site
+ * navigation.
+ */
+ function HeaderController($location) {
+ var ctrl = this;
+
+ ctrl.isActive = isActive;
+ ctrl.isCatalogActive = isCatalogActive;
+
+ /** Whether the Navbar is collapsed for small displays. */
+ ctrl.navbarCollapsed = true;
+
+ /**
+ * This determines whether a button should be in the active state based
+ * on the URL.
+ */
+ function isActive(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;
+ }
+
+ /** This determines the active state for the catalog dropdown. Type
+ * parameter should be passed in to specify if the catalog is the
+ * public or user one.
+ */
+ function isCatalogActive(type) {
+ return ctrl.isActive('/' + type + '_vendors')
+ || ctrl.isActive('/' + type + '_products');
+ }
+ }
+})();