diff options
author | 2019-04-11 06:39:25 +0000 | |
---|---|---|
committer | 2019-04-11 06:39:25 +0000 | |
commit | dbcc039303c7f010348814694b8f75d621aa51e3 (patch) | |
tree | 2ecc14d87b24166c2e6d49f33103b63e1ca4c6fd /3rd_party | |
parent | d32ce7d109fb36277681629c8e648777664862b2 (diff) | |
parent | 71bdc6752f47b7da7282f786570fbe717973fb6d (diff) |
Merge "Enhanced OVP Web Portal"
Diffstat (limited to '3rd_party')
13 files changed, 891 insertions, 346 deletions
diff --git a/3rd_party/static/testapi-ui/app.js b/3rd_party/static/testapi-ui/app.js index edf7663..55603aa 100644 --- a/3rd_party/static/testapi-ui/app.js +++ b/3rd_party/static/testapi-ui/app.js @@ -55,11 +55,11 @@ templateUrl: 'testapi-ui/components/guidelines/guidelines.html', controller: 'GuidelinesController as ctrl' }). - // state('communityResults', { - // url: '/community_results', - // templateUrl: 'testapi-ui/components/results/results.html', - // controller: 'ResultsController as ctrl' - // }). + state('communityResults', { + url: '/community_results', + templateUrl: 'testapi-ui/components/results/results.html', + controller: 'ResultsController as ctrl' + }). state('userResults', { url: '/user_results', templateUrl: 'testapi-ui/components/results/results.html', @@ -173,12 +173,26 @@ $rootScope.auth.doSignIn = doSignIn; $rootScope.auth.doSignOut = doSignOut; $rootScope.auth.doSignCheck = doSignCheck; + $rootScope.auth.canReview = canReview; var sign_in_url = testapiApiUrl + '/auth/signin'; var sign_out_url = testapiApiUrl + '/auth/signout'; var profile_url = testapiApiUrl + '/profile'; + function canReview(user) { + if (typeof user.role == undefined) { + return false; + } else if (user.role.indexOf('administrator') != -1) { + return true; + } else if (user.role.indexOf('reviewer') != -1) { + return true; + } else { + return false; + } + } + + /** This function initiates a sign in. */ function doSignIn(type) { $rootScope.auth.type = type; diff --git a/3rd_party/static/testapi-ui/assets/css/cvp-style.css b/3rd_party/static/testapi-ui/assets/css/cvp-style.css index ed1d938..e6d3ab1 100644 --- a/3rd_party/static/testapi-ui/assets/css/cvp-style.css +++ b/3rd_party/static/testapi-ui/assets/css/cvp-style.css @@ -2,6 +2,15 @@ font-size: 18px; } +.nav>li>a:hover, +.nav>li>a:focus, +.nav>li.active, +.nav>li.active>a { + background-color: #27CFC3; + color: #1C1C1C; +} + + table { font-size: 15px; } @@ -96,3 +105,22 @@ table .btn.medium { a { cursor: pointer; } + +.btn-success-cust { +color: #fff; +background-color: #27CFC3; +border-color: #27CFC3; +} + +.btn-success-cust:focus, .btn-success-cust:hover { +border-color: #1FA79C; +background-color: #1FA79C; +} + +input:invalid { + border: 2px dashed red; +} + +input:valid { + border: 2px solid black; +} diff --git a/3rd_party/static/testapi-ui/components/application/application.html b/3rd_party/static/testapi-ui/components/application/application.html index 0b45ab3..5e78546 100644 --- a/3rd_party/static/testapi-ui/components/application/application.html +++ b/3rd_party/static/testapi-ui/components/application/application.html @@ -1,207 +1,4 @@ <div class="container-fluid common-main-container"> - <div class="top-site-banner"> - <div class="container"> - <p class="p1">Complete this application then start your CVP journey</p> - </div> - </div> - - <div class="row" style="margin-top: 20px;"> - <div class="col-lg-12 container"> - <form id="OsLogoProgramForm_Form" action="/brand/logo-request/Form" method="post" - enctype="application/x-www-form-urlencoded"> - <p id="OsLogoProgramForm_Form_error" class="message" style="display: none;"></p> - <fieldset> - <div class="field text col-md-4"> - <label class="left" >Organization name</label> - <i uib-tooltip="Organization name" class="glyphicon glyphicon-question-sign opnfv-blue"></i> - <div class="middleColumn"> - <input type="text" class="text form-control" ng-model="ctrl.organization_name" required="required" - aria-required="true"> - </div> - </div> - <div class="field text col-md-4"> - <label class="left">Organization website (if public)</label> - <i uib-tooltip="Organization website if it is public" - class="glyphicon glyphicon-question-sign opnfv-blue"></i> - <div class="middleColumn"> - <input type="text" class="text form-control" ng-model="ctrl.organization_web" required="required" - aria-required="true"> - </div> - </div> - <div class="col-md-4"></div> - <div class="field email text col-md-4"> - <label class="left">Product name and/or identifier</label> - <i uib-tooltip="Product name and/or identifier" class="glyphicon glyphicon-question-sign opnfv-blue"></i> - <div class="middleColumn"> - <input type="text" class="email text form-control" ng-model="ctrl.product_name" required="required" - aria-required="true"> - </div> - </div> - <div class="field text col-md-4"> - <label class="left">Product specifications</label> - <i uib-tooltip="A link of product specifications" - class="glyphicon glyphicon-question-sign opnfv-blue"></i> - <div class="middleColumn"> - <input type="text" class="text form-control" ng-model="ctrl.product_spec" required="required" - aria-required="true"> - </div> - </div> - <div class="field text col-md-4"> - <label class="left">Product public documentation</label> - <i uib-tooltip="A link of product public documentation" - class="glyphicon glyphicon-question-sign opnfv-blue"></i> - <div class="middleColumn"> - <input type="text" class="text form-control" ng-model="ctrl.product_documentation" required="required" - aria-required="true"> - </div> - </div> - <div class="field text col-md-4"> - <label class="left">Product categories</label> - <i uib-tooltip="Product categories" class="glyphicon glyphicon-question-sign opnfv-blue"></i> - <div class="middleColumn"> - <select class="form-control" ng-model="ctrl.product_categories"> - <option value="soft&hard">software and hardware</option> - <option value="soft&3rd">software and third party hardware</option> - </select> - </div> - </div> - <div class="field text col-md-4"> - <label class="left">Primary contact name</label> - <i uib-tooltip="Primary contact name" class="glyphicon glyphicon-question-sign opnfv-blue"></i> - <div class="middleColumn"> - <input type="text" class="text form-control" ng-model="ctrl.prim_name" required="required" - aria-required="true"> - </div> - </div> - <div class="field text col-md-4"> - <label class="left">Primary business email</label> - <i uib-tooltip="Only the Business email address should be used for official communication with OPNFV CVP" - class="glyphicon glyphicon-question-sign opnfv-blue"></i> - <div class="middleColumn"> - <input type="text" class="text form-control" ng-model="ctrl.prim_email" required="required" - aria-required="true"> - </div> - </div> - <div class="field text col-md-4"> - <label class="left">Primary postal address</label> - <i uib-tooltip="Primary postal address" class="glyphicon glyphicon-question-sign opnfv-blue"></i> - <div class="middleColumn"> - <input type="text" class="text form-control" ng-model="ctrl.prim_address" required="required" - aria-required="true"> - </div> - </div> - <div class="field text col-md-4"> - <label class="left">Primary phone number</label> - <i uib-tooltip="Primary phone number" class="glyphicon glyphicon-question-sign opnfv-blue"></i> - <div class="middleColumn"> - <input type="text" class="text form-control" ng-model="ctrl.prim_phone" required="required" - aria-required="true"> - </div> - </div> - <div class="field text col-md-4"> - <label class="left">Description</label> - <i uib-tooltip="Product Description" class="glyphicon glyphicon-question-sign opnfv-blue"></i> - <div class="middleColumn"> - <input type="text" class="text form-control" ng-model="ctrl.description"> - </div> - </div> - <div class="field text col-md-4"> - <label class="left">SUT Version</label> - <i uib-tooltip="SUT Version" class="glyphicon glyphicon-question-sign opnfv-blue"></i> - <div class="middleColumn"> - <input type="text" class="text form-control" ng-model="ctrl.sut_version"> - </div> - </div> - <div class="field text col-md-4"> - <label class="left">SUT HW Version</label> - <i uib-tooltip="SUT HW Version - leave blank if not applicable" - class="glyphicon glyphicon-question-sign opnfv-blue"></i> - <div class="middleColumn"> - <input type="text" class="text form-control" ng-model="ctrl.sut_hw_version"> - </div> - </div> - <div class="field text col-md-4"> - <label class="left">OVP Version</label> - <i uib-tooltip="OVP Version" class="glyphicon glyphicon-question-sign opnfv-blue"></i> - <div class="middleColumn"> - <input type="text" class="text form-control" ng-model="ctrl.ovp_version"> - </div> - </div> - <div class="field text col-md-4"> - <label class="left">OVP Category</label> - <i uib-tooltip="OVP Category" class="glyphicon glyphicon-question-sign opnfv-blue"></i> - <div class="middleColumn"> - <input type="text" class="text form-control" ng-model="ctrl.ovp_category"> - </div> - </div> - <div class="field text col-md-4"> - <label class="left">Company Logo</label> - <i uib-tooltip="Company Logo" class="glyphicon glyphicon-question-sign opnfv-blue"></i> - <div class="middleColumn"> - <input type="text" class="text form-control" ng-model="ctrl.company_logo"> - </div> - </div> - <div class="field text col-md-4"> - <label class="left">Approve Date</label> - <i uib-tooltip="Approve Date - YYYY-MM-DD" class="glyphicon glyphicon-question-sign opnfv-blue"></i> - <div class="middleColumn"> - <input type="text" class="text form-control" ng-model="ctrl.approve_date"> - </div> - </div> - <div class="field text col-md-4"> - <label class="left">Approved</label> - <i uib-tooltip="Approved - insert true or false" class="glyphicon glyphicon-question-sign opnfv-blue"></i> - <div class="middleColumn"> - <input type="text" class="text form-control" ng-model="ctrl.approved"> - </div> - </div> - <div class="field text col-md-4"> - <label class="left">Test ID</label> - <i uib-tooltip="Test ID - enter approved test_id" - class="glyphicon glyphicon-question-sign opnfv-blue"></i> - <div class="middleColumn"> - <input type="text" class="text form-control" ng-model="ctrl.test_id"> - </div> - </div> - <div class="field text col-md-4"> - <label class="left">Location</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"> - <option value="internal">internal vendor lab</option> - <option value="third">third-party lab</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"> - </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="text" class="text form-control" ng-model="ctrl.lab_email"> - </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"> - </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="text" class="text form-control" ng-model="ctrl.lab_phone"> - </div> - </div> - </fieldset> - </form> - </div> - </div> - <div class="Actions"> - <button class="btn btn-success cvp-btn" ng-click="ctrl.openConfirmModal()">Submit</button> - </div> <div class="results-table" style="margin-top: 30px; overflow: scroll;"> <table class="table table-striped table-hover"> <thead> @@ -217,7 +14,7 @@ <th>Primary business email</th> <th>Primary postal address</th> <th>Primary phone number</th> - <th>Owner</th> + <th>User ID</th> <th>Description</th> <th>SUT version</th> <th>SUT HW version</th> @@ -225,7 +22,6 @@ <th>OVP category</th> <th>Company logo</th> <th>Approve date</th> - <th>Approved</th> <th>Test ID</th> <th>Location</th> <th>Operation</th> @@ -284,7 +80,6 @@ <td>{{ app.ovp_category }}</td> <td>{{ app.company_logo }}</td> <td>{{ app.approve_date }}</td> - <td>{{ app.approved }}</td> <td>{{ app.test_id }}</td> <td> <span popover-enable="app.lab_location != 'internal'" uib-popover-template="ctrl.lab_tpl" @@ -293,7 +88,13 @@ <i ng-if="app.lab_location != 'internal'" class="glyphicon glyphicon-info-sign opnfv-blue"></i> </td> <td> - <a ng-click="ctrl.deleteApp(app._id)" class="badge badge-info"> + <a ng-click="ctrl.toggleApproveApp(app._id, 'true')" class="badge badge-info" + ng-if="app.approved == 'false'" + data-toggle="tooltip" title="Approve Application"> + <i class="glyphicon glyphicon-ok" ></i> + </a> + <a ng-click="ctrl.deleteApp(app._id)" class="badge badge-info" + data-toggle="tooltip" title="Delete Application"> <i class="glyphicon glyphicon-remove" ></i> </a> </td> @@ -315,20 +116,4 @@ </uib-pagination> </div> </div> - - <div> - <br> - <h3>Company Logo Upload for Directory</h3> - <form enctype="multipart/form-data" method="post"> - <div class="form-group col-m-3"> - <input class="form-contrl btn btn-success cvp-btn medium accent-color regular-button" file-model="logoFile" - type="file"> - </div> - <div class="form-group col-m-3"> - <a class="btn btn-success cvp-btn medium accent-color regular-button" ng-click="ctrl.uploadLogo()"> - <span>Upload Logo</span> - </a> - </div> - </form> - </div> </div> diff --git a/3rd_party/static/testapi-ui/components/application/applicationController.js b/3rd_party/static/testapi-ui/components/application/applicationController.js index e2a4f75..6ae157e 100644 --- a/3rd_party/static/testapi-ui/components/application/applicationController.js +++ b/3rd_party/static/testapi-ui/components/application/applicationController.js @@ -28,35 +28,36 @@ $uibModal, testapiApiUrl, raiseAlert, ngDialog, $scope) { var ctrl = this; - ctrl.uploadLogo = uploadLogo; +// ctrl.uploadLogo = uploadLogo; function init() { - ctrl.organization_name = null; - ctrl.organization_web = null; - ctrl.product_name = null; - ctrl.product_spec = null; - ctrl.product_documentation = null; - ctrl.product_categories = "soft&hard"; - ctrl.prim_name = null; - ctrl.prim_email = null; - ctrl.prim_address = null; - ctrl.prim_phone = null; - ctrl.description = null; - ctrl.sut_version = null; - ctrl.sut_hw_version = null; - ctrl.ovp_version = "2018.01"; - ctrl.ovp_category = "Infrastructure"; - ctrl.company_logo = null; - ctrl.approve_date = null; - ctrl.approved = "false"; - ctrl.test_id = null; - ctrl.lab_location = "internal"; - ctrl.lab_name = null; - ctrl.lab_email = null; - ctrl.lab_address = null; - ctrl.lab_phone = null; ctrl.applications = []; - ctrl.showApplications = []; +// ctrl.organization_name = null; +// ctrl.organization_web = null; +// ctrl.product_name = null; +// ctrl.product_spec = null; +// ctrl.product_documentation = null; +// ctrl.product_categories = "soft&hard"; +// ctrl.prim_name = null; +// ctrl.prim_email = null; +// ctrl.prim_address = null; +// ctrl.prim_phone = null; +// ctrl.description = null; +// ctrl.sut_version = null; +// ctrl.sut_hw_version = null; +// ctrl.ovp_version = "2018.01"; +// ctrl.ovp_category = "Infrastructure"; +// ctrl.company_logo = null; +// ctrl.approve_date = null; +// ctrl.approved = "false"; +// ctrl.test_id = null; +// ctrl.lab_location = "internal"; +// ctrl.lab_name = null; +// ctrl.lab_email = null; +// ctrl.lab_address = null; +// ctrl.lab_phone = null; +// ctrl.applications = []; +// ctrl.showApplications = []; ctrl.totalItems = null; ctrl.currentPage = 1; @@ -70,52 +71,52 @@ } - ctrl.submitForm = function() { - var data = { - "organization_name": ctrl.organization_name, - "organization_web": ctrl.organization_web, - "product_name": ctrl.product_name, - "product_spec": ctrl.product_spec, - "product_documentation": ctrl.product_documentation, - "product_categories": ctrl.product_categories, - "prim_name": ctrl.prim_name, - "prim_email": ctrl.prim_email, - "prim_address": ctrl.prim_address, - "prim_phone": ctrl.prim_phone, - "description": ctrl.description, - "sut_version": ctrl.sut_version, - "sut_hw_version": ctrl.sut_hw_version, - "ovp_version": ctrl.ovp_version, - "ovp_category": ctrl.ovp_category, - "company_logo": ctrl.company_logo, - "approve_date": ctrl.approve_date, - "approved": ctrl.approved, - "test_id": ctrl.test_id, - "lab_location": ctrl.lab_location, - "lab_email": ctrl.lab_email, - "lab_address": ctrl.lab_address, - "lab_phone": ctrl.lab_phone - }; - $http.post(testapiApiUrl + "/cvp/applications", data).then(function(resp) { - if (resp.data.code && resp.data.code != 0) { - alert(resp.data.msg); - return; - } - getApplication(); - }, function(error) { - }); - } - - ctrl.openConfirmModal = function() { - var resp = confirm("Are you sure to submit?"); - if (resp) { - ctrl.submitForm(); - } - } - - ctrl.cancelSubmit = function() { - ngDialog.close(); - } +// ctrl.submitForm = function() { +// var data = { +// "organization_name": ctrl.organization_name, +// "organization_web": ctrl.organization_web, +// "product_name": ctrl.product_name, +// "product_spec": ctrl.product_spec, +// "product_documentation": ctrl.product_documentation, +// "product_categories": ctrl.product_categories, +// "prim_name": ctrl.prim_name, +// "prim_email": ctrl.prim_email, +// "prim_address": ctrl.prim_address, +// "prim_phone": ctrl.prim_phone, +// "description": ctrl.description, +// "sut_version": ctrl.sut_version, +// "sut_hw_version": ctrl.sut_hw_version, +// "ovp_version": ctrl.ovp_version, +// "ovp_category": ctrl.ovp_category, +// "company_logo": ctrl.company_logo, +// "approve_date": ctrl.approve_date, +// "approved": ctrl.approved, +// "test_id": ctrl.test_id, +// "lab_location": ctrl.lab_location, +// "lab_email": ctrl.lab_email, +// "lab_address": ctrl.lab_address, +// "lab_phone": ctrl.lab_phone +// }; +// $http.post(testapiApiUrl + "/cvp/applications", data).then(function(resp) { +// if (resp.data.code && resp.data.code != 0) { +// alert(resp.data.msg); +// return; +// } +// getApplication(); +// }, function(error) { +// }); +// } + +// ctrl.openConfirmModal = function() { +// var resp = confirm("Are you sure to submit?"); +// if (resp) { +// ctrl.submitForm(); +// } +// } +// +// ctrl.cancelSubmit = function() { +// ngDialog.close(); +// } ctrl.updatePage = function() { getApplication(); @@ -136,23 +137,52 @@ }); } - function uploadLogo() { - var file = $scope.logoFile; - var fd = new FormData(); - fd.append('file', file); + ctrl.toggleApproveApp = function(id, approved) { + if (approved === 'true') { + var text = 'Are you sure you want to approve this application?'; + } else { + var text = 'Are you sure you want to remove approval of this application?'; + } + + var resp = confirm(text); + if (!resp) + return; - $http.post(testapiApiUrl + "/cvp/applications/uploadlogo", fd, { + var updateUrl = testapiApiUrl + "/cvp/applications/" + id; + var data = {}; + data['item'] = 'approved'; + data['approved'] = approved; + + $http.put(updateUrl, JSON.stringify(data), { transformRequest: angular.identity, - headers: {'Content-Type': undefined} - }).then(function(resp) { - if (resp.data.code && resp.data.code != 0) { - alert(resp.data.msg); - return; - } + headers: {'Content-Type': 'application/json'}}).then(function(ret) { + if (ret.data.code && ret.data.code != 0) { + alert(ret.data.msg); + return; + } + getApplication(); }, function(error) { + alert('Error when update data'); }); + } - }; +// function uploadLogo() { +// var file = $scope.logoFile; +// var fd = new FormData(); +// fd.append('file', file); +// +// $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; +// } +// }, function(error) { +// }); +// +// }; function getApplication() { $http.get(testapiApiUrl + "/cvp/applications?page=" + ctrl.currentPage + "&signed&per_page=" + ctrl.itemsPerPage).then(function(response) { diff --git a/3rd_party/static/testapi-ui/components/profile/profile.html b/3rd_party/static/testapi-ui/components/profile/profile.html index 563adbf..cfcc79a 100644 --- a/3rd_party/static/testapi-ui/components/profile/profile.html +++ b/3rd_party/static/testapi-ui/components/profile/profile.html @@ -23,6 +23,67 @@ </tbody> </table> </div> + <br> + <br> + <h3>Organization Details</h3> + <table class="table table-striped table-hover"> + <tbody> + <tr> + <td>Company Name</td> + <td> + <div class="popover-wrapper"> + <a editable-theme="bs3" onbeforesave="ctrl.changeProfileDetails(ctrl.profile, 'companyName', $data)" + editable-text="ctrl.profile.companyName">{{ ctrl.profile.companyName || "None" }}</a> + </div> + </td> + </tr> + <tr> + <td>Company website</td> + <td> + <div class="popover-wrapper"> + <a editable-theme="bs3" onbeforesave="ctrl.changeProfileDetails(ctrl.profile, 'companyWebsite', $data)" + editable-url="ctrl.profile.companyWebsite">{{ ctrl.profile.companyWebsite || "None" }}</a> + </div> + </td> + </tr> + <tr> + <td>Primary Contact Name</td> + <td> + <div class="popover-wrapper"> + <a editable-theme="bs3" onbeforesave="ctrl.changeProfileDetails(ctrl.profile, 'primaryContactName', $data)" + editable-text="ctrl.profile.primaryContactName">{{ ctrl.profile.primaryContactName || "None" }}</a> + </div> + </td> + </tr> + <tr> + <td>Primary Contact Business email</td> + <td> + <div class="popover-wrapper"> + <a editable-theme="bs3" onbeforesave="ctrl.changeProfileDetails(ctrl.profile, 'primaryBusinessEmail', $data)" + editable-email="ctrl.profile.primaryBusinessEmail">{{ ctrl.profile.primaryBusinessEmail || "None" }}</a> + </div> + </td> + </tr> + <tr> + <td>Primary Contact Postal Address</td> + <td> + <div class="popover-wrapper"> + <a editable-theme="bs3" onbeforesave="ctrl.changeProfileDetails(ctrl.profile, 'primaryPostalAddress', $data)" + editable-text="ctrl.profile.primaryPostalAddress">{{ ctrl.profile.primaryPostalAddress || "None" }}</a> + </div> + </td> + </tr> + <tr> + <td>Primary Contact Phone Number</td> + <td> + <div class="popover-wrapper"> + <a editable-theme="bs3" onbeforesave="ctrl.changeProfileDetails(ctrl.profile, 'primaryPhoneNumber', $data)" + editable-tel="ctrl.profile.primaryPhoneNumber">{{ ctrl.profile.primaryPhoneNumber || "None" }}</a> + </div> + </td> + </tr> + </tbody> + </table> <div ng-show="ctrl.pubkeys"> <div class="container-fluid"> <div class="row"> diff --git a/3rd_party/static/testapi-ui/components/profile/profileController.js b/3rd_party/static/testapi-ui/components/profile/profileController.js index 0660e19..506771d 100644 --- a/3rd_party/static/testapi-ui/components/profile/profileController.js +++ b/3rd_party/static/testapi-ui/components/profile/profileController.js @@ -51,12 +51,38 @@ ctrl.updatePubKeys = updatePubKeys; ctrl.openImportPubKeyModal = openImportPubKeyModal; ctrl.openShowPubKeyModal = openShowPubKeyModal; + ctrl.changeProfileDetails = changeProfileDetails; // Must be authenticated to view this page. if (!$scope.auth.isAuthenticated) { $state.go('home'); } + ctrl.authRequest = $scope.auth.doSignCheck(); + ctrl.profile = $scope.auth.currentUser; + + function changeProfileDetails(profile, key, newValue){ + if (profile[key] === newValue) { + return; + } + var updateUrl = testapiApiUrl + "/profile"; + + var data = {}; + data[key] = 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 { + profile[key] = newValue; + } + }, function(error) { + alert("Error when update data"); + }); + } + /** * This function will fetch all the user's public keys from the * server and store them in an array. diff --git a/3rd_party/static/testapi-ui/components/results/modal/applicationModal.html b/3rd_party/static/testapi-ui/components/results/modal/applicationModal.html new file mode 100644 index 0000000..e7c4609 --- /dev/null +++ b/3rd_party/static/testapi-ui/components/results/modal/applicationModal.html @@ -0,0 +1,191 @@ +<div class="container-fluid common-main-container"> + <div class="top-site-banner"> + <div class="container"> + <p class="p1">Complete this application then start your CVP journey</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" >Organization name</label> + <i uib-tooltip="Organization name" class="glyphicon glyphicon-question-sign opnfv-blue"></i> + <div class="middleColumn"> + <input type="text" class="text form-control" ng-model="ctrl.organization_name" + ng-init="ctrl.organization_name=auth.currentUser.companyName" required + aria-required="true"> + </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">Organization website</label> + <i uib-tooltip="Organization website if it is public" + class="glyphicon glyphicon-question-sign opnfv-blue"></i> + <div class="middleColumn"> + <input type="url" class="text form-control" ng-model="ctrl.organization_web" + ng-init="ctrl.organization_web=auth.currentUser.companyWebsite" required + aria-required="true"> + </div> + </div> + <div class="field text col-md-4"> + <label class="left">Product name and/or identifier</label> + <i uib-tooltip="Product name and/or identifier" class="glyphicon glyphicon-question-sign opnfv-blue"></i> + <div class="middleColumn"> + <input type="text" class="email text form-control" ng-model="ctrl.product_name" required + aria-required="true"> + </div> + </div> + <div class="field text col-md-4"> + <label class="left">Product specifications</label> + <i uib-tooltip="A link of product specifications" + class="glyphicon glyphicon-question-sign opnfv-blue"></i> + <div class="middleColumn"> + <input type="text" class="text form-control" ng-model="ctrl.product_spec" required + aria-required="true"> + </div> + </div> + <div class="field text col-md-4"> + <label class="left">Product public documentation</label> + <i uib-tooltip="A link of product public documentation" + class="glyphicon glyphicon-question-sign opnfv-blue"></i> + <div class="middleColumn"> + <input type="text" class="text form-control" ng-model="ctrl.product_documentation" required + aria-required="true"> + </div> + </div> + <div class="field text col-md-4"> + <label class="left">Product categories</label> + <i uib-tooltip="Product categories" class="glyphicon glyphicon-question-sign opnfv-blue"></i> + <div class="middleColumn"> + <select class="form-control" ng-model="ctrl.product_categories" ng-init="ctrl.product_categories='soft&hard'"> + <option value="soft&hard">software and hardware</option> + <option value="soft&3rd">software and third party hardware</option> + </select> + </div> + </div> + <div class="field text col-md-4"> + <label class="left">Primary contact name</label> + <i uib-tooltip="Primary contact name" class="glyphicon glyphicon-question-sign opnfv-blue"></i> + <div class="middleColumn"> + <input type="text" class="text form-control" ng-model="ctrl.prim_name" + ng-init="ctrl.prim_name=auth.currentUser.primaryContactName" required + aria-required="true"> + </div> + </div> + <div class="field text col-md-4"> + <label class="left">Primary business email</label> + <i uib-tooltip="Only the Business email address should be used for official communication with OPNFV CVP" + class="glyphicon glyphicon-question-sign opnfv-blue"></i> + <div class="middleColumn"> + <input type="email" class="text form-control" ng-model="ctrl.prim_email" + ng-init="ctrl.prim_email=auth.currentUser.primaryBusinessEmail" required + aria-required="true"> + </div> + </div> + <div class="field text col-md-4"> + <label class="left">Primary postal address</label> + <i uib-tooltip="Primary postal address" class="glyphicon glyphicon-question-sign opnfv-blue"></i> + <div class="middleColumn"> + <input type="text" class="text form-control" ng-model="ctrl.prim_address" + ng-init="ctrl.prim_address=auth.currentUser.primaryPostalAddress" required + aria-required="true"> + </div> + </div> + <div class="field text col-md-4"> + <label class="left">Primary phone number</label> + <i uib-tooltip="Primary phone number" class="glyphicon glyphicon-question-sign opnfv-blue"></i> + <div class="middleColumn"> + <input type="text" class="text form-control" ng-model="ctrl.prim_phone" + ng-init="ctrl.prim_phone=auth.currentUser.primaryPhoneNumber" required + aria-required="true"> + </div> + </div> + <div class="field text col-md-4"> + <label class="left">Description</label> + <i uib-tooltip="Product Description" class="glyphicon glyphicon-question-sign opnfv-blue"></i> + <div class="middleColumn"> + <input type="text" class="text form-control" ng-model="ctrl.description" required> + </div> + </div> + <div class="field text col-md-4"> + <label class="left">SUT Version</label> + <i uib-tooltip="SUT Version" class="glyphicon glyphicon-question-sign opnfv-blue"></i> + <div class="middleColumn"> + <input type="text" class="text form-control" ng-model="ctrl.sut_version" required> + </div> + </div> + <div class="field text col-md-4"> + <label class="left">SUT Label</label> + <i uib-tooltip="SUT Label" class="glyphicon glyphicon-question-sign opnfv-blue"></i> + <div class="middleColumn"> + <input type="text" class="text form-control" ng-model="ctrl.sut_label" required> + </div> + </div> + <div class="field text col-md-4"> + <label class="left">SUT HW Version</label> + <i uib-tooltip="SUT HW Version - leave blank if not applicable" + class="glyphicon glyphicon-question-sign opnfv-blue"></i> + <div class="middleColumn"> + <input type="text" class="text form-control" ng-model="ctrl.sut_hw_version" required> + </div> + </div> + <div class="field text col-md-4"> + <label class="left">OVP Category</label> + <i uib-tooltip="OVP Category" class="glyphicon glyphicon-question-sign opnfv-blue"></i> + <div class="middleColumn"> + <input type="text" class="text form-control" ng-model="ctrl.ovp_category" required> + </div> + </div> + <div class="field text col-md-4"> + <label class="left">Location</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'"> + <option value="internal">internal vendor lab</option> + <option value="third">third-party lab</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="text" 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="text" 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/testapi-ui/components/results/modal/applicationView.html b/3rd_party/static/testapi-ui/components/results/modal/applicationView.html new file mode 100644 index 0000000..3cbbcb5 --- /dev/null +++ b/3rd_party/static/testapi-ui/components/results/modal/applicationView.html @@ -0,0 +1,107 @@ +<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">Organization name</label> + <div class="middleColumn">{{ ctrl.application.organization_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">Organization website</label> + <div class="middleColumn">{{ ctrl.application.organization_web }}</div> + </div> + <div class="field text col-md-4"> + <label class="left">Product name and/or identifier</label> + <div class="middleColumn">{{ ctrl.application.product_name }}</div> + </div> + <div class="field text col-md-4"> + <label class="left">Product specifications</label> + <div class="middleColumn">{{ ctrl.application.product_spec }}</div> + </div> + <div class="field text col-md-4"> + <label class="left">Product public documentation</label> + <div class="middleColumn">{{ ctrl.application.product_documentation }}</div> + </div> + <div class="field text col-md-4"> + <label class="left">Product categories</label> + <div class="middleColumn">{{ ctrl.application.product_categories }}</div> + </div> + <div class="field text col-md-4"> + <label class="left">Primary contact name</label> + <div class="middleColumn">{{ ctrl.application.prim_name }}</div> + </div> + <div class="field text col-md-4"> + <label class="left">Primary business email</label> + <div class="middleColumn">{{ ctrl.application.prim_email }}</div> + </div> + <div class="field text col-md-4"> + <label class="left">Primary postal address</label> + <div class="middleColumn">{{ ctrl.application.prim_address }}</div> + </div> + <div class="field text col-md-4"> + <label class="left">Primary phone number</label> + <div class="middleColumn">{{ ctrl.application.prim_phone }}</div> + </div> + <div class="field text col-md-4"> + <label class="left">Description</label> + <div class="middleColumn">{{ ctrl.application.description }}</div> + </div> + <div class="field text col-md-4"> + <label class="left">SUT Version</label> + <div class="middleColumn">{{ ctrl.application.sut_version }}</div> + </div> + <div class="field text col-md-4"> + <label class="left">SUT Label</label> + <div class="middleColumn">{{ ctrl.application.sut_label }}</div> + </div> + <div class="field text col-md-4"> + <label class="left">SUT HW Version</label> + <div class="middleColumn">{{ ctrl.application.sut_hw_version }}</div> + </div> + <div class="field text col-md-4"> + <label class="left">OVP Category</label> + <div class="middleColumn">{{ ctrl.application.ovp_category }}</div> + </div> + <div class="field text col-md-4"> + <label class="left">Location</label> + <div class="middleColumn">{{ ctrl.application.lab_location }}</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/testapi-ui/components/results/modal/reviewsModal.html b/3rd_party/static/testapi-ui/components/results/modal/reviewsModal.html new file mode 100644 index 0000000..c93d1ef --- /dev/null +++ b/3rd_party/static/testapi-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/testapi-ui/components/results/results.html b/3rd_party/static/testapi-ui/components/results/results.html index bc15169..30bcd94 100644 --- a/3rd_party/static/testapi-ui/components/results/results.html +++ b/3rd_party/static/testapi-ui/components/results/results.html @@ -1,17 +1,18 @@ <div class="container-fluid common-main-container"> <h3>{{ctrl.pageHeader}}</h3> <p>{{ctrl.pageParagraph}}</p> - <form class="form-inline" ng-show="ctrl.isUserResults"> + <form class="form-inline" ng-show="ctrl.isUserResults" + ng-if="auth.isAuthenticated && auth.currentUser.role.indexOf('user') != -1"> <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 cvp-btn medium accent-color regular-button" type="file" + <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 cvp-btn medium accent-color regular-button" ng-click="ctrl.uploadFile()"> + <a class="btn btn-success-cust cvp-btn medium accent-color regular-button" ng-click="ctrl.uploadFile()"> <span>upload result</span> </a> </div> @@ -36,7 +37,8 @@ <th>Status</th> <th>Log</th> <th>SUT</th> - <th>SUT Version</th> + <th>Application</th> + <th>Review Status</th> <th class="col-md-2">Operation</th> <th class="col-md-2">Share List</th> </tr> @@ -62,43 +64,52 @@ <td><a ng-click="ctrl.downloadLogs(result.id)">logs</a></td> <td><a ng-click="ctrl.gotoSUT(result.id)">info</a></td> <td> - <div class="popover-wrapper"> - <a editable-theme="bs3" onbeforesave="ctrl.changeLabel(result, 'sut_label', $data)" - editable-text="result.sut_label">{{ result.sut_label || "None" }}</a> - </div> + <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 cvp-btn medium accent-color regular-button" + <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" + <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.toPrivate(result, 'private')">withdraw submit</a> + <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" + <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.toReview(result, 'review')">submit to review</a> + 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('administrator') != -1" + <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.status == 'approved' || result.status == 'private'}" - ng-click="ctrl.toggleCheck(result, 'status', 'approved')">approve</a> + <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('administrator') != -1" + <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.status == 'not approved' || result.status == 'private'}" - ng-click="ctrl.toggleCheck(result, 'status', 'not approved')">not approve</a> + <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" + <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" + <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> @@ -108,7 +119,7 @@ <td> <div class="btn-group" uib-dropdown> <a id="single-button-two" type="button" - class="btn btn-success cvp-btn medium accent-color regular-button" style="width: 130px;" + 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> diff --git a/3rd_party/static/testapi-ui/components/results/resultsController.js b/3rd_party/static/testapi-ui/components/results/resultsController.js index 6e4e0ac..1fb4f0d 100644 --- a/3rd_party/static/testapi-ui/components/results/resultsController.js +++ b/3rd_party/static/testapi-ui/components/results/resultsController.js @@ -37,6 +37,24 @@ }; }]); + 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' ]; @@ -62,7 +80,6 @@ ctrl.gotoSUT = gotoSUT; ctrl.gotoResultDetail = gotoResultDetail; ctrl.toggleCheck = toggleCheck; - ctrl.changeLabel = changeLabel; ctrl.toReview = toReview; ctrl.toPrivate = toPrivate; ctrl.removeSharedUser = removeSharedUser; @@ -70,6 +87,16 @@ ctrl.openSharedModal = openSharedModal; ctrl.downloadLogs = downloadLogs; ctrl.deleteTest = deleteTest; + ctrl.deleteApplication = deleteApplication; + ctrl.openApplicationModal = openApplicationModal; + ctrl.toApprove = toApprove; + ctrl.toDisapprove = toDisapprove; + ctrl.toUndo = toUndo; + ctrl.openConfirmModal = openConfirmModal; + ctrl.openApplicationView = openApplicationView; + ctrl.submitApplication = submitApplication; + ctrl.openReviewsModal = openReviewsModal; + ctrl.doReview = doReview; /** Mappings of Interop WG components to marketing program names. */ ctrl.targetMappings = { @@ -110,10 +137,17 @@ // ctrl.isUserResults = $state.current.name === 'userResults'; // need auth to browse ctrl.isUserResults = $state.current.name === 'userResults'; + 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 user-results-page if authenticated. if (ctrl.isUserResults && !$scope.auth.isAuthenticated) { $state.go('home'); } @@ -167,6 +201,216 @@ }); } + function deleteApplication (result) { + var resp = confirm('Are you sure you want to delete this application?'); + if (!resp) + return; + + $http.get(testapiApiUrl + "/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.organization_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 = { + "organization_name": ctrl.organization_name, + "organization_web": ctrl.organization_web, + "product_name": ctrl.product_name, + "product_spec": ctrl.product_spec, + "product_documentation": ctrl.product_documentation, + "product_categories": ctrl.product_categories, + "prim_name": ctrl.prim_name, + "prim_email": ctrl.prim_email, + "prim_address": ctrl.prim_address, + "prim_phone": ctrl.prim_phone, + "description": ctrl.description, + "sut_version": ctrl.sut_version, + "sut_label": ctrl.sut_label, + "sut_hw_version": ctrl.sut_hw_version, + "ovp_version": result.version, + "ovp_category": ctrl.ovp_category, + "company_logo": logo_name, + "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 + }; + + $http.post(testapiApiUrl + "/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: 'testapi-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 + "/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: 'testapi-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 + '/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: 'testapi-ui/components/results/modal/reviewsModal.html', + scope: $scope, + className: 'ngdialog-theme-default custom-background', + width: 950, + showClose: true, + closeByDocument: true + }); + } + + function doReview(test, outcome) { + var createUrl = testapiApiUrl + "/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 OVP 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 toggleCheck(result, item, newValue) { var id = result._id; var updateUrl = testapiApiUrl + "/tests/"+ id; @@ -189,10 +433,6 @@ }); } - function changeLabel(result, key, data){ - toggleCheck(result, key, data); - } - function toReview(result, value){ var resp = confirm('Once you submit a test result for review, it will become readable to all OVP reviewers. Do you want to proceed?'); if(resp){ @@ -291,20 +531,24 @@ function update() { ctrl.showError = false; // Construct the API URL based on user-specified filters. - var content_url = testapiApiUrl + '/tests' + - '?page=' + ctrl.currentPage; + var content_url = testapiApiUrl + '/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 = content_url + '&from=' + start + ' 00:00:00'; } - var end = $filter('date')(ctrl.endDate, 'yyyy-MM-dd'); if (end) { content_url = content_url + '&to=' + end + ' 23:59:59'; } if (ctrl.isUserResults) { - content_url = content_url + '&signed'+'&per_page='+ ctrl.itemsPerPage; + content_url += '&signed'; + } else { + content_url += '&status={"$ne":"private"}&review'; } + ctrl.resultsRequest = $http.get(content_url).success(function (data) { ctrl.data = data; diff --git a/3rd_party/static/testapi-ui/index.html b/3rd_party/static/testapi-ui/index.html index 94aff67..961e4cf 100644 --- a/3rd_party/static/testapi-ui/index.html +++ b/3rd_party/static/testapi-ui/index.html @@ -30,6 +30,7 @@ <link rel="stylesheet" href="testapi-ui/node_modules/ng-dialog/css/ngDialog.min.css"> <link rel="stylesheet" href="testapi-ui/node_modules/ng-dialog/css/ngDialog-theme-default.min.css"> <link rel="stylesheet" href="testapi-ui/node_modules/angular-xeditable/dist/css/xeditable.min.css"> + <link rel="stylesheet" href="testapi-ui/assets/css/combine.css"> <!-- CSS Internal Code --> <link rel="stylesheet" href="testapi-ui/assets/css/cvp-style.css"> @@ -75,7 +76,8 @@ </head> <body class="container-fluid home page-template-default page page-id-6 do-etfw tribe-no-js ascend wpb-js-composer - js-comp-ver-5.2.1 vc_responsive index-header"> + js-comp-ver-5.2.1 vc_responsive index-header" + ng-controller="HeaderController as header"> <header ng-include src="'testapi-ui/shared/header/header.html'"></header> <div ui-view></div> <footer ng-include src="'testapi-ui/shared/footer/footer.html'"></footer> diff --git a/3rd_party/static/testapi-ui/shared/header/header.html b/3rd_party/static/testapi-ui/shared/header/header.html index 54470e7..fad240c 100644 --- a/3rd_party/static/testapi-ui/shared/header/header.html +++ b/3rd_party/static/testapi-ui/shared/header/header.html @@ -19,7 +19,12 @@ ng-if="auth.isAuthenticated && auth.currentUser.role.indexOf('administrator') != -1"> <a ui-sref="application">Applications</a> </li> - <li ng-class="{ active: header.isActive('/user_results')}" ng-if="auth.isAuthenticated"> + <li ng-class="{ active: header.isActive('/community_results')}" + ng-if="auth.isAuthenticated && auth.canReview(auth.currentUser)"> + <a ui-sref="communityResults">Incoming Reviews</a> + </li> + <li ng-class="{ active: header.isActive('/user_results')}" + ng-if="auth.isAuthenticated && auth.currentUser.role.indexOf('user') != -1"> <a ui-sref="userResults">My Results</a> </li> <li ng-class="{ active: header.isActive('/profile')}" ng-if="auth.isAuthenticated"> |