Skip to content

Commit

Permalink
seminar-javascript step 2
Browse files Browse the repository at this point in the history
  • Loading branch information
martin-kuba committed Nov 15, 2017
1 parent f36df2a commit 070e9aa
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* This package contains exceptions which are converted to specific HTTP status codes by the REST controllers.
*
* @author Martin Kuba [email protected]
*/
package cz.muni.fi.pa165.restapi.exceptions;
139 changes: 138 additions & 1 deletion eshop-angular/src/main/webapp/angular_app.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,35 @@ pa165eshopApp.config(['$routeProvider',
$routeProvider.
when('/shopping', {templateUrl: 'partials/shopping.html', controller: 'ShoppingCtrl'}).
when('/product/:productId', {templateUrl: 'partials/product_detail.html', controller: 'ProductDetailCtrl'}).
when('/category/:categoryId', {templateUrl: 'partials/category_detail.html', controller: 'CategoryDetailCtrl'}).
when('/admin/products', {templateUrl: 'partials/admin_products.html', controller: 'AdminProductsCtrl'}).
when('/admin/newproduct', {templateUrl: 'partials/admin_new_product.html', controller: 'AdminNewProductCtrl'}).
otherwise({redirectTo: '/shopping'});
}]);

/*
* alert closing functions defined in root scope to be available in every template
*/
pa165eshopApp.run(function($rootScope) {
$rootScope.hideSuccessAlert = function () {
$rootScope.successAlert = undefined;
};
$rootScope.hideWarningAlert = function () {
$rootScope.warningAlert = undefined;
};
$rootScope.hideErrorAlert = function () {
$rootScope.errorAlert = undefined;
};
});





/* Controllers */



/*
* Public eshop interface
*/
Expand Down Expand Up @@ -43,6 +69,7 @@ eshopControllers.controller('ShoppingCtrl', function ($scope, $http) {
});
});


/*
* Product detail page
*/
Expand All @@ -54,4 +81,114 @@ eshopControllers.controller('ProductDetailCtrl',
$scope.product = response.data;
console.log('AJAX loaded detail of product ' + $scope.product.name);
});
});
});

/*
* Category detail page
*/

eshopControllers.controller('CategoryDetailCtrl', ['$scope', '$routeParams', '$http',
function ($scope, $routeParams, $http) {
var categoryId = $routeParams.categoryId;
$http.get('/eshop/api/v1/categories/' + categoryId).then(function (response) {
var category = response.data;
$scope.category = category;
console.log('AJAX loaded detail of category ' + category.name);
loadCategoryProducts($http, category, category['_links'].products.href);
});
}]);

/*
* Administration interface
*/

/*
* Admin Products page
*/
function loadAdminProducts($http, $scope) {
$http.get('/eshop/api/v1/products').then(function (response) {
$scope.products = response.data._embedded.products;
console.log('AJAX loaded all products ');
});
}
eshopControllers.controller('AdminProductsCtrl',
function ($scope, $rootScope, $routeParams, $http) {
//initial load of all products
loadAdminProducts($http, $scope);
// function called when Delete button is clicked
$scope.deleteProduct = function (product) {
console.log("deleting product with id=" + product.id + ' (' + product.name + ')');
$http.delete(product._links.delete.href).then(
function success(response) {
console.log('deleted product ' + product.id + ' on server');
//display confirmation alert
$rootScope.successAlert='Deleted product "'+product.name+'"';
//load new list of all products
loadAdminProducts($http, $scope);
},
function error(response) {
console.log('server returned error');
$rootScope.errorAlert = 'Cannot delete product "'+product.name+'"! It is used in an order.';
}
);
};
});


/*
* Page with form for creating new product
*/
eshopControllers.controller('AdminNewProductCtrl',
function ($scope, $routeParams, $http, $location, $rootScope) {
//prepare data for selection lists
$scope.colors = ['RED', 'GREEN', 'BLUE', 'BLACK'];
$scope.currencies = ['CZK', 'EUR', 'USD'];
//get categories from server
$http.get('/eshop/api/v1/categories/').then(function (response) {
$scope.categories = response.data['_embedded']['categories'];
});
//set object bound to form fields
$scope.product = {
'name': '',
'description': '',
'categoryId': 1,
'price': 0,
'color': $scope.colors[1],
'currency': $scope.currencies[0]
};
// function called when submit button is clicked, creates product on server
$scope.create = function (product) {
$http({
method: 'POST',
url: '/eshop/api/v1/products/create',
data: product
}).then(function success(response) {
console.log('created product');
var createdProduct= response.data;
//display confirmation alert
$rootScope.successAlert = 'A new product "'+createdProduct.name+'" was created';
//change view to list of products
$location.path("/admin/products");
}, function error(response) {
//display error
$scope.errorAlert = 'Cannot create product !';
});
};
});

