Added autocomplete for order edit/create page.

This commit is contained in:
Alexey Zinchenko 2019-05-08 02:01:17 +03:00
parent 9fd15f37bd
commit 0c2f38ef7a
9 changed files with 109 additions and 11 deletions

View File

@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.github.prominence</groupId>
@ -75,6 +75,11 @@
<artifactId>jquery</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jQuery-Autocomplete</artifactId>
<version>1.4.9</version>
</dependency>
</dependencies>
<build>

View File

@ -0,0 +1,36 @@
package com.github.prominence.carrepair.controller.api;
import com.github.prominence.carrepair.model.Client;
import com.github.prominence.carrepair.model.Mechanic;
import com.github.prominence.carrepair.service.ClientService;
import com.github.prominence.carrepair.service.MechanicService;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/api/autocomplete")
public class AutocompleteApiController {
private ClientService clientService;
private MechanicService mechanicService;
public AutocompleteApiController(ClientService clientService, MechanicService mechanicService) {
this.clientService = clientService;
this.mechanicService = mechanicService;
}
@GetMapping(value = "/client", produces = MediaType.APPLICATION_JSON_VALUE)
public List<Client> clientAutocomplete(@RequestParam String query) {
return clientService.searchByInitials(query);
}
@GetMapping(value = "/mechanic", produces = MediaType.APPLICATION_JSON_VALUE)
public List<Mechanic> mechanicAutocomplete(@RequestParam String query) {
return mechanicService.searchByInitials(query);
}
}

View File

@ -3,6 +3,7 @@ package com.github.prominence.carrepair.repository;
import com.github.prominence.carrepair.model.Client;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@ -12,4 +13,7 @@ public interface ClientRepository extends JpaRepository<Client, Long> {
@Query(value = "select c.id from Client c")
public List<Long> findAllClientIds();
@Query(value = "select c from Client c where c.firstName like concat('%', :query, '%') or c.middleName like concat('%', :query, '%') or c.lastName like concat('%', :query, '%')")
public List<Client> findAllByInitials(@Param(value = "query") String query);
}

View File

@ -3,6 +3,7 @@ package com.github.prominence.carrepair.repository;
import com.github.prominence.carrepair.model.Mechanic;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@ -12,4 +13,7 @@ public interface MechanicRepository extends JpaRepository<Mechanic, Long> {
@Query(value = "select m.id from Mechanic m")
public List<Long> findAllMechanicIds();
@Query(value = "select m from Mechanic m where m.firstName like concat('%', :query, '%') or m.middleName like concat('%', :query, '%') or m.lastName like concat('%', :query, '%')")
public List<Mechanic> findAllByInitials(@Param(value = "query") String query);
}

View File

@ -46,4 +46,8 @@ public class ClientService {
public List<Long> getAllClientIds() {
return clientRepository.findAllClientIds();
}
public List<Client> searchByInitials(String query) {
return clientRepository.findAllByInitials(query);
}
}

View File

@ -66,4 +66,8 @@ public class MechanicService {
public List<Long> getAllMechanicIds() {
return mechanicRepository.findAllMechanicIds();
}
public List<Mechanic> searchByInitials(String query) {
return mechanicRepository.findAllByInitials(query);
}
}

View File

@ -12,3 +12,10 @@ body {
.btn-group {
display: flex;
}
.autocomplete-suggestions { border: 1px solid #999; background: #FFF; overflow: auto; }
.autocomplete-suggestion { padding: 2px 5px; white-space: nowrap; overflow: hidden; }
.autocomplete-selected { background: #F0F0F0; }
.autocomplete-suggestions strong { font-weight: normal; color: #3399FF; }
.autocomplete-group { padding: 2px 5px; }
.autocomplete-group strong { display: block; border-bottom: 1px solid #000; }

View File

@ -50,10 +50,13 @@
</div>
</footer>
<div>
<th:block>
<script src="/webjars/jquery/3.3.1/jquery.min.js"></script>
<script src="/webjars/bootstrap/3.4.0/js/bootstrap.min.js"></script>
</div>
<th:block layout:fragment="scripts">
</th:block>
</th:block>
</body>
</html>

View File

@ -17,20 +17,20 @@
</div>
</div>
<div class="form-group row">
<label for="orderClient" class="col-sm-2 col-form-label" th:text="#{client.label}"></label>
<label for="orderClient_tmp" class="col-sm-2 col-form-label" th:text="#{client.label}"></label>
<div class="col-sm-10">
<select name="client.id" class="form-control" id="orderClient" th:field="*{client.id}" th:errorclass="fieldError" th:value="${order.client != null ? order.client.id : null}">
<option th:each="clientId : ${clientIdsList}" th:value="${clientId}" th:text="${clientId}"></option>
</select>
<input type="text" name="client.id_tmp" class="form-control" id="orderClient_tmp"
th:value="${order.client != null ? order.client.firstName + ' ' + order.client.lastName : null}">
<input type="hidden" name="client.id" id="orderClient" th:value="${order.client != null ? order.client.id : null}">
<div th:replace="common::errors('client')"></div>
</div>
</div>
<div class="form-group row">
<label for="orderMechanic" class="col-sm-2 col-form-label" th:text="#{mechanic.label}"></label>
<div class="col-sm-10">
<select name="mechanic.id" class="form-control" id="orderMechanic" th:field="*{mechanic.id}" th:errorclass="fieldError" th:value="${order.mechanic != null ? order.mechanic.id : null}">
<option th:each="mechanicId : ${mechanicIdsList}" th:value="${mechanicId}" th:text="${mechanicId}"></option>
</select>
<input type="text" name="mechanic.id_tmp" class="form-control" id="orderMechanic_tmp"
th:value="${order.mechanic != null ? order.mechanic.firstName + ' ' + order.mechanic.lastName : null}">
<input type="hidden" name="mechanic.id" id="orderMechanic" th:value="${order.mechanic != null ? order.mechanic.id : null}">
<div th:replace="common::errors('mechanic')"></div>
</div>
</div>
@ -71,7 +71,38 @@
</div>
</div>
</form>
</div>
<th:block layout:fragment="scripts">
<script src="/webjars/jQuery-Autocomplete/1.4.9/jquery.autocomplete.min.js"></script>
<script type="text/javascript">
function initializeAutocomplete(entity, inputId) {
$('#' + inputId + '_tmp').autocomplete({
serviceUrl: '/api/autocomplete/' + entity,
paramName: "query",
minChars: 3,
transformResult: function(response) {
return {
suggestions: $.map($.parseJSON(response), function(item) {
return { value: item.firstName + ' ' + item.lastName, data: item.id};
})
};
},
onSelect: function (suggestion) {
$('#' + inputId).val(suggestion.data);
},
onInvalidateSelection: function () {
$('#' + inputId).val('');
},
showNoSuggestionNotice: true
});
}
initializeAutocomplete('client', 'orderClient');
initializeAutocomplete('mechanic', 'orderMechanic');
</script>
</th:block>
</body>
</html>