Add vendor UI
This adds the initial UI functionality for the UI in relations to vendors. Change-Id: I58a3b00a421d2d65d59014e586bacc974aa8637b Co-Authored-By: Andrey Pavlov <andrey-mp@yandex.ru>
This commit is contained in:
parent
9888cf2bc1
commit
3c82bc3443
@ -78,6 +78,21 @@
|
||||
url: '/logout',
|
||||
templateUrl: '/components/logout/logout.html',
|
||||
controller: 'LogoutController as ctrl'
|
||||
}).
|
||||
state('userVendors', {
|
||||
url: '/user_vendors',
|
||||
templateUrl: '/components/vendors/vendors.html',
|
||||
controller: 'VendorsController as ctrl'
|
||||
}).
|
||||
state('publicVendors', {
|
||||
url: '/public_vendors',
|
||||
templateUrl: '/components/vendors/vendors.html',
|
||||
controller: 'VendorsController as ctrl'
|
||||
}).
|
||||
state('vendor', {
|
||||
url: '/vendor/:vendorID',
|
||||
templateUrl: '/components/vendors/vendor.html',
|
||||
controller: 'VendorController as ctrl'
|
||||
});
|
||||
}
|
||||
|
||||
|
85
refstack-ui/app/components/vendors/vendor.html
vendored
Normal file
85
refstack-ui/app/components/vendors/vendor.html
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
<div ng-show="ctrl.vendor" class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="pull-left">
|
||||
<div class="test-report">
|
||||
<strong>Vendor ID:</strong> {{ctrl.vendorId}}<br />
|
||||
<strong>Type:</strong>
|
||||
<span ng-show="ctrl.vendor.type == 0">OpenStack</span>
|
||||
<span ng-show="ctrl.vendor.type == 1" class="text-info">Private</span>
|
||||
<span ng-show="ctrl.vendor.type == 2" class="text-warning">Pending Approval</span>
|
||||
<span ng-show="ctrl.vendor.type == 3" class="text-success">Official</span>
|
||||
<br />
|
||||
<strong>Name:</strong> {{ctrl.vendor.name}}<br />
|
||||
<strong>Description:</strong> {{ctrl.vendor.description}}<br />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pull-right">
|
||||
<a ng-if="ctrl.vendor.canDelete" href="javascript:void(0)" ng-click="ctrl.deleteVendor()" confirm="Are you sure you want to delete this vendor?">Delete</a><br />
|
||||
<a ng-if="ctrl.vendor.canRegister" href="javascript:void(0)" ng-click="ctrl.registerVendor()">Register with Foundation</a><br />
|
||||
<a ng-if="ctrl.vendor.canApprove && ctrl.vendor.type == 2" href="javascript:void(0)" ng-click="ctrl.approveVendor()"
|
||||
confirm="Are you sure you want to approve this vendor?">Approve registration</a><br />
|
||||
<a ng-if="ctrl.vendor.canApprove && ctrl.vendor.type == 2" href="javascript:void(0)" ng-click="ctrl.declineVendor()">Decline registration</a><br />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div ng-if="ctrl.vendorProperties.reason">
|
||||
<hr />
|
||||
<strong>Decline reason:</strong> {{ctrl.vendorProperties.reason}}<br />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-show="ctrl.vendorUsers" class="row">
|
||||
<hr />
|
||||
<h3>Vendor Users</h3>
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Open ID</th>
|
||||
<th>Full Name</th>
|
||||
<th>E-Mail</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr ng-repeat="user in ctrl.vendorUsers">
|
||||
<td>{{user.openid}}</td>
|
||||
<td>{{user.fullname}}</td>
|
||||
<td>{{user.email}}</td>
|
||||
<td>
|
||||
<a ng-if="user.openid != ctrl.currentUser"
|
||||
href="javascript:void(0)"
|
||||
ng-click="ctrl.removeUserFromVendor(user.openid)"
|
||||
confirm="Are you sure you want to remove this user from vendor?">Remove</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="row form-group">
|
||||
<div class="col-md-6">
|
||||
<label for="new_user">Add user to vendor:</label>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
id="new_user"
|
||||
placeholder="Input Open ID"
|
||||
ng-model="ctrl.userToAdd">
|
||||
</div>
|
||||
<div class="col-md-1" style="margin-top:25px;">
|
||||
<button type="submit" class="btn btn-primary" ng-click="ctrl.addUserToVendor(ctrl.userToAdd)">Add User</button>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Loading animation divs -->
|
||||
<div cg-busy="{promise:ctrl.vendorRequest,message:'Loading'}"></div>
|
||||
<div cg-busy="{promise:ctrl.usersRequest,message:'Loading'}"></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>
|
185
refstack-ui/app/components/vendors/vendorController.js
vendored
Normal file
185
refstack-ui/app/components/vendors/vendorController.js
vendored
Normal file
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* 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('refstackApp')
|
||||
.controller('VendorController', VendorController);
|
||||
|
||||
VendorController.$inject = [
|
||||
'$rootScope', '$scope', '$http', '$state', '$stateParams', '$window',
|
||||
'refstackApiUrl', 'raiseAlert', 'confirmModal'
|
||||
];
|
||||
|
||||
/**
|
||||
* RefStack Vendor Controller
|
||||
* This controller is for the '/vendor/' details page where owner can
|
||||
* view details of the Vendor and manage users.
|
||||
*/
|
||||
function VendorController($rootScope, $scope, $http, $state, $stateParams,
|
||||
$window, refstackApiUrl, raiseAlert, confirmModal) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.getVendor = getVendor;
|
||||
ctrl.getVendorUsers = getVendorUsers;
|
||||
ctrl.registerVendor = registerVendor;
|
||||
ctrl.approveVendor = approveVendor;
|
||||
ctrl.declineVendor = declineVendor;
|
||||
ctrl.deleteVendor = deleteVendor;
|
||||
ctrl.removeUserFromVendor = removeUserFromVendor;
|
||||
ctrl.addUserToVendor = addUserToVendor;
|
||||
|
||||
/** The vendor id extracted from the URL route. */
|
||||
ctrl.vendorId = $stateParams.vendorID;
|
||||
|
||||
// Should only be on user-vendors-page if authenticated.
|
||||
if (!$scope.auth.isAuthenticated) {
|
||||
$state.go('home');
|
||||
}
|
||||
|
||||
/**
|
||||
* This will contact the Refstack API to get a vendor information.
|
||||
*/
|
||||
function getVendor() {
|
||||
ctrl.showError = false;
|
||||
ctrl.vendor = null;
|
||||
// Construct the API URL based on user-specified filters.
|
||||
var contentUrl = refstackApiUrl + '/vendors/' + ctrl.vendorId;
|
||||
ctrl.vendorRequest =
|
||||
$http.get(contentUrl).success(function(data) {
|
||||
ctrl.vendor = data;
|
||||
var isAdmin = $rootScope.auth.currentUser.is_admin;
|
||||
ctrl.vendor.canDelete = ctrl.vendor.type != 0
|
||||
&& (ctrl.vendor.can_manage || isAdmin);
|
||||
ctrl.vendor.canRegister =
|
||||
ctrl.vendor.type == 1;
|
||||
ctrl.vendor.canApprove = isAdmin;
|
||||
ctrl.vendorProperties = angular.fromJson(data.properties);
|
||||
}).error(function(error) {
|
||||
ctrl.showError = true;
|
||||
ctrl.error =
|
||||
'Error retrieving from server: ' +
|
||||
angular.toJson(error);
|
||||
});
|
||||
}
|
||||
ctrl.getVendor();
|
||||
|
||||
/**
|
||||
* This will 'send' application for registration.
|
||||
*/
|
||||
function registerVendor() {
|
||||
var url = [refstackApiUrl, '/vendors/', ctrl.vendorId,
|
||||
'/action'].join('');
|
||||
$http.post(url, {register: null}).success(function() {
|
||||
ctrl.getVendor();
|
||||
}).error(function(error) {
|
||||
raiseAlert('danger', 'Error: ', error.detail);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This will approve application for registration.
|
||||
*/
|
||||
function approveVendor() {
|
||||
var url = [refstackApiUrl, '/vendors/', ctrl.vendorId,
|
||||
'/action'].join('');
|
||||
$http.post(url, {approve: null}).success(function() {
|
||||
ctrl.getVendor();
|
||||
}).error(function(error) {
|
||||
raiseAlert('danger', 'Error: ', error.detail);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This will decline a vendor's application for registration.
|
||||
*/
|
||||
function declineVendor() {
|
||||
confirmModal('Please input decline reason', function(reason) {
|
||||
var url = [refstackApiUrl, '/vendors/', ctrl.vendorId,
|
||||
'/action'].join('');
|
||||
$http.post(url, {deny: null, reason: reason}).success(
|
||||
function() {
|
||||
ctrl.getVendor();
|
||||
}).error(function(error) {
|
||||
raiseAlert('danger', 'Error: ', error.detail);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the current vendor.
|
||||
*/
|
||||
function deleteVendor() {
|
||||
var url = [refstackApiUrl, '/vendors/', ctrl.vendorId].join('');
|
||||
$http.delete(url).success(function () {
|
||||
$window.location.href = '/';
|
||||
}).error(function (error) {
|
||||
raiseAlert('danger', 'Error: ', error.detail);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates list of users in the vendor's group
|
||||
*/
|
||||
function getVendorUsers() {
|
||||
ctrl.showError = false;
|
||||
var contentUrl = refstackApiUrl + '/vendors/' + ctrl.vendorId
|
||||
+ '/users';
|
||||
ctrl.usersRequest =
|
||||
$http.get(contentUrl).success(function(data) {
|
||||
ctrl.vendorUsers = data;
|
||||
ctrl.currentUser = $rootScope.auth.currentUser.openid;
|
||||
}).error(function(error) {
|
||||
ctrl.showError = true;
|
||||
ctrl.error =
|
||||
'Error retrieving from server: ' +
|
||||
angular.toJson(error);
|
||||
});
|
||||
}
|
||||
ctrl.getVendorUsers();
|
||||
|
||||
/**
|
||||
* Removes user with specific openid from vendor's group
|
||||
* @param {Object} openid
|
||||
*/
|
||||
function removeUserFromVendor(openid) {
|
||||
var url = [refstackApiUrl, '/vendors/', ctrl.vendorId,
|
||||
'/users/', btoa(openid)].join('');
|
||||
$http.delete(url).success(function () {
|
||||
ctrl.getVendorUsers();
|
||||
}).error(function (error) {
|
||||
raiseAlert('danger', 'Error: ', error.detail);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a user to a vendor group given an Open ID.
|
||||
* @param {Object} openid
|
||||
*/
|
||||
function addUserToVendor(openid) {
|
||||
var url = [refstackApiUrl, '/vendors/', ctrl.vendorId,
|
||||
'/users/', btoa(openid)].join('');
|
||||
$http.put(url).success(function() {
|
||||
ctrl.userToAdd = '';
|
||||
ctrl.getVendorUsers();
|
||||
}).error(function(error) {
|
||||
raiseAlert('danger', 'Problem adding user. ' +
|
||||
'Is the Open ID correct? Error: ',
|
||||
error.detail);
|
||||
});
|
||||
}
|
||||
}
|
||||
})();
|
69
refstack-ui/app/components/vendors/vendors.html
vendored
Normal file
69
refstack-ui/app/components/vendors/vendors.html
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
<h3>{{ctrl.pageHeader}}</h3>
|
||||
<p>{{ctrl.pageParagraph}}</p>
|
||||
|
||||
<div cg-busy="{promise:ctrl.authRequest,message:'Loading'}"></div>
|
||||
<div cg-busy="{promise:ctrl.vendorsRequest,message:'Loading'}"></div>
|
||||
|
||||
<div ng-show="ctrl.data" class="vendors-table">
|
||||
<label ng-if="ctrl.isAdminView && ctrl.isUserVendors">
|
||||
<input type="checkbox" ng-model="ctrl.withPrivate" ng-change="ctrl.updateData();"> Show private vendors
|
||||
</label>
|
||||
<br />
|
||||
<table ng-show="ctrl.data" class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Type</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="vendor in ctrl.data.vendors">
|
||||
<td ng-if="ctrl.isUserVendors"><a ui-sref="vendor({vendorID: vendor.id})">{{vendor.name}}</a></td>
|
||||
<td ng-if="!ctrl.isUserVendors">{{vendor.name}}</td>
|
||||
<td>{{vendor.description || '-'}}</td>
|
||||
<td>
|
||||
<span ng-show="vendor.type == 0" class="glyphicon glyphicon-exclamation-sign"> OpenStack</span>
|
||||
<span ng-show="vendor.type == 1" class="glyphicon glyphicon-eye-close"> Private</span>
|
||||
<span ng-show="vendor.type == 2" class="glyphicon glyphicon-transfer"> Pending Approval</span>
|
||||
<span ng-show="vendor.type == 3" class="glyphicon glyphicon-check"> Official</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div ng-if="ctrl.isUserVendors">
|
||||
<hr />
|
||||
<h4>Add new vendor</h4>
|
||||
<p>Creating a vendor allows you to associate test results to specific vendors/products.
|
||||
Created vendors are private, but vendors can be registered with the Foundation to become public and official.
|
||||
This will require approval by a Foundation administrator.</p>
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<label>Name</label>
|
||||
<p class="input-group">
|
||||
<input type="text" class="form-control"
|
||||
ng-model="ctrl.name" close-text="Close" />
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label>Description</label>
|
||||
<p class="input-group">
|
||||
<input type="text" class="form-control" size="80"
|
||||
ng-model="ctrl.description" close-text="Close" />
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-3" style="margin-top:24px;">
|
||||
<button type="submit" class="btn btn-primary" ng-click="ctrl.addVendor()">Add Vendor</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div cg-busy="{promise:ctrl.vendorsRequest,message:'Loading'}"></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>
|
162
refstack-ui/app/components/vendors/vendorsController.js
vendored
Normal file
162
refstack-ui/app/components/vendors/vendorsController.js
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* 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('refstackApp')
|
||||
.controller('VendorsController', VendorsController);
|
||||
|
||||
VendorsController.$inject = [
|
||||
'$rootScope', '$scope', '$http', '$state',
|
||||
'refstackApiUrl','raiseAlert'
|
||||
];
|
||||
|
||||
/**
|
||||
* RefStack Vendors Controller
|
||||
* This controller is for the '/user_vendors' or '/public_vendors' page
|
||||
* where a user can browse a listing of his/her vendors or public vendors.
|
||||
*/
|
||||
function VendorsController($rootScope, $scope, $http, $state,
|
||||
refstackApiUrl, raiseAlert) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.update = update;
|
||||
ctrl.updateData = updateData;
|
||||
ctrl._filterVendor = _filterVendor;
|
||||
ctrl.addVendor = addVendor;
|
||||
|
||||
/** Check to see if this page should display user-specific vendors. */
|
||||
ctrl.isUserVendors = $state.current.name === 'userVendors';
|
||||
|
||||
/** Show private vendors in list for foundation admin */
|
||||
ctrl.withPrivate = false;
|
||||
|
||||
/** Properties for adding new vendor */
|
||||
ctrl.name = '';
|
||||
ctrl.description = '';
|
||||
|
||||
// Should only be on user-vendors-page if authenticated.
|
||||
if (ctrl.isUserVendors && !$scope.auth.isAuthenticated) {
|
||||
$state.go('home');
|
||||
}
|
||||
|
||||
ctrl.pageHeader = ctrl.isUserVendors ?
|
||||
'My Vendors' : 'Public Vendors';
|
||||
|
||||
ctrl.pageParagraph = ctrl.isUserVendors ?
|
||||
'Your added vendors are listed here.' :
|
||||
'Public Vendors approved by the OpenStack Foundation are ' +
|
||||
'listed here.';
|
||||
|
||||
if (ctrl.isUserVendors) {
|
||||
ctrl.authRequest = $scope.auth.doSignCheck()
|
||||
.then(ctrl.update);
|
||||
} else {
|
||||
ctrl.update();
|
||||
}
|
||||
|
||||
ctrl.rawData = null;
|
||||
ctrl.isAdminView = $rootScope.auth
|
||||
&& $rootScope.auth.currentUser
|
||||
&& $rootScope.auth.currentUser.is_admin;
|
||||
|
||||
/**
|
||||
* This will contact the Refstack API to get a listing of test run
|
||||
* results.
|
||||
*/
|
||||
function update() {
|
||||
ctrl.showError = false;
|
||||
ctrl.data = null;
|
||||
// Construct the API URL based on user-specified filters.
|
||||
var contentUrl = refstackApiUrl + '/vendors';
|
||||
if (typeof ctrl.rawData == 'undefined'
|
||||
|| ctrl.rawData === null) {
|
||||
ctrl.vendorsRequest =
|
||||
$http.get(contentUrl).success(function (data) {
|
||||
ctrl.rawData = data;
|
||||
ctrl.updateData();
|
||||
}).error(function (error) {
|
||||
ctrl.rawData = null;
|
||||
ctrl.showError = true;
|
||||
ctrl.error =
|
||||
'Error retrieving vendors listing from server: ' +
|
||||
angular.toJson(error);
|
||||
});
|
||||
} else {
|
||||
ctrl.updateData();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This will update data for view with current settings on page.
|
||||
*/
|
||||
function updateData() {
|
||||
ctrl.data = {};
|
||||
ctrl.data.vendors = ctrl.rawData.vendors.filter(function(vendor) {
|
||||
return ctrl._filterVendor(vendor);
|
||||
});
|
||||
ctrl.data.vendors.sort(function(a, b) {
|
||||
if (a.type > b.type) {
|
||||
return 1;
|
||||
}
|
||||
if (a.type < b.type) {
|
||||
return -1;
|
||||
}
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if vendor can be displayed on this page.
|
||||
*/
|
||||
function _filterVendor(vendor) {
|
||||
if (!ctrl.isUserVendors) {
|
||||
return (vendor.type == 0 || vendor.type == 3);
|
||||
}
|
||||
|
||||
if (!$rootScope.auth || !$rootScope.auth.currentUser) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($rootScope.auth.currentUser.is_admin) {
|
||||
return vendor.type != 1 || ctrl.withPrivate;
|
||||
}
|
||||
|
||||
return vendor.can_manage;
|
||||
}
|
||||
|
||||
/**
|
||||
* This will add a new vendor record.
|
||||
*/
|
||||
function addVendor() {
|
||||
var url = refstackApiUrl + '/vendors';
|
||||
var data = {
|
||||
name: ctrl.name,
|
||||
description: ctrl.description
|
||||
};
|
||||
ctrl.name = '';
|
||||
ctrl.description = '';
|
||||
$http.post(url, data).success(function (data) {
|
||||
ctrl.rawData = null;
|
||||
ctrl.update();
|
||||
}).error(function (error) {
|
||||
ctrl.showError = true;
|
||||
ctrl.error =
|
||||
'Error adding new vendor: ' + angular.toJson(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
})();
|
@ -38,12 +38,15 @@
|
||||
<!-- Controllers -->
|
||||
<script src="shared/header/headerController.js"></script>
|
||||
<script src="shared/alerts/alertModalFactory.js"></script>
|
||||
<script src="shared/alerts/confirmModalFactory.js"></script>
|
||||
<script src="components/guidelines/guidelinesController.js"></script>
|
||||
<script src="components/results/resultsController.js"></script>
|
||||
<script src="components/results-report/resultsReportController.js"></script>
|
||||
<script src="components/profile/profileController.js"></script>
|
||||
<script src="components/auth-failure/authFailureController.js"></script>
|
||||
<script src="components/logout/logoutController.js"></script>
|
||||
<script src="components/vendors/vendorController.js"></script>
|
||||
<script src="components/vendors/vendorsController.js"></script>
|
||||
|
||||
<!-- Filters -->
|
||||
<script src="shared/filters.js"></script>
|
||||
|
13
refstack-ui/app/shared/alerts/confirmModal.html
Normal file
13
refstack-ui/app/shared/alerts/confirmModal.html
Normal file
@ -0,0 +1,13 @@
|
||||
<div class="modal-header"><h3 class="modal-title">Confirm</h3></div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="confirmText">{{confirmModal.data.text}}:</label>
|
||||
<textarea type="text" class="form-control"
|
||||
rows="5" ng-model="confirmModal.inputText" id="confirmText">
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary" ng-click="confirmModal.confirm()">Ok</button>
|
||||
<button class="btn btn-default" ng-click="confirmModal.cancel()">Cancel</button>
|
||||
</div>
|
67
refstack-ui/app/shared/alerts/confirmModalFactory.js
Normal file
67
refstack-ui/app/shared/alerts/confirmModalFactory.js
Normal file
@ -0,0 +1,67 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('refstackApp')
|
||||
.factory('confirmModal', confirmModal);
|
||||
|
||||
confirmModal.$inject = ['$uibModal'];
|
||||
|
||||
/**
|
||||
* Opens confirm modal dialog with input textbox
|
||||
*/
|
||||
function confirmModal($uibModal) {
|
||||
return function(text, successHandler) {
|
||||
$uibModal.open({
|
||||
templateUrl: '/shared/alerts/confirmModal.html',
|
||||
controller: 'CustomConfirmModalController as confirmModal',
|
||||
size: 'md',
|
||||
resolve: {
|
||||
data: function () {
|
||||
return {
|
||||
text: text,
|
||||
successHandler: successHandler
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
angular
|
||||
.module('refstackApp')
|
||||
.controller('CustomConfirmModalController',
|
||||
CustomConfirmModalController);
|
||||
|
||||
CustomConfirmModalController.$inject = ['$uibModalInstance', 'data'];
|
||||
|
||||
/**
|
||||
* This is the controller for the alert pop-up.
|
||||
*/
|
||||
function CustomConfirmModalController($uibModalInstance, data) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.confirm = confirm;
|
||||
ctrl.cancel = cancel;
|
||||
|
||||
ctrl.data = angular.copy(data);
|
||||
|
||||
/**
|
||||
* Initiate confirmation and call the success handler with the
|
||||
* input text.
|
||||
*/
|
||||
function confirm() {
|
||||
$uibModalInstance.close();
|
||||
if (angular.isDefined(ctrl.data.successHandler)) {
|
||||
ctrl.data.successHandler(ctrl.inputText);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the confirm modal without initiating changes.
|
||||
*/
|
||||
function cancel() {
|
||||
$uibModalInstance.dismiss('cancel');
|
||||
}
|
||||
}
|
||||
})();
|
@ -19,9 +19,25 @@ RefStack
|
||||
<li ng-class="{ active: header.isActive('/about')}"><a ui-sref="about">About</a></li>
|
||||
<li ng-class="{ active: header.isActive('/guidelines')}"><a ui-sref="guidelines">DefCore Guidelines</a></li>
|
||||
<li ng-class="{ active: header.isActive('/community_results')}"><a ui-sref="communityResults">Community Results</a></li>
|
||||
<li ng-class="{ active: header.isCatalogActive('public')}" class="dropdown" uib-dropdown>
|
||||
<a role="button" class="dropdown-toggle" uib-dropdown-toggle>
|
||||
Catalog <strong class="caret"></strong>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a ui-sref="publicVendors">Vendors</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li ng-class="{ active: header.isActive('/user_results')}" ng-if="auth.isAuthenticated"><a ui-sref="userResults">My Results</a></li>
|
||||
<li ng-if="auth.isAuthenticated" ng-class="{ active: header.isCatalogActive('user')}" class="dropdown" uib-dropdown>
|
||||
<a role="button" class="dropdown-toggle" uib-dropdown-toggle>
|
||||
My Catalog <strong class="caret"></strong>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a ui-sref="userVendors">My Vendors</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li ng-class="{ active: header.isActive('/profile')}" ng-if="auth.isAuthenticated"><a ui-sref="profile">Profile</a></li>
|
||||
<li ng-if="auth.isAuthenticated"><a href="" ng-click="auth.doSignOut()">Sign Out</a></li>
|
||||
<li ng-if="!auth.isAuthenticated"><a href="" ng-click="auth.doSignIn()">Sign In / Sign Up</a></li>
|
||||
|
@ -30,6 +30,7 @@
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.isActive = isActive;
|
||||
ctrl.isCatalogActive = isCatalogActive;
|
||||
|
||||
/** Whether the Navbar is collapsed for small displays. */
|
||||
ctrl.navbarCollapsed = true;
|
||||
@ -49,5 +50,13 @@
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** This determines the active state for the catalog dropdown. Type
|
||||
* parameter should be passed in to specify if the catalog is the
|
||||
* public or user one.
|
||||
*/
|
||||
function isCatalogActive(type) {
|
||||
return ctrl.isActive('/' + type + '_vendors');
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
@ -724,6 +724,40 @@ describe('Refstack controllers', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('TestCustomConfirmModalController', function() {
|
||||
var data, someFunc, modalInstance, ctrl;
|
||||
|
||||
beforeEach(inject(function ($controller) {
|
||||
modalInstance = {
|
||||
dismiss: jasmine.createSpy('modalInstance.dismiss'),
|
||||
close: jasmine.createSpy('modalInstance.close')
|
||||
};
|
||||
|
||||
someFunc = jasmine.createSpy('someFunc');
|
||||
data = {
|
||||
text: 'Some input',
|
||||
successHandler: someFunc
|
||||
};
|
||||
|
||||
ctrl = $controller('CustomConfirmModalController',
|
||||
{$uibModalInstance: modalInstance, data: data}
|
||||
);
|
||||
}));
|
||||
|
||||
it('should have a function to confirm',
|
||||
function () {
|
||||
ctrl.inputText = 'foo';
|
||||
ctrl.confirm();
|
||||
expect(someFunc).toHaveBeenCalledWith('foo');
|
||||
});
|
||||
|
||||
it('should have a function to dismiss the modal',
|
||||
function () {
|
||||
ctrl.cancel();
|
||||
expect(modalInstance.dismiss).toHaveBeenCalledWith('cancel');
|
||||
});
|
||||
});
|
||||
|
||||
describe('AuthFailureController', function() {
|
||||
var $location, ctrl;
|
||||
|
||||
@ -740,4 +774,177 @@ describe('Refstack controllers', function () {
|
||||
expect(ctrl.message).toBe('some_error_message');
|
||||
});
|
||||
});
|
||||
|
||||
describe('VendorController', function() {
|
||||
var rootScope, scope, stateParams, ctrl;
|
||||
var confirmModal = jasmine.createSpy('confirmModal');
|
||||
var fakeResp = {'id': 'fake-id', 'type': 1,
|
||||
'can_manage': true, 'properties' : {}};
|
||||
var fakeUsersResp = [{'openid': 'foo'}];
|
||||
var fakeWindow = {
|
||||
location: {
|
||||
href: ''
|
||||
}
|
||||
};
|
||||
|
||||
beforeEach(inject(function ($controller, $rootScope) {
|
||||
scope = $rootScope.$new();
|
||||
rootScope = $rootScope.$new();
|
||||
rootScope.auth = {'currentUser' : {'is_admin': false,
|
||||
'openid': 'foo'}
|
||||
};
|
||||
stateParams = {vendorID: 1234};
|
||||
ctrl = $controller('VendorController',
|
||||
{$rootScope: rootScope, $scope: scope,
|
||||
$stateParams: stateParams, $window: fakeWindow,
|
||||
confirmModal: confirmModal}
|
||||
);
|
||||
|
||||
$httpBackend.when('GET', fakeApiUrl +
|
||||
'/vendors/1234').respond(fakeResp);
|
||||
$httpBackend.when('GET', fakeApiUrl +
|
||||
'/vendors/1234/users').respond(fakeUsersResp);
|
||||
}));
|
||||
|
||||
it('should have a function to get vendor info from API',
|
||||
function () {
|
||||
ctrl.getVendor();
|
||||
$httpBackend.flush();
|
||||
expect(ctrl.vendor.id).toEqual('fake-id');
|
||||
expect(ctrl.vendor.can_manage).toEqual(true);
|
||||
expect(ctrl.vendor.canDelete).toEqual(true);
|
||||
expect(ctrl.vendor.canRegister).toEqual(true);
|
||||
expect(ctrl.vendor.canApprove).toEqual(false);
|
||||
});
|
||||
|
||||
it('should have a function to get vendor users',
|
||||
function () {
|
||||
ctrl.getVendorUsers();
|
||||
$httpBackend.flush();
|
||||
expect(ctrl.vendorUsers).toEqual(fakeUsersResp);
|
||||
expect(ctrl.currentUser).toEqual('foo');
|
||||
});
|
||||
|
||||
it('should have a function to register a vendor',
|
||||
function () {
|
||||
$httpBackend.expectPOST(
|
||||
fakeApiUrl + '/vendors/1234/action',
|
||||
{'register': null})
|
||||
.respond(201, '');
|
||||
ctrl.registerVendor();
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
it('should have a function to approve a vendor',
|
||||
function () {
|
||||
$httpBackend.expectPOST(
|
||||
fakeApiUrl + '/vendors/1234/action',
|
||||
{'approve': null})
|
||||
.respond(201, '');
|
||||
ctrl.approveVendor();
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
it('a confirmation modal should come up when declining a vendor',
|
||||
function () {
|
||||
ctrl.declineVendor();
|
||||
expect(confirmModal).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should have a function to delete a vendor',
|
||||
function () {
|
||||
$httpBackend.expectDELETE(
|
||||
fakeApiUrl + '/vendors/1234').respond(202, '');
|
||||
ctrl.deleteVendor();
|
||||
$httpBackend.flush();
|
||||
expect(fakeWindow.location.href).toEqual('/');
|
||||
});
|
||||
|
||||
it('should have to a function to remove a user from a vendor',
|
||||
function () {
|
||||
var fakeId = 'fake-id';
|
||||
$httpBackend.expectDELETE(
|
||||
fakeApiUrl + '/vendors/1234/users/' + btoa(fakeId))
|
||||
.respond(202, '');
|
||||
ctrl.removeUserFromVendor(fakeId);
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
it('should have to a function to add a user to a vendor',
|
||||
function () {
|
||||
var fakeId = 'fake-id';
|
||||
$httpBackend.expectPUT(
|
||||
fakeApiUrl + '/vendors/1234/users/' + btoa(fakeId))
|
||||
.respond(204, '');
|
||||
ctrl.addUserToVendor(fakeId);
|
||||
$httpBackend.flush();
|
||||
});
|
||||
});
|
||||
|
||||
describe('VendorsController', function() {
|
||||
var rootScope, scope, ctrl;
|
||||
var fakeResp = {'vendors': [{'can_manage': true,
|
||||
'type': 3,
|
||||
'name': 'Foo'},
|
||||
{'can_manage': true,
|
||||
'type': 3,
|
||||
'name': 'Bar'}]};
|
||||
beforeEach(inject(function ($controller, $rootScope) {
|
||||
scope = $rootScope.$new();
|
||||
rootScope = $rootScope.$new();
|
||||
rootScope.auth = {'currentUser' : {'is_admin': false,
|
||||
'openid': 'foo'}
|
||||
};
|
||||
ctrl = $controller('VendorsController',
|
||||
{$rootScope: rootScope, $scope: scope}
|
||||
);
|
||||
$httpBackend.when('GET', fakeApiUrl +
|
||||
'/vendors').respond(fakeResp);
|
||||
}));
|
||||
|
||||
it('should have a function to get a listing of all vendors',
|
||||
function () {
|
||||
$httpBackend.expectGET(fakeApiUrl + '/vendors')
|
||||
.respond(fakeResp);
|
||||
ctrl.update();
|
||||
$httpBackend.flush();
|
||||
expect(ctrl.rawData).toEqual(fakeResp);
|
||||
});
|
||||
|
||||
it('should have a function to update/sort data based on settings',
|
||||
function () {
|
||||
ctrl.rawData = fakeResp;
|
||||
ctrl.updateData();
|
||||
var expectedResponse = {'vendors': [{'can_manage': true,
|
||||
'type': 3,
|
||||
'name' : 'Bar'},
|
||||
{'can_manage': true,
|
||||
'type': 3,
|
||||
'name': 'Foo'}]};
|
||||
expect(ctrl.data).toEqual(expectedResponse);
|
||||
});
|
||||
|
||||
it('should have a function to determine if a vendor should be shown',
|
||||
function () {
|
||||
var fakeVendor = {'type': 0, 'can_manage': false};
|
||||
expect(ctrl._filterVendor(fakeVendor)).toEqual(true);
|
||||
ctrl.isUserVendors = true;
|
||||
expect(ctrl._filterVendor(fakeVendor)).toEqual(false);
|
||||
ctrl.isUserVendors = false;
|
||||
rootScope.auth.currentUser.is_admin = true;
|
||||
expect(ctrl._filterVendor(fakeVendor)).toEqual(true);
|
||||
});
|
||||
|
||||
it('should have a function to add a new vendor',
|
||||
function () {
|
||||
ctrl.name = 'New Vendor';
|
||||
ctrl.description = 'A description';
|
||||
$httpBackend.expectPOST(
|
||||
fakeApiUrl + '/vendors',
|
||||
{name: ctrl.name, description: ctrl.description})
|
||||
.respond(200, fakeResp);
|
||||
ctrl.addVendor();
|
||||
$httpBackend.flush();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user