piątek, 9 grudnia 2016

How to add user to new record in JHipster


When you have user relation to entity and need to add user to newly created record, follow this way.

Entity is i.e. Order.
In OrderResource.java add:


    @Inject
    private UserRepository UserRepository;



Somewhere at the end add:


 public String getCurrentUserLogin() {
        org.springframework.security.core.context.SecurityContext securityContext = SecurityContextHolder.getContext();
        Authentication authentication = securityContext.getAuthentication();
        String login = null;
        if (authentication != null)
            if (authentication.getPrincipal() instanceof UserDetails)
             login = ((UserDetails) authentication.getPrincipal()).getUsername();
            else if (authentication.getPrincipal() instanceof String)
             login = (String) authentication.getPrincipal();
        
        return login; 
        }





In the POST section, before *OrderRepository.save* add:



     User user=new User();
     user=UserRepository.findOneByLogin(getCurrentUserLogin()).get();
     Order.setUser(user);

wtorek, 6 grudnia 2016

How to create new custom view of entity in JHipster

I have normal entity productOnStock.
I need to have custom view for this entity for normal user.

To do this follow these steps.

  1. Create folder /src/main/webapp/app/manager/stock/
  2. Copy from /src/main/webapp/app/entities/product-on-stock/ files:
    1. product-on-stocks.html
    2. product-on-stock.state.js
    3. product-on-stock.service.js
    4. product-on-stock.search.service.js
    5. product-on-stock.controller.js
