Skip to content

Add ui #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
Expand All @@ -31,7 +35,7 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<version>1.18.28</version>
<scope>provided</scope>
</dependency>
</dependencies>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.thelivelock.elasticsearch_autocomplete.controller;

import com.thelivelock.elasticsearch_autocomplete.model.User;
import com.thelivelock.elasticsearch_autocomplete.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.List;
import java.util.stream.Stream;

@Controller
public class UIController {
private UserService userService;

@Autowired
public UIController(UserService userService) {
this.userService = userService;
}

//when reload localhost:8080/search
@GetMapping("/search")
public String home(Model model) {
List<User> users = this.userService.search("");
List<String> names = users.stream().flatMap(user -> Stream.of(user.getCountry())).toList();
model.addAttribute("names", names);
return "search";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;
import java.util.stream.Stream;

@RestController
@RequestMapping("/users")
public class UserController {

@Autowired
private UserService userService;

Expand All @@ -22,9 +23,17 @@ public List<User> getAllUsers() {
return this.userService.listAll();
}

@GetMapping(path = "/search")
@GetMapping(path = "/query")
@ResponseBody
public List<User> searchUsers(@RequestParam String keywords) {
return this.userService.search(keywords);
}

@GetMapping("/suggestion")
@ResponseBody
public List<String> fetchSuggestions(@RequestParam(value = "q", required = false) String query) {
List<User> users = this.userService.search(query);
List<String> names = users.stream().flatMap(user-> Stream.of(user.getCountry())).toList();
return names;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.thelivelock.elasticsearch_autocomplete.model;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Document(indexName = "productindex")
public class Product {
@Id
private String id;

@Field(type = FieldType.Text, name = "name")
private String name;

@Field(type = FieldType.Double, name = "price")
private Double price;

@Field(type = FieldType.Integer, name = "quantity")
private Integer quantity;

@Field(type = FieldType.Keyword, name = "category")
private String category;

@Field(type = FieldType.Text, name = "desc")
private String description;

@Field(type = FieldType.Keyword, name = "manufacturer")
private String manufacturer;
}
3 changes: 1 addition & 2 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
# Elasticsearch config
spring.data.elasticsearch.cluster-nodes=localhost:9300
spring.data.elasticsearch.cluster-name=elasticsearch
spring.elasticsearch.rest.uris=http://localhost:9200
79 changes: 79 additions & 0 deletions src/main/resources/templates/search.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-4.dtd">
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
<title>User Search</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
</head>
<body>

<div class="card mb-3" style="max-width: 540px;">
<p class="text-info">Search Users By Their Country</p>
<span class="border border-info">
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Search Users By Their Country" aria-label="Country Name" aria-describedby="btnNameSearch" id="countryName-id">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" id="btnNameSearch">Search</button>
</div>
</div>
</span>
</div>

<div id="results" class="card"></div>


<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
<script th:inline="javascript">
$(document).ready(function() {
$('#countryName-id').autocomplete({
source: function (request, response){
$.get("http://localhost:8080/users/suggestion?",{q : request.term},function(data, status){
$("#results").html("");
if(status=='success'){
response(data);
}
});
}
}
);

$("#btnNameSearch").click(function(){
var inputText = $("#countryName-id").val();
if(inputText.length == 0) {
alert("Enter country name");
}else{
var response = '';
$.ajax({
type: "GET",
url: "http://localhost:8080/users/query?keywords="+inputText,
async: true,
success: function(resp) {
var len = resp.length;
var strHtml = "";
if(len == 0) {
$("#results").html("<p class='text-danger'>Zero matches</p>");
}else{
strHTML = "<p class='text-success'>"+len + " matches found.</p>";
strHTML += "<ul class='list-unstyled'>";
for(var i=0; i<len; i++){
strHTML += "<li>" + resp[i].firstName + " " + resp[i].lastName + " from " + resp[i].country+"</li>";
}
strHTML = strHTML + "</ul>";
$("#results").html(strHTML)
}
}
});
}
});
});
</script>

</body>
</html>