summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerenaFeng <feng.xiaowei@zte.com.cn>2018-01-05 14:39:12 +0800
committerthuva4 <tharma.thuva@gmail.com>2018-01-09 19:56:56 +0530
commit349609818abcf10cc94088b043f71b5c8bc504a1 (patch)
tree3a59930127379f50121c066041121a3cc96a7ff2
parent8dbe224064851d439b18ad4254e119aff7f02e30 (diff)
Design the scenario create method
design scenario create method in modal way. design scenario page. Add,delete for installers,versions, projects, customs, trust indicators and scores are implemented. tests are not included. validations are not added. Change-Id: I999229c00869fcd5a4efa97cb2679a08fc24b271 Signed-off-by: thuva4 <tharma.thuva@gmail.com>
-rw-r--r--testapi/docker/Dockerfile7
-rw-r--r--testapi/opnfv_testapi/common/check.py2
-rw-r--r--testapi/opnfv_testapi/handlers/base_handlers.py1
-rw-r--r--testapi/opnfv_testapi/models/testcase_models.py6
-rw-r--r--testapi/opnfv_testapi/tests/unit/handlers/test_scenario.py37
-rw-r--r--testapi/opnfv_testapi/ui/app.js10
-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.html121
-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.html234
-rw-r--r--testapi/opnfv_testapi/ui/components/scenarios/scenario/scenarioController.js724
-rw-r--r--testapi/opnfv_testapi/ui/components/scenarios/scenarios.html60
-rw-r--r--testapi/opnfv_testapi/ui/components/scenarios/scenariosController.js609
-rw-r--r--testapi/opnfv_testapi/ui/index.html2
-rw-r--r--testapi/opnfv_testapi/ui/shared/header/header.html3
-rw-r--r--testapi/requirements.txt1
21 files changed, 2149 insertions, 10 deletions
diff --git a/testapi/docker/Dockerfile b/testapi/docker/Dockerfile
index 33088c7..bbf12fc 100644
--- a/testapi/docker/Dockerfile
+++ b/testapi/docker/Dockerfile
@@ -40,7 +40,7 @@ python-pip \
crudini \
--no-install-recommends
-RUN pip install --upgrade pip
+RUN pip install --upgrade pip requests
RUN git config --global http.sslVerify false
RUN git clone https://gerrit.opnfv.org/gerrit/releng-testresults /home/releng-testresults
@@ -48,10 +48,5 @@ RUN git clone https://gerrit.opnfv.org/gerrit/releng-testresults /home/releng-te
WORKDIR /home/releng-testresults/testapi
RUN pip install -r requirements.txt
-# bugfix
-# SSLError: hostname 'identity.linuxfoundation.org' doesn't match 'c.sni.fastly.net'
-# hope it is a temprary, try to fix it in upstream python-cas lib
-RUN sed -i '152,152s/)/,\ verify=False)/g' /usr/local/lib/python2.7/dist-packages/cas.py
-
RUN python setup.py install
CMD ["bash", "docker/start-server.sh"]
diff --git a/testapi/opnfv_testapi/common/check.py b/testapi/opnfv_testapi/common/check.py
index 333871d..9b3ab01 100644
--- a/testapi/opnfv_testapi/common/check.py
+++ b/testapi/opnfv_testapi/common/check.py
@@ -21,7 +21,7 @@ from opnfv_testapi.db import api as dbapi
def is_authorized(method):
@functools.wraps(method)
def wrapper(self, *args, **kwargs):
- if CONF.api_authenticate and self.table in ['pods', 'projects', 'testcases']:
+ if CONF.api_authenticate and self.table in ['pods', 'projects', 'testcases', 'scenarios']:
testapi_id = self.get_secure_cookie(constants.TESTAPI_ID)
if not testapi_id:
raises.Unauthorized(message.not_login())
diff --git a/testapi/opnfv_testapi/handlers/base_handlers.py b/testapi/opnfv_testapi/handlers/base_handlers.py
index 9eac737..537077d 100644
--- a/testapi/opnfv_testapi/handlers/base_handlers.py
+++ b/testapi/opnfv_testapi/handlers/base_handlers.py
@@ -200,6 +200,7 @@ class GenericApiHandler(web.RequestHandler):
@gen.coroutine
@check.no_body
@check.not_exist
+ @check.is_authorized
@check.updated_one_not_exist
def pure_update(self, data, query=None, **kwargs):
data = self.table_cls.from_dict(data)
diff --git a/testapi/opnfv_testapi/models/testcase_models.py b/testapi/opnfv_testapi/models/testcase_models.py
index 1a55cf7..96195b2 100644
--- a/testapi/opnfv_testapi/models/testcase_models.py
+++ b/testapi/opnfv_testapi/models/testcase_models.py
@@ -51,8 +51,10 @@ class TestcaseUpdateRequest(TestcaseCreateRequest):
@swagger.model()
class Testcase(TestcaseCreateRequest):
- def __init__(self, _id=None, **kwargs):
- self._id = None
+ def __init__(self, **kwargs):
+ self._id = kwargs.pop('_id', '')
+ self.project_name = kwargs.pop('project_name', '')
+ self.creation_date = kwargs.pop('creation_date', '')
super(Testcase, self).__init__(**kwargs)
diff --git a/testapi/opnfv_testapi/tests/unit/handlers/test_scenario.py b/testapi/opnfv_testapi/tests/unit/handlers/test_scenario.py
index 5d1b738..481078d 100644
--- a/testapi/opnfv_testapi/tests/unit/handlers/test_scenario.py
+++ b/testapi/opnfv_testapi/tests/unit/handlers/test_scenario.py
@@ -4,6 +4,7 @@ import httplib
from opnfv_testapi.common import message
import opnfv_testapi.models.scenario_models as sm
+from opnfv_testapi.tests.unit import executor
from opnfv_testapi.tests.unit.handlers import test_base as base
@@ -20,6 +21,7 @@ class TestScenarioBase(base.TestBase):
self.req_d = self.load_json('scenario-c1')
self.req_2 = self.load_json('scenario-c2')
+ @executor.mock_valid_lfid()
def create_return_name(self, req):
_, res = self.create(req)
return res.href.split('/')[-1]
@@ -45,27 +47,32 @@ class TestScenarioBase(base.TestBase):
class TestScenarioCreate(TestScenarioBase):
+ @executor.mock_valid_lfid()
def test_withoutBody(self):
(code, body) = self.create()
self.assertEqual(code, httplib.BAD_REQUEST)
+ @executor.mock_valid_lfid()
def test_emptyName(self):
req_empty = sm.ScenarioCreateRequest('')
(code, body) = self.create(req_empty)
self.assertEqual(code, httplib.BAD_REQUEST)
self.assertIn(message.missing('name'), body)
+ @executor.mock_valid_lfid()
def test_noneName(self):
req_none = sm.ScenarioCreateRequest(None)
(code, body) = self.create(req_none)
self.assertEqual(code, httplib.BAD_REQUEST)
self.assertIn(message.missing('name'), body)
+ @executor.mock_valid_lfid()
def test_success(self):
(code, body) = self.create_d()
self.assertEqual(code, httplib.OK)
self.assert_create_body(body)
+ @executor.mock_valid_lfid()
def test_alreadyExist(self):
self.create_d()
(code, body) = self.create_d()
@@ -128,6 +135,7 @@ class TestScenarioDelete(TestScenarioBase):
code, body = self.delete('notFound')
self.assertEqual(code, httplib.NOT_FOUND)
+ @executor.mock_valid_lfid()
def test_success(self):
scenario = self.create_return_name(self.req_d)
code, _ = self.delete(scenario)
@@ -182,6 +190,7 @@ class TestScenarioUpdate(TestScenarioBase):
return wrapper
return _update_partial
+ @executor.mock_valid_lfid()
@update_partial('_add', '_success')
def test_addScore(self):
add = sm.ScenarioScore(date=str(datetime.now()), score='11/12')
@@ -193,6 +202,7 @@ class TestScenarioUpdate(TestScenarioBase):
return add
+ @executor.mock_valid_lfid()
@update_partial('_add', '_success')
def test_addTrustIndicator(self):
add = sm.ScenarioTI(date=str(datetime.now()), status='gold')
@@ -204,6 +214,7 @@ class TestScenarioUpdate(TestScenarioBase):
return add
+ @executor.mock_valid_lfid()
@update_partial('_add', '_success')
def test_addCustoms(self):
adds = ['odl', 'parser', 'vping_ssh']
@@ -214,6 +225,7 @@ class TestScenarioUpdate(TestScenarioBase):
self.locate_project)
return adds
+ @executor.mock_valid_lfid()
@update_partial('_update', '_success')
def test_updateCustoms(self):
updates = ['odl', 'parser', 'vping_ssh']
@@ -225,6 +237,7 @@ class TestScenarioUpdate(TestScenarioBase):
return updates
+ @executor.mock_valid_lfid()
@update_partial('_delete', '_success')
def test_deleteCustoms(self):
deletes = ['vping_ssh']
@@ -236,6 +249,7 @@ class TestScenarioUpdate(TestScenarioBase):
return deletes
+ @executor.mock_valid_lfid()
@update_url_fixture('projects')
@update_partial('_add', '_success')
def test_addProjects_succ(self):
@@ -243,12 +257,14 @@ class TestScenarioUpdate(TestScenarioBase):
self.req_d['installers'][0]['versions'][0]['projects'].append(add)
return [add]
+ @executor.mock_valid_lfid()
@update_url_fixture('projects')
@update_partial('_add', '_conflict')
def test_addProjects_already_exist(self):
add = sm.ScenarioProject(project='functest').format()
return [add]
+ @executor.mock_valid_lfid()
@update_url_fixture('projects')
@update_partial('_add', '_bad_request')
def test_addProjects_bad_schema(self):
@@ -256,6 +272,7 @@ class TestScenarioUpdate(TestScenarioBase):
add['score'] = None
return [add]
+ @executor.mock_valid_lfid()
@update_url_fixture('projects')
@update_partial('_update', '_success')
def test_updateProjects_succ(self):
@@ -263,12 +280,14 @@ class TestScenarioUpdate(TestScenarioBase):
self.req_d['installers'][0]['versions'][0]['projects'] = [update]
return [update]
+ @executor.mock_valid_lfid()
@update_url_fixture('projects')
@update_partial('_update', '_conflict')
def test_updateProjects_duplicated(self):
update = sm.ScenarioProject(project='qtip').format()
return [update, update]
+ @executor.mock_valid_lfid()
@update_url_fixture('projects')
@update_partial('_update', '_bad_request')
def test_updateProjects_bad_schema(self):
@@ -276,6 +295,7 @@ class TestScenarioUpdate(TestScenarioBase):
update['score'] = None
return [update]
+ @executor.mock_valid_lfid()
@update_url_fixture('projects')
@update_partial('_delete', '_success')
def test_deleteProjects(self):
@@ -286,6 +306,7 @@ class TestScenarioUpdate(TestScenarioBase):
projects)
return deletes
+ @executor.mock_valid_lfid()
@update_url_fixture('owner')
@update_partial('_update', '_success')
def test_changeOwner(self):
@@ -294,6 +315,7 @@ class TestScenarioUpdate(TestScenarioBase):
self.req_d['installers'][0]['versions'][0]['owner'] = new_owner
return update
+ @executor.mock_valid_lfid()
@update_url_fixture('versions')
@update_partial('_add', '_success')
def test_addVersions_succ(self):
@@ -301,12 +323,14 @@ class TestScenarioUpdate(TestScenarioBase):
self.req_d['installers'][0]['versions'].append(add)
return [add]
+ @executor.mock_valid_lfid()
@update_url_fixture('versions')
@update_partial('_add', '_conflict')
def test_addVersions_already_exist(self):
add = sm.ScenarioVersion(version='master').format()
return [add]
+ @executor.mock_valid_lfid()
@update_url_fixture('versions')
@update_partial('_add', '_bad_request')
def test_addVersions_bad_schema(self):
@@ -314,6 +338,7 @@ class TestScenarioUpdate(TestScenarioBase):
add['notexist'] = None
return [add]
+ @executor.mock_valid_lfid()
@update_url_fixture('versions')
@update_partial('_update', '_success')
def test_updateVersions_succ(self):
@@ -321,12 +346,14 @@ class TestScenarioUpdate(TestScenarioBase):
self.req_d['installers'][0]['versions'] = [update]
return [update]
+ @executor.mock_valid_lfid()
@update_url_fixture('versions')
@update_partial('_update', '_conflict')
def test_updateVersions_duplicated(self):
update = sm.ScenarioVersion(version='euphrates').format()
return [update, update]
+ @executor.mock_valid_lfid()
@update_url_fixture('versions')
@update_partial('_update', '_bad_request')
def test_updateVersions_bad_schema(self):
@@ -334,6 +361,7 @@ class TestScenarioUpdate(TestScenarioBase):
update['not_owner'] = 'Iam'
return [update]
+ @executor.mock_valid_lfid()
@update_url_fixture('versions')
@update_partial('_delete', '_success')
def test_deleteVersions(self):
@@ -344,6 +372,7 @@ class TestScenarioUpdate(TestScenarioBase):
versions)
return deletes
+ @executor.mock_valid_lfid()
@update_url_fixture('installers')
@update_partial('_add', '_success')
def test_addInstallers_succ(self):
@@ -351,12 +380,14 @@ class TestScenarioUpdate(TestScenarioBase):
self.req_d['installers'].append(add)
return [add]
+ @executor.mock_valid_lfid()
@update_url_fixture('installers')
@update_partial('_add', '_conflict')
def test_addInstallers_already_exist(self):
add = sm.ScenarioInstaller(installer='apex').format()
return [add]
+ @executor.mock_valid_lfid()
@update_url_fixture('installers')
@update_partial('_add', '_bad_request')
def test_addInstallers_bad_schema(self):
@@ -364,6 +395,7 @@ class TestScenarioUpdate(TestScenarioBase):
add['not_exist'] = 'not_exist'
return [add]
+ @executor.mock_valid_lfid()
@update_url_fixture('installers')
@update_partial('_update', '_success')
def test_updateInstallers_succ(self):
@@ -371,12 +403,14 @@ class TestScenarioUpdate(TestScenarioBase):
self.req_d['installers'] = [update]
return [update]
+ @executor.mock_valid_lfid()
@update_url_fixture('installers')
@update_partial('_update', '_conflict')
def test_updateInstallers_duplicated(self):
update = sm.ScenarioInstaller(installer='daisy').format()
return [update, update]
+ @executor.mock_valid_lfid()
@update_url_fixture('installers')
@update_partial('_update', '_bad_request')
def test_updateInstallers_bad_schema(self):
@@ -384,6 +418,7 @@ class TestScenarioUpdate(TestScenarioBase):
update['not_exist'] = 'not_exist'
return [update]
+ @executor.mock_valid_lfid()
@update_url_fixture('installers')
@update_partial('_delete', '_success')
def test_deleteInstallers(self):
@@ -394,6 +429,7 @@ class TestScenarioUpdate(TestScenarioBase):
installers)
return deletes
+ @executor.mock_valid_lfid()
@update_url_fixture('rename')
@update_partial('_update', '_success')
def test_renameScenario(self):
@@ -402,6 +438,7 @@ class TestScenarioUpdate(TestScenarioBase):
self.req_d['name'] = new_name
return update
+ @executor.mock_valid_lfid()
@update_url_fixture('rename')
@update_partial('_update', '_forbidden')
def test_renameScenario_exist(self):
diff --git a/testapi/opnfv_testapi/ui/app.js b/testapi/opnfv_testapi/ui/app.js
index 2a34838..590b48e 100644
--- a/testapi/opnfv_testapi/ui/app.js
+++ b/testapi/opnfv_testapi/ui/app.js
@@ -79,6 +79,16 @@
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',
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..5885a61
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/scenarios/modals/projectModal.html
@@ -0,0 +1,121 @@
+<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"> Trust&nbsp;Indicator: </label>
+ </div>
+ <div class="col-sm-6">
+ <button class="btn btn-primary" ng-click="projectModalCtrl.openTrustIndicatorModal()">Add&nbsp;Trust&nbsp;Indicator</button>
+ <p class="help-block"></p>
+ </div>
+ </div>
+ <div class="update-project">
+ <div class="col-sm-4">
+ <label for="cpid" class="control-label"> Score: </label>
+ </div>
+ <div class="col-sm-6">
+ <button class="btn btn-primary" ng-click="projectModalCtrl.openScoreModal()">Add&nbsp;Score</button>
+ <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>Scores</h3>
+ <div class="table-responsive">
+ <table class="table table-bordered table-hover" ng-data="projectModalCtrl.project.scores">
+ <thead>
+ <tr style="
+ text-align: center;">
+ <th style="width: 1%;">Score</th>
+ <th style="width: 19%;">Date</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat-start="(index, score) in projectModalCtrl.project.scores" style="padding:9px">
+ <td>{{score.score}}</td>
+ <td>{{score.date}}</td>
+ </tr>
+ <tr ng-repeat-end=>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ <div class='clo-md-12' style="padding-right:0px">
+ <h3>Trust&nbsp;Indicator</h3>
+ <div class="table-responsive">
+ <table class="table table-bordered table-hover" ng-data="projectModalCtrl.project.trust_indicators">
+ <thead>
+ <tr style="
+ text-align: center;">
+ <th style="width: 1%;">Status</th>
+ <th style="width: 19%;">Date</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat-start="(index, trustIndicator) in projectModalCtrl.project.trust_indicators" style="padding:9px">
+ <td>{{trustIndicator.status}}</td>
+ <td>{{trustIndicator.date}}</td>
+ </tr>
+ <tr ng-repeat-end=>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </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..d96986e
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenario.html
@@ -0,0 +1,234 @@
+<legend>Scenario</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.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">
+ <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="(index, installer) in ctrl.data.scenarios[0].installers">
+ <tr style="padding:9px">
+ <td class="podsTableTd">
+ {{index+1}}.&nbsp;Installer:&nbsp;
+ </td>
+ <td class="podsTableLeftTd" style="width:10%;padding-top: 7px;">
+ <a ng-click="ctrl.expandInstaller(index)">{{installer.installer}}</a>
+ </td>
+ <td style="width:80%;border: none; padding: 0px;">
+ <button type="button" 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[index] }">
+ <td class="podsTableTd">
+ Versions:
+ </td>
+ <td width="90%" class="podsTableLeftTd">
+ <div class="col-md-1" style="padding:0px">
+ <a ng-click="ctrl.expandVersions(index)">
+ <p ng-if="ctrl.collapeVersions[index]">Hide</p>
+ <p ng-if="!ctrl.collapeVersions[index]">Show</p>
+ </a>
+ </div>
+ <div class="col-md-1" style="padding:0px">
+ <button type="button" class="btn btn-success btn-xs" ng-click="ctrl.openAddVersionModal(installer.installer)" ><i class="fa fa-plus"></i>Add</button>
+ </div>
+ <div ng-class="{ 'hidden' : ! ctrl.collapeVersions[index] } " class="col-md-12">
+ <div class="table-responsive">
+ <table class="table " ng-data="inctrl.data.scenarios[0].installers">
+ <tbody ng-repeat="(index, version) in installer.versions">
+ <tr style="padding:9px">
+ <td class="podsTableTd">
+ {{index+1}}.&nbsp;Version:
+ </td>
+ <td class="podsTableLeftTd" style="width:10%;padding-top: 7px;">
+ <a ng-click="ctrl.expandVersion(index)">{{version.version}}</a>
+ </td>
+ <td style="width:80%;border: none; padding: 0px;">
+ <button type="button" class="btn btn-danger btn-xs" 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[index] } ">
+ <td class="podsTableTd">
+ Owner:
+ </td>
+ <td class="podsTableLeftTd" style="width:90%">{{version.owner}}</td>
+ </tr>
+ <tr style="padding:9px" ng-class="{ 'hidden' : ! ctrl.collapeVersion[index] }">
+ <td class="podsTableTd">
+ Projects:
+ </td>
+ <td width="90%" class="podsTableLeftTd">
+ <div class="col-md-1" style="padding:0px">
+ <a ng-click="ctrl.expandProjects(index)">
+ <p style="width:50%" ng-if="ctrl.collapeProjects[index]">Hide</p>
+ <p style="width:50%" ng-if="!ctrl.collapeProjects[index]">Show</p>
+ </a>
+ </div>
+ <div class="col-md-1" style="padding:0px">
+ <button type="button" 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[index] } " class="col-md-12">
+ <div class="table-responsive">
+ <table class="table " ng-data="version.projects">
+ <tbody ng-repeat="(index, project) in version.projects" >
+ <tr style="padding:9px">
+ <td class="podsTableTd">
+ {{index+1}}.&nbsp;Project:
+ </td>
+ <td class="podsTableLeftTd" style="width:90%">
+ <a ng-click="ctrl.expandProject(index)">{{project.project}}</a>
+ </td>
+ </tr>
+ <tr ng-class="{ 'hidden' : ! ctrl.collapeProject[index] }">
+ <td class="podsTableTd">
+ Trust&nbsp;Indicators:
+ </td>
+ <td class="podsTableLeftTd" style="width:90%">
+ <a ng-click="ctrl.expandTrustIndicator(index)">
+ <p ng-if="ctrl.collapeTrustIndicator[index]">Hide</p>
+ <p ng-if="!ctrl.collapeTrustIndicator[index]">Show</p>
+ </a>
+ <table class="table " ng-class="{ 'hidden' : ! ctrl.collapeTrustIndicator[index] } " ng-data="project.trust_indicators">
+ <tbody ng-repeat="(index, 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]}">
+ <i class="fa fa-plus"></i>Add</button>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr ng-class="{ 'hidden' : ! ctrl.collapeProject[index] }">
+ <td class="podsTableTd">
+ Scores:
+ </td>
+ <td class="podsTableLeftTd" style="width:90%">
+ <a ng-click="ctrl.expandScore(index)">
+ <p ng-if="ctrl.collapeScore[index]">Hide</p>
+ <p ng-if="!ctrl.collapeScore[index]">Show</p>
+ </a>
+ <table class="table" ng-class="{ 'hidden' : ! ctrl.collapeScore[index] } " ng-data="project.scores">
+ <tbody ng-repeat="(index, 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]}"><i class="fa fa-plus"></i>Add</button>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr ng-class="{ 'hidden' : ! ctrl.collapeProject[index] }">
+ <td class="podsTableTd">
+ Customs:
+ </td>
+ <td class="podsTableLeftTd" style="width:90%">
+ <a ng-click="ctrl.expandCustom(index)">
+ <p ng-if="ctrl.collapeCustom[index]">Hide</p>
+ <p ng-if="!ctrl.collapeCustom[index]">Show</p>
+ </a>
+ <table class="table" ng-class="{ 'hidden' : ! ctrl.collapeCustom[index] } " ng-data="project.customs">
+ <tbody>
+ <tr ng-repeat-start="(index, 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)" ><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[index]}"><i class="fa fa-plus"></i>Add</button>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ <!-- </div> -->
+ <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 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/scenarios/scenario/scenarioController.js b/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenarioController.js
new file mode 100644
index 0000000..eff1930
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenarioController.js
@@ -0,0 +1,724 @@
+/*
+ * 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.openAddTrustIndicatorModal = openAddTrustIndicatorModal;
+ ctrl.addTrustindicator = addTrustindicator;
+ ctrl.addScore = addScore;
+ ctrl.openAddScoreModal = openAddScoreModal;
+ 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
+
+ /**
+ * 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(index){
+ if(ctrl.collapeTrustIndicator[index]){
+ ctrl.collapeTrustIndicator[index] = false;
+ }else{
+ ctrl.collapeTrustIndicator[index] = true;
+ }
+ }
+
+ function expandScore(index){
+ if(ctrl.collapeScore[index]){
+ ctrl.collapeScore[index] = false;
+ }else{
+ ctrl.collapeScore[index] = true;
+ }
+ }
+
+ function expandCustom(index){
+ if(ctrl.collapeCustom[index]){
+ ctrl.collapeCustom[index] = false;
+ }else{
+ ctrl.collapeCustom[index] = true;
+ }
+ }
+
+ function expandVersion(index){
+ if(ctrl.collapeVersion[index]){
+ ctrl.collapeVersion[index] = false;
+ }else{
+ ctrl.collapeVersion[index] = true;
+ }
+ }
+
+ function expandVersions(index){
+ if(ctrl.collapeVersions[index]){
+ ctrl.collapeVersions[index] = false;
+ }else{
+ ctrl.collapeVersions[index] = true;
+ }
+ }
+
+ function expandProjects(index){
+ if(ctrl.collapeProjects[index]){
+ ctrl.collapeProjects[index] = false;
+ }
+ else{
+ ctrl.collapeProjects[index]= true;
+ }
+ }
+
+ function expandProject(index){
+ if(ctrl.collapeProject[index]){
+ ctrl.collapeProject[index] = false;
+ }
+ else{
+ ctrl.collapeProject[index]= 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 openAddTrustIndicatorModal(project, version, installer){
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/scenarios/modals/trustIndicatorModal.html',
+ controller: 'trustIndicatorAddModalCtrl as trustIndicatorModalCtrl',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Add Trust Indicator",
+ successHandler: ctrl.addTrustindicator,
+ project: project,
+ version: version,
+ installer: installer
+ };
+ }
+ }
+ });
+ }
+
+ function openAddScoreModal(project, version, installer){
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/scenarios/modals/scoreModal.html',
+ controller: 'scoreAddModalCtrl as scoreModalCtrl',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Add Score",
+ successHandler: ctrl.addScore,
+ project: project,
+ version: version,
+ installer: installer
+ };
+ }
+ }
+ });
+ }
+
+ function addTrustindicator(trust_indicator, project, version, installer){
+ ctrl.customReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/trust_indicators?installer="+installer+"&version="+version+"&project="+ project
+ $http.post(ctrl.customReqest,trust_indicator ).success(function (data){
+ ctrl.showSuccess = true ;
+ ctrl.success = "Trust indicators are successfully updated."
+ ctrl.loadDetails();
+ })
+ .catch(function (data) {
+ ctrl.showError = true;
+ ctrl.error = data.statusText;
+ });
+ }
+
+ function addScore(score, project, version, installer){
+ ctrl.customReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/scores?installer="+installer+"&version="+version+"&project="+ project
+ $http.post(ctrl.customReqest,score ).success(function (data){
+ ctrl.showSuccess = true ;
+ ctrl.success = "Scores are successfully updated."
+ 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('trustIndicatorAddModalCtrl', trustIndicatorAddModalCtrl);
+ trustIndicatorAddModalCtrl.$inject = ['$scope', '$uibModalInstance', 'data'];
+ function trustIndicatorAddModalCtrl($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.ti, ctrl.data.project, ctrl.data.version, ctrl.data.installer);
+ $uibModalInstance.dismiss('cancel');
+
+ }
+
+ /**
+ * Close the confirm modal without initiating changes.
+ */
+ function cancel() {
+ $uibModalInstance.dismiss('cancel');
+ }
+
+ function handleModalData(){
+
+ }
+
+ /**
+ * This is called when the date filter calendar is opened. It
+ * does some event handling, and sets a scope variable so the UI
+ * knows which calendar was opened.
+ * @param {Object} $event - The Event object
+ * @param {String} openVar - Tells which calendar was opened
+ */
+ function open($event, openVar) {
+ $event.preventDefault();
+ $event.stopPropagation();
+ ctrl[openVar] = true;
+ }
+ }
+
+ /**
+ * 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('scoreAddModalCtrl', scoreAddModalCtrl);
+ scoreAddModalCtrl.$inject = ['$scope', '$uibModalInstance', 'data'];
+ function scoreAddModalCtrl($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.score, ctrl.data.project, ctrl.data.version, ctrl.data.installer);
+ $uibModalInstance.dismiss('cancel');
+ }
+
+ /**
+ * Close the confirm modal without initiating changes.
+ */
+ function cancel() {
+ $uibModalInstance.dismiss('cancel');
+ }
+
+ function handleModalData(){
+
+ }
+
+ /**
+ * This is called when the date filter calendar is opened. It
+ * does some event handling, and sets a scope variable so the UI
+ * knows which calendar was opened.
+ * @param {Object} $event - The Event object
+ * @param {String} openVar - Tells which calendar was opened
+ */
+ function open($event, openVar) {
+ $event.preventDefault();
+ $event.stopPropagation();
+ ctrl[openVar] = true;
+ }
+ }
+
+ /**
+ * 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.openScoreModal = openScoreModal;
+ ctrl.openTrustIndicatorModal = openTrustIndicatorModal;
+ ctrl.openCustomModal = openCustomModal;
+ ctrl.handleScore = handleScore;
+ ctrl.handleModalTrustIndicator = handleModalTrustIndicator;
+ 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 handleModalTrustIndicator(trustIndicator){
+ ctrl.project.trust_indicators.push(trustIndicator)
+ }
+
+ function handleScore(score){
+ ctrl.project.scores.push(score);
+ }
+
+ function handleModalCustom(custom){
+ ctrl.project.customs.push(custom);
+ }
+
+ function openScoreModal(){
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/scenarios/modals/scoreModal.html',
+ controller: 'scoreModalCtrl as scoreModalCtrl',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Score",
+ successHandler: ctrl.handleScore,
+ };
+ }
+ }
+ });
+ }
+ function openTrustIndicatorModal(){
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/scenarios/modals/trustIndicatorModal.html',
+ controller: 'trustIndicatorModalCtrl as trustIndicatorModalCtrl',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Trust Indicator",
+ successHandler: ctrl.handleModalTrustIndicator
+ };
+ }
+ }
+ });
+ }
+ 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..75a21b7
--- /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&nbsp;Scenario</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 Name">
+ <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..4243e21
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/components/scenarios/scenariosController.js
@@ -0,0 +1,609 @@
+/*
+ * 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.openScoreModal = openScoreModal;
+ ctrl.openTrustIndicatorModal = openTrustIndicatorModal;
+ ctrl.openCustomModal = openCustomModal;
+ ctrl.handleScore = handleScore;
+ ctrl.handleModalTrustIndicator = handleModalTrustIndicator;
+ 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 handleModalTrustIndicator(trustIndicator){
+ ctrl.project.trust_indicators.push(trustIndicator)
+ }
+
+ function handleScore(score){
+ ctrl.project.scores.push(score);
+ }
+
+ function handleModalCustom(custom){
+ ctrl.project.customs.push(custom);
+ }
+
+ function openScoreModal(){
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/scenarios/modals/scoreModal.html',
+ controller: 'scoreModalCtrl as scoreModalCtrl',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Score",
+ successHandler: ctrl.handleScore,
+ };
+ }
+ }
+ });
+ }
+ function openTrustIndicatorModal(){
+ $uibModal.open({
+ templateUrl: 'testapi-ui/components/scenarios/modals/trustIndicatorModal.html',
+ controller: 'trustIndicatorModalCtrl as trustIndicatorModalCtrl',
+ size: 'md',
+ resolve: {
+ data: function () {
+ return {
+ text: "Trust Indicator",
+ successHandler: ctrl.handleModalTrustIndicator
+ };
+ }
+ }
+ });
+ }
+ 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('scoreModalCtrl', scoreModalCtrl);
+ scoreModalCtrl.$inject = ['$scope', '$uibModalInstance', 'data'];
+ function scoreModalCtrl($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.score);
+ $uibModalInstance.dismiss('cancel');
+ }
+
+ /**
+ * Close the confirm modal without initiating changes.
+ */
+ function cancel() {
+ $uibModalInstance.dismiss('cancel');
+ }
+
+ function handleModalData(){
+
+ }
+
+ /**
+ * This is called when the date filter calendar is opened. It
+ * does some event handling, and sets a scope variable so the UI
+ * knows which calendar was opened.
+ * @param {Object} $event - The Event object
+ * @param {String} openVar - Tells which calendar was opened
+ */
+ function open($event, openVar) {
+ $event.preventDefault();
+ $event.stopPropagation();
+ ctrl[openVar] = true;
+ }
+ }
+
+ /**
+ * 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('trustIndicatorModalCtrl', trustIndicatorModalCtrl);
+ trustIndicatorModalCtrl.$inject = ['$scope', '$uibModalInstance', 'data'];
+ function trustIndicatorModalCtrl($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.ti);
+ $uibModalInstance.dismiss('cancel');
+
+ }
+
+ /**
+ * Close the confirm modal without initiating changes.
+ */
+ function cancel() {
+ $uibModalInstance.dismiss('cancel');
+ }
+
+ function handleModalData(){
+
+ }
+
+ /**
+ * This is called when the date filter calendar is opened. It
+ * does some event handling, and sets a scope variable so the UI
+ * knows which calendar was opened.
+ * @param {Object} $event - The Event object
+ * @param {String} openVar - Tells which calendar was opened
+ */
+ function open($event, openVar) {
+ $event.preventDefault();
+ $event.stopPropagation();
+ ctrl[openVar] = true;
+ }
+ }
+
+ /**
+ * 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/index.html b/testapi/opnfv_testapi/ui/index.html
index 98f1ed8..5f982a2 100644
--- a/testapi/opnfv_testapi/ui/index.html
+++ b/testapi/opnfv_testapi/ui/index.html
@@ -44,6 +44,8 @@
<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>
diff --git a/testapi/opnfv_testapi/ui/shared/header/header.html b/testapi/opnfv_testapi/ui/shared/header/header.html
index d0501a2..6bbdcb8 100644
--- a/testapi/opnfv_testapi/ui/shared/header/header.html
+++ b/testapi/opnfv_testapi/ui/shared/header/header.html
@@ -19,7 +19,8 @@ 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">
<li ng-class="{ active: header.isActive('/profile')}" ng-if="auth.isAuthenticated"><a ui-sref="profile">Profile</a></li>
diff --git a/testapi/requirements.txt b/testapi/requirements.txt
index fbd2e0e..f752a64 100644
--- a/testapi/requirements.txt
+++ b/testapi/requirements.txt
@@ -9,3 +9,4 @@ epydoc>=0.3.1
six>=1.9.0 # MIT
motor # Apache-2.0
python-cas
+requests[security] \ No newline at end of file