3. Paste them into  /src/main/webapp/app/manager/stock/
4. Change their names from product-on-stocks.* to stock.*
5. In stock.service.js:
  • change: .factory('ProductOnStock', ProductOnStock);
  • to: .factory(‘Stock', Stock);
  • -------------------------------
  • ProductOnStock.$inject = ['$resource', 'DateUtils'];
  • to: Stock.$inject = ['$resource', 'DateUtils'];
  • --------------------------------
  • function ProductOnStock ($resource, DateUtils) {
  •        var resourceUrl =  'api/product-on-stocks/:id';
  • to:
  • function Stock ($resource, DateUtils) {
  •        var resourceUrl =  'api/stock/:id';
6. In stock.state.js:
Change:


        .state('product-on-stock', {
            parent: 'entity',
            url: '/product-on-stock',
            data: {
                authorities: ['ROLE_USER'],
                pageTitle: 'barfitterApp.productOnStock.home.title'
            },
            views: {
                'content@': {
                    templateUrl: 'app/entities/product-on-stock/product-on-stocks.html',
                    controller: 'ProductOnStockController',
                    controllerAs: 'vm'
                }
            },
            resolve: {
                translatePartialLoader: ['$translate', '$translatePartialLoader', function ($translate, $translatePartialLoader) {
                    $translatePartialLoader.addPart('productOnStock');
                    $translatePartialLoader.addPart('global');
                    return $translate.refresh();
                }]
            }
        })


to:


        .state('stock', {
            parent: 'manager',
            url: '/stock',
            data: {
                authorities: ['ROLE_MANAGER'],
                pageTitle: 'barfitterApp.productOnStock.home.title'
            },
            views: {
                'content@': {
                    templateUrl: 'app/manager/stock/stock.html',
                    controller: 'StockController',
                    controllerAs: 'vm'
                }
            },
            resolve: {
                translatePartialLoader: ['$translate', '$translatePartialLoader', function ($translate, $translatePartialLoader) {
                    $translatePartialLoader.addPart('productOnStock');
                    $translatePartialLoader.addPart('global');
                    return $translate.refresh();
                }]
            }
        })


Comment other states for now.



7. In stock.controller.js

change:


        .controller('ProductOnStockController', ProductOnStockController);


    ProductOnStockController.$inject = ['$scope', '$state', 'ProductOnStock', 'ProductOnStockSearch'];


    function ProductOnStockController ($scope, $state, ProductOnStock, ProductOnStockSearch) {

to:

        .controller('StockController', StockController);


    StockController.$inject = ['$scope', '$state', 'ProductOnStock', 'ProductOnStockSearch', 'Stock'];


    function StockController ($scope, $state, ProductOnStock, ProductOnStockSearch, Stock) {

----------------

change:

        function loadAll() {
            ProductOnStock.query(function(result) {

to:

        function loadAll() {
            Stock.query(function(result) {



8. In stock.search.service.js change:



        .factory('ProductOnStockSearch', ProductOnStockSearch);

    ProductOnStockSearch.$inject = ['$resource'];

    function ProductOnStockSearch($resource) {
        var resourceUrl =  'api/_search/product-on-stocks/:id';

to:


        .factory('StockSearch', StockSearch);

    StockSearch.$inject = ['$resource'];

    function StockSearch($resource) {
        var resourceUrl =  'api/_search/stock/:id';







wtorek, 29 listopada 2016

How to create new ROLE in JHipster


Let’s assume you want to add new role ROLE_MANAGER.

1. In /src/main/resources/config/liquibase/authorities.csv
add ROLE_MANAGER in new line.


In AuthoritiesConstants.java add:

public static final String MANAGER = "ROLE_MANAGER";



2. In /src/main/webapp/app/admin/user-management/user-management.controller.js and user-management-dialog.controller.js
add new role:
vm.authorities = ['ROLE_USER', 'ROLE_ADMIN', 'ROLE_MANAGER'];

3. In
/src/main/webapp/app/account/password/password.state.js
/src/main/webapp/app/account/sessions/sessions.state.js
/src/main/webapp/app/account/settings/settings.state.js

add
authorities: ['ROLE_USER', 'ROLE_MANAGER'],

4. In table jhi_authority
add ROLE_MANAGER


5. In console run:
./mvnw liquibase:clearCheckSums

poniedziałek, 14 listopada 2016

How to delete multiple records in Spring Boot and Jhipster

I have authorization.html with records listing as it’s generated in JHipster.
Each record has it’s own delete button, but if I need to delete many of them, it’s more convenient to have checkboxes assigned to each record and one button to delete selected records.
My entity is productDelivered not authorization.

In html file, I added checkboxes:


<th><input type="checkbox" ng-click="vm.allNeedsClicked()" ng-checked="vm.allNeedsMet()"></th>
...
<tbody>
    <tr
     ng-repeat="productDelivered in vm.authorizations track by productDelivered.id">
     <td><input type='checkbox'  ng-model="productDelivered.checked"></td>
     <td><a
      ui-sref="product-delivered-detail({id:productDelivered.id})">{{productDelivered.id}}</a></td>

[ng-click="vm.allNeedsClicked()" ng-checked="vm.allNeedsMet()" are functions for selecting all checkboxes]

and below </table> added:


<br>
 <button ng-click="vm.deleteSelectedItems()"
  class="pull-left btn btn-danger" type="button" title="Delete">
  Delete selected <span class="glyphicon glyphicon-trash"></span>
 </button>


In authorization.controller.js added:

       function deleteSelectedItems() { // pressed button in the bottom
         Authorization.update({id: 7});
         var deletedIndex=[];
   angular.forEach(vm.authorizations, function(productDelivered) {
    if (productDelivered.checked) {
     deletedIndex.push(vm.authorizations.indexOf(productDelivered));          
     ProductDelivered.delete({id: productDelivered.id});
    }
   });
   // splice usuwa element tablicy przez co zmienia indeksację powodując że usuwany jest tylko co drugi element, dlatego przed tym tablica jest odwracana
   deletedIndex.reverse(); 
   deletedIndex.forEach(function(elt) {
    vm.authorizations.splice(elt, 1);
   })
  }


  
  function allNeedsClicked() {
      var newValue = !vm.allNeedsMet();
        angular.forEach(vm.authorizations, function (productDelivered) {
        productDelivered.checked = newValue;
      });
    };
    
    // Returns true if and only if all todos are done.
    function allNeedsMet() {
      var needsMet = vm.authorizations.reduce(function (memo, productDelivered) {
        return memo + (productDelivered.checked ? 1 : 0);
      }, 0);
      return (needsMet === vm.authorizations.length);
    };

On the top we need also:

        vm.deleteSelectedItems=deleteSelectedItems;
        
        vm.allNeedsClicked=allNeedsClicked;
        vm.allNeedsMet=allNeedsMet;



Warning! It deletes records without any confirmation!



How to list two [or more] entities in one view in Jhipster

I created new menu entry like this:

On new page - authorization.html I want to list two entities generated by JHipster:
  • productDelivered
  • category

I created /src/main/webapp/app/authorization/ folder. I copied there files from /src/main/webapp/app/entities/product-delivered/:
  • product-delivereds.html
  • product-delivered.state.js
  • product-delivered.service.js
  • product-delivered.controller.js

and changed their names from product-delivered to authorization and some instances of product-delivered inside of these files as well.

In authorization.controller.js added Category:

(function() {
    'use strict';

    angular
        .module('barfitterApp')
        .controller('AuthorizationController', AuthorizationController);

    AuthorizationController.$inject = ['$scope', '$state', 'Authorization', 'ProductDelivered', 'Category', 'ProductDeliveredSearch', 'ParseLinks', 'AlertService', 'pagingParams', 'paginationConstants'];

    function AuthorizationController ($scope, $state, Authorization, ProductDelivered, Category, ProductDeliveredSearch, ParseLinks, AlertService, pagingParams, paginationConstants) {

and:


vm.categories = [];
...

            Category.query(function(result) {
                vm.categories = result;
            });



and in authorization.html added at the bottom content from category.html




wtorek, 25 października 2016

Handling with LocalDate issues in Spring Boot.




If you have LocalDate field in your entities you can get errors like:


Servlet.service() for servlet [dispatcherServlet] in context with path [] 
threw exception [Request processing failed; nested exception is 
org.springframework.orm.jpa.JpaSystemException: could not deserialize; 
nested exception is org.hibernate.type.SerializationException: 
could not deserialize] with root cause

or:


Failed to read HTTP message: 
org.springframework.http.converter.HttpMessageNotReadableException: 
Could not read document: Can not construct instance of java.time.LocalDate: 
no suitable constructor found, can not deserialize from Object value 
(missing default constructor or creator, or perhaps need to add/enable type 
information?)


nested exception is com.fasterxml.jackson.databind.JsonMappingException: 
Can not construct instance of java.time.LocalDate: 
no suitable constructor found, can not deserialize from Object value 
(missing default constructor or creator, or perhaps need to add/enable 
type information?)



To solve that, insert in pom.xml:


                <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-java8</artifactId>
  </dependency>
  <dependency>
   <groupId>com.fasterxml.jackson.datatype</groupId>
   <artifactId>jackson-datatype-jsr310</artifactId>
   </dependency>


sobota, 22 października 2016

How to create simple REST app using Spring Boot, AngularJS and MariaDB in Eclipse. Part 3

How to delete all selected entities


In previous part we could delete each entity one by one. But sometimes it’s more convenient to select some or all entities and delete them at once.


In this case I added ‘Select All’ button above checkboxes and ‘Delete selected‘ button on the bottom.




To get it to work I needed to change index.html to:


<table class="jh-table table table-striped">
     <thead>
      <tr>
       <th><input type="checkbox" ng-model="isAllSelected"
        ng-click="selectAll()"></th>
       <th>ID</th>
       <th>Description</th>
       <th>Rate</th>
       <th>Active</th>
       <th></th>
      </tr>
     </thead>
     <tbody>
      <tr ng-repeat="vat in vats track by vat.id">
       <td><input type="checkbox" ng-model="vat.checked"
        ng-change="optionSelected()" /></td>
       <td>{{vat.id}}</td>
       <td>{{vat.description}}</td>
       <td>{{vat.rate}}</td>
       <td>{{vat.active}}</td>
       <td class="text-right">
        <div class="btn-group flex-btn-group-container">
         <button class="pull-right btn btn-danger" type="button"
          title="Delete" ng-click="deleteVat(vat)">
          <span class="glyphicon glyphicon-trash"></span>
         </button>
        </div>
       </td>
      </tr>
     </tbody>
    </table>



And add controllers in vat_controller.js:


 $scope.selectAll = function() {
  var toggleStatus = $scope.isAllSelected;
  angular.forEach($scope.vats, function(itm) {
   itm.checked = toggleStatus;
  });

 }

 $scope.optionSelected = function() {
  $scope.isAllSelected = $scope.vats
    .every(function(itm) {
     return itm.checked;
    })
 }
    


Delete buttons work on the left and at the bottom:


$scope.deleteVat = function(vat) {
  if (vat) { // pressed button on the right
   vat.$remove(function() {
    $scope.vats.splice($scope.vats
      .indexOf(vat), 1);
   });
  } else { // pressed button in the bottom
   angular.forEach($scope.vats, function(vat) {
    if (vat.checked) {
     vat.$remove(function() {
      $scope.vats.splice($scope.vats
        .indexOf(vat), 1);
     });
    }
   });
  }
 };

How to create simple REST app using Spring Boot, AngularJS and MariaDB in Eclipse. Part 2

In part 1 we created some basis structure for our app.
Here I’ll show how to display two lists of entities on one page in web browser.


We will need 6 files at the beginning. This allows only to add and remove entities.


/src/main/resources/static/index.html
/src/main/resources/static/webapp/app.js
/src/main/resources/static/webapp/entities/category/category_controller.js
/src/main/resources/static/webapp/entities/category/category_service.js
/src/main/resources/static/webapp/entities/vat/vat_controller.js
/src/main/resources/static/webapp/entities/vat/vat_service.js




/src/main/resources/static/index.html:


<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet"
 href="./bower_components/bootstrap-css-only/css/bootstrap.min.css" />
</head>
<body ng-app="myApp">
 <div class="container" ng-controller="AppVatController">
  <div class="page-header">
   <h1>Vat</h1>
  </div>
  <div class="alert alert-info" role="alert"
   ng-hide="vats && vats.length > 0">There are no vats yet.</div>

  <form class="form-horizontal" role="form"
   ng-submit="addVat(newVatDescription, newVatRate, newVatActive)">
   <div class="table-responsive">
    <table class="jh-table table table-striped">
     <thead>
      <tr>
       <th></th>
       <th>ID</th>
       <th>Description</th>
       <th>Rate</th>
       <th>Active</th>
       <th></th>
      </tr>
     </thead>
     <tbody>
      <tr ng-repeat="vat in vats track by vat.id">
       <td><input type="checkbox" ng-model="vat.checked"
        ng-change="updateVat(vat)" /></td>
       <td>{{vat.id}}</td>
       <td>{{vat.description}}</td>
       <td>{{vat.rate}}</td>
       <td>{{vat.active}}</td>
       <td class="text-right">
        <div class="btn-group flex-btn-group-container">
         <button class="pull-right btn btn-danger" type="button"
          title="Delete" ng-click="deleteVat(vat)">
          <span class="glyphicon glyphicon-trash"></span>
         </button>
        </div>
       </td>
      </tr>
     </tbody>
    </table>
   </div>
   <hr />
   <div class="input-group">
    <input type="text" class="form-control" ng-model="newVatDescription"
     placeholder="Enter vat description..." /> <input type="text"
     class="form-control" ng-model="newVatRate"
     placeholder="Enter vat rate [i.e 0.23]..." /> <input type="text"
     class="form-control" ng-model="newVatActive"
     placeholder="Is it active? [true or false]..." /> <span
     class="input-group-btn">
     <button class="btn btn-default" type="submit"
      ng-disabled="!newVatDescription" title="Add">
      <span class="glyphicon glyphicon-plus"></span>
     </button>
    </span>
   </div>
  </form>




  <hr />

  <div class="container" ng-controller="AppCategoryController">
   <div class="page-header">
    <h1>Categories</h1>
   </div>
   <form class="form-horizontal" role="form"
    ng-submit="addCategory(newCategoryName, newCategoryParentId)">
    <div class="alert alert-info" role="alert"
     ng-hide="categories && categories.length > 0">There are no
     categories yet.</div>
    <div class="table-responsive">
     <table class="jh-table table table-striped">
      <thead>
       <tr>
        <th></th>
        <th>ID</th>
        <th>Name</th>
        <th>Parent Id</th>
       </tr>
      </thead>
      <tbody>
       <tr ng-repeat="category in categories">
        <td><input type="checkbox" ng-model="category.checked"
         ng-change="updateCategory(category)" /></td>
        <td>{{category.id}}</td>
        <td>{{category.name}}</td>
        <td>{{category.parentId}}
         <button class="pull-right btn btn-danger" type="button"
          title="Delete" ng-click="deleteCategory(category)">
          <span class="glyphicon glyphicon-trash"></span>
         </button>
        </td>
       </tr>
      </tbody>
     </table>
    </div>

    <hr />
    <div class="input-group">
     <input type="text" class="form-control" ng-model="newCategoryName"
      placeholder="Enter category name..." /> <input type="text"
      class="form-control" ng-model="newCategoryParentId"
      placeholder="Enter category parentId..." /> <span
      class="input-group-btn">
      <button class="btn btn-default" type="submit"
       ng-disabled="!newCategoryName" title="Add">
       <span class="glyphicon glyphicon-plus"></span>
      </button>
     </span>
    </div>
   </form>
  </div>



  <script type="text/javascript"
   src="./bower_components/angular/angular.min.js"></script>
  <script type="text/javascript"
   src="./bower_components/angular-resource/angular-resource.min.js"></script>
  <script type="text/javascript"
   src="./bower_components/lodash/dist/lodash.min.js"></script>
  <script type="text/javascript" src="./webapp/app.js"></script>
  <script type="text/javascript"
   src="./webapp/entities/vat/vat_controller.js"></script>
  <script type="text/javascript"
   src="./webapp/entities/vat/vat_service.js"></script>
  <script type="text/javascript"
   src="./webapp/entities/category/category_controller.js"></script>
  <script type="text/javascript"
   src="./webapp/entities/category/category_service.js"></script>
</body>
</html>


/src/main/resources/static/webapp/app.js:


(function(angular) {
   angular.module("myApp.vat_controller", []);
   angular.module("myApp.vat_service", []);
   angular.module("myApp.category_controller", []);
   angular.module("myApp.category_service", []);
  angular.module("myApp", ["ngResource", "myApp.vat_controller", "myApp.vat_service", 
   "myApp.category_controller", "myApp.category_service"]);
}(angular));




/src/main/resources/static/webapp/entities/category/category_controller.js


(function(angular) {
  var AppCategoryController = function($scope, Category) {
   Category.query(function(response) {
      $scope.categories = response ? response : [];
    });
    
    $scope.addCategory = function(name, parentId) {
      new Category({
          name: name,
          parentId: parentId,
          checked: false
      }).$save(function(category) {
        $scope.categories.push(category);
      });
      $scope.newCategoryParentId = "";
      $scope.newCategoryName = "";
    };
    
//    $scope.updateCategory = function(category) {
//     category.$update();
//    };
//    
    $scope.deleteCategory = function(category) {
     category.$remove(function() {
        $scope.categories.splice($scope.categories.indexOf(category), 1);
      });
    };
  };
  
  AppCategoryController.$inject = ['$scope', 'Category'];
  angular.module("myApp.category_controller").controller("AppCategoryController", AppCategoryController);
}(angular));





/src/main/resources/static/webapp/entities/category/category_service.js:



(function(angular) {
  var CategoryFactory = function($resource) {
    return $resource('/category/:id', {
      id: '@id'
    }, {
      update: {
        method: "PUT"
      },
      remove: {
        method: "DELETE"
      }
    });
  };
  
  CategoryFactory.$inject = ['$resource'];
  angular.module("myApp.category_service").factory("Category", CategoryFactory);
}(angular));





/src/main/resources/static/webapp/entities/vat/vat_controller.js:


(function(angular) {
  var AppVatController = function($scope, Vat) {
    Vat.query(function(response) {
      $scope.vats = response ? response : [];
    });
    
    $scope.addVat = function(description, rate, active) {
      new Vat({
        description: description,
        rate: rate,
        active: active,
        checked: false
      }).$save(function(vat) {
        $scope.vats.push(vat);
      });
      $scope.newVatDescription = "";
      $scope.newVatRate = "";
      $scope.newVatActive = "";
    };
//    
//    $scope.updateVat = function(vat) {
//      vat.$update();
//    };
//    
    $scope.deleteVat = function(vat) {
      vat.$remove(function() {
        $scope.vats.splice($scope.vats.indexOf(vat), 1);
      });
    };
  };
  
  AppVatController.$inject = ['$scope', 'Vat'];
  angular.module("myApp.vat_controller").controller("AppVatController", AppVatController);
}(angular));





/src/main/resources/static/webapp/entities/vat/vat_service.js:


(function(angular) {
  var VatFactory = function($resource) {
    return $resource('/vats/:id', {
      id: '@id'
    }, {
      update: {
        method: "PUT"
      },
      remove: {
        method: "DELETE"
      }
    });
  };
  
  VatFactory.$inject = ['$resource'];
  angular.module("myApp.vat_service").factory("Vat", VatFactory);
}(angular));


Now it should look like this: