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.js310
-rw-r--r--testapi/opnfv_testapi/ui/app.js65
-rw-r--r--testapi/opnfv_testapi/ui/components/pods/pods.html20
-rw-r--r--testapi/opnfv_testapi/ui/components/pods/podsController.js41
-rw-r--r--testapi/opnfv_testapi/ui/components/profile/profileController.js11
-rw-r--r--testapi/opnfv_testapi/ui/components/projects/modals/projectModal.html39
-rw-r--r--testapi/opnfv_testapi/ui/components/projects/project/project.html65
-rw-r--r--testapi/opnfv_testapi/ui/components/projects/project/projectController.js131
-rw-r--r--testapi/opnfv_testapi/ui/components/projects/project/testCases/modals/testCaseModal.html39
-rw-r--r--testapi/opnfv_testapi/ui/components/projects/project/testCases/testCase/testCase.html80
-rw-r--r--testapi/opnfv_testapi/ui/components/projects/project/testCases/testCase/testCaseController.js57
-rw-r--r--testapi/opnfv_testapi/ui/components/projects/project/testCases/testCases.html68
-rw-r--r--testapi/opnfv_testapi/ui/components/projects/project/testCases/testCasesController.js279
-rw-r--r--testapi/opnfv_testapi/ui/components/projects/project/updateModal.html26
-rw-r--r--testapi/opnfv_testapi/ui/components/projects/projects.html125
-rw-r--r--testapi/opnfv_testapi/ui/components/projects/projectsController.js259
-rw-r--r--testapi/opnfv_testapi/ui/components/results/result/result.html115
-rw-r--r--testapi/opnfv_testapi/ui/components/results/result/resultController.js74
-rw-r--r--testapi/opnfv_testapi/ui/components/results/results.html71
-rw-r--r--testapi/opnfv_testapi/ui/components/results/resultsController.js306
-rw-r--r--testapi/opnfv_testapi/ui/components/scenarios/modals/customModal.html28
-rw-r--r--testapi/opnfv_testapi/ui/components/scenarios/modals/installerModal.html59
-rw-r--r--testapi/opnfv_testapi/ui/components/scenarios/modals/projectModal.html59
-rw-r--r--testapi/opnfv_testapi/ui/components/scenarios/modals/scenarioModal.html59
-rw-r--r--testapi/opnfv_testapi/ui/components/scenarios/modals/scenarioNameUpdate.html28
-rw-r--r--testapi/opnfv_testapi/ui/components/scenarios/modals/scoreModal.html51
-rw-r--r--testapi/opnfv_testapi/ui/components/scenarios/modals/trustIndicatorModal.html49
-rw-r--r--testapi/opnfv_testapi/ui/components/scenarios/modals/versionModal.html68
-rw-r--r--testapi/opnfv_testapi/ui/components/scenarios/scenario/scenario.html241
-rw-r--r--testapi/opnfv_testapi/ui/components/scenarios/scenario/scenarioController.js581
-rw-r--r--testapi/opnfv_testapi/ui/components/scenarios/scenarios.html60
-rw-r--r--testapi/opnfv_testapi/ui/components/scenarios/scenariosController.js467
-rw-r--r--testapi/opnfv_testapi/ui/config.json3
-rw-r--r--testapi/opnfv_testapi/ui/index.html5
-rw-r--r--testapi/opnfv_testapi/ui/shared/alerts/confirmModalFactory.js1
-rw-r--r--testapi/opnfv_testapi/ui/shared/header/header.html5
36 files changed, 3187 insertions, 758 deletions
diff --git a/testapi/opnfv_testapi/ui/Gruntfile.js b/testapi/opnfv_testapi/ui/Gruntfile.js
index dd116a0..1be08b5 100644
--- a/testapi/opnfv_testapi/ui/Gruntfile.js
+++ b/testapi/opnfv_testapi/ui/Gruntfile.js
@@ -1,154 +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: '../../3rd_party/static/testapi-ui/assets',
- src: '**',
- dest: 'testapi-ui/assets',
- },
- components: {
- 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',
- options: {
- async: false
- }
- },
- options: {
- stdout: false,
- stderr: false
- }
- },
- instrument: {
- files: ['components/**/*.js'],
- options: {
- lazy: false,
- basePath: "./testapi-ui/"
- }
- },
- karma: {
- unit: {
- configFile: 'karma.conf.js'
- }
- },
- protractor_coverage: {
- options: {
- keepAlive: true,
- noColor: false,
- coverageDir: '../tests/UI/coverage',
- args: {
- specs: ['../tests/UI/e2e/podsControllerSpec.js',
- '../tests/UI/e2e/projectsControllerSpec.js',
- '../tests/UI/e2e/projectControllerSpec.js']
- }
- },
- local: {
- options: {
- configFile: '../tests/UI/protractor-conf.js'
- }
- }
- },
- makeReport: {
- src: '../tests/UI/coverage/*.json',
- options: {
- print: 'detail'
- }
- }
- });
- grunt.registerTask('test', [
- 'karma:unit'
- ]);
- grunt.registerTask('e2e', [
- 'copy:assets',
- 'copy:components',
- 'copy:shared',
- 'copy:filesPng',
- 'copy:filesIco',
- 'copy:filesJs',
- 'copy:filesJson',
- 'instrument',
- 'connect',
- 'shell:updateSelenium',
- 'shell:startSelenium',
- 'wait:default',
- 'protractor_coverage',
- 'makeReport',
- 'shell:deleteFiles'
- ]);
+ 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.toUpperCase() == "DELETE")
+ {
+ req.method='GET';
+ }
+ return next();
+ });
+ return middlewares;
+ }
+ }
+ }
+ },
+ copy: {
+ assets: {
+ expand: true,
+ cwd: '../../3rd_party/static/testapi-ui/assets',
+ src: '**',
+ dest: 'testapi-ui/assets',
+ },
+ components: {
+ 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',
+ options: {
+ async: false
+ }
+ },
+ options: {
+ stdout: false,
+ stderr: false
+ }
+ },
+ instrument: {
+ files: ['components/**/*.js'],
+ options: {
+ lazy: false,
+ basePath: "./testapi-ui/"
+ }
+ },
+ karma: {
+ unit: {
+ configFile: 'karma.conf.js'
+ }
+ },
+ protractor_coverage: {
+ options: {
+ keepAlive: true,
+ noColor: false,
+ coverageDir: '../tests/UI/coverage',
+ args: {
+ specs: [
+ '../tests/UI/e2e/homeControllerSpec.js',
+ '../tests/UI/e2e/podsControllerSpec.js',
+ '../tests/UI/e2e/projectsControllerSpec.js',
+ '../tests/UI/e2e/testCasesControllerSpec.js',
+ '../tests/UI/e2e/resultsControllerSpec.js',
+ '../tests/UI/e2e/scenariosControllerSpec.js',
+ '../tests/UI/e2e/scenarioControllerSpec.js'
+ ]
+ }
+ },
+ local: {
+ options: {
+ configFile: '../tests/UI/protractor-conf.js'
+ }
+ }
+ },
+ makeReport: {
+ src: '../tests/UI/coverage/*.json',
+ options: {
+ print: 'detail'
+ }
+ }
+ });
+ grunt.registerTask('test', [
+ 'karma:unit'
+ ]);
+ grunt.registerTask('e2e', [
+ 'copy:assets',
+ 'copy:components',
+ '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
index 28e5810..c2fa774 100644
--- a/testapi/opnfv_testapi/ui/app.js
+++ b/testapi/opnfv_testapi/ui/app.js
@@ -79,11 +79,31 @@
templateUrl: 'testapi-ui/components/projects/project/project.html',
controller: 'ProjectController as ctrl'
}).
+ state('scenarios', {
+ url: '/scenarios',
+ templateUrl: 'testapi-ui/components/scenarios/scenarios.html',
+ controller: 'ScenariosController as ctrl'
+ }).
+ state('scenario', {
+ url: '/scenarios/:name',
+ templateUrl: 'testapi-ui/components/scenarios/scenario/scenario.html',
+ controller: 'ScenarioController as ctrl'
+ }).
+ state('testCase', {
+ url: '/projects/:project_name/:name',
+ templateUrl: 'testapi-ui/components/projects/project/testCases/testCase/testCase.html',
+ controller: 'TestCaseController as ctrl'
+ }).
state('results', {
url: '/results',
templateUrl: 'testapi-ui/components/results/results.html',
controller: 'ResultsController as ctrl'
}).
+ state('result', {
+ url: '/result/:_id',
+ templateUrl: 'testapi-ui/components/results/result/result.html',
+ controller: 'ResultController as ctrl'
+ }).
state('profile', {
url: '/profile',
templateUrl: 'testapi-ui/components/profile/profile.html',
@@ -124,16 +144,17 @@
.run(setup);
setup.$inject = [
- '$http', '$rootScope', '$window', '$state', 'testapiApiUrl'
+ '$http', '$rootScope', '$window', '$state', 'testapiApiUrl', "authenticate"
];
/**
* Set up the app with injections into $rootscope. This is mainly for auth
* functions.
*/
- function setup($http, $rootScope, $window, $state, testapiApiUrl) {
+ function setup($http, $rootScope, $window, $state, testapiApiUrl, authenticate) {
$rootScope.auth = {};
+ $rootScope.authenticate = authenticate
$rootScope.auth.doSignIn = doSignIn;
$rootScope.auth.doSignOut = doSignOut;
$rootScope.auth.doSignCheck = doSignCheck;
@@ -150,10 +171,14 @@
/** 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;
+ if(authenticate){
+ $rootScope.auth.currentUser = null;
+ $rootScope.auth.isAuthenticated = false;
+ $rootScope.auth.projectNames = [];
+ $window.location.href = sign_out_url;
+ }else{
+ $state.go("home", {reload: true})
+ }
}
/**
@@ -161,17 +186,23 @@
* 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 = [];
- });
+ if(authenticate){
+ 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 = [];
+ });
+ }else{
+ $rootScope.auth.currentUser = null;
+ $rootScope.auth.isAuthenticated = true;
+ $rootScope.auth.projectNames = []
+ }
}
function doSubmitterCheck(groups){
diff --git a/testapi/opnfv_testapi/ui/components/pods/pods.html b/testapi/opnfv_testapi/ui/components/pods/pods.html
index 02f4a48..4fa8fb1 100644
--- a/testapi/opnfv_testapi/ui/components/pods/pods.html
+++ b/testapi/opnfv_testapi/ui/components/pods/pods.html
@@ -22,14 +22,7 @@
</div>
<div class="col-sm-3 pull-right">
<span style="margin-top:6px">Search:&nbsp;&nbsp;</span>
- <input type="text" class="form-control search" ngModel="filter" placeholder="Search String">
- </div>
- <div class="col-md-3 row pull-right">
- <span style="margin-top:6px">Filter:&nbsp;&nbsp;</span>
- <select ng-model="ctrl.filter" class="form-control">
- <option value="name">Name</option>
- <option value="owner">Owner</option>
- </select>
+ <input type="text" class="form-control search" ng-Model="ctrl.filterText" placeholder="Search String">
</div>
</div>
<div class="col-md-12">
@@ -48,11 +41,11 @@
<thead>
<tr style="
text-align: center;">
- <th>Bulk Select</th>
+ <th style="width:1%">Bulk Select</th>
<th>Name</th>
<th>Role</th>
<th>Mode</th>
- <th>Operation</th>
+ <th ng-class="{ 'hidden': !auth.isAuthenticated }">Operation</th>
</tr>
</thead>
<tbody>
@@ -62,16 +55,13 @@
<input type="checkbox" value="{{pod.name}}" ng-model="ctrl.checkBox[index]" >
</div>
</td>
- <td>{{pod.name}}</td>
+ <td><a class="text-info" ng-click="ctrl.viewPod(pod.name)">{{pod.name}}</a></td>
<td>{{pod.role}}</td>
<td>{{pod.mode}}</td>
- <td>
+ <td ng-class="{ 'hidden': !auth.isAuthenticated }">
<span class="podsTable-col">
- <a class="text-warning" title="Edit" ng-class="{ 'hidden': !auth.isAuthenticated }" >
- <i class="fa fa-pencil-square-o"></i></a>
<a class="text-danger" ng-click="ctrl.openDeleteModal(pod.name)" title="Delete" ng-class="{ 'hidden': !auth.isAuthenticated }">
<i class="fa fa-trash-o"></i></a>
- <a class="text-info" ng-click="ctrl.viewPod(pod.name)"><i class="fa fa-eye"></i></a>
</span>
</td>
</tr>
diff --git a/testapi/opnfv_testapi/ui/components/pods/podsController.js b/testapi/opnfv_testapi/ui/components/pods/podsController.js
index c66873a..95e3571 100644
--- a/testapi/opnfv_testapi/ui/components/pods/podsController.js
+++ b/testapi/opnfv_testapi/ui/components/pods/podsController.js
@@ -40,13 +40,13 @@
ctrl.listPods = listPods;
ctrl.open = open;
ctrl.filter = 'name'
- ctrl.clearFilters = clearFilters;
ctrl.openDeleteModal = openDeleteModal
ctrl.openBatchDeleteModal = openBatchDeleteModal
ctrl.openCreateModal = openCreateModal
ctrl.podDelete = podDelete
ctrl.batchDelete = batchDelete;
ctrl.viewPod = viewPod
+ ctrl.filterText = ''
/**
* This is called when the date filter calendar is opened. It
@@ -61,13 +61,6 @@
ctrl[openVar] = true;
}
- /**
- * This function will clear all filters and update the results
- * listing.
- */
- function clearFilters() {
- ctrl.listPods();
- }
/**
* This will contact the TestAPI to create a new pod.
@@ -91,7 +84,7 @@
ctrl.listPods();
}).catch(function (data) {
ctrl.showError = true;
- ctrl.error = "Error creating the new pod from server: " + data.statusText;
+ ctrl.error = data.statusText;
});
}
else{
@@ -105,21 +98,21 @@
*/
function listPods() {
ctrl.showError = false;
+ var reqURL = ctrl.url;
+ if(ctrl.filterText!=''){
+ reqURL = ctrl.url + "?name=" + ctrl.filterText
+ }
ctrl.podsRequest =
- $http.get(ctrl.url).success(function (data) {
+ $http.get(reqURL).success(function (data) {
ctrl.data = data;
- // mapNametoRandom
- }).error(function (error) {
+ }).catch(function (data) {
ctrl.data = null;
ctrl.showError = true;
- ctrl.error =
- 'Error retrieving pods from server: ' +
- angular.toJson(error);
+ ctrl.error = data.statusText;
});
}
function viewPod(name){
- console.log('hello');
$state.go('pod', {'name':name}, {reload: true});
}
/**
@@ -192,22 +185,6 @@
});
}
- // function openUpdateModal(podName){
- // $uibModal.open({
- // templateUrl: 'testapi-ui/components/pods/modals/createModal.html',
- // controller: 'PodModalCtrl as PodModalCtrl',
- // size: 'md',
- // resolve: {
- // data: function () {
- // return {
- // text: "Update",
- // successHandler: ctrl.update,
- // // pod: ctrl.
- // };
- // }
- // }
- // });
- // }
ctrl.listPods();
}
diff --git a/testapi/opnfv_testapi/ui/components/profile/profileController.js b/testapi/opnfv_testapi/ui/components/profile/profileController.js
index 5dbdf7b..e34e745 100644
--- a/testapi/opnfv_testapi/ui/components/profile/profileController.js
+++ b/testapi/opnfv_testapi/ui/components/profile/profileController.js
@@ -35,7 +35,7 @@
ProfileController.$inject = [
'$scope', '$http', 'testapiApiUrl', 'PubKeys',
- '$uibModal', 'raiseAlert', '$state'
+ '$uibModal', 'raiseAlert', '$state' , 'authenticate'
];
/**
@@ -44,7 +44,7 @@
* account-specific information.
*/
function ProfileController($scope, $http, testapiApiUrl,
- PubKeys, $uibModal, raiseAlert, $state) {
+ PubKeys, $uibModal, raiseAlert, $state, authenticate) {
var ctrl = this;
@@ -53,7 +53,7 @@
ctrl.openShowPubKeyModal = openShowPubKeyModal;
// Must be authenticated to view this page.
- if (!$scope.auth.isAuthenticated) {
+ if (!$scope.auth.isAuthenticated || !authenticate) {
$state.go('home');
}
@@ -115,8 +115,9 @@
ctrl.updatePubKeys();
});
}
-
- ctrl.authRequest = $scope.auth.doSignCheck().then(ctrl.updatePubKeys);
+ if(authenticate){
+ ctrl.authRequest = $scope.auth.doSignCheck().then(ctrl.updatePubKeys);
+ }
}
angular
diff --git a/testapi/opnfv_testapi/ui/components/projects/modals/projectModal.html b/testapi/opnfv_testapi/ui/components/projects/modals/projectModal.html
new file mode 100644
index 0000000..ca00f80
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/projects/modals/projectModal.html
@@ -0,0 +1,39 @@
+<div class="ball" style="padding:5px;">
+ <div class="modal-body">
+ <div class="form-horizontal">
+ <fieldset>
+ <div class="form-group">
+ <legend>{{ProjectModalCtrl.data.text}}</legend>
+ <div class="row">
+ <div ng-repeat="require in ProjectModalCtrl.createRequirements" style="margin-left:15px">
+ <div class="update-project">
+ <label for="cpid" class="control-label col-sm-2">{{require.label|capitalize}}: </label>
+ <div class="col-sm-9">
+ <a ng-if="require.type == 'select'">
+ <select class="form-control" dynamic-model="'ProjectModalCtrl.project.' + require.label" ng-options="option for option in require.selects"></select>
+ </a>
+ <a ng-if="require.type == 'text'">
+ <input type="text" class="form-control" dynamic-model="'ProjectModalCtrl.project.' + require.label"/>
+ </a>
+ <a ng-if="require.type == 'textarea'">
+ <textarea rows="2" class="form-control" cols="50" dynamic-model="'ProjectModalCtrl.project.' + require.label">
+ </textarea>
+ </a>
+ <p class="help-block"></p>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </fieldset>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <div ng-show="ProjectModalCtrl.showCreateError" style="padding:0px;" class="col-md-6 alert alert-danger" role="alert">
+ <span class="pull-right">&nbsp;{{ProjectModalCtrl.error}}</span>
+ <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span>
+ </div>
+ <button class="btn btn-primary" ng-click="ProjectModalCtrl.confirm()">Ok</button>
+ <button class="btn btn-default" ng-click="ProjectModalCtrl.cancel()">Cancel</button>
+ </div>
+</div> \ No newline at end of file
diff --git a/testapi/opnfv_testapi/ui/components/projects/project/project.html b/testapi/opnfv_testapi/ui/components/projects/project/project.html
index 9d46364..2921bd9 100644
--- a/testapi/opnfv_testapi/ui/components/projects/project/project.html
+++ b/testapi/opnfv_testapi/ui/components/projects/project/project.html
@@ -1,25 +1,56 @@
-<div ng-show="ctrl.data" class="projects-table" style="margin-top:24px; margin-left:8px;">
- <table class="table">
- <tbody>
- <tr> <td class="col-md-3">Name</td> <td class="col-md-9">{{ctrl.data.name}}</td> </tr>
- <tr> <td>Description</td> <td>{{ctrl.data.description}}</td> </tr>
- <tr> <td>Creation date</td> <td>{{ctrl.data.creation_date}}</td> </tr>
- </tbody>
- </table>
-</div>
-
+<legend>Project</legend>
<div class="row" style="margin-bottom:24px;"></div>
-<div class="project-create col-md-3" style="margin-top:10px" ng-class="{ 'hidden': ! ((auth.projectNames.length>0) &&
- auth.isAuthenticated) }">
- <button type="submit" class="btn btn-primary" ng-click="ctrl.openDeleteModal()">Delete Project</button>
- <button type="submit" class="btn btn-primary" ng-click="ctrl.openUpdateModal()">Update Project</button>
+
+<div class="tabbable tabs-below" ng-init="selectedTab = 1;">
+ <ul class="nav nav-tabs nav-justified" style="width:30%">
+ <li ng-class="{active: selectedTab == 1}">
+ <a ng-click="selectedTab = 1;">Overview</a>
+ </li>
+ <li ng-class="{active: selectedTab == 2}">
+ <a ng-click="selectedTab = 2;">Test Cases</a>
+ </li>
+ </ul>
+
+ <div class="tab-content" ng-show="selectedTab == 1">
+ <div style="padding-right:0px; margin-top:20px" >
+ <div class="table-responsive">
+ <table class="table" ng-data="ctrl.data.pods">
+ <tbody>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Id&nbsp;:</td>
+ <td class="podsTableLeftTd">{{ctrl.data._id}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Name&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.name}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Owner&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.owner}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Created&nbsp;at&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data['creation_date']}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Description&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.description}}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ <div class="tab-content" ng-show="selectedTab == 2">
+ <div ng-include src="'testapi-ui/components/projects/project/testCases/testCases.html'"></div>
+ </div>
</div>
-<div ng-show="ctrl.showError" class="alert alert-danger col-md-9" role="alert">
+<div ng-show="ctrl.showError" class="alert alert-danger col-md-9" role="alert" style="margin-top:0px">
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
{{ctrl.error}}
</div>
-<div ng-show="ctrl.showSuccess" class="alert alert-success col-md-9" role="alert">
+<div ng-show="ctrl.showSuccess" class="alert alert-success col-md-9" role="alert" style="margin-top:0px">
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
Update Success
-</div> \ No newline at end of file
+</div>
diff --git a/testapi/opnfv_testapi/ui/components/projects/project/projectController.js b/testapi/opnfv_testapi/ui/components/projects/project/projectController.js
index 8f4bd20..78b805d 100644
--- a/testapi/opnfv_testapi/ui/components/projects/project/projectController.js
+++ b/testapi/opnfv_testapi/ui/components/projects/project/projectController.js
@@ -36,88 +36,6 @@
ctrl.url = testapiApiUrl + '/projects/' + ctrl.name;
ctrl.loadDetails = loadDetails;
- ctrl.deleteProject = deleteProject;
- ctrl.openDeleteModal = openDeleteModal;
- ctrl.openUpdateModal = openUpdateModal;
- ctrl.updateProject = updateProject;
-
-
- /**
- * This will contact the TestAPI to update an existing project.
- */
- function updateProject(name,description) {
- ctrl.showError = false;
- ctrl.showSuccess = false;
- if(ctrl.name != ""){
- var projects_url = ctrl.url;
- var body = {
- name: name,
- description: description
- };
- ctrl.projectsRequest =
- $http.put(projects_url, body).success(function (data){
- ctrl.showSuccess = true ;
- })
- .error(function (data) {
- ctrl.showError = true;
- ctrl.error = 'Error updating the existing Project from server: ' + angular.toJson(data);
- });
- ctrl.name = "";
- ctrl.description="";
- }
- else{
- ctrl.showError = true;
- ctrl.error = 'Name is missing.'
- }
- }
-
- /**
- * This will contact the TestAPI to delete an existing project.
- */
- function deleteProject() {
- ctrl.showError = false;
- ctrl.showSuccess = false;
- ctrl.projectsRequest =
- $http.delete(ctrl.url).success(function (data) {
- $state.go('projects', {}, {reload: true});
- ctrl.showSuccess = true ;
-
- }).error(function (error) {
- ctrl.showError = true;
- ctrl.error =
- 'Error deleting project from server: ' +
- angular.toJson(error);
- });
- }
-
- /**
- * This will open the modal that will show the delete confirm
- * message
- */
- function openDeleteModal() {
- confirmModal("Delete",ctrl.deleteProject);
- }
-
- /**
- * This will open the modal that will show the update
- * view
- */
- function openUpdateModal(){
- $uibModal.open({
- templateUrl: 'testapi-ui/components/projects/project/updateModal.html',
- controller: 'ModalInstanceCtrl as updateModal',
- size: 'md',
- resolve: {
- data: function () {
- return {
- text: "Update",
- successHandler: ctrl.updateProject,
- project: ctrl.data
- };
- }
- }
- });
- }
/**
* This will contact the TestAPI to get a listing of declared projects.
@@ -127,57 +45,12 @@
ctrl.projectsRequest =
$http.get(ctrl.url).success(function (data) {
ctrl.data = data;
- }).error(function (error) {
+ }).catch(function (error) {
ctrl.data = null;
ctrl.showError = true;
- ctrl.error =
- 'Error retrieving projects from server: ' +
- angular.toJson(error);
+ ctrl.error = error.statusText
});
}
ctrl.loadDetails();
}
-
-
- /**
- * TestAPI Modal instance Controller
- * This controller is for the update modal where a user can update
- * the project information.
- */
- angular.module('testapiApp').controller('ModalInstanceCtrl', ModalInstanceCtrl);
- ModalInstanceCtrl.$inject = ['$scope', '$uibModalInstance', 'data'];
- function ModalInstanceCtrl($scope, $uibModalInstance, data) {
- var ctrl = this;
- ctrl.confirm = confirm;
- ctrl.cancel = cancel;
- ctrl.data = angular.copy(data);
-
- ctrl.createRequirements = [
- {label: 'name', type: 'text', required: true},
- {label: 'description', type: 'textarea', required: false}
- ];
-
- ctrl.name = ctrl.data.project.name;
- ctrl.description = ctrl.data.project.description;
-
- /**
- * Initiate confirmation and call the success handler with the
- * inputs.
- */
- function confirm() {
- $uibModalInstance.close();
- if (angular.isDefined(ctrl.data.successHandler)) {
- ctrl.data.successHandler(ctrl.name,ctrl.description);
- }
- }
-
- /**
- * Close the confirm modal without initiating changes.
- */
- function cancel() {
- $uibModalInstance.dismiss('cancel');
- }
- }
-
-
})();
diff --git a/testapi/opnfv_testapi/ui/components/projects/project/testCases/modals/testCaseModal.html b/testapi/opnfv_testapi/ui/components/projects/project/testCases/modals/testCaseModal.html
new file mode 100644
index 0000000..d1c9cb5
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/projects/project/testCases/modals/testCaseModal.html
@@ -0,0 +1,39 @@
+<div class="ball" style="padding:5px;">
+ <div class="modal-body">
+ <div class="form-horizontal">
+ <fieldset>
+ <div class="form-group">
+ <legend>{{TestCaseModalCtrl.data.text}}</legend>
+ <div class="row">
+ <div ng-repeat="require in TestCaseModalCtrl.createRequirements" style="margin-left:15px">
+ <div class="update-project">
+ <label for="cpid" class="control-label col-sm-3">{{require.label.replace("_","&nbsp;")|capitalize}}: </label>
+ <div class="col-sm-8">
+ <a ng-if="require.type == 'select'">
+ <select class="form-control" dynamic-model="'TestCaseModalCtrl.testcase.' + require.label" ng-options="option for option in require.selects"></select>
+ </a>
+ <a ng-if="require.type == 'text'">
+ <input type="text" class="form-control" dynamic-model="'TestCaseModalCtrl.testcase.' + require.label"/>
+ </a>
+ <a ng-if="require.type == 'textarea'">
+ <textarea rows="2" class="form-control" cols="50" dynamic-model="'TestCaseModalCtrl.testcase.' + require.label">
+ </textarea>
+ </a>
+ <p class="help-block"></p>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </fieldset>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <div ng-show="TestCaseModalCtrl.showCreateError" style="padding:0px;" class="col-md-6 alert alert-danger" role="alert">
+ <span class="pull-right">&nbsp;{{TestCaseModalCtrl.error}}</span>
+ <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span>
+ </div>
+ <button class="btn btn-primary" ng-click="TestCaseModalCtrl.confirm()">Ok</button>
+ <button class="btn btn-default" ng-click="TestCaseModalCtrl.cancel()">Cancel</button>
+ </div>
+</div> \ No newline at end of file
diff --git a/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCase/testCase.html b/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCase/testCase.html
new file mode 100644
index 0000000..70c026a
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCase/testCase.html
@@ -0,0 +1,80 @@
+<legend>Test Case</legend>
+<div style="padding-right:0px">
+ <div class="table-responsive">
+ <table class="table" ng-data="ctrl.data">
+ <tbody>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Id&nbsp;:</td>
+ <td class="podsTableLeftTd">{{ctrl.data._id}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Name&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.name}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Project&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.project_name}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Tier&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.tier}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Blocking&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.blocking}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">CI&nbsp;Loop&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.ci_loop}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Tags&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.tags}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Version&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.version}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Created&nbsp;at&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data['creation_date']}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Dependencies&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.dependencies}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Trust&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.trust}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Criteria&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.criteria}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Catalog&nbsp;Description&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.catalog_description}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">URL&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.url}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Run&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.run}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Description&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.description}}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+</div>
+<div class="row" style="margin-bottom:24px;"></div>
+<div ng-show="ctrl.showError" class="alert alert-danger col-md-8" role="alert" style="margin-top:0px">
+ <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
+ <span class="sr-only">Error:</span>
+ {{ctrl.error}}
+</div>
+<div class="row" style="margin-bottom:24px;"></div> \ No newline at end of file
diff --git a/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCase/testCaseController.js b/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCase/testCaseController.js
new file mode 100644
index 0000000..a38b633
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCase/testCaseController.js
@@ -0,0 +1,57 @@
+/*
+ * 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('TestCaseController', TestCaseController);
+
+ TestCaseController.$inject = [
+ '$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl','raiseAlert',
+ 'confirmModal'
+ ];
+
+ /**
+ * TestAPI Project Controller
+ * This controller is for the '/projects' page where a user can browse
+ * through projects declared in TestAPI.
+ */
+ function TestCaseController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl,
+ raiseAlert, confirmModal) {
+ var ctrl = this;
+ ctrl.name = $state.params['name'];
+ ctrl.projectName = $state.params['project_name'];
+ ctrl.url = testapiApiUrl + '/projects/' + ctrl.projectName + "/cases/" + ctrl.name;
+
+ ctrl.loadDetails = loadDetails;
+
+ /**
+ * This will contact the TestAPI to get a listing of declared projects.
+ */
+ function loadDetails() {
+ ctrl.showError = false;
+ ctrl.projectsRequest =
+ $http.get(ctrl.url).success(function (data) {
+ ctrl.data = data;
+ }).catch(function (error) {
+ ctrl.data = null;
+ ctrl.showError = true;
+ ctrl.error = error.statusText
+ });
+ }
+ ctrl.loadDetails();
+ }
+})();
diff --git a/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCases.html b/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCases.html
new file mode 100644
index 0000000..ee87e0a
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCases.html
@@ -0,0 +1,68 @@
+<div ng-controller="TestCasesController as testCasesCtrl" class="col-md-12">
+<div class="row podsTable" style="vertical-align:middle">
+ <div class="col-sm-1 pull-right" ng-class="{ 'hidden': ! ((auth.projectNames.length>0) &&
+ auth.isAuthenticated) }" >
+ <button type="button" class="btn btn-danger" ng-click="testCasesCtrl.openBatchDeleteModal()">
+ <i class="fa fa-minus"></i> Delete</button>
+ </div>
+ <div class="col-sm-1 pull-right" ng-class="{ 'hidden': ! ((auth.projectNames.length>0) &&
+ auth.isAuthenticated) }">
+ <button type="button" class="btn btn-success" ng-click="testCasesCtrl.openCreateModal()">
+ <i class="fa fa-plus"></i> Create</button>
+ </div>
+</div>
+<div class='clo-md-12'>
+ <div ng-show="testCasesCtrl.showError" class="alert alert-danger" role="alert">
+ <span class="pull-right">&nbsp;{{testCasesCtrl.error}}</span>
+ <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span>
+ </div>
+ <div ng-show="testCasesCtrl.showSuccess" class="alert alert-success" role="alert">
+ <span class="pull-right">&nbsp;{{testCasesCtrl.successMessage}}</span>
+ <span class="glyphicon glyphicon-ok pull-right" aria-hidden="true"></span>
+ </div>
+</div>
+<div class='clo-md-12' style="padding-right:0px">
+ <div class="table-responsive">
+ <table class="table table-bordered table-hover" ng-data="testCasesCtrl.data.testcases">
+ <thead>
+ <tr style="
+ text-align: center;">
+ <th style="width: 1%;">Bulk Select</th>
+ <th style="width: 19%;">Name</th>
+ <th style="width: 20%;">Tier</th>
+ <th style="width: 20%;">Blocking</th>
+ <th style="width: 20%;">CI&nbsp;Loop</th>
+ <th style="width: 20%;" ng-class="{'hidden': ! ((auth.projectNames.length>0) && auth.isAuthenticated)}">Operations</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat-start="(index, testcase) in testCasesCtrl.data.testcases" style="padding:9px">
+ <td>
+ <div class="text-center">
+ <input type="checkbox" value="{{project.name}}" ng-model="testCasesCtrl.checkBox[index]" >
+ </div>
+ </td>
+ <td>
+ <a class="text-info" ng-click="testCasesCtrl.viewTestCase(testcase.name, testcase.project_name)">
+ {{testcase.name}}
+ </a>
+ </td>
+ <td>{{testcase.tier}}</td>
+ <td>{{testcase.blocking}}</td>
+ <td>{{testcase.ci_loop}}</td>
+ <td ng-class="{'hidden': ! ((auth.projectNames.length>0) && auth.isAuthenticated)}">
+ <span class="podsTable-col">
+ <a class="text-warning" ng-click="testCasesCtrl.openUpdateTestModal(testcase.name)" title="Edit">
+ <i class="fa fa-pencil-square-o"></i></a>
+ <a class="text-danger" ng-click="testCasesCtrl.openDeleteTestModal(testcase.name)" title="Delete">
+ <i class="fa fa-trash-o"></i></a>
+ </span>
+ </td>
+ </tr>
+ <tr ng-repeat-end=>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+</div>
+</div>
diff --git a/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCasesController.js b/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCasesController.js
new file mode 100644
index 0000000..6d3c245
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCasesController.js
@@ -0,0 +1,279 @@
+/*
+ * 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('TestCasesController', TestCasesController);
+
+ TestCasesController.$inject = [
+ '$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl','raiseAlert',
+ 'confirmModal'
+ ];
+
+ /**
+ * TestAPI Test cases Controller
+ * This controller is for the tescases page where a user can browse
+ * through testcases declared in TestAPI and perform the CRUD operations
+ * in them.
+ */
+ function TestCasesController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl,
+ raiseAlert, confirmModal) {
+ var ctrl = this;
+ ctrl.loadDetails = loadDetails;
+ ctrl.name = $state.params['name'];
+ ctrl.requestUrl = testapiApiUrl + '/projects/' + ctrl.name +'/cases';
+
+ ctrl.createTestCase = createTestCase;
+ ctrl.openCreateModal = openCreateModal;
+ ctrl.deleteTestCase = deleteTestCase;
+ ctrl.openDeleteTestModal = openDeleteTestModal;
+ ctrl.updateTestCase = updateTestCase;
+ ctrl.openUpdateTestModal = openUpdateTestModal;
+ ctrl.batchDelete = batchDelete;
+ ctrl.openBatchDeleteModal = openBatchDeleteModal;
+ ctrl.viewTestCase = viewTestCase;
+
+ ctrl.checkBox = [];
+ ctrl.checkBoxList = [];
+
+ /**
+ * This will contact the TestAPI to create a new test case.
+ */
+ function createTestCase(name, testcase) {
+ ctrl.showError = false;
+ ctrl.showSuccess = false;
+ if(testcase.name != "" && testcase.name!=null){
+ var testCase_url = ctrl.requestUrl;
+ ctrl.testCasesRequest =
+ $http.post(testCase_url, testcase).success(function (data){
+ ctrl.showSuccess = true ;
+ ctrl.successMessage = "Testcase is successfully created."
+ loadDetails();
+ })
+ .catch(function (data) {
+ ctrl.showError = true;
+ ctrl.error = data.statusText;
+ });
+ }
+ else{
+ ctrl.showError = true;
+ ctrl.error = 'Name is missing.'
+ }
+ }
+
+ function viewTestCase(name, project_name){
+ $state.go('testCase', {'name':name, 'project_name':project_name}, {reload: true});
+ }
+
+ /**
+ * This will open the modal that will show the batch delete confirm
+ * message
+ */
+ function openBatchDeleteModal() {
+ confirmModal("Delete",ctrl.batchDelete);
+ }
+
+ /**
+ * This will delete list of test cases.
+ */
+ function batchDelete(){
+ var index;
+ var checkedBox = [];
+ ctrl.checkBox.forEach(function(testcase, index){
+ if(!ctrl.showError){
+ if(testcase){
+ ctrl.deleteTestCase(ctrl.data.testcases[index].name);
+ }
+ }
+ });
+ ctrl.checkBox = []
+ }
+ /**
+ * This will contact the TestAPI to update an existing test case.
+ */
+ function updateTestCase(name, testCase) {
+ ctrl.showError = false;
+ ctrl.showSuccess = false;
+ if(testCase.name != ""){
+ var testCase_url = ctrl.requestUrl + '/' + name;
+ ctrl.testCasesRequest =
+ $http.put(testCase_url, testCase).success(function (data){
+ ctrl.showSuccess = true ;
+ ctrl.successMessage = "Test case is successfully updated"
+ loadDetails();
+ })
+ .catch(function (data) {
+ ctrl.showError = true;
+ ctrl.error = data.statusText;
+ });
+ }
+ else{
+ ctrl.showError = true;
+ ctrl.error = 'Name is missing.'
+ }
+ }
+
+ /**
+ * This will contact the TestAPI to delete an existing test case.
+ */
+ function deleteTestCase(name) {
+ ctrl.showError = false;
+ ctrl.showSuccess = false;
+ ctrl.testCasesRequest =
+ $http.delete(ctrl.requestUrl+"/"+name).success(function (data) {
+ loadDetails();
+ ctrl.showSuccess = true ;
+ ctrl.successMessage = "Test case is successfully deleted"
+ }).catch(function (error) {
+ ctrl.showError = true;
+ ctrl.error = data.statusText;
+ });
+ }
+
+ /**
+ * This will open the modal that will show the delete confirm
+ * message
+ */
+ function openDeleteTestModal(name) {
+ confirmModal("Delete", ctrl.deleteTestCase, name);
+ }
+
+ /**
+ * This will open the modal that will show the Create
+ * view
+ */
+ function openCreateModal(name){
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/projects/project/testCases/modals/testCaseModal.html',
+ controller: 'TestCaseModalCtrl as TestCaseModalCtrl',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Create",
+ successHandler: ctrl.createTestCase
+ };
+ }
+ }
+ });
+ }
+
+ /**
+ * This will open the modal that will show the update
+ * view
+ */
+ function openUpdateTestModal(name){
+ var testcase;
+ var index;
+ for(index in ctrl.data.testcases){
+ if(ctrl.data.testcases[index].name==name){
+ testcase = ctrl.data.testcases[index]
+ continue
+ }
+ }
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/projects/project/testCases/modals/testCaseModal.html',
+ controller: 'TestCaseModalCtrl as TestCaseModalCtrl',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Update",
+ successHandler: ctrl.updateTestCase,
+ testCase: testcase
+ };
+ }
+ }
+ });
+ }
+
+ /**
+ * This will contact the TestAPI to get a listing of declared test cases.
+ */
+ function loadDetails() {
+ ctrl.testCasesReguest =
+ $http.get(ctrl.requestUrl).success(function (data) {
+ ctrl.data = data;
+ }).catch(function (error) {
+ ctrl.data = null;
+ ctrl.showError = true;
+ ctrl.error = error.statusText;
+ });
+ }
+ ctrl.loadDetails();
+ }
+
+
+ /**
+ * TestAPI Modal instance Controller
+ * This controller is for the modal where a user can create
+ * test case or update the test case information.
+ */
+ angular.module('testapiApp').controller('TestCaseModalCtrl', TestCaseModalCtrl);
+ TestCaseModalCtrl.$inject = ['$scope', '$uibModalInstance', 'data'];
+ function TestCaseModalCtrl($scope, $uibModalInstance, data) {
+ var ctrl = this;
+ ctrl.confirm = confirm;
+ ctrl.cancel = cancel;
+ ctrl.data = angular.copy(data);
+
+ ctrl.createRequirements = [
+ {label: 'name', type: 'text', required: true},
+ {label: 'description', type: 'textarea', required: false},
+ {label: 'version', type: 'text', required: false},
+ {label: 'tier', type: 'text', required: false},
+ {label: 'tags', type: 'text', required: false},
+ {label: 'run', type: 'text', required: false},
+ {label: 'dependencies', type: 'text', required: false},
+ {label: 'trust', type: 'text', required: false},
+ {label: 'url', type: 'text', required: false},
+ {label: 'blocking', type: 'text', required: false},
+ {label: 'criteria', type: 'text', required: false},
+ {label: 'domains', type: 'text', required: false},
+ {label: 'ci_loop', type: 'text', required: false},
+ {label: 'catalog_description', type: 'text', required: false}
+ ];
+
+ ctrl.testcase = {name : null, description : null,version : null, tier : null, tags : null,
+ run : null, dependencies : null, trust : null, url : null, blocking : null,
+ criteria : null, domains : null, ci_loop: null, catalog_description : null};
+
+ if(ctrl.data.text=="Update"){
+ ctrl.testcase = ctrl.data.testCase
+ delete ctrl.testcase._id;
+ ctrl.name = ctrl.data.testCase.name
+ }
+
+ /**
+ * Initiate confirmation and call the success handler with the
+ * inputs.
+ */
+ function confirm() {
+ $uibModalInstance.close();
+ if (angular.isDefined(ctrl.data.successHandler)) {
+ ctrl.data.successHandler(ctrl.name, ctrl.testcase);
+ }
+ }
+
+ /**
+ * Close the confirm modal without initiating changes.
+ */
+ function cancel() {
+ $uibModalInstance.dismiss('cancel');
+ }
+ }
+})();
diff --git a/testapi/opnfv_testapi/ui/components/projects/project/updateModal.html b/testapi/opnfv_testapi/ui/components/projects/project/updateModal.html
deleted file mode 100644
index ab8d64e..0000000
--- a/testapi/opnfv_testapi/ui/components/projects/project/updateModal.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<div class="modal-header"><h3 class="modal-title">Confirm</h3></div>
-<div class="modal-body">
- <div class="form-group">
- <h4>Update</h4>
- <div class="row">
- <div ng-repeat="require in updateModal.createRequirements">
- <div class="update-project" style="margin-left:24px;">
- <p class="input-group">
- <label for="cpid">{{require.label|capitalize}}: </label>
- <a ng-if="require.type == 'text'">
- <input type="text" dynamic-model="'updateModal.' + require.label"/>
- </a>
- <a ng-if="require.type == 'textarea'">
- <textarea rows="2" cols="50" value={{require.vaule}} dynamic-model="'updateModal.' + require.label">
- </textarea>
- </a>
- </p>
- </div>
- </div>
- </div>
- </div>
-</div>
-<div class="modal-footer">
- <button class="btn btn-primary" ng-click="updateModal.confirm()">Ok</button>
- <button class="btn btn-default" ng-click="updateModal.cancel()">Cancel</button>
-</div>
diff --git a/testapi/opnfv_testapi/ui/components/projects/projects.html b/testapi/opnfv_testapi/ui/components/projects/projects.html
index 28c08b1..b6b73d4 100644
--- a/testapi/opnfv_testapi/ui/components/projects/projects.html
+++ b/testapi/opnfv_testapi/ui/components/projects/projects.html
@@ -1,76 +1,69 @@
<h3>Projects</h3>
<div class="row" style="margin-bottom:24px;"></div>
-<div class="project-create" ng-class="{ 'hidden': ! ((auth.projectNames.length>0) &&
- auth.isAuthenticated) }">
- <h4>Create</h4>
- <div class="row">
- <div ng-repeat="require in ctrl.createRequirements">
- <div class="create-project" style="margin-left:24px;">
- <p class="input-group">
- <label for="cpid">{{require.label|capitalize}}: </label>
- <a ng-if="require.type == 'text'">
- <input type="text" dynamic-model="'ctrl.' + require.label"/>
- </a>
- <a ng-if="require.type == 'textarea'">
- <textarea rows="2" cols="50" dynamic-model="'ctrl.' + require.label">
- </textarea>
- </a>
- </p>
- </div>
- </div>
- <div class="col-md-1 col-sm-1 col-xs-1 " style="margin-top:15px;">
- <button type="submit" class="btn btn-primary" ng-click="ctrl.create()">Create</button>
- </div>
- <div class="col-md-11 col-sm-11 col-xs-11">
- <div ng-show="ctrl.showCreateError" class="alert alert-danger" role="alert">
- <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
- <span class="sr-only">Error:</span>
- {{ctrl.error}}
- </div>
- <div ng-show="ctrl.showCreateSuccess" class="alert alert-success" role="alert">
- <span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
- Create Success
- </div>
- </div>
+<div class="row podsTable" style="vertical-align:middle">
+ <div class="col-sm-1 pull-right" ng-class="{ 'hidden': !((auth.projectNames.length>0) &&
+ auth.isAuthenticated) && authenticate}" >
+ <button type="button" class="btn btn-danger" ng-click="ctrl.openBatchDeleteModal()">
+ <i class="fa fa-minus"></i> Delete</button>
+ </div>
+ <div class="col-sm-1 pull-right" ng-class="{ 'hidden': ! ((auth.projectNames.length>0) &&
+ auth.isAuthenticated) && authenticate}">
+ <button type="button" class="btn btn-success" ng-click="ctrl.openCreateModal()">
+ <i class="fa fa-plus"></i> Create</button>
+ </div>
+ <div class="col-sm-1 pull-right">
+ <button type="button" class="btn btn-success" ng-click="ctrl.listProjects()">
+ <i class="fa fa-search"></i> Filter</button>
+ </div>
+ <div class="col-sm-3 pull-right">
+ <span style="margin-top:6px">Search:&nbsp;&nbsp;</span>
+ <input type="text" class="form-control search" ng-Model="ctrl.filterText" style="width:80%;" placeholder="Search By Name">
</div>
</div>
-
-
-<div class="project-filters">
- <h4>Filters</h4>
- <div class="row">
- <div class="col-md-3">
- <label for="cpid">Name</label>
- <input type="text" class="form-control"
- ng-model="ctrl.filterName"/>
- </div>
- <div class="col-md-1" style="margin-top:24px;">
- <button type="submit" class="btn btn-primary" ng-click="ctrl.update()">Filter</button>
- </div>
- <div class="col-md-1" style="margin-top:24px;">
- <button type="submit" class="btn btn-primary btn-danger" ng-click="ctrl.clearFilters()">Clear</button>
- </div>
- <div class="col-md-7" style="margin-top:10px;">
- <div ng-show="ctrl.showUpdateError" class="alert alert-danger" role="alert">
- <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
- <span class="sr-only">Error:</span>
- {{ctrl.error}}
- </div>
- </div>
+<div class='clo-md-12'>
+ <div ng-show="ctrl.showError" class="alert alert-danger" role="alert">
+ <span class="pull-right">&nbsp;{{ctrl.error}}</span>
+ <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span>
+ </div>
+ <div ng-show="ctrl.showSuccess" class="alert alert-success" role="alert">
+ <span class="pull-right">&nbsp;{{ctrl.success}}</span>
+ <span class="glyphicon glyphicon-ok pull-right" aria-hidden="true"></span>
</div>
</div>
-
-<div ng-show="ctrl.data" class="projects-table" style="margin-top:24px; margin-left:8px;">
- <table ng-data="ctrl.data.projects" ng-show="ctrl.data" class="table table-striped table-hover">
+<div class='clo-md-12' style="padding-right:0px">
+ <div class="table-responsive">
+ <table class="table table-bordered table-hover" ng-data="ctrl.data.projects">
+ <thead>
+ <tr style="
+ text-align: center;">
+ <th style="width: 1%;">Bulk Select</th>
+ <th style="width: 19%;">Name</th>
+ <th style="width: 70%;">Description</th>
+ <th style="width: 10%;" ng-class="{'hidden': ! ((auth.projectNames.length>0) && auth.isAuthenticated) && authenticate}">Operations</th>
+ </tr>
+ </thead>
<tbody>
- <tr ng-repeat-start="(index, project) in ctrl.data.projects">
- <td>
- <a ui-sref='project({name: project.name})'>{{project.name}}</a>
- </td>
- </tr>
- <tr ng-repeat-end=>
- </tr>
+ <tr ng-repeat-start="(index, project) in ctrl.data.projects" style="padding:9px">
+ <td>
+ <div class="text-center">
+ <input type="checkbox" value="{{project.name}}" ng-model="ctrl.checkBox[index]" >
+ </div>
+ </td>
+ <td><a class="text-info" ng-click="ctrl.viewProject(project.name)">{{project.name}}</a></td>
+ <td>{{project.description}}</td>
+ <td ng-class="{'hidden': ! ((auth.projectNames.length>0) && auth.isAuthenticated) && authenticate}">
+ <span class="podsTable-col">
+ <a class="text-warning" ng-click="ctrl.openUpdateModal(project.name)" title="Edit" >
+ <i class="fa fa-pencil-square-o"></i></a>
+ <a class="text-danger" ng-click="ctrl.openDeleteModal(project.name)" title="Delete" >
+ <i class="fa fa-trash-o"></i></a>
+ </span>
+ </td>
+ </tr>
+ <tr ng-repeat-end=>
+ </tr>
</tbody>
- </table>
+ </table>
+ </div>
</div> \ No newline at end of file
diff --git a/testapi/opnfv_testapi/ui/components/projects/projectsController.js b/testapi/opnfv_testapi/ui/components/projects/projectsController.js
index 468407b..940c1e2 100644
--- a/testapi/opnfv_testapi/ui/components/projects/projectsController.js
+++ b/testapi/opnfv_testapi/ui/components/projects/projectsController.js
@@ -20,7 +20,8 @@
.controller('ProjectsController', ProjectsController);
ProjectsController.$inject = [
- '$scope', '$http', '$filter', '$state', 'testapiApiUrl','raiseAlert'
+ '$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl',
+ 'raiseAlert', 'confirmModal', 'authenticate'
];
/**
@@ -28,80 +29,248 @@
* This controller is for the '/projects' page where a user can browse
* through projects declared in TestAPI.
*/
- function ProjectsController($scope, $http, $filter, $state, testapiApiUrl,
- raiseAlert) {
+ function ProjectsController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl,
+ raiseAlert, confirmModal, authenticate) {
var ctrl = this;
ctrl.url = testapiApiUrl + '/projects';
+
ctrl.create = create;
+ ctrl.listProjects = listProjects;
+ ctrl.openCreateModal = openCreateModal;
+ ctrl.viewProject = viewProject;
+ ctrl.openUpdateModal = openUpdateModal;
ctrl.update = update;
- ctrl.clearFilters = clearFilters;
-
- ctrl.createRequirements = [
- {label: 'name', type: 'text', required: true},
- {label: 'description', type: 'textarea', required: false}
- ];
+ ctrl.openDeleteModal = openDeleteModal;
+ ctrl.openBatchDeleteModal = openBatchDeleteModal;
+ ctrl.projectDelete = projectDelete;
+ ctrl.batchDelete = batchDelete;
+ ctrl.checkBox = [];
+ ctrl.checkBoxList = [];
ctrl.name = '';
ctrl.details = '';
- ctrl.filterName='';
+ ctrl.filterText='';
+
/**
* This will contact the TestAPI to create a new project.
*/
- function create() {
- ctrl.showCreateError = false;
- ctrl.showCreateSuccess = false;
- if(ctrl.name != ""){
- var projects_url = ctrl.url;
- var body = {
- name: ctrl.name,
- description: ctrl.description
- };
- ctrl.projectsRequest =
- $http.post(projects_url, body).success(function (data){
- ctrl.showCreateSuccess = true ;
- ctrl.update();
- }).catch(function (data) {
- ctrl.showCreateError = true;
- ctrl.error = data.statusText;
- });
- ctrl.name = "";
- ctrl.description="";
- }
- else{
- ctrl.showCreateError = true;
- ctrl.error = 'Name is missing.'
+ function create(project) {
+ ctrl.showError = false;
+ ctrl.showSuccess = false;
+ var projects_url = ctrl.url;
+ var body = {
+ name: project.name,
+ description: project.description
+ };
+ ctrl.projectsRequest =
+ $http.post(projects_url, body).success(function (data){
+ ctrl.showSuccess = true ;
+ ctrl.success = "Project is successfully created."
+ ctrl.listProjects();
+ }).catch(function (data) {
+ ctrl.showError = true;
+ ctrl.error = data.statusText;
+ });
+ }
+
+ /**
+ * This will open the modal that will show the create
+ * project view
+ */
+ function openCreateModal(){
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/projects/modals/projectModal.html',
+ controller: 'ProjectModalCtrl as ProjectModalCtrl',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Create Project",
+ successHandler: ctrl.create
+ };
+ }
+ }
+ });
+ }
+
+ /**
+ * This will open the modal that will show the update
+ * project view
+ */
+ function openUpdateModal(name){
+ var project;
+ var index;
+ for(index in ctrl.data.projects){
+ if(ctrl.data.projects[index].name==name){
+ project = ctrl.data.projects[index]
+ continue
+ }
}
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/projects/modals/projectModal.html',
+ controller: 'ProjectModalCtrl as ProjectModalCtrl',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Update Project",
+ successHandler: ctrl.update,
+ project : project
+ };
+ }
+ }
+ });
+ }
+
+ /**
+ * This will contact the TestAPI to update an existing test case.
+ */
+ function update(name, project) {
+ ctrl.showError = false;
+ ctrl.showSuccess = false;
+ var projectUrl = ctrl.url + '/' + name;
+ ctrl.testCasesRequest =
+ $http.put(projectUrl, project).success(function (data){
+ ctrl.showSuccess = true ;
+ ctrl.success = "Project is successfully updated."
+ listProjects();
+ })
+ .catch(function (data) {
+ ctrl.showError = true;
+ ctrl.error = data.statusText;
+ });
}
/**
* This will contact the TestAPI to get a listing of declared projects.
*/
- function update() {
- ctrl.showUpdateError = false;
+ function listProjects() {
+ ctrl.showError = false;
var content_url = ctrl.url + '?';
- var name = ctrl.filterName;
- if(name){
+ var filterText = ctrl.filterText;
+ if(filterText != ''){
content_url = content_url + 'name=' +
- name;
+ filterText;
}
ctrl.resultsRequest =
$http.get(content_url).success(function (data) {
ctrl.data = data;
}).catch(function (data) {
ctrl.data = null;
- ctrl.showUpdateError = true;
+ ctrl.showError = true;
ctrl.error = data.statusText;
});
}
+ function viewProject(name){
+ $state.go('project', {'name':name}, {reload: true});
+ }
+
+ /**
+ * This will contact the TestAPI to delete a project for given
+ * name.
+ */
+ function projectDelete(projectName){
+ var projectUrl = ctrl.url + "/" + projectName
+ $http.delete(projectUrl).success(function(){
+ ctrl.showSuccess = true ;
+ ctrl.success = "Projects is successfully deleted"
+ ctrl.listProjects();
+ }).catch(function (data) {
+ ctrl.showError = true;
+ ctrl.showSuccess = false;
+ ctrl.error = data.statusText;
+ });
+ }
+
/**
- * This function will clear all filters and update the projects
- * listing.
+ * This will delete list of projects.
*/
- function clearFilters() {
- ctrl.filterName = null;
- ctrl.showUpdateError = false;
- ctrl.update();
+ function batchDelete(){
+ var index;
+ var checkedBox = [];
+ ctrl.checkBox.forEach(function(project, index){
+ if(!ctrl.showError){
+ if(project){
+ projectDelete(ctrl.data.projects[index].name);
+ }
+ }
+ });
+ ctrl.checkBox = []
+ }
+
+ /**
+ * This will open the modal that will show the batch delete confirm
+ * message
+ */
+ function openBatchDeleteModal() {
+ confirmModal("Delete",ctrl.batchDelete);
+ }
+
+ /**
+ * This will open the modal that will show the delete confirm
+ * message
+ */
+ function openDeleteModal(name) {
+ confirmModal("Delete", ctrl.projectDelete, name);
+ }
+
+ ctrl.listProjects();
+ }
+
+ /**
+ * TestAPI Project Modal Controller
+ * This controller is for the create modal where a user can create
+ * the project information and for the edit modal where user can
+ * edit the project's details
+ */
+ angular.module('testapiApp').controller('ProjectModalCtrl', ProjectModalCtrl);
+ ProjectModalCtrl.$inject = ['$scope', '$uibModalInstance', 'data'];
+ function ProjectModalCtrl($scope, $uibModalInstance, data) {
+ var ctrl = this;
+ ctrl.confirm = confirm;
+ ctrl.cancel = cancel;
+ ctrl.data = angular.copy(data);
+ ctrl.createRequirements = [
+ {label: 'name', type: 'text', required: true},
+ {label: 'description', type: 'textarea', required: false}
+ ];
+ ctrl.project = {
+ name : '',
+ description : ''
+ }
+ if(ctrl.data.project){
+ ctrl.projectName = ctrl.data.project.name
+ ctrl.project = ctrl.data.project
+ delete ctrl.project._id;
+ }
+
+ /**
+ * Initiate confirmation and call the success handler with the
+ * inputs.
+ */
+ function confirm() {
+ if (angular.isDefined(ctrl.data.successHandler)) {
+ if(ctrl.project.name != ""){
+ $uibModalInstance.close();
+ if(ctrl.data.project){
+ ctrl.data.successHandler(ctrl.projectName, ctrl.project);
+ }else{
+ ctrl.data.successHandler(ctrl.project);
+ }
+ }else{
+ ctrl.showCreateError = true;
+ ctrl.error = 'Name is missing.'
+ }
+ }
+ }
+
+ /**
+ * Close the confirm modal without initiating changes.
+ */
+ function cancel() {
+ $uibModalInstance.dismiss('cancel');
}
}
+
})();
diff --git a/testapi/opnfv_testapi/ui/components/results/result/result.html b/testapi/opnfv_testapi/ui/components/results/result/result.html
new file mode 100644
index 0000000..b435dce
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/results/result/result.html
@@ -0,0 +1,115 @@
+<legend>Result</legend>
+<div style="padding-right:0px">
+ <div class="table-responsive">
+ <table class="table" ng-data="ctrl.data.pods">
+ <tbody>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Id&nbsp;:</td>
+ <td class="podsTableLeftTd">{{ctrl.data._id}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Pod&nbsp;Name:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.pod_name}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Project&nbsp;Name:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.project_name}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Case&nbsp;Name&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.case_name}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Installer&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.installer}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Version&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.version}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Scenario&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.scenario}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Build&nbsp;tag&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data['build_tag']}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Criteria&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.criteria}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Start&nbsp;Date:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.start_date}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Stop&nbsp;Date&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.stop_date}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Trust&nbsp;Indicator&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">
+ <a ng-click="ctrl.showTrustIndicator()">
+ <p ng-if="ctrl.trust_indicator">Hide</p>
+ <p ng-if="!ctrl.trust_indicator">Show</p>
+ </a>
+ <table class="table" ng-class="{'hidden' : !ctrl.trust_indicator}" style="margin:10px">
+ <tbody>
+ <tr style="padding:9px"></tr>
+ <tr style="padding:9px" >
+ <td class="podsTableTd">Current&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.trust_indicator.current}}</td>
+ </tr>
+ <tr style="padding:9px" >
+ <td class="podsTableTd">Histories&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.trust_indicator.histories}}</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Details&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">
+ <a ng-click="ctrl.showDetails()">
+ <p ng-if="ctrl.details">Hide</p>
+ <p ng-if="!ctrl.details">Show</p>
+ </a>
+ <table class="table" ng-class="{'hidden' : !ctrl.details}" style="margin:10px">
+ <tbody>
+ <tr style="padding:9px"></tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Failures&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.details.failures}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Details&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.details.errors}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Stream&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd"><p>{{ctrl.data.details.stream}}</p></td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">TestsRun&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd"><p>{{ctrl.data.details.testsRun}}</p></td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+</div>
+<div class="col-md-12">
+ <div ng-show="ctrl.showError" class="col-md-12 alert alert-danger" role="alert">
+ <span class="pull-right">&nbsp;{{ctrl.error}}</span>
+ <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span>
+ </div>
+ <div ng-show="ctrl.showSuccess" class="col-md-12 alert alert-success" role="alert">
+ <span class="pull-right">&nbsp;{{ctrl.success}}</span>
+ <span class="glyphicon glyphicon-ok pull-right" aria-hidden="true"></span>
+ </div>
+ </div> \ No newline at end of file
diff --git a/testapi/opnfv_testapi/ui/components/results/result/resultController.js b/testapi/opnfv_testapi/ui/components/results/result/resultController.js
new file mode 100644
index 0000000..028e5d8
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/results/result/resultController.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')
+ .controller('ResultController', ResultController);
+
+ ResultController.$inject = [
+ '$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl','raiseAlert',
+ 'confirmModal'
+ ];
+
+ /**
+ * TestAPI ResultController
+ * This controller is for the '/result/:_id' page where a user can browse
+ * through result declared in TestAPI.
+ */
+ function ResultController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl,
+ raiseAlert, confirmModal) {
+ var ctrl = this;
+ ctrl.url = testapiApiUrl + '/results';
+ ctrl._id = $state.params['_id'];
+ ctrl.loadDetails = loadDetails
+ ctrl.showTrustIndicator = showTrustIndicator
+ ctrl.showDetails = showDetails
+
+ /**
+ *Contact the testapi and retrevie the result details
+ */
+ function loadDetails(){
+ var resultUrl = ctrl.url + '/' + ctrl._id;
+ ctrl.showError = false;
+ ctrl.podsRequest =
+ $http.get(resultUrl).success(function (data) {
+ ctrl.data = data;
+ }).catch(function (error) {
+ ctrl.data = null;
+ ctrl.showError = true;
+ ctrl.error = error.statusText;
+ });
+ }
+
+ function showTrustIndicator(){
+ if(ctrl.trust_indicator){
+ ctrl.trust_indicator = false
+ }else{
+ ctrl.trust_indicator = true
+ }
+ }
+
+ function showDetails(){
+ if(ctrl.details){
+ ctrl.details = false
+ }else{
+ ctrl.details = true
+ }
+ }
+ ctrl.loadDetails();
+ }
+})(); \ No newline at end of file
diff --git a/testapi/opnfv_testapi/ui/components/results/results.html b/testapi/opnfv_testapi/ui/components/results/results.html
index 2ae5339..b0c05ba 100644
--- a/testapi/opnfv_testapi/ui/components/results/results.html
+++ b/testapi/opnfv_testapi/ui/components/results/results.html
@@ -18,15 +18,28 @@
</div>
</form>
<div class="row" style="margin-bottom:24px;"></div>
-<div class="result-filters">
- <h4>Filters</h4>
- <div class="row">
- <div class="col-md-3">
- <label for="cpid">Start Date</label>
- <p class="input-group">
+<div class="result-filters" style="border-top: none;">
+ <div class="row podTable" style="vertical-align:middle">
+ <div class="col-sm-1 pull-right">
+ <button type="button" class="btn btn-danger" ng-click="ctrl.clearFilters()">
+ <i class="fa fa-search"></i> Clear
+ </button>
+ </div>
+ <div class="col-sm-1 pull-right">
+ <button type="button" class="btn btn-success" ng-click="ctrl.filterList()">
+ <i class="fa fa-search"></i> Filter</button>
+ </div>
+ <div class="col-sm-2 pull-right" ng-class="{'hidden': ctrl.filter=='start_date' || ctrl.filter=='end_date'}">
+ <span style="margin-top:6px">Search:&nbsp;&nbsp;</span>
+ <input type="text" class="form-control search" style="display:inline;width:105px;padding-left:6px;"
+ ng-Model="ctrl.filterText" placeholder="Search String">
+ </div>
+ <div class="col-sm-3 pull-right" style="width:20%" ng-class="{'hidden': ctrl.filter!='start_date'}">
+ <span style="margin-top:6px">Start&nbsp;Date:&nbsp;&nbsp;</span>
+ <p class="input-group" style="width:48%;display:inline-flex;">
<input type="text" class="form-control"
uib-datepicker-popup="{{ctrl.format}}"
- ng-model="ctrl.startDate" is-open="ctrl.startOpen"
+ ng-model="ctrl.filterText" is-open="ctrl.startOpen"
close-text="Close" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="ctrl.open($event, 'startOpen')">
@@ -35,12 +48,12 @@
</span>
</p>
</div>
- <div class="col-md-3">
- <label for="cpid">End Date</label>
- <p class="input-group">
+ <div class="col-sm-3 pull-right" style="width:20%" ng-class="{'hidden': ctrl.filter!='end_date'}">
+ <span style="margin-top:6px">End&nbsp;Date:&nbsp;&nbsp;</span>
+ <p class="input-group" style="width:48%;display:inline-flex;">
<input type="text" class="form-control"
uib-datepicker-popup="{{ctrl.format}}"
- ng-model="ctrl.endDate" is-open="ctrl.endOpen"
+ ng-model="ctrl.filterText" is-open="ctrl.endOpen"
close-text="Close" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="ctrl.open($event, 'endOpen')">
@@ -49,9 +62,29 @@
</span>
</p>
</div>
- <div class="col-md-3" style="margin-top:24px;">
- <button type="submit" class="btn btn-primary" ng-click="ctrl.update()">Filter</button>
- <button type="submit" class="btn btn-primary btn-danger" ng-click="ctrl.clearFilters()">Clear</button>
+ <div class="col-md-2 row pull-right" style="width: 20%;">
+ <span style="margin-top:6px">Filter:&nbsp;&nbsp;</span>
+ <select ng-model="ctrl.filter" class="form-control" style="display:inline; width:150px;">
+ <option value="pod" ng-disabled="ctrl.testFilter('pod')" >Pod Name</option>
+ <option value="project" ng-disabled="ctrl.testFilter('project')" >Project Name</option>
+ <option value="case" ng-disabled="ctrl.testFilter('case')">Case Name</option>
+ <option value="installer" ng-disabled="ctrl.testFilter('installer')">Installer</option>
+ <option value="version" ng-disabled="ctrl.testFilter('version')">Version</option>
+ <option value="scenario" ng-disabled="ctrl.testFilter('scenario')">Scenario</option>
+ <option value="build_tag" ng-disabled="ctrl.testFilter('build_tag')">Build Tag</option>
+ <option value="criteria" ng-disabled="ctrl.testFilter('criteria')">Criteria</option>
+ <option value="start_date" ng-disabled="ctrl.testFilter('start_date')">Start Date</option>
+ <option value="end_date" ng-disabled="ctrl.testFilter('end_date')">End Date</option>
+ </select>
+ </div>
+
+ <div class='filter-box'>
+ <div class='filter-tag' ng-repeat="(key, tag) in ctrl.tagArray">
+ {{key}}&nbsp:&nbsp{{tag}}
+ <div class='delete-tag' ng-click='ctrl.deleteTag(key)'>
+ &times;
+ </div>
+ </div>
</div>
</div>
</div>
@@ -70,14 +103,13 @@
<th>Version</th>
<th>Scenario</th>
<th>Criteria</th>
- <th>Start Date</th>
- <th>Stop Date</th>
+ <th>Build&nbsp;tag</th>
</tr>
</thead>
<tbody>
<tr ng-repeat-start="(index, result) in ctrl.data.results">
- <td>{{ result._id }}</td>
+ <td><a ng-click="ctrl.viewResult(result._id)">{{ result._id.substr(-8) }}</a></td>
<td>{{ result.pod_name }}</td>
<td>{{ result.project_name }}</td>
<td>{{ result.case_name }}</td>
@@ -85,8 +117,7 @@
<td>{{ result.version }}</td>
<td>{{ result.scenario }}</td>
<td>{{ result.criteria }}</td>
- <td>{{ result.start_date }}</td>
- <td>{{ result.stop_date }}</td>
+ <td>{{ result["build_tag"]}}</td>
</tr>
<tr ng-repeat-end=>
</tr>
@@ -103,7 +134,7 @@
boundary-links="true"
rotate="false"
num-pages="ctrl.numPages"
- ng-change="ctrl.update()">
+ ng-change="ctrl.filterList()">
</uib-pagination>
</div>
</div>
diff --git a/testapi/opnfv_testapi/ui/components/results/resultsController.js b/testapi/opnfv_testapi/ui/components/results/resultsController.js
index cc6cc0b..73f3c15 100644
--- a/testapi/opnfv_testapi/ui/components/results/resultsController.js
+++ b/testapi/opnfv_testapi/ui/components/results/resultsController.js
@@ -50,16 +50,14 @@
raiseAlert) {
var ctrl = this;
- ctrl.uploadFile=uploadFile;
- ctrl.update = update;
ctrl.open = open;
ctrl.clearFilters = clearFilters;
- ctrl.associateMeta = associateMeta;
- ctrl.getVersionList = getVersionList;
- ctrl.getUserProducts = getUserProducts;
- ctrl.associateProductVersion = associateProductVersion;
- ctrl.getProductVersions = getProductVersions;
- ctrl.prepVersionEdit = prepVersionEdit;
+ ctrl.deleteTag = deleteTag;
+ ctrl.filterList= filterList;
+ ctrl.testFilter = testFilter
+ ctrl.viewResult = viewResult;
+
+ ctrl.tagArray = {}
/** Mappings of Interop WG components to marketing program names. */
ctrl.targetMappings = {
@@ -97,99 +95,98 @@
/** Check to see if this page should display user-specific results. */
// ctrl.isUserResults = $state.current.name === 'userResults';
// need auth to browse
- ctrl.isUserResults = $state.current.name === 'userResults';
+ // ctrl.isUserResults = $state.current.name === 'userResults';
- // Should only be on user-results-page if authenticated.
- if (ctrl.isUserResults && !$scope.auth.isAuthenticated) {
- $state.go('home');
- }
+ // // Should only be on user-results-page if authenticated.
+ // if (ctrl.isUserResults && !$scope.auth.isAuthenticated) {
+ // $state.go('home');
+ // }
- ctrl.pageHeader = ctrl.isUserResults ?
- 'Private test results' : 'Community test results';
+ ctrl.pageHeader = "Test Results"
ctrl.pageParagraph = ctrl.isUserResults ?
'Your most recently uploaded test results are listed here.' :
'The most recently uploaded community test results are listed ' +
'here.';
- ctrl.uploadState = '';
+ // ctrl.uploadState = '';
ctrl.isPublic = false;
- if (ctrl.isUserResults) {
- ctrl.authRequest = $scope.auth.doSignCheck()
- .then(ctrl.update);
- // ctrl.getUserProducts();
- } else {
- ctrl.update();
- }
-
-
- function uploadFileToUrl(file, uploadUrl){
- var fd = new FormData();
- fd.append('file', file);
- fd.append('public', ctrl.isPublic)
-
- $http.post(uploadUrl, fd, {
- transformRequest: angular.identity,
- headers: {'Content-Type': undefined}
- })
-
- .success(function(data){
- var id = data.href.substr(data.href.lastIndexOf('/')+1);
- ctrl.uploadState = "Upload succeed. Result id is " + id;
- ctrl.update();
- })
+ // if (ctrl.isUserResults) {
+ // ctrl.authRequest = $scope.auth.doSignCheck()
+ // .then(ctrl.filterList);
+ // // ctrl.getUserProducts();
+ // } else {
+ // ctrl.filterList();
+ // }
- .error(function(data, status){
- ctrl.uploadState = "Upload failed. Error code is " + status;
- });
+ function viewResult(_id){
+ $state.go('result', {'_id':_id}, {reload: true});
}
- function uploadFile(){
- var file = $scope.resultFile;
- console.log('file is ' );
- console.dir(file);
+ function deleteTag(index){
+ delete ctrl.tagArray[index];
+ ctrl.filterList();
+ }
- var uploadUrl = testapiApiUrl + "/results/upload";
- uploadFileToUrl(file, uploadUrl);
- };
+ function testFilter(text){
+ for (var filter in ctrl.tagArray){
+ if(text==filter){
+ return true;
+ }
+ }
+ return false;
+ }
/**
* This will contact the TestAPI API to get a listing of test run
* results.
*/
- function update() {
+ function filterList(){
+ if(ctrl.filter && ctrl.filterText!=""){
+ ctrl.tagArray[ctrl.filter] = ctrl.filterText;
+ }
ctrl.showError = false;
- // Construct the API URL based on user-specified filters.
var content_url = testapiApiUrl + '/results' +
'?page=' + ctrl.currentPage;
- var start = $filter('date')(ctrl.startDate, 'yyyy-MM-dd');
- if (start) {
- content_url =
- content_url + '&from=' + start + ' 00:00:00';
- }
- var end = $filter('date')(ctrl.endDate, 'yyyy-MM-dd');
- if (end) {
- content_url = content_url + '&to=' + end + ' 23:59:59';
- }
- if (ctrl.isUserResults) {
- content_url = content_url + '&signed';
+ for(var key in ctrl.tagArray){
+ if(key=="start_date"){
+ var start = $filter('date')(ctrl.tagArray[key], 'yyyy-MM-dd');
+ if (start) {
+ content_url =
+ content_url + '&from=' + start + ' 00:00:00';
+ }
+ }
+ else if(key=="end_date"){
+ var end = $filter('date')(ctrl.tagArray[key], 'yyyy-MM-dd');
+ if (end) {
+ content_url = content_url + '&to=' + end + ' 23:59:59';
+ }
+ }
+ else{
+ content_url = content_url + "&" + key + "=" + ctrl.tagArray[key]
+ }
+ if (ctrl.isUserResults) {
+ content_url = content_url + '&signed';
+ }
}
ctrl.resultsRequest =
- $http.get(content_url).success(function (data) {
- ctrl.data = data;
- ctrl.totalItems = ctrl.data.pagination.total_pages * ctrl.itemsPerPage;
- ctrl.currentPage = ctrl.data.pagination.current_page;
- }).error(function (error) {
- ctrl.data = null;
- ctrl.totalItems = 0;
- ctrl.showError = true;
- ctrl.error =
- 'Error retrieving results listing from server: ' +
- angular.toJson(error);
- });
+ $http.get(content_url).success(function (data) {
+ ctrl.data = data;
+ ctrl.totalItems = ctrl.data.pagination.total_pages * ctrl.itemsPerPage;
+ ctrl.currentPage = ctrl.data.pagination.current_page;
+ }).error(function (error) {
+ ctrl.data = null;
+ ctrl.totalItems = 0;
+ ctrl.showError = true;
+ ctrl.error =
+ 'Error retrieving results listing from server: ' +
+ angular.toJson(error);
+ });
+ ctrl.filterText = ''
}
+ ctrl.filterList();
/**
* This is called when the date filter calendar is opened. It
@@ -209,162 +206,9 @@
* listing.
*/
function clearFilters() {
- ctrl.startDate = null;
- ctrl.endDate = null;
- ctrl.update();
- }
-
- /**
- * This will send an API request in order to associate a metadata
- * key-value pair with the given testId
- * @param {Number} index - index of the test object in the results list
- * @param {String} key - metadata key
- * @param {String} value - metadata value
- */
- function associateMeta(index, key, value) {
- var testId = ctrl.data.results[index].id;
- var metaUrl = [
- testapiApiUrl, '/results/', testId, '/meta/', key
- ].join('');
-
- var editFlag = key + 'Edit';
- if (value) {
- ctrl.associateRequest = $http.post(metaUrl, value)
- .success(function () {
- ctrl.data.results[index][editFlag] = false;
- }).error(function (error) {
- raiseAlert('danger', error.title, error.detail);
- });
- }
- else {
- ctrl.unassociateRequest = $http.delete(metaUrl)
- .success(function () {
- ctrl.data.results[index][editFlag] = false;
- }).error(function (error) {
- if (error.code == 404) {
- // Key doesn't exist, so count it as a success,
- // and don't raise an alert.
- ctrl.data.results[index][editFlag] = false;
- }
- else {
- raiseAlert('danger', error.title, error.detail);
- }
- });
- }
+ ctrl.tagArray = {}
+ ctrl.filter = undefined
+ ctrl.filterList();
}
-
- /**
- * Retrieve an array of available capability files from the TestAPI
- * API server, sort this array reverse-alphabetically, and store it in
- * a scoped variable.
- * Sample API return array: ["2015.03.json", "2015.04.json"]
- */
- function getVersionList() {
- if (ctrl.versionList) {
- return;
- }
- var content_url = testapiApiUrl + '/guidelines';
- ctrl.versionsRequest =
- $http.get(content_url).success(function (data) {
- ctrl.versionList = data.sort().reverse();
- }).error(function (error) {
- raiseAlert('danger', error.title,
- 'Unable to retrieve version list');
- });
- }
-
- /**
- * Get products user has management rights to or all products depending
- * on the passed in parameter value.
- */
- function getUserProducts() {
- if (ctrl.products) {
- return;
- }
- var contentUrl = testapiApiUrl + '/products';
- ctrl.productsRequest =
- $http.get(contentUrl).success(function (data) {
- ctrl.products = {};
- angular.forEach(data.products, function(prod) {
- if (prod.can_manage) {
- ctrl.products[prod.id] = prod;
- }
- });
- }).error(function (error) {
- ctrl.products = null;
- ctrl.showError = true;
- ctrl.error =
- 'Error retrieving Products listing from server: ' +
- angular.toJson(error);
- });
- }
-
- /**
- * Send a PUT request to the API server to associate a product with
- * a test result.
- */
- function associateProductVersion(result) {
- var verId = (result.selectedVersion ?
- result.selectedVersion.id : null);
- var testId = result.id;
- var url = testapiApiUrl + '/results/' + testId;
- ctrl.associateRequest = $http.put(url, {'product_version_id':
- verId})
- .success(function (data) {
- result.product_version = result.selectedVersion;
- if (result.selectedVersion) {
- result.product_version.product_info =
- result.selectedProduct;
- }
- result.productEdit = false;
- }).error(function (error) {
- raiseAlert('danger', error.title, error.detail);
- });
- }
-
- /**
- * Get all versions for a product.
- */
- function getProductVersions(result) {
- if (!result.selectedProduct) {
- result.productVersions = [];
- result.selectedVersion = null;
- return;
- }
-
- var url = testapiApiUrl + '/products/' +
- result.selectedProduct.id + '/versions';
- ctrl.getVersionsRequest = $http.get(url)
- .success(function (data) {
- result.productVersions = data;
-
- // If the test result isn't already associated to a
- // version, default it to the null version.
- if (!result.product_version) {
- angular.forEach(data, function(ver) {
- if (!ver.version) {
- result.selectedVersion = ver;
- }
- });
- }
- }).error(function (error) {
- raiseAlert('danger', error.title, error.detail);
- });
- }
-
- /**
- * Instantiate variables needed for editing product/version
- * associations.
- */
- function prepVersionEdit(result) {
- result.productEdit = true;
- if (result.product_version) {
- result.selectedProduct =
- ctrl.products[result.product_version.product_info.id];
- }
- result.selectedVersion = result.product_version;
- ctrl.getProductVersions(result);
- }
-
}
})();
diff --git a/testapi/opnfv_testapi/ui/components/scenarios/modals/customModal.html b/testapi/opnfv_testapi/ui/components/scenarios/modals/customModal.html
new file mode 100644
index 0000000..987cb1e
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/scenarios/modals/customModal.html
@@ -0,0 +1,28 @@
+<div class="ball" style="padding:5px;">
+ <div class="modal-body">
+ <div class="form-horizontal">
+ <fieldset>
+ <div class="form-group">
+ <legend>{{customModalCtrl.data.text}}</legend>
+ <div class="row">
+ <div class="update-project">
+ <label for="cpid" class="control-label col-sm-4">Custom: </label>
+ <div class="col-sm-6">
+ <input type="text" class="form-control" ng-model="customModalCtrl.custom"/>
+ <p class="help-block"></p>
+ </div>
+ </div>
+ </div>
+ </div>
+ </fieldset>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <div ng-show="customModalCtrl.showCreateError" style="padding:0px;" class="col-md-6 alert alert-danger" role="alert">
+ <span class="pull-right">&nbsp;{{customModalCtrl.error}}</span>
+ <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span>
+ </div>
+ <button class="btn btn-primary" ng-click="customModalCtrl.confirm()">Ok</button>
+ <button class="btn btn-default" ng-click="customModalCtrl.cancel()">Cancel</button>
+ </div>
+ </div> \ No newline at end of file
diff --git a/testapi/opnfv_testapi/ui/components/scenarios/modals/installerModal.html b/testapi/opnfv_testapi/ui/components/scenarios/modals/installerModal.html
new file mode 100644
index 0000000..4be1375
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/scenarios/modals/installerModal.html
@@ -0,0 +1,59 @@
+<div class="ball" style="padding:5px;">
+ <div class="modal-body">
+ <div class="form-horizontal">
+ <fieldset>
+ <div class="form-group">
+ <legend>{{installerModalCtrl.data.text}}</legend>
+ <div class="row">
+ <div class="update-project">
+ <div class="col-sm-4">
+ <label for="cpid" class="control-label col-sm-2"> Name: </label>
+ </div>
+ <div class="col-sm-6">
+ <input type="text" class="form-control" ng-model="installerModalCtrl.installer.installer"/>
+ <p class="help-block"></p>
+ </div>
+ </div>
+ <div class="update-project">
+ <div class="col-sm-4">
+ <label for="cpid" class="control-label col-sm-2"> Version: </label>
+ </div>
+ <div class="col-sm-6">
+ <button class="btn btn-primary" ng-click="installerModalCtrl.openVersionModal()">Add&nbsp;Version</button>
+ <p class="help-block"></p>
+ </div>
+ </div>
+ </div>
+ </div>
+ </fieldset>
+ </div>
+ <div class='clo-md-12' style="padding-right:0px">
+ <h3>Version</h3>
+ <div class="table-responsive">
+ <table class="table table-bordered table-hover" ng-data="installerModalCtrl.installer.versions">
+ <thead>
+ <tr style="
+ text-align: center;">
+ <th style="width: 19%;">Version</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat-start="(index, version) in installerModalCtrl.installer.versions" style="padding:9px">
+ <td>{{version.version}}</td>
+ </tr>
+ <tr ng-repeat-end=>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <div ng-show="installerModalCtrl.showCreateError" style="padding:0px;" class="col-md-6 alert alert-danger" role="alert">
+ <span class="pull-right">&nbsp;{{installerModalCtrl.error}}</span>
+ <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span>
+ </div>
+ <button class="btn btn-primary" ng-click="installerModalCtrl.confirm()">Ok</button>
+ <button class="btn btn-default" ng-click="installerModalCtrl.cancel()">Cancel</button>
+ </div>
+ </div> \ No newline at end of file
diff --git a/testapi/opnfv_testapi/ui/components/scenarios/modals/projectModal.html b/testapi/opnfv_testapi/ui/components/scenarios/modals/projectModal.html
new file mode 100644
index 0000000..0a14be9
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/scenarios/modals/projectModal.html
@@ -0,0 +1,59 @@
+<div class="ball" style="padding:5px;">
+ <div class="modal-body">
+ <div class="form-horizontal">
+ <fieldset>
+ <div class="form-group">
+ <legend>{{projectModalCtrl.data.text}}</legend>
+ <div class="row">
+ <div class="update-project">
+ <div class="col-sm-4">
+ <label for="cpid" class="control-label"> Project&nbsp;Name: </label>
+ </div>
+ <div class="col-sm-6">
+ <input type="text" class="form-control" ng-model="projectModalCtrl.project.project"/>
+ <p class="help-block"></p>
+ </div>
+ </div>
+ <div class="update-project">
+ <div class="col-sm-4">
+ <label for="cpid" class="control-label"> Custom: </label>
+ </div>
+ <div class="col-sm-6">
+ <button class="btn btn-primary" ng-click="projectModalCtrl.openCustomModal()">Add&nbsp;Custom</button>
+ <p class="help-block"></p>
+ </div>
+ </div>
+ </div>
+ </div>
+ </fieldset>
+ </div>
+ <div class='clo-md-12' style="padding-right:0px">
+ <h3>Customs</h3>
+ <div class="table-responsive">
+ <table class="table table-bordered table-hover" ng-data="projectModalCtrl.project.customs">
+ <thead>
+ <tr style="
+ text-align: center;">
+ <th style="width: 1%;">Custom</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat-start="(index, custom) in projectModalCtrl.project.customs" style="padding:9px">
+ <td>{{custom}}</td>
+ </tr>
+ <tr ng-repeat-end=>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <div ng-show="projectModalCtrl.showCreateError" style="padding:0px;" class="col-md-6 alert alert-danger" role="alert">
+ <span class="pull-right">&nbsp;{{projectModalCtrl.error}}</span>
+ <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span>
+ </div>
+ <button class="btn btn-primary" ng-click="projectModalCtrl.confirm()">Ok</button>
+ <button class="btn btn-default" ng-click="projectModalCtrl.cancel()">Cancel</button>
+ </div>
+ </div> \ No newline at end of file
diff --git a/testapi/opnfv_testapi/ui/components/scenarios/modals/scenarioModal.html b/testapi/opnfv_testapi/ui/components/scenarios/modals/scenarioModal.html
new file mode 100644
index 0000000..2b5ba9e
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/scenarios/modals/scenarioModal.html
@@ -0,0 +1,59 @@
+<div class="ball" style="padding:5px;">
+ <div class="modal-body">
+ <div class="form-horizontal">
+ <fieldset>
+ <div class="form-group">
+ <legend>{{scenarioModalController.data.text}}</legend>
+ <div class="row">
+ <div class="update-project">
+ <div class="col-sm-4">
+ <label for="cpid" class="control-label col-sm-2"> Name: </label>
+ </div>
+ <div class="col-sm-6">
+ <input type="text" class="form-control" ng-model="scenarioModalController.scenario.name"/>
+ <p class="help-block"></p>
+ </div>
+ </div>
+ <div class="update-project">
+ <div class="col-sm-4">
+ <label for="cpid" class="control-label col-sm-2"> Installer: </label>
+ </div>
+ <div class="col-sm-6">
+ <button class="btn btn-primary" ng-click="scenarioModalController.openInstallerModal()">Add&nbsp;Installer</button>
+ <p class="help-block"></p>
+ </div>
+ </div>
+ </div>
+ </div>
+ </fieldset>
+ </div>
+ <div class='clo-md-12' style="padding-right:0px">
+ <h3>Installers</h3>
+ <div class="table-responsive">
+ <table class="table table-bordered table-hover" ng-data="scenarioModalController.scenario">
+ <thead>
+ <tr style="
+ text-align: center;">
+ <th style="width: 19%;">Installers</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat-start="(index, installer) in scenarioModalController.scenario.installers" style="padding:9px">
+ <td>{{installer.installer}}</td>
+ </tr>
+ <tr ng-repeat-end=>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <div ng-show="scenarioModalController.showCreateError" style="padding:0px;" class="col-md-6 alert alert-danger" role="alert">
+ <span class="pull-right">&nbsp;{{scenarioModalController.error}}</span>
+ <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span>
+ </div>
+ <button class="btn btn-primary" ng-click="scenarioModalController.confirm()">Ok</button>
+ <button class="btn btn-default" ng-click="scenarioModalController.cancel()">Cancel</button>
+ </div>
+</div> \ No newline at end of file
diff --git a/testapi/opnfv_testapi/ui/components/scenarios/modals/scenarioNameUpdate.html b/testapi/opnfv_testapi/ui/components/scenarios/modals/scenarioNameUpdate.html
new file mode 100644
index 0000000..e793c05
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/scenarios/modals/scenarioNameUpdate.html
@@ -0,0 +1,28 @@
+<div class="ball" style="padding:5px;">
+ <div class="modal-body">
+ <div class="form-horizontal">
+ <fieldset>
+ <div class="form-group">
+ <legend>{{ScenarioNameUpdateCtrl.data.text}}</legend>
+ <div class="row">
+ <div class="update-project">
+ <label for="cpid" class="control-label col-sm-4">Name: </label>
+ <div class="col-sm-6">
+ <input type="text" class="form-control" ng-model="ScenarioNameUpdateCtrl.name"/>
+ <p class="help-block"></p>
+ </div>
+ </div>
+ </div>
+ </div>
+ </fieldset>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <div ng-show="ScenarioNameUpdateCtrl.showCreateError" style="padding:0px;" class="col-md-6 alert alert-danger" role="alert">
+ <span class="pull-right">&nbsp;{{ScenarioNameUpdateCtrl.error}}</span>
+ <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span>
+ </div>
+ <button class="btn btn-primary" ng-click="ScenarioNameUpdateCtrl.confirm()">Ok</button>
+ <button class="btn btn-default" ng-click="ScenarioNameUpdateCtrl.cancel()">Cancel</button>
+ </div>
+ </div> \ No newline at end of file
diff --git a/testapi/opnfv_testapi/ui/components/scenarios/modals/scoreModal.html b/testapi/opnfv_testapi/ui/components/scenarios/modals/scoreModal.html
new file mode 100644
index 0000000..55b5cfd
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/scenarios/modals/scoreModal.html
@@ -0,0 +1,51 @@
+
+
+ <div class="ball" style="padding:5px;">
+ <div class="modal-body">
+ <div class="form-horizontal">
+ <fieldset>
+ <div class="form-group">
+ <legend>{{scoreModalCtrl.data.text}}</legend>
+ <div class="row">
+ <div class="update-project">
+ <label for="cpid" class="control-label col-sm-4">Score: </label>
+ <div class="col-sm-6">
+ <input type="text" class="form-control" ng-model="scoreModalCtrl.score.score"/>
+ <p class="help-block"></p>
+ </div>
+ </div>
+ <div class="update-project">
+ <div>
+ <div class="col-md-4" style="text-align:right;">
+ <span style="margin-top:6px;">Date:&nbsp;&nbsp;</span>
+ </div>
+ <div class="col-md-6">
+ <p class="input-group" style="display:inline-flex;">
+ <input type="text" class="form-control"
+ uib-datepicker-popup="{{scoreModalCtrl.format}}"
+ ng-model="scoreModalCtrl.score.date" is-open="scoreModalCtrl.endOpen"
+ close-text="Close" />
+ <span class="input-group-btn">
+ <button type="button" class="btn btn-default" ng-click="scoreModalCtrl.open($event, 'endOpen')">
+ <i class="glyphicon glyphicon-calendar"></i>
+ </button>
+ </span>
+ </p>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </fieldset>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <div ng-show="scoreModalCtrl.showCreateError" style="padding:0px;" class="col-md-6 alert alert-danger" role="alert">
+ <span class="pull-right">&nbsp;{{scoreModalCtrl.error}}</span>
+ <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span>
+ </div>
+ <button class="btn btn-primary" ng-click="scoreModalCtrl.confirm()">Ok</button>
+ <button class="btn btn-default" ng-click="scoreModalCtrl.cancel()">Cancel</button>
+ </div>
+ </div> \ No newline at end of file
diff --git a/testapi/opnfv_testapi/ui/components/scenarios/modals/trustIndicatorModal.html b/testapi/opnfv_testapi/ui/components/scenarios/modals/trustIndicatorModal.html
new file mode 100644
index 0000000..b84bd5d
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/scenarios/modals/trustIndicatorModal.html
@@ -0,0 +1,49 @@
+<div class="ball" style="padding:5px;">
+ <div class="modal-body">
+ <div class="form-horizontal">
+ <fieldset>
+ <div class="form-group">
+ <legend>{{trustIndicatorModalCtrl.data.text}}</legend>
+ <div class="row">
+ <div class="update-project">
+ <label for="cpid" class="control-label col-sm-4">Status: </label>
+ <div class="col-sm-6">
+ <input type="text" class="form-control" ng-model="trustIndicatorModalCtrl.ti.status"/>
+ <p class="help-block"></p>
+ </div>
+ </div>
+ <div class="update-project">
+ <div>
+ <div class="col-md-4" style="text-align:right;">
+ <span style="margin-top:6px;">Date:&nbsp;&nbsp;</span>
+ </div>
+ <div class="col-md-6">
+ <p class="input-group" style="display:inline-flex;">
+ <input type="text" class="form-control"
+ uib-datepicker-popup="{{trustIndicatorModalCtrl.format}}"
+ ng-model="trustIndicatorModalCtrl.ti.date" is-open="trustIndicatorModalCtrl.endOpen"
+ close-text="Close" />
+ <span class="input-group-btn">
+ <button type="button" class="btn btn-default" ng-click="trustIndicatorModalCtrl.open($event, 'endOpen')">
+ <i class="glyphicon glyphicon-calendar"></i>
+ </button>
+ </span>
+ </p>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </fieldset>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <div ng-show="trustIndicatorModalCtrl.showCreateError" style="padding:0px;" class="col-md-6 alert alert-danger" role="alert">
+ <span class="pull-right">&nbsp;{{trustIndicatorModalCtrl.error}}</span>
+ <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span>
+ </div>
+ <button class="btn btn-primary" ng-click="trustIndicatorModalCtrl.confirm()">Ok</button>
+ <button class="btn btn-default" ng-click="trustIndicatorModalCtrl.cancel()">Cancel</button>
+ </div>
+ </div> \ No newline at end of file
diff --git a/testapi/opnfv_testapi/ui/components/scenarios/modals/versionModal.html b/testapi/opnfv_testapi/ui/components/scenarios/modals/versionModal.html
new file mode 100644
index 0000000..f679f0b
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/scenarios/modals/versionModal.html
@@ -0,0 +1,68 @@
+<div class="ball" style="padding:5px;">
+ <div class="modal-body">
+ <div class="form-horizontal">
+ <fieldset>
+ <div class="form-group">
+ <legend>{{versionModalCtrl.data.text}}</legend>
+ <div class="row">
+ <div class="update-project">
+ <div class="col-sm-4">
+ <label for="cpid" class="control-label col-sm-2"> Version: </label>
+ </div>
+ <div class="col-sm-6">
+ <input type="text" class="form-control" ng-model="versionModalCtrl.version.version"/>
+ <p class="help-block"></p>
+ </div>
+ </div>
+ <div class="update-project">
+ <div class="col-sm-4">
+ <label for="cpid" class="control-label col-sm-2"> Owner: </label>
+ </div>
+ <div class="col-sm-6">
+ <input type="text" class="form-control" ng-model="versionModalCtrl.version.owner"/>
+ <p class="help-block"></p>
+ </div>
+ </div>
+ <div class="update-project">
+ <div class="col-sm-4">
+ <label for="cpid" class="control-label col-sm-2"> Project: </label>
+ </div>
+ <div class="col-sm-4">
+ <button class="btn btn-primary" ng-click="versionModalCtrl.openProjectModal()">Add&nbsp;Project:</button>
+ <p class="help-block"></p>
+ </div>
+ </div>
+ </div>
+ </div>
+ </fieldset>
+ </div>
+ <div class='clo-md-12' style="padding-right:0px">
+ <h3>Projects</h3>
+ <div class="table-responsive">
+ <table class="table table-bordered table-hover" ng-data="versionModalCtrl.version.projects">
+ <thead>
+ <tr style="
+ text-align: center;">
+ <th style="width: 19%;">Project</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat-start="(index, project) in versionModalCtrl.version.projects" style="padding:9px">
+ <td>{{project.project}}</td>
+ </tr>
+ <tr ng-repeat-end=>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <div ng-show="versionModalCtrl.showCreateError" style="padding:0px;" class="col-md-6 alert alert-danger" role="alert">
+ <span class="pull-right">&nbsp;{{versionModalCtrl.error}}</span>
+ <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span>
+ </div>
+ <button class="btn btn-primary" ng-click="versionModalCtrl.confirm()">Ok</button>
+ <button class="btn btn-default" ng-click="versionModalCtrl.cancel()">Cancel</button>
+ </div>
+ </div> \ No newline at end of file
diff --git a/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenario.html b/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenario.html
new file mode 100644
index 0000000..328a5e6
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenario.html
@@ -0,0 +1,241 @@
+<legend>Scenario</legend>
+<div style="padding-right:0px" class="col-md-12">
+ <div class="table-responsive">
+ <table class="table" ng-data="ctrl.data">
+ <tbody>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Id&nbsp;:</td>
+ <td class="podsTableLeftTd">{{ctrl.data.scenarios[0]._id}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Name&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.scenarios[0].name}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Created&nbsp;at&nbsp;:</td>
+ <td width="90%" class="podsTableLeftTd">{{ctrl.data.scenarios[0].creation_date}}</td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">Installers</td>
+ <td width="90%" class="podsTableLeftTd">
+ <div class="col-md-1" style="padding:0px">
+ <a ng-click="ctrl.expandInstallers()">
+ <p ng-if="ctrl.collapeInstallers">Hide</p>
+ <p ng-if="!ctrl.collapeInstallers">Show</p>
+ </a>
+ </div>
+ <div class="col-md-1" style="padding:0px" ng-class="{'hidden' : !ctrl.buttonInstaller || !auth.isAuthenticated}">
+ <button type="button" class="btn btn-success btn-xs" ng-click="ctrl.openAddInstaller()" ><i class="fa fa-plus"></i>Add</button>
+ </div>
+ <div ng-class="{ 'hidden' : ! ctrl.collapeInstallers } ">
+ <div class="table-responsive">
+ <table class="table " ng-data="ctrl.data.scenarios[0].installers">
+ <tbody ng-repeat="(indexI, installer) in ctrl.data.scenarios[0].installers">
+ <tr style="padding:9px">
+ <td class="podsTableTd">
+ {{indexI+1}}.&nbsp;Installer:&nbsp;
+ </td>
+ <td class="podsTableLeftTd" style="width:10%;padding-top: 7px;">
+ <a ng-click="ctrl.expandInstaller(indexI)">{{installer.installer}}</a>
+ </td>
+ <td style="width:80%;border: none; padding: 0px;" ng-class="{'hidden' : !ctrl.buttonInstaller}">
+ <button type="button" ng-class="{'hidden' : !auth.isAuthenticated}" class="btn btn-danger btn-xs" ng-click="ctrl.openDeleteInstallerModal(installer.installer)" ><i class="fa fa-minus"></i>Delete</button>
+ </td>
+ </tr>
+ <tr ng-class="{ 'hidden' : ! ctrl.collapeInstaller[indexI] }">
+ <td class="podsTableTd">
+ Versions:
+ </td>
+ <td width="90%" class="podsTableLeftTd">
+ <div class="col-md-1" style="padding:0px">
+ <a ng-click="ctrl.expandVersions(indexI)">
+ <p ng-if="ctrl.collapeVersions[indexI]">Hide</p>
+ <p ng-if="!ctrl.collapeVersions[indexI]">Show</p>
+ </a>
+ </div>
+ <div class="col-md-1" style="padding:0px" ng-class="{'hidden' : !ctrl.buttonVersion}">
+ <button type="button" class="btn btn-success btn-xs" ng-class="{'hidden' : !auth.isAuthenticated}" ng-click="ctrl.openAddVersionModal(installer.installer)" ><i class="fa fa-plus"></i>Add</button>
+ </div>
+ <div ng-class="{ 'hidden' : ! ctrl.collapeVersions[indexI] } " class="col-md-12">
+ <div class="table-responsive">
+ <table class="table " ng-data="inctrl.data.scenarios[0].installers">
+ <tbody ng-repeat="(indexV, version) in installer.versions">
+ <tr style="padding:9px">
+ <td class="podsTableTd">
+ {{indexV+1}}.&nbsp;Version:
+ </td>
+ <td class="podsTableLeftTd" style="width:10%;padding-top: 7px;">
+ <a ng-click="ctrl.expandVersion(indexI,indexV)">{{version.version}}</a>
+ </td>
+ <td style="width:80%;border: none; padding: 0px;" ng-class="{'hidden' : !ctrl.buttonVersion}">
+ <button type="button" class="btn btn-danger btn-xs" ng-class="{'hidden' : !auth.isAuthenticated}" ng-click="ctrl.openDeleteVersionModal(version.version, installer.installer)" ><i class="fa fa-minus"></i>Delete</button>
+ </td>
+ </tr>
+ <tr style="padding:9px" ng-class="{ 'hidden' : ! ctrl.collapeVersion[indexI][indexV] } ">
+ <td class="podsTableTd">
+ Owner:
+ </td>
+ <td class="podsTableLeftTd" style="width:90%">{{version.owner}}</td>
+ </tr>
+ <tr style="padding:9px" ng-class="{ 'hidden' : ! ctrl.collapeVersion[indexI][indexV] }">
+ <td class="podsTableTd">
+ Projects:
+ </td>
+ <td width="90%" class="podsTableLeftTd">
+ <div class="col-md-1" style="padding:0px">
+ <a ng-click="ctrl.expandProjects(indexI,indexV)">
+ <p style="width:50%" ng-if="ctrl.collapeProjects[indexI][indexV]">Hide</p>
+ <p style="width:50%" ng-if="!ctrl.collapeProjects[indexI][indexV]">Show</p>
+ </a>
+ </div>
+ <div class="col-md-1" style="padding:0px" ng-class="{'hidden' : !ctrl.buttonProject }">
+ <button type="button" ng-class="{'hidden' : !auth.isAuthenticated}" class="btn btn-success btn-xs" ng-click="ctrl.openAddProjectModal(version.version,installer.installer)" ><i class="fa fa-plus"></i>Add</button>
+ </div>
+ <div ng-class="{ 'hidden' : ! ctrl.collapeProjects[indexI][indexV] } " class="col-md-12">
+ <div class="table-responsive">
+ <table class="table " ng-data="version.projects">
+ <tbody ng-repeat="(indexP, project) in version.projects" >
+ <tr style="padding:9px">
+ <td class="podsTableTd">
+ {{indexP+1}}.&nbsp;Project:
+ </td>
+ <td class="podsTableLeftTd" style="width:10%;padding-top: 7px;">
+ <a ng-click="ctrl.expandProject(indexI, indexV, indexP)">{{project.project}}</a>
+ </td>
+ <td style="width:80%;border: none; padding: 0px;" ng-class="{'hidden' : !ctrl.buttonProject}">
+ <button type="button" class="btn btn-danger btn-xs" ng-class="{'hidden' : !auth.isAuthenticated}" ng-click="ctrl.openDeleteProjectModal(project,version.version, installer.installer)" ><i class="fa fa-minus"></i>Delete</button>
+ </td>
+ </tr>
+ <tr ng-class="{ 'hidden' : ! ctrl.collapeProject[indexI][indexV][indexP] }">
+ <td class="podsTableTd">
+ Trust&nbsp;Indicators:
+ </td>
+ <td class="podsTableLeftTd" style="width:90%">
+ <a ng-click="ctrl.expandTrustIndicator(indexI, indexV, indexP)">
+ <p ng-if="ctrl.collapeTrustIndicator[indexI][indexV][indexP]">Hide</p>
+ <p ng-if="!ctrl.collapeTrustIndicator[indexI][indexV][indexP]">Show</p>
+ </a>
+ <table class="table " ng-class="{ 'hidden' : ! ctrl.collapeTrustIndicator[indexI][indexV][indexP] } " ng-data="project.trust_indicators">
+ <tbody ng-repeat="(indexTI, trust_indicator) in project.trust_indicators" >
+ <tr style="padding:9px">
+ <td class="podsTableTd">
+ Status:&nbsp;
+ </td>
+ <td width="90%" class="podsTableLeftTd">
+ {{trust_indicator.status}}
+ </td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">
+ Date:&nbsp;
+ </td>
+ <td width="90%" class="podsTableLeftTd">
+ {{trust_indicator.date}}
+ </td>
+ </tr>
+ </tbody>
+ <tr>
+ <button type="button" class="btn btn-success btn-xs" ng-click="ctrl.openAddTrustIndicatorModal(project.project,version.version,installer.installer)" ng-class="{ 'hidden' : !ctrl.collapeTrustIndicator[index] || !auth.isAuthenticated}">
+ <i class="fa fa-plus"></i>Add</button>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr ng-class="{ 'hidden' : ! ctrl.collapeProject[indexI][indexV][indexP] }">
+ <td class="podsTableTd">
+ Scores:
+ </td>
+ <td class="podsTableLeftTd" style="width:90%">
+ <a ng-click="ctrl.expandScore(indexI, indexV, indexP)">
+ <p ng-if="ctrl.collapeScore[indexI][indexV][indexP]">Hide</p>
+ <p ng-if="!ctrl.collapeScore[indexI][indexV][indexP]">Show</p>
+ </a>
+ <table class="table" ng-class="{ 'hidden' : ! ctrl.collapeScore[indexI][indexV][indexP] } " ng-data="project.scores">
+ <tbody ng-repeat="(indexSC, score) in project.scores" >
+ <tr style="padding:9px">
+ <td class="podsTableTd">
+ Score:&nbsp;
+ </td>
+ <td width="90%" class="podsTableLeftTd">
+ {{score.score}}
+ </td>
+ </tr>
+ <tr style="padding:9px">
+ <td class="podsTableTd">
+ Date:&nbsp;
+ </td>
+ <td width="90%" class="podsTableLeftTd">
+ {{score.date}}
+ </td>
+ </tr>
+ </tbody>
+ <tr>
+ <button type="button" class="btn btn-success btn-xs" ng-click="ctrl.openAddScoreModal(project.project,version.version,installer.installer)" ng-class="{ 'hidden' : !ctrl.collapeScore[index] || !auth.isAuthenticated}"><i class="fa fa-plus"></i>Add</button>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr ng-class="{ 'hidden' : ! ctrl.collapeProject[indexI][indexV][indexP] }">
+ <td class="podsTableTd">
+ Customs:
+ </td>
+ <td class="podsTableLeftTd" style="width:90%">
+ <a ng-click="ctrl.expandCustom(indexI, indexV, indexP)">
+ <p ng-if="ctrl.collapeCustom[indexI][indexV][indexP]">Hide</p>
+ <p ng-if="!ctrl.collapeCustom[indexI][indexV][indexP]">Show</p>
+ </a>
+ <table class="table" ng-class="{ 'hidden' : ! ctrl.collapeCustom[indexI][indexV][indexP] } " ng-data="project.customs">
+ <tbody>
+ <tr ng-repeat-start="(indexCU, custom) in project.customs" style="padding:9px">
+ <td class="podsTableTd" style="float: none!important;">
+ {{custom}}
+ </td>
+ <td width="90%" class="podsTableLeftTd">
+ <button type="button" class="btn btn-danger btn-xs" ng-click="ctrl.openDeleteCustomModal(custom,project.project,version.version,installer.installer)" ng-class="{'hidden' : !auth.isAuthenticated}" ><i class="fa fa-minus"></i>Delete</button>
+ </td>
+ </tr>
+ <tr ng-repeat-end=>
+ </tr>
+ <tr>
+ <button type="button" class="btn btn-success btn-xs" ng-click="ctrl.openAddCustomModal(project.project,version.version,installer.installer)" ng-class="{ 'hidden' : !ctrl.collapeCustom[indexI][indexV][indexP] || !auth.isAuthenticated}"><i class="fa fa-plus"></i>Add</button>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ <tr ng-repeat-end=>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+</div>
+<div class="row" style="margin-bottom:24px;"></div>
+<div class='clo-md-12'>
+ <div ng-show="ctrl.showError" class="alert alert-danger" role="alert">
+ <span class="pull-right">&nbsp;{{ctrl.error}}</span>
+ <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span>
+ </div>
+ <div ng-show="ctrl.showSuccess" class="alert alert-success" role="alert">
+ <span class="pull-right">&nbsp;{{ctrl.success}}</span>
+ <span class="glyphicon glyphicon-ok pull-right" aria-hidden="true"></span>
+ </div>
+</div>
+<div class="row" style="margin-bottom:24px;"></div> \ No newline at end of file
diff --git a/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenarioController.js b/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenarioController.js
new file mode 100644
index 0000000..53eb13a
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenarioController.js
@@ -0,0 +1,581 @@
+/*
+ * 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('ScenarioController', ScenarioController);
+
+ ScenarioController.$inject = [
+ '$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl','raiseAlert',
+ 'confirmModal'
+ ];
+
+ /**
+ * TestAPI Scenario Controller
+ * This controller is for the '/Scenario/:name' page where a user can browse
+ * through Scenario declared in TestAPI.
+ */
+ function ScenarioController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl,
+ raiseAlert, confirmModal) {
+ var ctrl = this;
+ ctrl.name = $state.params['name'];
+ ctrl.url = testapiApiUrl + '/scenarios?name=' + ctrl.name;
+ ctrl.expandInstallers = expandInstallers;
+ ctrl.expandInstaller = expandInstaller;
+ ctrl.expandInstaller = ctrl.expandInstaller;
+ ctrl.expandVersion = expandVersion;
+ ctrl.expandVersions = expandVersions;
+ ctrl.loadDetails = loadDetails;
+ ctrl.expandProjects = expandProjects
+ ctrl.expandProject = expandProject
+ ctrl.expandTrustIndicator = expandTrustIndicator;
+ ctrl.expandScore = expandScore;
+ ctrl.expandCustom = expandCustom;
+ ctrl.collapeVersion = [];
+ ctrl.collapeVersions = [];
+ ctrl.collapeProjects = [];
+ ctrl.collapeProject = [];
+ ctrl.collapeTrustIndicator = [];
+ ctrl.collapeScore = [];
+ ctrl.collapeCustom = [];
+ ctrl.collapeInstaller = [];
+ ctrl.addCustom = addCustom;
+ ctrl.openAddCustomModal = openAddCustomModal;
+ ctrl.openDeleteCustomModal = openDeleteCustomModal;
+ ctrl.deleteCustom = deleteCustom;
+ ctrl.addProject = addProject
+ ctrl.openAddProjectModal = openAddProjectModal
+ ctrl.openAddVersionModal = openAddVersionModal
+ ctrl.addVersion = addVersion
+ ctrl.openDeleteVersionModal = openDeleteVersionModal
+ ctrl.deleteVersion = deleteVersion
+ ctrl.openAddInstaller = openAddInstaller
+ ctrl.addInstaller = addInstaller
+ ctrl.openDeleteInstallerModal = openDeleteInstallerModal
+ ctrl.deleteInstaller = deleteInstaller
+ ctrl.openDeleteProjectModal = openDeleteProjectModal
+ ctrl.deleteProject = deleteProject
+
+ ctrl.buttonInstaller = true
+ ctrl.buttonVersion = true
+ ctrl.buttonProject = true
+
+ /**
+ * This will contact the TestAPI to get a listing of declared projects.
+ */
+ function loadDetails() {
+ ctrl.showError = false;
+ ctrl.projectsRequest =
+ $http.get(ctrl.url).success(function (data) {
+ ctrl.data = data;
+ }).catch(function (error) {
+ ctrl.data = null;
+ ctrl.showError = true;
+ ctrl.error = error.statusText
+ });
+ }
+
+ function expandTrustIndicator(indexI, indexV, indexP){
+ if(ctrl.collapeTrustIndicator[indexI]==undefined){
+ ctrl.collapeTrustIndicator[indexI] = []
+ if(ctrl.collapeTrustIndicator[indexI][indexV]==undefined){
+ ctrl.collapeTrustIndicator[indexI][indexV] = []
+ }
+ }
+ if(ctrl.collapeTrustIndicator[indexI][indexV][indexP]){
+ ctrl.collapeTrustIndicator[indexI][indexV][indexP] = false;
+ }else{
+ ctrl.collapeTrustIndicator[indexI][indexV][indexP] = true;
+ }
+ }
+
+ function expandScore(indexI, indexV, indexP){
+ if(ctrl.collapeScore[indexI]==undefined){
+ ctrl.collapeScore[indexI] = []
+ if(ctrl.collapeScore[indexI][indexV]==undefined){
+ ctrl.collapeScore[indexI][indexV] = []
+ }
+ }
+ if(ctrl.collapeScore[indexI][indexV][indexP]){
+ ctrl.collapeScore[indexI][indexV][indexP] = false;
+ }else{
+ ctrl.collapeScore[indexI][indexV][indexP] = true;
+ }
+ }
+
+ function expandCustom(indexI, indexV, indexP){
+ if(ctrl.collapeCustom[indexI]==undefined){
+ ctrl.collapeCustom[indexI] = []
+ if(ctrl.collapeCustom[indexI][indexV]==undefined){
+ ctrl.collapeCustom[indexI][indexV] = []
+ }
+ }
+ if(ctrl.collapeCustom[indexI][indexV][indexP]){
+ ctrl.collapeCustom[indexI][indexV][indexP] = false;
+ ctrl.buttonProject = true
+ }else{
+ ctrl.collapeCustom[indexI][indexV][indexP] = true;
+ ctrl.buttonProject = false
+ }
+ }
+
+ function expandVersion(indexI, indexV){
+ if(ctrl.collapeVersion[indexI]==undefined){
+ ctrl.collapeVersion[indexI] = []
+ }
+ if(ctrl.collapeVersion[indexI][indexV]){
+ ctrl.collapeVersion[indexI][indexV] = false;
+ }else{
+ ctrl.collapeVersion[indexI][indexV] = true;
+ }
+ }
+
+ function expandVersions(index){
+ if(ctrl.collapeVersions[index]){
+ ctrl.collapeVersions[index] = false;
+ ctrl.buttonInstaller = true
+ }else{
+ ctrl.collapeVersions[index] = true;
+ ctrl.buttonInstaller = false
+ }
+ }
+
+ function expandProjects(indexI, indexV){
+ if(ctrl.collapeProjects[indexI]==undefined){
+ ctrl.collapeProjects[indexI] = []
+ }
+ if(ctrl.collapeProjects[indexI][indexV]){
+ ctrl.collapeProjects[indexI][indexV] = false;
+ ctrl.buttonVersion = true
+ }
+ else{
+ ctrl.collapeProjects[indexI][indexV]= true;
+ ctrl.buttonVersion = false
+ }
+ }
+
+ function expandProject(indexI, indexV, indexP){
+ if(ctrl.collapeProject[indexI]==undefined){
+ ctrl.collapeProject[indexI] = []
+ if(ctrl.collapeProject[indexI][indexV]==undefined){
+ ctrl.collapeProject[indexI][indexV] = []
+ }
+ }
+ if(ctrl.collapeProject[indexI][indexV][indexP]){
+ ctrl.collapeProject[indexI][indexV][indexP] = false;
+ }
+ else{
+ ctrl.collapeProject[indexI][indexV][indexP]= true;
+ }
+ }
+
+ function expandInstaller(index){
+ if(ctrl.collapeInstaller[index]){
+ ctrl.collapeInstaller[index] = false;
+ }
+ else{
+ ctrl.collapeInstaller[index]= true;
+ }
+ }
+
+ function expandInstallers(){
+ if(ctrl.collapeInstallers){
+ ctrl.collapeInstallers= false
+ }else{
+ ctrl.collapeInstallers= true
+ }
+ }
+
+ function deleteInstaller(data){
+ ctrl.installerReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/installers"
+ $http.delete(ctrl.installerReqest, {data: data.installers, headers: {'Content-Type': 'application/json'}}).success(function (data){
+ ctrl.showSuccess = true ;
+ ctrl.success = "Installer is successfully deleted."
+ ctrl.loadDetails();
+ })
+ .catch(function (data) {
+ ctrl.showError = true;
+ ctrl.error = data.statusText;
+ });
+ }
+
+ function openDeleteInstallerModal(installer){
+ var installers = []
+ installers.push(installer)
+ var data = {
+ "installers": installers
+ }
+ confirmModal("Delete",ctrl.deleteInstaller,data);
+ }
+
+ function addInstaller(installer){
+ var installers = []
+ installers.push(installer)
+ ctrl.installerReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/installers"
+ $http.post(ctrl.installerReqest, installers).success(function (data){
+ ctrl.showSuccess = true ;
+ ctrl.success = "Installers are successfully updated."
+ ctrl.loadDetails();
+ })
+ .catch(function (data) {
+ ctrl.showError = true;
+ ctrl.error = data.statusText;
+ });
+ }
+
+ function openAddInstaller(){
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/scenarios/modals/installerModal.html',
+ controller: 'installerModalCtrl as installerModalCtrl',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Add Installer",
+ successHandler: ctrl.addInstaller
+ };
+ }
+ }
+ });
+ }
+
+ function addVersion(versions, installer){
+ ctrl.versionReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/versions?installer="+installer
+ $http.post(ctrl.versionReqest, versions).success(function (data){
+ ctrl.showSuccess = true ;
+ ctrl.success = "Versions are successfully updated."
+ ctrl.loadDetails();
+ })
+ .catch(function (data) {
+ ctrl.showError = true;
+ ctrl.error = data.statusText;
+ });
+ }
+
+ function openDeleteVersionModal(version, installer){
+ var versions = []
+ versions.push(version)
+ var data = {
+ "version": versions,
+ "installer": installer
+ }
+ confirmModal("Delete",ctrl.deleteVersion,data);
+ }
+
+ function deleteVersion(data){
+ ctrl.versionReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/versions?installer="+data.installer
+ $http.delete(ctrl.versionReqest, {data: data.version, headers: {'Content-Type': 'application/json'}}).success(function (data){
+ ctrl.showSuccess = true ;
+ ctrl.success = "Versions are successfully deleted."
+ ctrl.loadDetails();
+ })
+ .catch(function (data) {
+ ctrl.showError = true;
+ ctrl.error = data.statusText;
+ });
+ }
+
+ function openAddVersionModal(installer){
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/scenarios/modals/versionModal.html',
+ controller: 'versionAddModalCtrl as versionModalCtrl',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Add Version",
+ successHandler: ctrl.addVersion,
+ installer: installer
+ };
+ }
+ }
+ });
+ }
+
+ function addProject(project, version, installer){
+ ctrl.projectReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/projects?installer="+installer+"&version="+version
+ $http.post(ctrl.projectReqest, project).success(function (data){
+ ctrl.showSuccess = true ;
+ ctrl.success = "Projects are successfully updated."
+ ctrl.loadDetails();
+ })
+ .catch(function (data) {
+ ctrl.showError = true;
+ ctrl.error = data.statusText;
+ });
+ }
+
+ function openAddProjectModal(version, installer){
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/scenarios/modals/projectModal.html',
+ controller: 'projectAddModalCtrl as projectModalCtrl',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Add Project",
+ successHandler: ctrl.addProject,
+ version: version,
+ installer: installer
+ };
+ }
+ }
+ });
+ }
+
+ function addCustom(custom,project,version,installer){
+ ctrl.customReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/customs?installer="+installer+"&version="+version+"&project="+ project
+ $http.post(ctrl.customReqest, custom).success(function (data){
+ ctrl.showSuccess = true ;
+ ctrl.success = "Customs are successfully updated."
+ ctrl.loadDetails();
+ })
+ .catch(function (data) {
+ ctrl.showError = true;
+ ctrl.error = data.statusText;
+ });
+ }
+
+ function openDeleteCustomModal(custom,project,version,installer){
+ var customs = []
+ customs.push(custom)
+ var data = {
+ "customs": customs,
+ "project": project,
+ "version": version,
+ "installer": installer
+ }
+ confirmModal("Delete",ctrl.deleteCustom,data);
+ }
+
+ function deleteCustom(data){
+ ctrl.customReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/customs?installer="+data.installer+"&version="+data.version+"&project="+ data.project
+ $http.delete(ctrl.customReqest, {data: data.customs, headers: {'Content-Type': 'application/json'}}).success(function (data){
+ ctrl.showSuccess = true ;
+ ctrl.success = "Customs are successfully deleted."
+ ctrl.loadDetails();
+ })
+ .catch(function (data) {
+ ctrl.showError = true;
+ ctrl.error = data.statusText;
+ });
+ }
+
+ function openAddCustomModal(project,version,installer){
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/scenarios/modals/customModal.html',
+ controller: 'customAddModalCtrl as customModalCtrl',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Add Custom",
+ successHandler: ctrl.addCustom,
+ project: project,
+ version: version,
+ installer: installer
+ };
+ }
+ }
+ });
+ }
+
+ function openDeleteProjectModal(project, version, installer){
+ var projects = []
+ projects.push(project.project)
+ var data = {
+ "projects": projects,
+ "version": version,
+ "installer": installer
+ }
+ confirmModal("Delete",ctrl.deleteProject,data);
+ }
+
+ function deleteProject(data){
+ ctrl.projectReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/projects?installer="+data.installer+"&version="+data.version
+ $http.delete(ctrl.projectReqest, {data: data.projects, headers: {'Content-Type': 'application/json'}}).success(function (data){
+ ctrl.showSuccess = true ;
+ ctrl.success = "Projects are successfully Deleted."
+ ctrl.loadDetails();
+ })
+ .catch(function (data) {
+ ctrl.showError = true;
+ ctrl.error = data.statusText;
+ });
+ }
+
+ ctrl.loadDetails();
+ }
+
+ /**
+ * TestAPI Project Modal Controller
+ * This controller is for the create modal where a user can create
+ * the project information and for the edit modal where user can
+ * edit the project's details
+ */
+ angular.module('testapiApp').controller('customAddModalCtrl', customAddModalCtrl);
+ customAddModalCtrl.$inject = ['$scope', '$uibModalInstance', 'data'];
+ function customAddModalCtrl($scope, $uibModalInstance, data) {
+ var ctrl = this;
+ ctrl.confirm = confirm;
+ ctrl.cancel = cancel;
+ ctrl.data = angular.copy(data);
+ ctrl.open = open;
+
+
+ /**
+ * Initiate confirmation and call the success handler with the
+ * inputs.
+ */
+ function confirm() {
+ ctrl.customs = []
+ ctrl.customs.push(ctrl.custom)
+ ctrl.data.successHandler(ctrl.customs,ctrl.data.project,ctrl.data.version,ctrl.data.installer);
+ $uibModalInstance.dismiss('cancel');
+
+ }
+
+ /**
+ * Close the confirm modal without initiating changes.
+ */
+ function cancel() {
+ $uibModalInstance.dismiss('cancel');
+ }
+ }
+
+
+ /**
+ * TestAPI Project Modal Controller
+ * This controller is for the create modal where a user can create
+ * the project information and for the edit modal where user can
+ * edit the project's details
+ */
+ angular.module('testapiApp').controller('projectAddModalCtrl', projectAddModalCtrl);
+ projectAddModalCtrl.$inject = ['$scope', '$uibModal', '$uibModalInstance', 'data'];
+ function projectAddModalCtrl($scope, $uibModal, $uibModalInstance, data) {
+ var ctrl = this;
+ ctrl.confirm = confirm;
+ ctrl.cancel = cancel;
+ ctrl.data = angular.copy(data);
+ ctrl.openCustomModal = openCustomModal;
+ ctrl.handleModalCustom = handleModalCustom;
+ ctrl.projects = []
+ ctrl.project = {
+ "scores": [],
+ "trust_indicators": [],
+ "customs": []
+ }
+
+
+ /**
+ * Initiate confirmation and call the success handler with the
+ * inputs.
+ */
+ function confirm() {
+ ctrl.projects.push(ctrl.project)
+ ctrl.data.successHandler(ctrl.projects, ctrl.data.version, ctrl.data.installer);
+ $uibModalInstance.dismiss('cancel');
+
+ }
+
+ /**
+ * Close the confirm modal without initiating changes.
+ */
+ function cancel() {
+ $uibModalInstance.dismiss('cancel');
+ }
+
+ function handleModalCustom(custom){
+ ctrl.project.customs.push(custom);
+ }
+
+ function openCustomModal(){
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/scenarios/modals/customModal.html',
+ controller: 'customModalCtrl as customModalCtrl',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Custom",
+ successHandler: ctrl.handleModalCustom
+ };
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * TestAPI Project Modal Controller
+ * This controller is for the create modal where a user can create
+ * the project information and for the edit modal where user can
+ * edit the project's details
+ */
+ angular.module('testapiApp').controller('versionAddModalCtrl', versionAddModalCtrl);
+ versionAddModalCtrl.$inject = ['$scope', '$uibModal','$uibModalInstance', 'data'];
+ function versionAddModalCtrl($scope, $uibModal, $uibModalInstance, data) {
+ var ctrl = this;
+ ctrl.confirm = confirm;
+ ctrl.cancel = cancel;
+ ctrl.data = angular.copy(data);
+ ctrl.openProjectModal = openProjectModal;
+ ctrl.handleModalData = handleModalData;
+ ctrl.versions = []
+ ctrl.version = {
+ "projects": []
+ }
+
+ /**
+ * Initiate confirmation and call the success handler with the
+ * inputs.
+ */
+ function confirm() {
+ ctrl.versions.push(ctrl.version)
+ ctrl.data.successHandler(ctrl.versions, ctrl.data.installer);
+ $uibModalInstance.dismiss('cancel');
+
+ }
+
+ /**
+ * Close the confirm modal without initiating changes.
+ */
+ function cancel() {
+ $uibModalInstance.dismiss('cancel');
+ }
+
+ function handleModalData(project){
+ ctrl.version.projects.push(project)
+ }
+ function openProjectModal(){
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/scenarios/modals/projectModal.html',
+ controller: 'projectModalCtrl as projectModalCtrl',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Project",
+ successHandler: ctrl.handleModalData,
+ };
+ }
+ }
+ });
+ }
+ }
+
+})();
diff --git a/testapi/opnfv_testapi/ui/components/scenarios/scenarios.html b/testapi/opnfv_testapi/ui/components/scenarios/scenarios.html
new file mode 100644
index 0000000..9057b0f
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/scenarios/scenarios.html
@@ -0,0 +1,60 @@
+<h3>Scenarios</h3>
+<div class="row" style="margin-bottom:24px;"></div>
+<div class="row podsTable" style="vertical-align:middle">
+ <div class="col-sm-1 pull-right" ng-class="{ 'hidden': !auth.isAuthenticated }" >
+ <button type="button" class="btn btn-danger" ng-click="ctrl.openBatchDeleteModal()">
+ <i class="fa fa-minus"></i> Delete</button>
+ </div>
+ <div class="col-sm-2 pull-right" ng-class="{ 'hidden': !auth.isAuthenticated}">
+ <button type="button" class="btn btn-success" ng-click="ctrl.openScenarioModal()">
+ <i class="fa fa-plus"></i>Create</button>
+ </div>
+</div>
+<div class='clo-md-12'>
+ <div ng-show="ctrl.showError" class="alert alert-danger" role="alert">
+ <span class="pull-right">&nbsp;{{ctrl.error}}</span>
+ <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span>
+ </div>
+ <div ng-show="ctrl.showCreateSuccess" class="alert alert-success" role="alert">
+ <span class="pull-right">&nbsp;{{ctrl.success}}</span>
+ <span class="glyphicon glyphicon-ok pull-right" aria-hidden="true"></span>
+ </div>
+</div>
+<div class='clo-md-12' style="padding-right:0px">
+ <div class="table-responsive">
+ <table class="table table-bordered table-hover" ng-data="ctrl.data.scenarios">
+ <thead>
+ <tr style="
+ text-align: center;">
+ <th style="width: 1%;">Bulk&nbsp;Select</th>
+ <th style="width: 80%;">Name</th>
+ <th style="width: 19%;" ng-class="{'hidden': !auth.isAuthenticated}">Operations</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat-start="(index, scenario) in ctrl.data.scenarios" style="padding:9px">
+ <td>
+ <div class="text-center">
+ <input type="checkbox" value="{{scenario.name}}" ng-model="ctrl.checkBox[index]" >
+ </div>
+ </td>
+ <td>
+ <a class="text-info" ng-click="ctrl.viewScenario(scenario.name)">
+ {{scenario.name}}
+ </a>
+ </td>
+ <td ng-class="{'hidden': !auth.isAuthenticated}">
+ <span class="podsTable-col">
+ <a class="text-warning" ng-click="ctrl.openUpdateModal(scenario.name)" title="Edit">
+ <i class="fa fa-pencil-square-o"></i></a>
+ <a class="text-danger" ng-click="ctrl.openDeleteModal(scenario.name)" title="Delete">
+ <i class="fa fa-trash-o"></i></a>
+ </span>
+ </td>
+ <tr ng-repeat-end=>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+</div>
+
diff --git a/testapi/opnfv_testapi/ui/components/scenarios/scenariosController.js b/testapi/opnfv_testapi/ui/components/scenarios/scenariosController.js
new file mode 100644
index 0000000..fd137e5
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/scenarios/scenariosController.js
@@ -0,0 +1,467 @@
+/*
+ * 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('ScenariosController', ScenariosController);
+
+ ScenariosController.$inject = [
+ '$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl',
+ 'raiseAlert', 'confirmModal'
+ ];
+
+ /**
+ * TestAPI Project Controller
+ * This controller is for the '/projects' page where a user can browse
+ * through projects declared in TestAPI.
+ */
+ function ScenariosController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl,
+ raiseAlert, confirmModal) {
+ var ctrl = this;
+ ctrl.url = testapiApiUrl + '/scenarios';
+
+ ctrl.createScenario = createScenario;
+ ctrl.listScenarios = listScenarios;
+ ctrl.openScenarioModal = openScenarioModal;
+ ctrl.viewScenario = viewScenario;
+ ctrl.openUpdateModal = openUpdateModal;
+ ctrl.updateScenarioName = updateScenarioName;
+ ctrl.openDeleteModal = openDeleteModal;
+ ctrl.deleteScenario = deleteScenario;
+ ctrl.openBatchDeleteModal = openBatchDeleteModal;
+ ctrl.deleteBatchScenario = deleteBatchScenario
+
+ ctrl.checkBox = [];
+
+ function openUpdateModal(name){
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/scenarios/modals/scenarioNameUpdate.html',
+ controller: 'ScenarioNameUpdateCtrl as ScenarioNameUpdateCtrl',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Name Change: Scenario",
+ successHandler: ctrl.updateScenarioName,
+ name: name
+ };
+ }
+ }
+ });
+ }
+
+ function openDeleteModal(name){
+ confirmModal("Delete",ctrl.deleteScenario,name);
+ }
+
+ function deleteScenario(name){
+ var scenarioURL = ctrl.url+"/"+name;
+ ctrl.scenarioRequest =
+ $http.delete(scenarioURL).success(function (data){
+ ctrl.showCreateSuccess = true;
+ ctrl.success = "Scenario is successfully deleted.";
+ ctrl.listScenarios();
+ }).catch(function (data) {
+ ctrl.showError = true;
+ ctrl.error = data.statusText;
+ });
+ }
+
+ function openBatchDeleteModal(){
+ confirmModal("Delete",ctrl.deleteBatchScenario);
+ }
+
+ function deleteBatchScenario(){
+ var index;
+ var checkedBox = [];
+ ctrl.checkBox.forEach(function(project, index){
+ if(!ctrl.showError){
+ if(project){
+ deleteScenario(ctrl.data.scenarios[index].name);
+ }
+ }
+ });
+ ctrl.checkBox = []
+ }
+
+ function updateScenarioName(newName, name){
+ var scenarioURL = ctrl.url+"/"+name
+ var body = {
+ "name": newName
+ }
+ ctrl.scenarioRequest =
+ $http.put(scenarioURL, body).success(function (data){
+ ctrl.showCreateSuccess = true;
+ ctrl.success = "Scenario is successfully Updated."
+ ctrl.listScenarios()
+ }).catch(function (data) {
+ ctrl.showError = true;
+ ctrl.error = data.statusText;
+ });
+ }
+
+ function viewScenario(name){
+ $state.go('scenario', {'name':name}, {reload: true});
+ }
+
+ function createScenario(scenario) {
+ console.log(scenario)
+ ctrl.scenarioRequest =
+ $http.post(ctrl.url, scenario).success(function (data){
+ ctrl.showCreateSuccess = true;
+ ctrl.success = "Scenario is successfully created."
+ }).catch(function (data) {
+ ctrl.showError = true;
+ ctrl.error = data.statusText;
+ });
+ }
+
+ function listScenarios() {
+ ctrl.showError = false;
+ ctrl.resultsRequest =
+ $http.get(ctrl.url).success(function (data) {
+ ctrl.data = data;
+ }).catch(function (data) {
+ ctrl.data = null;
+ ctrl.showError = true;
+ ctrl.error = data.statusText;
+ });
+ }
+
+ function openScenarioModal(){
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/scenarios/modals/scenarioModal.html',
+ controller: 'scenarioModalController as scenarioModalController',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Scenario",
+ successHandler: ctrl.createScenario,
+ };
+ }
+ }
+ });
+ }
+
+ listScenarios();
+ }
+
+
+ /**
+ * TestAPI Project Modal Controller
+ * This controller is for the create modal where a user can create
+ * the project information and for the edit modal where user can
+ * edit the project's details
+ */
+ angular.module('testapiApp').controller('scenarioModalController', scenarioModalController);
+ scenarioModalController.$inject = ['$scope', '$uibModal', '$uibModalInstance', 'data'];
+ function scenarioModalController($scope, $uibModal, $uibModalInstance, data) {
+ var ctrl = this;
+ ctrl.confirm = confirm;
+ ctrl.cancel = cancel;
+ ctrl.data = angular.copy(data);
+ ctrl.handleModalData = handleModalData;
+ ctrl.openInstallerModal = openInstallerModal;
+ ctrl.scenario = {
+ "installers": [],
+ }
+
+
+ /**
+ * Initiate confirmation and call the success handler with the
+ * inputs.
+ */
+ function confirm() {
+ ctrl.data.successHandler(ctrl.scenario);
+ $uibModalInstance.dismiss('cancel');
+
+ }
+
+ /**
+ * Close the confirm modal without initiating changes.
+ */
+ function cancel() {
+ $uibModalInstance.dismiss('cancel');
+ }
+
+ function handleModalData(installer){
+ ctrl.scenario.installers.push(installer)
+ }
+
+ function openInstallerModal(){
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/scenarios/modals/installerModal.html',
+ controller: 'installerModalCtrl as installerModalCtrl',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Installer",
+ successHandler: ctrl.handleModalData,
+ };
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * TestAPI Project Modal Controller
+ * This controller is for the create modal where a user can create
+ * the project information and for the edit modal where user can
+ * edit the project's details
+ */
+ angular.module('testapiApp').controller('installerModalCtrl', installerModalCtrl);
+ installerModalCtrl.$inject = ['$scope', '$uibModal', '$uibModalInstance', 'data'];
+ function installerModalCtrl($scope, $uibModal, $uibModalInstance, data) {
+ var ctrl = this;
+ ctrl.confirm = confirm;
+ ctrl.cancel = cancel;
+ ctrl.data = angular.copy(data);
+ ctrl.openVersionModal = openVersionModal;
+ ctrl.handleModalData = handleModalData;
+ ctrl.installer = {
+ "versions":[]
+ }
+
+
+ /**
+ * Initiate confirmation and call the success handler with the
+ * inputs.
+ */
+ function confirm() {
+ ctrl.data.successHandler(ctrl.installer);
+ $uibModalInstance.dismiss('cancel');
+
+ }
+
+ /**
+ * Close the confirm modal without initiating changes.
+ */
+ function cancel() {
+ $uibModalInstance.dismiss('cancel');
+ }
+
+ function handleModalData(version){
+ ctrl.installer.versions.push(version);
+ }
+
+ function openVersionModal(){
+ console.log("Hello");
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/scenarios/modals/versionModal.html',
+ controller: 'versionModalCtrl as versionModalCtrl',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Version",
+ successHandler: ctrl.handleModalData,
+ };
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * TestAPI Project Modal Controller
+ * This controller is for the create modal where a user can create
+ * the project information and for the edit modal where user can
+ * edit the project's details
+ */
+ angular.module('testapiApp').controller('versionModalCtrl', versionModalCtrl);
+ versionModalCtrl.$inject = ['$scope', '$uibModal','$uibModalInstance', 'data'];
+ function versionModalCtrl($scope, $uibModal, $uibModalInstance, data) {
+ var ctrl = this;
+ ctrl.confirm = confirm;
+ ctrl.cancel = cancel;
+ ctrl.data = angular.copy(data);
+ ctrl.openProjectModal = openProjectModal;
+ ctrl.handleModalData = handleModalData;
+ ctrl.version = {
+ "projects": []
+ }
+
+ /**
+ * Initiate confirmation and call the success handler with the
+ * inputs.
+ */
+ function confirm() {
+ ctrl.data.successHandler(ctrl.version);
+ $uibModalInstance.dismiss('cancel');
+
+ }
+
+ /**
+ * Close the confirm modal without initiating changes.
+ */
+ function cancel() {
+ $uibModalInstance.dismiss('cancel');
+ }
+
+ function handleModalData(project){
+ ctrl.version.projects.push(project)
+ }
+ function openProjectModal(){
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/scenarios/modals/projectModal.html',
+ controller: 'projectModalCtrl as projectModalCtrl',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Project",
+ successHandler: ctrl.handleModalData,
+ };
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * TestAPI Project Modal Controller
+ * This controller is for the create modal where a user can create
+ * the project information and for the edit modal where user can
+ * edit the project's details
+ */
+ angular.module('testapiApp').controller('projectModalCtrl', projectModalCtrl);
+ projectModalCtrl.$inject = ['$scope', '$uibModal', '$uibModalInstance', 'data'];
+ function projectModalCtrl($scope, $uibModal, $uibModalInstance, data) {
+ var ctrl = this;
+ ctrl.confirm = confirm;
+ ctrl.cancel = cancel;
+ ctrl.data = angular.copy(data);
+ ctrl.openCustomModal = openCustomModal;
+ ctrl.handleModalCustom = handleModalCustom;
+ ctrl.project = {
+ "scores": [],
+ "trust_indicators": [],
+ "customs": []
+ }
+
+
+ /**
+ * Initiate confirmation and call the success handler with the
+ * inputs.
+ */
+ function confirm() {
+
+ ctrl.data.successHandler(ctrl.project);
+ $uibModalInstance.dismiss('cancel');
+
+ }
+
+ /**
+ * Close the confirm modal without initiating changes.
+ */
+ function cancel() {
+ $uibModalInstance.dismiss('cancel');
+ }
+
+ function handleModalCustom(custom){
+ ctrl.project.customs.push(custom);
+ }
+
+ function openCustomModal(){
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/scenarios/modals/customModal.html',
+ controller: 'customModalCtrl as customModalCtrl',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Custom",
+ successHandler: ctrl.handleModalCustom
+ };
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * TestAPI Project Modal Controller
+ * This controller is for the create modal where a user can create
+ * the project information and for the edit modal where user can
+ * edit the project's details
+ */
+ angular.module('testapiApp').controller('customModalCtrl', customModalCtrl);
+ customModalCtrl.$inject = ['$scope', '$uibModalInstance', 'data'];
+ function customModalCtrl($scope, $uibModalInstance, data) {
+ var ctrl = this;
+ ctrl.confirm = confirm;
+ ctrl.cancel = cancel;
+ ctrl.data = angular.copy(data);
+ ctrl.open = open;
+
+
+ /**
+ * Initiate confirmation and call the success handler with the
+ * inputs.
+ */
+ function confirm() {
+ ctrl.data.successHandler(ctrl.custom);
+ $uibModalInstance.dismiss('cancel');
+
+ }
+
+ /**
+ * Close the confirm modal without initiating changes.
+ */
+ function cancel() {
+ $uibModalInstance.dismiss('cancel');
+ }
+ }
+
+ /**
+ * TestAPI Project Modal Controller
+ * This controller is for the create modal where a user can create
+ * the project information and for the edit modal where user can
+ * edit the project's details
+ */
+ angular.module('testapiApp').controller('ScenarioNameUpdateCtrl', ScenarioNameUpdateCtrl);
+ ScenarioNameUpdateCtrl.$inject = ['$scope', '$uibModalInstance', 'data'];
+ function ScenarioNameUpdateCtrl($scope, $uibModalInstance, data) {
+ var ctrl = this;
+ ctrl.confirm = confirm;
+ ctrl.cancel = cancel;
+ ctrl.data = angular.copy(data);
+ ctrl.open = open;
+ ctrl.name = ctrl.data.name;
+
+
+ /**
+ * Initiate confirmation and call the success handler with the
+ * inputs.
+ */
+ function confirm() {
+ ctrl.data.successHandler(ctrl.name,ctrl.data.name);
+ $uibModalInstance.dismiss('cancel');
+
+ }
+
+ /**
+ * Close the confirm modal without initiating changes.
+ */
+ function cancel() {
+ $uibModalInstance.dismiss('cancel');
+ }
+ }
+})();
diff --git a/testapi/opnfv_testapi/ui/config.json b/testapi/opnfv_testapi/ui/config.json
index 5d48c7b..26dfd08 100644
--- a/testapi/opnfv_testapi/ui/config.json
+++ b/testapi/opnfv_testapi/ui/config.json
@@ -1 +1,2 @@
-{"testapiApiUrl": "http://localhost:8000/api/v1"}
+{"testapiApiUrl": "http://localhost:8000/api/v1",
+"authenticate": true}
diff --git a/testapi/opnfv_testapi/ui/index.html b/testapi/opnfv_testapi/ui/index.html
index 3191858..beec61d 100644
--- a/testapi/opnfv_testapi/ui/index.html
+++ b/testapi/opnfv_testapi/ui/index.html
@@ -44,13 +44,18 @@
<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/scenarios/scenario/scenarioController.js"></script>
+ <script src="testapi-ui/components/scenarios/scenariosController.js"></script>
<script src="testapi-ui/components/pods/pod/podController.js"></script>
<script src="testapi-ui/components/projects/projectsController.js"></script>
<script src="testapi-ui/components/projects/project/projectController.js"></script>
<script src="testapi-ui/components/results/resultsController.js"></script>
+ <script src="testapi-ui/components/results/result/resultController.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/project/testCases/testCasesController.js"></script>
+ <script src="testapi-ui/components/projects/project/testCases/testCase/testCaseController.js"></script>
<!-- Filters -->
<script src="testapi-ui/shared/filters.js"></script>
diff --git a/testapi/opnfv_testapi/ui/shared/alerts/confirmModalFactory.js b/testapi/opnfv_testapi/ui/shared/alerts/confirmModalFactory.js
index fc0bfe6..5e79775 100644
--- a/testapi/opnfv_testapi/ui/shared/alerts/confirmModalFactory.js
+++ b/testapi/opnfv_testapi/ui/shared/alerts/confirmModalFactory.js
@@ -46,7 +46,6 @@
ctrl.cancel = cancel;
ctrl.data = angular.copy(data);
- console.log(ctrl.data)
/**
* Initiate confirmation and call the success handler with the
* input text.
diff --git a/testapi/opnfv_testapi/ui/shared/header/header.html b/testapi/opnfv_testapi/ui/shared/header/header.html
index d0501a2..3b2aba1 100644
--- a/testapi/opnfv_testapi/ui/shared/header/header.html
+++ b/testapi/opnfv_testapi/ui/shared/header/header.html
@@ -19,9 +19,10 @@ TestAPI
<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('/projects')}"><a ui-sref="projects">Projects</a></li>
- <li ng-class="{ active: header.isActive('/results')}"><a ui-sref="results">Results</a></li>
+ <li ng-class="{ active: header.isActive('/results')}"><a ui-sref="results">Results</a></li>
+ <li ng-class="{ active: header.isActive('/scenarios')}"><a ui-sref="scenarios">Scenarios</a></li>
</ul>
- <ul class="nav navbar-nav navbar-right">
+ <ul class="nav navbar-nav navbar-right" ng-class="{'hidden' : !authenticate}">
<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>