aboutsummaryrefslogtreecommitdiffstats
path: root/3rd_party/static/onap-ui/components/results
diff options
context:
space:
mode:
authorpkaralis <pkaralis@intracom-telecom.com>2018-12-06 00:43:12 +0200
committerPanagiotis Karalis <pkaralis@intracom-telecom.com>2019-03-20 15:28:23 +0200
commitd0bbf3b8952379883550c6eb2062476a6d15043e (patch)
tree106f65b223054077279bda7ff988a73bea314a34 /3rd_party/static/onap-ui/components/results
parent5f20495d6e3ec984c4e86fd76399ddf0d042b336 (diff)
Enable Web Portal for ONAP results
The web portal needs to be able to read test results of the ONAP compliance program and display them. In order for the above goal to be achieved, the following two parts should be impacted: 1- A new front-end should be prepared in order to handle and display the results 2- The REST API should be extended in order to support the aforementioned operation. JIRA: DOVETAIL-669 Change-Id: I36bbb6e602a67020d7e27aedbfc776f5cf4f3dc3 Signed-off-by: pkaralis <pkaralis@intracom-telecom.com> Co-Authored-By: Stamatis Katsaounis <mokats@intracom-telecom.com>
Diffstat (limited to '3rd_party/static/onap-ui/components/results')
-rw-r--r--3rd_party/static/onap-ui/components/results/modal/applicationModal.html158
-rw-r--r--3rd_party/static/onap-ui/components/results/modal/applicationView.html103
-rw-r--r--3rd_party/static/onap-ui/components/results/modal/reviewsModal.html41
-rw-r--r--3rd_party/static/onap-ui/components/results/modal/sharedModal.html16
-rw-r--r--3rd_party/static/onap-ui/components/results/results.html168
-rw-r--r--3rd_party/static/onap-ui/components/results/resultsController.js614
6 files changed, 1100 insertions, 0 deletions
diff --git a/3rd_party/static/onap-ui/components/results/modal/applicationModal.html b/3rd_party/static/onap-ui/components/results/modal/applicationModal.html
new file mode 100644
index 0000000..0ca4b84
--- /dev/null
+++ b/3rd_party/static/onap-ui/components/results/modal/applicationModal.html
@@ -0,0 +1,158 @@
+<div class="container-fluid common-main-container">
+ <div class="top-site-banner">
+ <div class="container">
+ <p class="p1">Application Details</p>
+ </div>
+ </div>
+
+ <div class="row" style="margin-top: 20px;">
+ <div class="col-lg-12 container">
+ <p class="message" style="display: none;"></p>
+ <fieldset>
+ <div class="field text col-md-4">
+ <label class="left">Company Name</label>
+ <i uib-tooltip="Company Name" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+ <div class="middleColumn">
+ <input type="text" class="text form-control" ng-model="ctrl.company_name"
+ ng-init="ctrl.company_name=auth.currentUser.companyName" required>
+ </div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Company Logo</label>
+ <i uib-tooltip="Required dimensions (Max Values): {width: 165pixels, height: 40pixels}" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+ <div class="middleColumn">
+ <input class="form-control btn btn-success-cust cvp-btn medium accent-color regular-button"
+ modal-file-model="logoFile" type="file" style="padding: 0;" required>
+ </div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Company Website</label>
+ <i uib-tooltip="Company Website" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+ <div class="middleColumn">
+ <input type="url" class="text form-control" ng-model="ctrl.company_website"
+ ng-init="ctrl.company_website=auth.currentUser.companyWebsite" required>
+ </div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Primary Contact Name</label>
+ <i uib-tooltip="Primary Contact name (optional)"
+ class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+ <div class="middleColumn">
+ <input type="text" class="text form-control" ng-model="ctrl.primary_contact_name"
+ ng-init="ctrl.primary_contact_name=auth.currentUser.primaryContactName" required>
+ </div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Primary Contact Number</label>
+ <i uib-tooltip="Primary Contact phone number(optional)"
+ class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+ <div class="middleColumn">
+ <input type="tel" class="text form-control" ng-model="ctrl.primary_phone_number"
+ ng-init="ctrl.primary_phone_number=auth.currentUser.primaryPhoneNumber" required>
+ </div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Primary Contact Email</label>
+ <i uib-tooltip="Primary Contact email (optional)"
+ class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+ <div class="middleColumn">
+ <input type="email" class="text form-control" ng-model="ctrl.primary_business_email"
+ ng-init="ctrl.primary_business_email=auth.currentUser.primaryBusinessEmail" required>
+ </div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Test Agency</label>
+ <i uib-tooltip="Location" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+ <div class="middleColumn">
+ <select class="form-control" ng-model="ctrl.lab_location" ng-init="ctrl.lab_location='internal'" required>
+ <option value="internal">1st Party - Submitter</option>
+ <option value="third">3rd Party - External Lab</option>
+ </select>
+ </div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">xNF Version</label>
+ <i uib-tooltip="xNF Version"
+ class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+ <div class="middleColumn">
+ <input type="text" class="text form-control" ng-model="ctrl.xnf_version" required>
+ </div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">xNF Name</label>
+ <i uib-tooltip="xNF Name"
+ class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+ <div class="middleColumn">
+ <input type="text" class="text form-control" ng-model="ctrl.xnf_name" required>
+ </div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Test Type</label>
+ <i uib-tooltip="xNF Type" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+ <div class="middleColumn">
+ <select class="form-control" ng-model="ctrl.xnf_type" ng-init="ctrl.xnf_type='VNF'" required>
+ <option value="VNF">VNF</option>
+ </select>
+ </div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">xNF Description</label>
+ <i uib-tooltip="xNF Description"
+ class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+ <div class="middleColumn">
+ <input type="text" class="text form-control" ng-model="ctrl.xnf_description" required>
+ </div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">xNFD Id</label>
+ <i uib-tooltip="xNFD Id" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+ <div class="middleColumn">
+ <input type="text" class="text form-control" ng-model="ctrl.xnfd_id" required>
+ </div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Test Category</label>
+ <i uib-tooltip="Define test category<" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+ <div class="middleColumn">
+ <select class="form-control" ng-model="ctrl.xnf_test_period" ng-init="ctrl.xnf_test_period='Packaging Compliance Test'" required>
+ <option value="Packaging Compliance Test">Packaging Compliance Test</option>
+ <option value="Lifecycle">Lifecycle Test</option>
+ <option value="Functional">Functional Test</option>
+ <option value="Performance">Performance Test</option>
+ </select>
+ </div>
+ </div>
+ <div ng-if="ctrl.lab_location=='third'" class="field text">
+ <div class="field text col-md-4">
+ <label class="left">Lab Name</label>
+ <i uib-tooltip="Lab Name" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+ <input type="text" class="text form-control" ng-model="ctrl.lab_name" required>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Lab Email</label>
+ <i uib-tooltip="Lab Email" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+ <input type="email" class="text form-control" ng-model="ctrl.lab_email" required>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Lab Address</label>
+ <i uib-tooltip="Lab Address" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+ <input type="text" class="text form-control" ng-model="ctrl.lab_address" required>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Lab Phone Number</label>
+ <i uib-tooltip="Lab Phone Number" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+ <input type="tel" class="text form-control" ng-model="ctrl.lab_phone" required>
+ </div>
+ </div>
+ </fieldset>
+ </div>
+ </div>
+ <button class="btn btn-default"
+ ng-click="ctrl.openConfirmModal(ctrl.tempResult)">Submit</button>
+</div>
+
+<style type="text/css">
+ .ngdialog.custom-background .ngdialog-content {
+ background: #ffffff;
+ }
+</style>
diff --git a/3rd_party/static/onap-ui/components/results/modal/applicationView.html b/3rd_party/static/onap-ui/components/results/modal/applicationView.html
new file mode 100644
index 0000000..79341f8
--- /dev/null
+++ b/3rd_party/static/onap-ui/components/results/modal/applicationView.html
@@ -0,0 +1,103 @@
+<div class="container-fluid common-main-container">
+ <div class="top-site-banner">
+ <div class="container">
+ <p class="p1">Application Details</p>
+ </div>
+ </div>
+
+ <div class="row" style="margin-top: 20px;">
+ <div class="col-lg-12 container">
+ <p class="message" style="display: none;"></p>
+ <fieldset>
+ <div class="field text col-md-4">
+ <label class="left">Company Name</label>
+ <div class="middleColumn">{{ ctrl.application.company_name }}</div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Company Logo</label>
+ <div class="middleColumn">{{ ctrl.application.company_logo }}</div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Company Website</label>
+ <div class="middleColumn">{{ ctrl.application.company_website }}</div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">ONAP Version</label>
+ <div class="middleColumn">{{ ctrl.application.onap_version }}</div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Primary Contact Name</label>
+ <div class="middleColumn">{{ ctrl.application.primary_contact_name }}</div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Primary Contact Number</label>
+ <div class="middleColumn">{{ ctrl.application.primary_phone_number }}</div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Primary Contact Email</label>
+ <div class="middleColumn">{{ ctrl.application.primary_business_email }}</div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Test Agency</label>
+ <div class="middleColumn">{{ ctrl.application.lab_location }}</div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">xNF Version</label>
+ <div class="middleColumn">{{ ctrl.application.xnf_version }}</div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">xNF Name</label>
+ <div class="middleColumn">{{ ctrl.application.xnf_name }}</div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Test Type</label>
+ <div class="middleColumn">{{ ctrl.application.xnf_type }}</div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">xNF Description</label>
+ <div class="middleColumn">{{ ctrl.application.xnf_description }}</div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">xNFD Id</label>
+ <div class="middleColumn">{{ ctrl.application.xnfd_id }}</div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">xNF Model Language</label>
+ <div class="middleColumn">{{ ctrl.application.xnfd_model_lang }}</div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Test Category</label>
+ <div class="middleColumn">{{ ctrl.application.xnf_test_period }}</div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">xNF Checksum (SHA256)</label>
+ <div class="middleColumn">{{ ctrl.application.xnf_checksum }}</div>
+ </div>
+ <div ng-if="ctrl.lab_location=='third'" class="field text">
+ <div class="field text col-md-4">
+ <label class="left">Lab Name</label>
+ <div>{{ ctrl.application.lab_name }}</div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Lab Email</label>
+ <div>{{ ctrl.application.lab_email }}</div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Lab Address</label>
+ <div>{{ ctrl.application.lab_address }}</div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Lab Phone Number</label>
+ <div>{{ ctrl.application.lab_phone }}</div>
+ </div>
+ </div>
+ </fieldset>
+ </div>
+ </div>
+</div>
+
+<style type="text/css">
+ .ngdialog.custom-background .ngdialog-content {
+ background: #ffffff;
+ }
+</style>
diff --git a/3rd_party/static/onap-ui/components/results/modal/reviewsModal.html b/3rd_party/static/onap-ui/components/results/modal/reviewsModal.html
new file mode 100644
index 0000000..c93d1ef
--- /dev/null
+++ b/3rd_party/static/onap-ui/components/results/modal/reviewsModal.html
@@ -0,0 +1,41 @@
+<div class="container-fluid common-main-container">
+ <div class="top-site-banner">
+ <div class="container">
+ <p class="p1">Community Reviews</p>
+ </div>
+ </div>
+
+ <div class="row" style="margin-top: 20px;">
+ <div class="col-lg-12 container">
+ <div cg-busy="{promise:ctrl.reviewsRequest,message:'Loading'}"></div>
+ <div ng-show="ctrl.reviews" class="results-table" style="width: 100%; overflow-x: scroll;">
+ <table ng-data="ctrl.reviews" ng-show="ctrl.reviews" class="table table-striped table-hover">
+ <thead>
+ <tr>
+ <th>Reviewer</th>
+ <th>Linux Foundation OpenId</th>
+ <th>Email</th>
+ <th>Review Date</th>
+ <th>Outcome</th>
+ </tr>
+ </thead>
+ <tbody style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
+ <tr ng-repeat="(index, review) in ctrl.reviews">
+ <td>{{ review.reviewer_name }}</td>
+ <td>{{ review.reviewer_openid }}</td>
+ <td>{{ review.reviewer_email }}</td>
+ <td>{{ review.creation_date | limitTo:19}}</td>
+ <td>{{ review.outcome }}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+</div>
+
+<style type="text/css">
+ .ngdialog.custom-background .ngdialog-content {
+ background: #ffffff;
+ }
+</style>
diff --git a/3rd_party/static/onap-ui/components/results/modal/sharedModal.html b/3rd_party/static/onap-ui/components/results/modal/sharedModal.html
new file mode 100644
index 0000000..021a355
--- /dev/null
+++ b/3rd_party/static/onap-ui/components/results/modal/sharedModal.html
@@ -0,0 +1,16 @@
+<div>
+ <h4>Enter user name or email</h4>
+ <input type="text" ng-model="ctrl.userName">
+ <div style="text-align: center; margin-top: 20px;">
+ <button class="btn btn-default" ng-disabled="ctrl.userName==null || ctrl.userName==''"
+ ng-click="ctrl.addSharedUser(ctrl.tempResult, ctrl.userName)">Commit</button>
+ </div>
+</div>
+
+<style>
+ input {
+ border-radius: 10px;
+ border: 1px solid #eeeeee;
+ width: 100%;
+ }
+</style>
diff --git a/3rd_party/static/onap-ui/components/results/results.html b/3rd_party/static/onap-ui/components/results/results.html
new file mode 100644
index 0000000..ce43036
--- /dev/null
+++ b/3rd_party/static/onap-ui/components/results/results.html
@@ -0,0 +1,168 @@
+<div class="container-fluid common-main-container">
+ <h3>{{ctrl.pageHeader}}</h3>
+ <p>{{ctrl.pageParagraph}}</p>
+ <form class="form-inline" ng-show="ctrl.isUserResults">
+ <h4>Upload Results
+ <i class="glyphicon glyphicon-question-sign opnfv-blue"
+ uib-tooltip="results file is logs.xxx.tar.gz under your dovetail installation path"></i>
+ </h4>
+ <div class="form-group col-m-3">
+ <input class="form-contrl btn btn-success-cust cvp-btn medium accent-color regular-button" type="file"
+ file-model="resultFile">
+ </div>
+ <div class="form-group col-m-3">
+ <a class="btn btn-success-cust cvp-btn medium accent-color regular-button" ng-click="ctrl.uploadFile()">
+ <span>upload result</span>
+ </a>
+ </div>
+ <div>
+ <label>{{ctrl.uploadState}}</label>
+ </div>
+ </form>
+ <div class="row" style="margin-bottom: 24px;"></div>
+ <div cg-busy="{promise:ctrl.authRequest,message:'Loading'}"></div>
+ <div cg-busy="{promise:ctrl.resultsRequest,message:'Loading'}"></div>
+
+ <div ng-show="ctrl.data" class="results-table" style="width: 100%; overflow-x: scroll;">
+ <table ng-data="ctrl.data.result" ng-show="ctrl.data" class="table table-striped table-hover">
+ <thead>
+ <tr>
+ <th>Upload Date</th>
+ <th>Test ID</th>
+ <th>ONAP Version</th>
+ <th>Modeling Language</th>
+ <th>Owner</th>
+ <th>File Name</th>
+ <th>Label</th>
+ <th>Status</th>
+ <th>Log</th>
+ <th>Application</th>
+ <th>Review Status</th>
+ <th class="col-md-2">Operation</th>
+ <th class="col-md-2">Share List</th>
+ </tr>
+ </thead>
+
+ <tbody style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
+ <tr ng-repeat="(index, result) in ctrl.data.tests">
+ <td>{{ result.upload_date | limitTo:19}}</td>
+ <td>
+ <a uib-tooltip="{{ result.id }}" tooltip-placement="top" tooltip-append-to-body="true"
+ ng-click="ctrl.gotoResultDetail(result.id, result._id)">{{ result.id | limitTo:8 }}</a>
+ </td>
+ <td>{{ result.version || "2019.04" }}</td>
+ <td>{{ result.vnf_type.toUpperCase() }}</td>
+ <td>{{ result.owner }}</td>
+ <td>{{ result.filename || "None"}}</td>
+ <td>
+ <div class="popover-wrapper">
+ <a editable-theme="bs3" onbeforesave="ctrl.changeLabel(result, 'label', $data)"
+ editable-text="result.label">{{ result.label || "None" }}</a>
+ </div>
+ </td>
+ <td>{{ result.status }}</td>
+ <td><a ng-click="ctrl.downloadLogs(result.id)">logs</a></td>
+ <td>
+ <a ng-if="result.status !='private'" ng-click="ctrl.openApplicationView(result)">View Application</a>
+ <div ng-if="result.status == 'private'">Not created</div>
+ </td>
+ <td><a ng-if="result.status !='private'" ng-click="ctrl.openReviewsModal(result.id)">View Reviews</a>
+ <div ng-if="result.status == 'private'"></div>
+ </td>
+ <td>
+ <div class="btn-group" uib-dropdown>
+ <a id="single-button" type="button" class="btn btn-success-cust cvp-btn medium accent-color regular-button"
+ uib-dropdown-toggle>
+ Operation<span class="caret"></span>
+ </a>
+ <ul class="dropdown-menu" uib-dropdown-menu role="menu" aria-labelledby="single-button">
+ <li role="menuitem" ng-if="auth.currentUser.openid == result.owner && ctrl.isUserResults"
+ class="menu-item menu-item-type-post_type menu-item-object-page">
+ <a ng-class="{'hide': result.status != 'review'}"
+ ng-click="ctrl.deleteApplication(result)">withdraw submit</a>
+ </li>
+ <li role="menuitem" ng-if="auth.currentUser.openid == result.owner && ctrl.isUserResults"
+ class="menu-item menu-item-type-post_type menu-item-object-page">
+ <a ng-class="{'hide': result.status != 'private'}"
+ ng-click="ctrl.openApplicationModal(result)">submit to review</a>
+ </li>
+ <li role="menuitem"
+ ng-if="auth.currentUser.role.indexOf('reviewer') != -1 && !ctrl.isUserResults"
+ class="menu-item menu-item-type-post_type menu-item-object-page">
+ <a ng-class="{'hide': (result.voted == 'true') || (result.status != 'review')}"
+ ng-click="ctrl.toApprove(result)">approve</a>
+ </li>
+ <li role="menuitem"
+ ng-if="auth.currentUser.role.indexOf('reviewer') != -1 && !ctrl.isUserResults"
+ class="menu-item menu-item-type-post_type menu-item-object-page">
+ <a ng-class="{'hide': (result.voted == 'true') || (result.status != 'review')}"
+ ng-click="ctrl.toDisapprove(result)">not approve</a>
+ </li>
+ <li role="menuitem"
+ ng-if="auth.currentUser.role.indexOf('reviewer') != -1 && !ctrl.isUserResults"
+ class="menu-item menu-item-type-post_type menu-item-object-page">
+ <a ng-class="{'hide': (result.voted == 'false') || (result.status != 'review')}"
+ ng-click="ctrl.toUndo(result)">undo</a>
+ </li>
+ <li role="menuitem" ng-if="auth.currentUser.openid == result.owner && ctrl.isUserResults"
+ class="menu-item menu-item-type-post_type menu-item-object-page">
+ <a ng-click="ctrl.openSharedModal(result)">share with</a>
+ </li>
+ <li role="menuitem" ng-if="auth.currentUser.openid == result.owner && ctrl.isUserResults"
+ class="menu-item menu-item-type-post_type menu-item-object-page">
+ <a ng-click="ctrl.deleteTest(result._id)">delete</a>
+ </li>
+ </ul>
+ </div>
+ </td>
+ <td>
+ <div class="btn-group" uib-dropdown>
+ <a id="single-button-two" type="button"
+ class="btn btn-success-cust cvp-btn medium accent-color regular-button" style="width: 130px;"
+ uib-dropdown-toggle>
+ Share List<span class="caret"></span>
+ </a>
+ <ul class="dropdown-menu" uib-dropdown-menu role="menu" aria-labelledby="single-button-two"
+ style="min-width: 200%;">
+ <li class="menu-item menu-item-type-post_type menu-item-object-page" role="menuitem"
+ ng-repeat="share in result.shared track by $index">
+ <span>
+ {{ share }}
+ <i ng-if="auth.currentUser.openid == result.owner" class="pull-right glyphicon glyphicon-remove"
+ ng-click="ctrl.removeSharedUser(result, share)"></i>
+ </span>
+ </li>
+ </ul>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <div class="pages">
+ <uib-pagination
+ total-items="ctrl.totalItems"
+ ng-model="ctrl.currentPage"
+ items-per-page="ctrl.itemsPerPage"
+ max-size="ctrl.maxSize"
+ class="pagination-sm"
+ boundary-links="true"
+ rotate="false"
+ num-pages="ctrl.numPages"
+ ng-change="ctrl.update()">
+ </uib-pagination>
+ </div>
+ </div>
+</div>
+
+<div ng-show="ctrl.showError" 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>
+
+
+<style>
+ .button-disabled {
+ pointer-events: none;
+ }
+</style>
diff --git a/3rd_party/static/onap-ui/components/results/resultsController.js b/3rd_party/static/onap-ui/components/results/resultsController.js
new file mode 100644
index 0000000..d459495
--- /dev/null
+++ b/3rd_party/static/onap-ui/components/results/resultsController.js
@@ -0,0 +1,614 @@
+/*
+ * 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('ResultsController', ResultsController);
+
+ angular
+ .module('testapiApp')
+ .directive('fileModel', ['$parse', function ($parse) {
+ return {
+ restrict: 'A',
+ link: function(scope, element, attrs) {
+ var model = $parse(attrs.fileModel);
+ var modelSetter = model.assign;
+
+ element.bind('change', function(){
+ scope.$apply(function(){
+ modelSetter(scope, element[0].files[0]);
+ });
+ });
+ }
+ };
+ }]);
+
+ angular
+ .module('testapiApp')
+ .directive('modalFileModel', ['$parse', function ($parse) {
+ return {
+ restrict: 'A',
+ link: function(scope, element, attrs) {
+ var model = $parse(attrs.modalFileModel);
+ var modelSetter = model.assign;
+
+ element.bind('change', function(){
+ scope.$apply(function(){
+ modelSetter(scope.$parent, element[0].files[0]);
+ });
+ });
+ }
+ };
+ }]);
+
+ ResultsController.$inject = [
+ '$scope', '$http', '$filter', '$state', 'testapiApiUrl','raiseAlert', 'ngDialog', '$resource'
+ ];
+
+ /**
+ * TestAPI Results Controller
+ * This controller is for the '/results' page where a user can browse
+ * a listing of community uploaded results.
+ */
+ function ResultsController($scope, $http, $filter, $state, testapiApiUrl, raiseAlert, ngDialog, $resource) {
+ var ctrl = this;
+
+ ctrl.uploadFile=uploadFile;
+ ctrl.update = update;
+ ctrl.open = open;
+ ctrl.clearFilters = clearFilters;
+ ctrl.associateMeta = associateMeta;
+ ctrl.gotoResultDetail = gotoResultDetail;
+ ctrl.toggleCheck = toggleCheck;
+ ctrl.changeLabel = changeLabel;
+ ctrl.toApprove = toApprove;
+ ctrl.toDisapprove = toDisapprove;
+ ctrl.toUndo = toUndo;
+ ctrl.toReview = toReview;
+ ctrl.toPrivate = toPrivate;
+ ctrl.removeSharedUser = removeSharedUser;
+ ctrl.addSharedUser = addSharedUser;
+ ctrl.openSharedModal = openSharedModal;
+ ctrl.downloadLogs = downloadLogs;
+ ctrl.deleteApplication = deleteApplication;
+ ctrl.deleteTest = deleteTest;
+ ctrl.openApplicationModal = openApplicationModal;
+ ctrl.openApplicationView = openApplicationView;
+ ctrl.submitApplication = submitApplication;
+ ctrl.openConfirmModal = openConfirmModal;
+ ctrl.openReviewsModal = openReviewsModal;
+
+ /** Mappings of Interop WG components to marketing program names. */
+ ctrl.targetMappings = {
+ 'platform': 'Openstack Powered Platform',
+ 'compute': 'OpenStack Powered Compute',
+ 'object': 'OpenStack Powered Object Storage'
+ };
+
+ /** Initial page to be on. */
+ ctrl.currentPage = 1;
+
+ /**
+ * How many results should display on each page. Since pagination
+ * is server-side implemented, this value should match the
+ * 'results_per_page' configuration of the TestAPI server which
+ * defaults to 20.
+ */
+ ctrl.itemsPerPage = 20;
+
+ /**
+ * How many page buttons should be displayed at max before adding
+ * the '...' button.
+ */
+ ctrl.maxSize = 5;
+
+ /** The upload date lower limit to be used in filtering results. */
+ ctrl.startDate = '';
+
+ /** The upload date upper limit to be used in filtering results. */
+ ctrl.endDate = '';
+
+ /** The date format for the date picker. */
+ ctrl.format = 'yyyy-MM-dd';
+
+ ctrl.userName = null;
+
+ /** Check to see if this page should display user-specific results. */
+ ctrl.isUserResults = $state.current.name === 'userResults';
+
+ /** Check to see if this page should display community results. */
+ ctrl.isReviewer = $scope.auth.currentUser.role.indexOf('reviewer') != -1;
+ ctrl.isAdministrator = $scope.auth.currentUser.role.indexOf('administrator') != -1;
+
+ ctrl.currentUser = $scope.auth.currentUser ? $scope.auth.currentUser.openid : null;
+
+ // Should only be on user-results-page if authenticated.
+ if (!$scope.auth.isAuthenticated) {
+ $state.go('home');
+ }
+ // Should only be on community-results if reviewer
+ if (!ctrl.isUserResults && !ctrl.isReviewer) {
+ $state.go('home');
+ }
+
+ ctrl.pageHeader = ctrl.isUserResults ?
+ 'Private test results' : 'Community 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.authRequest = $scope.auth.doSignCheck().then(ctrl.update);
+
+ function downloadLogs(id) {
+ // var logsUrl = testapiApiUrl + "/logs/log_" + id+".tar.gz";
+ var logsUrl = "/logs/" + id + "/results/";
+ window.location.href = logsUrl;
+ // $http.get(logsUrl);
+ }
+
+ function deleteTest(inner_id) {
+ var resp = confirm('Are you sure to delete this test?');
+ if (!resp)
+ return;
+
+ var delUrl = testapiApiUrl + "/onap/tests/" + inner_id;
+ $http.get(delUrl)
+ .then( function(resp) {
+ var results = resp.data.results;
+ $http.delete(delUrl)
+ .then( function(ret) {
+ if(ret.data.code && ret.data.code != 0) {
+ alert(ret.data.msg);
+ return;
+ }
+ ctrl.update();
+ angular.forEach(results, function(ele) {
+ delUrl = testapiApiUrl + "/results/" + ele;
+ $http.delete(delUrl);
+ });
+ });
+ });
+ }
+
+ function deleteApplication (result) {
+ var resp = confirm('Are you sure you want to delete this application?');
+ if (!resp)
+ return;
+
+ $http.get(testapiApiUrl + "/onap/cvp/applications?test_id=" + result.id).then(function(response) {
+ ctrl.application = response.data.applications[0];
+ var app_id = ctrl.application._id;
+ var delUrl = testapiApiUrl + "/cvp/applications/" + app_id;
+ $http.delete(delUrl)
+ .then(function(ret) {
+ if (ret.data.code && ret.data.code != 0) {
+ alert(ret.data.msg);
+ return;
+ }
+ result['status'] = 'private';
+ });
+
+ }, function(error) {
+ /* do nothing */
+ });
+
+ }
+
+ function submitApplication(result) {
+ var file = $scope.logoFile;
+ var logo_name = null;
+ if (typeof file !== 'undefined') {
+
+ var fd = new FormData();
+ fd.append('file', file);
+ fd.append('company_name', ctrl.company_name)
+
+ $http.post(testapiApiUrl + "/cvp/applications/uploadlogo", fd, {
+ transformRequest: angular.identity,
+ headers: {'Content-Type': undefined}
+ }).then(function(resp) {
+ if (resp.data.code && resp.data.code != 0) {
+ alert(resp.data.msg);
+ return;
+ } else {
+ logo_name = resp.data.filename;
+ var data = {
+ "description": ctrl.description,
+ "onap_version": result.version,
+ "company_name": ctrl.company_name,
+ "company_logo": logo_name,
+ "company_website": ctrl.company_website,
+ "approve_date": "",
+ "approved": "false",
+ "test_id": result.id,
+ "lab_location": ctrl.lab_location,
+ "lab_email": ctrl.lab_email,
+ "lab_address": ctrl.lab_address,
+ "lab_phone": ctrl.lab_phone,
+ "xnf_version": ctrl.xnf_version,
+ "certification_type": ctrl.certification_type,
+ "xnf_name": ctrl.xnf_name,
+ "xnf_type": ctrl.xnf_type,
+ "xnf_description": ctrl.xnf_description,
+ "xnfd_id": ctrl.xnfd_id,
+ "xnfd_model_lang": result.vnf_type.toUpperCase(),
+ "xnf_checksum": result.vnf_checksum,
+ "xnf_test_period": ctrl.xnf_test_period,
+ "primary_contact_name": ctrl.primary_contact_name,
+ "primary_phone_number": ctrl.primary_phone_number,
+ "primary_business_email": ctrl.primary_business_email
+ };
+
+ $http.post(testapiApiUrl + "/onap/cvp/applications", data).then(function(resp) {
+ if (resp.data.code && resp.data.code != 0) {
+ alert(resp.data.msg);
+ return;
+ }
+ toggleCheck(result, 'status', 'review');
+ }, function(error) {
+ /* do nothing */
+ });
+ }
+ }, function(error) {
+ /* do nothing */
+ });
+ logo_name = file.name;
+ }
+ ngDialog.close();
+ }
+
+ function openConfirmModal(result) {
+ var resp = confirm("Are you sure to submit?");
+ if (resp) {
+ ctrl.submitApplication(result);
+ }
+ }
+
+ function openApplicationModal(result) {
+ ctrl.tempResult = result;
+ ngDialog.open({
+ preCloseCallback: function(value) {
+ },
+ template: 'onap-ui/components/results/modal/applicationModal.html',
+ scope: $scope,
+ className: 'ngdialog-theme-default custom-background',
+ width: 950,
+ showClose: true,
+ closeByDocument: true
+ });
+ }
+
+ function openApplicationView(result) {
+
+ $http.get(testapiApiUrl + "/onap/cvp/applications?test_id=" + result.id).then(function(response) {
+ ctrl.application = response.data.applications[0];
+ }, function(error) {
+ /* do nothing */
+ });
+
+ ctrl.tempResult = result;
+ ngDialog.open({
+ preCloseCallback: function(value) {
+ },
+ template: 'onap-ui/components/results/modal/applicationView.html',
+ scope: $scope,
+ className: 'ngdialog-theme-default custom-background',
+ width: 950,
+ showClose: true,
+ closeByDocument: true
+ });
+ }
+
+ function getReviews(test) {
+ var reviews_url = testapiApiUrl + '/onap/reviews?test_id=' + test;
+ ctrl.reviewsRequest =
+ $http.get(reviews_url).success(function (data) {
+ ctrl.reviews = data.reviews;
+ }).error(function (error) {
+ ctrl.reviews = null;
+ });
+ }
+
+ function openReviewsModal(test) {
+ getReviews(test);
+ ngDialog.open({
+ preCloseCallback: function(value) {
+ },
+ template: 'onap-ui/components/results/modal/reviewsModal.html',
+ scope: $scope,
+ className: 'ngdialog-theme-default custom-background',
+ width: 950,
+ showClose: true,
+ closeByDocument: true
+ });
+ }
+
+ function toggleCheck(result, item, newValue) {
+ var id = result._id;
+ var updateUrl = testapiApiUrl + "/onap/tests/"+ id;
+
+ var data = {};
+ data['item'] = item;
+ data[item] = newValue;
+
+ $http.put(updateUrl, JSON.stringify(data), {
+ transformRequest: angular.identity,
+ headers: {'Content-Type': 'application/json'}}).then(function(ret) {
+ if(ret.data.code && ret.data.code != 0) {
+ alert(ret.data.msg);
+ } else {
+ result[item] = newValue;
+ }
+ }, function(error) {
+ alert('Error when update data');
+ });
+ }
+
+ function changeLabel(result, key, data){
+ if (result[key] !== data) {
+ toggleCheck(result, key, data);
+ }
+ }
+
+ function doReview(test, outcome) {
+ var createUrl = testapiApiUrl + "/onap/reviews";
+ var data = {
+ 'test_id': test.id,
+ 'outcome': outcome
+ };
+
+ $http.post(createUrl, JSON.stringify(data), {
+ transformRequest: angular.identity,
+ headers: {'Content-Type': 'application/json'}}).then(function(ret) {
+ if (ret.data.code && ret.data.code != 0) {
+ alert(ret.data.msg);
+ } else {
+ if (outcome === null) {
+ test.voted = 'false';
+ } else {
+ test.voted = 'true';
+ }
+ }
+ }, function(error) {
+ alert('Error when creating review');
+ });
+ }
+
+ function toApprove(test) {
+ var resp = confirm('Once you approve a test result, your action will become visible. Do you want to proceed?');
+ if (resp) {
+ doReview(test, 'positive');
+ }
+ }
+
+ function toDisapprove(test) {
+ var resp = confirm('Once you disapprove a test result, your action will become visible. Do you want to proceed?');
+ if (resp) {
+ doReview(test, 'negative');
+ }
+ }
+
+ function toUndo(test) {
+ var resp = confirm('Once you undo your previous vote, your action will become visible. Do you want to proceed?');
+ if (resp) {
+ doReview(test, null);
+ }
+ }
+
+ function toReview(result, value){
+ var resp = confirm('Once you submit a test result for review, it will become readable to all ONAPVP reviewers. Do you want to proceed?');
+ if(resp){
+ toggleCheck(result, 'status', value);
+ }
+ }
+
+ function toPrivate(result, value){
+ var resp = confirm('Do you want to proceed?');
+ if(resp){
+ toggleCheck(result, 'status', value);
+ }
+ }
+
+ function openSharedModal(result){
+ ctrl.tempResult = result;
+ ngDialog.open({
+ preCloseCallback: function(value) {
+ },
+ template: 'onap-ui/components/results/modal/sharedModal.html',
+ scope: $scope,
+ className: 'ngdialog-theme-default',
+ width: 950,
+ showClose: true,
+ closeByDocument: true
+ });
+ }
+
+ function addSharedUser(result, userId){
+ var tempList = copy(result.shared);
+ tempList.push(userId);
+ toggleCheck(result, 'shared', tempList);
+ ngDialog.close();
+ }
+
+ function removeSharedUser(result, userId){
+ var tempList = copy(result.shared);
+ var idx = tempList.indexOf(userId);
+ if(idx != -1){
+ tempList.splice(idx, 1);
+ toggleCheck(result, 'shared', tempList);
+ }
+ }
+
+ function copy(arrList){
+ var tempList = [];
+ angular.forEach(arrList, function(ele){
+ tempList.push(ele);
+ });
+ return tempList;
+ }
+
+ function uploadFileToUrl(file, uploadUrl){
+ var fd = new FormData();
+ fd.append('file', file);
+
+ $http.post(uploadUrl, fd, {
+ transformRequest: angular.identity,
+ headers: {'Content-Type': undefined}
+ }).then(function(data){
+
+ if(data.data.code && data.data.code != 0){
+ alert(data.data.msg);
+ return;
+ }
+
+ ctrl.uploadState = "";
+ data.data.filename = file.name;
+ var createTestUrl = testapiApiUrl + "/onap/tests"
+
+ $http.post(createTestUrl, data.data).then(function(data){
+ if (data.data.code && data.data.code != 0) {
+ alert(data.data.msg);
+ } else {
+ ctrl.update();
+ }
+ }, function(error){
+ });
+
+ }, function(error){
+ ctrl.uploadState = "Upload failed. Error code is " + error.status;
+ });
+ }
+
+ function uploadFile(){
+ var file = $scope.resultFile;
+
+ var uploadUrl = testapiApiUrl + "/onap/results/upload";
+ uploadFileToUrl(file, uploadUrl);
+ };
+
+ /**
+ * This will contact the TestAPI API to get a listing of test run
+ * results.
+ */
+ function update() {
+ ctrl.showError = false;
+ // Construct the API URL based on user-specified filters.
+ var content_url = testapiApiUrl + '/onap/tests';
+ var start = $filter('date')(ctrl.startDate, 'yyyy-MM-dd');
+ var end = $filter('date')(ctrl.endDate, 'yyyy-MM-dd');
+
+ content_url += '?page=' + ctrl.currentPage;
+ content_url += '&per_page=' + ctrl.itemsPerPage;
+ if (start) {
+ content_url += '&from=' + start + ' 00:00:00';
+ }
+ if (end) {
+ content_url += '&to=' + end + ' 23:59:59';
+ }
+ if (ctrl.isUserResults) {
+ content_url += '&signed';
+ } else {
+ content_url += '&status={"$ne":"private"}&review';
+ }
+
+ 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;
+ ctrl.numPages = ctrl.data.pagination.total_pages;
+ }).error(function (error) {
+ ctrl.data = null;
+ ctrl.totalItems = 0;
+ ctrl.showError = true;
+ ctrl.error =
+ 'Error retrieving results listing from server: ' +
+ angular.toJson(error);
+ });
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * This function will clear all filters and update the results
+ * 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);
+ }
+ });
+ }
+ }
+
+ function gotoResultDetail(testId, innerID) {
+ $state.go('resultsDetail', {'testID': testId, 'innerID': innerID});
+ }
+ }
+})();