diff options
author | SerenaFeng <feng.xiaowei@zte.com.cn> | 2017-11-21 14:54:15 +0800 |
---|---|---|
committer | SerenaFeng <feng.xiaowei@zte.com.cn> | 2017-11-21 14:54:15 +0800 |
commit | 30b87f5d9c3fd3a27755e3974435afab2a42d081 (patch) | |
tree | 37d7d89a33069edc45146bec7bbdf16a9b858c38 /testapi/opnfv_testapi | |
parent | b8c925baa4f00185d5465e6f85ebce832c0c41f6 (diff) |
move self-developed front-end codes to ui/
Change-Id: I0b64661e73d940a577f27ded9322086788e4f5f3
Signed-off-by: SerenaFeng <feng.xiaowei@zte.com.cn>
Diffstat (limited to 'testapi/opnfv_testapi')
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 Binary files differnew file mode 100755 index 0000000..e08c8a1 --- /dev/null +++ b/testapi/opnfv_testapi/ui/favicon-16x16.png diff --git a/testapi/opnfv_testapi/ui/favicon-32x32.png b/testapi/opnfv_testapi/ui/favicon-32x32.png Binary files differnew file mode 100755 index 0000000..7bf57e2 --- /dev/null +++ b/testapi/opnfv_testapi/ui/favicon-32x32.png diff --git a/testapi/opnfv_testapi/ui/favicon.ico b/testapi/opnfv_testapi/ui/favicon.ico Binary files differnew file mode 100644 index 0000000..156019a --- /dev/null +++ b/testapi/opnfv_testapi/ui/favicon.ico 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'); + } + } +})(); |