// defines new directive (HTML attribute "convert-to-int") for conversion between string and int
// of the value of a selection list in a form
// without this, the value of the selected option is always a string, not an integer
eshopControllers.directive('convertToInt', function () {
return {
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
ngModel.$parsers.push(function (val) {
return parseInt(val, 10);
});
ngModel.$formatters.push(function (val) {
return '' + val;
});
}
};
});
25 changes: 24 additions & 1 deletion eshop-angular/src/main/webapp/index.jsp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li><a href="#!/shopping">Go shopping</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Admin<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="#!/admin/products">Products</a></li>
<li><a href="#!/admin/categories">Categories</a></li>
</ul>
</li>
</ul>
</div><!--/.nav-collapse -->
</div>
Expand All @@ -39,7 +46,23 @@
<div class="container">

<div ng-app="pa165eshopApp"><!-- AngularJS takes care of this element -->
<div ng-view></div><!-- the place where HTML templates are replaced by AngularJS routing -->

<!-- Bootstrap-styled alerts, visible when $rootScope.xxxAlert is defined -->
<div ng-show="warningAlert" class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" aria-label="Close" ng-click="hideWarningAlert()"> <span aria-hidden="true">&times;</span></button>
<strong>Warning!</strong> <span>{{warningAlert}}</span>
</div>
<div ng-show="errorAlert" class="alert alert-danger alert-dismissible" role="alert">
<button type="button" class="close" aria-label="Close" ng-click="hideErrorAlert()"> <span aria-hidden="true">&times;</span></button>
<strong>Error!</strong> <span>{{errorAlert}}</span>
</div>
<div ng-show="successAlert" class="alert alert-success alert-dismissible" role="alert">
<button type="button" class="close" aria-label="Close" ng-click="hideSuccessAlert()"> <span aria-hidden="true">&times;</span></button>
<strong>Success !</strong> <span>{{successAlert}}</span>
</div>

<!-- the place where HTML templates are replaced by AngularJS routing -->
<div ng-view></div>
</div>

<footer class="footer">
Expand Down
40 changes: 37 additions & 3 deletions eshop-angular/src/main/webapp/jquery_example.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,35 @@
<meta charset="UTF-8">
<title>Product AJAX</title>
<!-- import jQuery from content delivery network -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
function loadProducts() {
$.ajax({
type: 'GET',
url: '/eshop/api/v1/products',
success: function (data) {
var products = data._embedded.products;
var productsTable = $('#products_list');
productsTable.empty(); //remove all existing rows
for(var i=0;i<products.length;i++) {
var p = products[i];
$('#products_list').append('<tr><td>'+p.id+'</td><td>'+p.name+'</td><td>'+p.price+' '+p.currency+'</td></tr>');
productsTable.append('<tr><td>'+p.id+'</td><td>'+p.name+'</td><td>'+p.price+' '+p.currency+'</td></tr>');
}
}
});
}

function loadCategories() {
$.ajax({
type: 'GET',
url: '/eshop/api/v1/categories',
success: function (data) {
var categories = data._embedded.categories;
var categoriesTable = $('#categories_list');
categoriesTable.empty();
for(var i=0;i<categories.length;i++) {
var p = categories[i];
categoriesTable.append('<tr><td>'+p.id+'</td><td>'+p.name+'</td></tr>');
}
}
});
Expand Down Expand Up @@ -43,5 +61,21 @@ <h1>JQuery AJAX Example</h1>
<tbody id="products_list"></tbody>
</table>

<hr>

<button onclick="loadCategories()">Load all categories to table</button>

<table class="basic">
<caption>Categories</caption>
<thead>
<tr>
<th>id</th>
<th>name</th>
</tr>
</thead>
<tbody id="categories_list"></tbody>
</table>


</body>
</html>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,4 @@

<!-- show disabled button if form is not valid -->
<button ng-disabled="!form.$valid" class="btn btn-primary" type="submit" ng-click="create(product)">Create product</button>
</form>
</form>
18 changes: 18 additions & 0 deletions eshop-angular/src/main/webapp/partials/category_detail.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<div>
<h1>{{category.name}}</h1>

<div class="row">
<div class="col-xs-12 col-sm-4 col-md-3 col-lg-2" ng-repeat="product in category.products">
<a href="#!/product/{{product.id}}">
<div class="thumbnail">
<img ng-src="{{product._links.image.href}}"><br>

<div class="caption">
<h3>{{product.name}}</h3>
<span style="color: red; font-weight: bold;">{{product.price}}&nbsp;{{product.currency}}</span>
</div>
</div>
</a>
</div>
</div>
</div>

0 comments on commit 070e9aa

Please sign in to comment.