From f7a1f86d286dde810abcbbbe91cd74415e11cef3 Mon Sep 17 00:00:00 2001 From: PARKJONGGYEONG Date: Thu, 9 May 2024 20:42:13 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=ED=8E=98=EC=9D=B4=EC=A7=95=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EC=9E=90=EB=8F=99=EC=99=84?= =?UTF-8?q?=EC=84=B1=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../elastic/client/ElasticClient.java | 13 ++- .../controller/AutocompleteController.java | 23 +++++ .../static/assets/main/css/elastic.css | 29 +++++++ .../static/assets/main/js/elastic.js | 85 +++++++++++++++++++ .../templates/main/fragment/searchbar.html | 48 ++--------- .../templates/main/page/elasticSearch.html | 2 +- 6 files changed, 152 insertions(+), 48 deletions(-) create mode 100644 src/main/java/com/t3t/frontserver/elastic/controller/AutocompleteController.java create mode 100644 src/main/resources/static/assets/main/css/elastic.css create mode 100644 src/main/resources/static/assets/main/js/elastic.js diff --git a/src/main/java/com/t3t/frontserver/elastic/client/ElasticClient.java b/src/main/java/com/t3t/frontserver/elastic/client/ElasticClient.java index 9f4eb02..80f9812 100644 --- a/src/main/java/com/t3t/frontserver/elastic/client/ElasticClient.java +++ b/src/main/java/com/t3t/frontserver/elastic/client/ElasticClient.java @@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.RequestParam; import java.math.BigDecimal; +import java.util.List; @FeignClient(name = "ElasticAdaptor", url = "${t3t.feignClient.url}") public interface ElasticClient { @@ -43,8 +44,12 @@ public interface ElasticClient { @GetMapping("/t3t/bookstore/category/{categoryId}/search") ResponseEntity>> getCategorySearchPage(@RequestParam String query, - @RequestParam String searchType, - @RequestParam int pageNo, - @PathVariable(value = "categoryId",required = false) BigDecimal categoryId, - @RequestParam(value = "sortBy", defaultValue = "_score", required = false) String sortBy); + @RequestParam String searchType, + @RequestParam int pageNo, + @PathVariable(value = "categoryId",required = false) BigDecimal categoryId, + @RequestParam(value = "sortBy", defaultValue = "_score", required = false) String sortBy); + @GetMapping("/t3t/bookstore/autocomplete") + ResponseEntity>> autocomplete(@RequestParam String prefix); } + + diff --git a/src/main/java/com/t3t/frontserver/elastic/controller/AutocompleteController.java b/src/main/java/com/t3t/frontserver/elastic/controller/AutocompleteController.java new file mode 100644 index 0000000..9d1948e --- /dev/null +++ b/src/main/java/com/t3t/frontserver/elastic/controller/AutocompleteController.java @@ -0,0 +1,23 @@ +package com.t3t.frontserver.elastic.controller; + +import com.t3t.frontserver.elastic.client.ElasticClient; +import com.t3t.frontserver.model.response.BaseResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +@RequiredArgsConstructor +public class AutocompleteController { + private final ElasticClient elasticAdaptor; + + + @GetMapping("/autocomplete") + public ResponseEntity>> proxyAutocomplete(@RequestParam String prefix) { + return elasticAdaptor.autocomplete(prefix); + } +} \ No newline at end of file diff --git a/src/main/resources/static/assets/main/css/elastic.css b/src/main/resources/static/assets/main/css/elastic.css new file mode 100644 index 0000000..c63f69e --- /dev/null +++ b/src/main/resources/static/assets/main/css/elastic.css @@ -0,0 +1,29 @@ +.autocomplete-container { + position: relative; +} + +.autocomplete-items { + position: absolute; + border: 1px solid #d4d4d4; + border-bottom: none; + border-top: none; + z-index: 99; + top: 100%; + left: 0; + right: 0; + background-color: white; + overflow: hidden; + border-radius: 4px; + box-shadow: 0 4px 6px rgba(0,0,0,0.1); +} + +.autocomplete-items div { + padding: 10px; + cursor: pointer; + background-color: #fff; + border-bottom: 1px solid #d4d4d4; +} + +.autocomplete-items div:hover { + background-color: #e9e9e9; +} diff --git a/src/main/resources/static/assets/main/js/elastic.js b/src/main/resources/static/assets/main/js/elastic.js new file mode 100644 index 0000000..817dd8e --- /dev/null +++ b/src/main/resources/static/assets/main/js/elastic.js @@ -0,0 +1,85 @@ +document.addEventListener('DOMContentLoaded', function() { + updateSearchTypeDisplay(); + updateSearchQueryDisplay(); + updateCategoryIdFromURL(); + + var searchInput = document.getElementById('searchQueryInput'); + var resultsContainer = document.getElementById('autocompleteResults'); + + searchInput.addEventListener('input', function() { + var query = this.value; + if (query.length > 1) { + fetch('/autocomplete?prefix=' + encodeURIComponent(query)) + .then(response => response.json()) + .then(response => { + if (response.data && response.data.length) { + resultsContainer.innerHTML = ''; + response.data.forEach(item => { + var resultItem = document.createElement('div'); + resultItem.textContent = item; + resultItem.addEventListener('click', function() { + searchInput.value = this.textContent; + resultsContainer.innerHTML = ''; + resultsContainer.style.display = 'none'; + }); + resultsContainer.appendChild(resultItem); + }); + resultsContainer.style.display = 'block'; + } else { + resultsContainer.innerHTML = ''; + resultsContainer.style.display = 'none'; + } + }) + .catch(error => console.error('Error fetching autocomplete suggestions:', error)); + } else { + resultsContainer.innerHTML = ''; + resultsContainer.style.display = 'none'; + } + }); + + document.addEventListener('click', function(event) { + if (!searchInput.contains(event.target) && !resultsContainer.contains(event.target)) { + resultsContainer.style.display = 'none'; + } + }); + + searchInput.addEventListener('focus', function() { + if (resultsContainer.innerHTML !== '') { + resultsContainer.style.display = 'block'; + } + }); +}); + +function updateCategoryIdFromURL() { + const path = window.location.pathname; + const categoryPattern = /\/category\/(\d+)/; // '/category/' 다음에 오는 숫자를 찾는 정규 표현식 + const match = path.match(categoryPattern); + + if (match && match[1]) { + document.getElementById('categoryIdInput').value = match[1]; + } else { + document.getElementById('categoryIdInput').parentNode.removeChild(document.getElementById('categoryIdInput')); + } +} +function setSearchType(type) { + var typeNames = { + 'all': '통합검색', + 'book_name': '책 이름', + 'publisher_name': '출판사', + 'participant_name': '참여자' + }; + document.getElementById('searchTypeInput').value = type; + document.getElementById('dropdownMenuButton').textContent = typeNames[type]; +} +function updateSearchTypeDisplay() { + var searchParams = new URLSearchParams(window.location.search); + var currentType = searchParams.get('searchType') || 'all'; + setSearchType(currentType); +} +function updateSearchQueryDisplay() { + var searchParams = new URLSearchParams(window.location.search); + var currentQuery = searchParams.get('query'); + if (currentQuery) { + document.getElementById('searchQueryInput').value = currentQuery; + } +} \ No newline at end of file diff --git a/src/main/resources/templates/main/fragment/searchbar.html b/src/main/resources/templates/main/fragment/searchbar.html index b2e1962..53a9af6 100644 --- a/src/main/resources/templates/main/fragment/searchbar.html +++ b/src/main/resources/templates/main/fragment/searchbar.html @@ -34,7 +34,8 @@
찾고 싶으신 도서가 있으신가요?
- + +
@@ -47,46 +48,7 @@
찾고 싶으신 도서가 있으신가요?
- + + - + \ No newline at end of file diff --git a/src/main/resources/templates/main/page/elasticSearch.html b/src/main/resources/templates/main/page/elasticSearch.html index b63f73d..7a8fdb4 100644 --- a/src/main/resources/templates/main/page/elasticSearch.html +++ b/src/main/resources/templates/main/page/elasticSearch.html @@ -98,7 +98,7 @@

검색 결과가 없습니다..

  • From 93837ddd6abb0323c88cd6a7c7b445f56d720eca Mon Sep 17 00:00:00 2001 From: PARKJONGGYEONG Date: Fri, 10 May 2024 16:59:24 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=EC=9E=90=EB=8F=99=EC=99=84=EC=84=B1?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/static/assets/main/css/elastic.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/static/assets/main/css/elastic.css b/src/main/resources/static/assets/main/css/elastic.css index c63f69e..61b62ea 100644 --- a/src/main/resources/static/assets/main/css/elastic.css +++ b/src/main/resources/static/assets/main/css/elastic.css @@ -22,6 +22,7 @@ cursor: pointer; background-color: #fff; border-bottom: 1px solid #d4d4d4; + font-size: 12px; } .autocomplete-items div:hover { From b1599909d14f3326d0fbdacff233a9b20802b38c Mon Sep 17 00:00:00 2001 From: PARKJONGGYEONG Date: Mon, 13 May 2024 14:20:56 +0900 Subject: [PATCH 3/3] =?UTF-8?q?docs:=20#30=20java=20Docs=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/t3t/frontserver/elastic/client/ElasticClient.java | 7 +++++++ .../elastic/controller/AutocompleteController.java | 8 +++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/t3t/frontserver/elastic/client/ElasticClient.java b/src/main/java/com/t3t/frontserver/elastic/client/ElasticClient.java index 80f9812..9a0dd9d 100644 --- a/src/main/java/com/t3t/frontserver/elastic/client/ElasticClient.java +++ b/src/main/java/com/t3t/frontserver/elastic/client/ElasticClient.java @@ -48,6 +48,13 @@ public interface ElasticClient { @RequestParam int pageNo, @PathVariable(value = "categoryId",required = false) BigDecimal categoryId, @RequestParam(value = "sortBy", defaultValue = "_score", required = false) String sortBy); + /** + * + * elasticsearch 기반 실시간 자동완성 + * + * @param prefix text 검색어 + * @return 서버의 데이터를 가지고 옴 + */ @GetMapping("/t3t/bookstore/autocomplete") ResponseEntity>> autocomplete(@RequestParam String prefix); } diff --git a/src/main/java/com/t3t/frontserver/elastic/controller/AutocompleteController.java b/src/main/java/com/t3t/frontserver/elastic/controller/AutocompleteController.java index 9d1948e..51258a7 100644 --- a/src/main/java/com/t3t/frontserver/elastic/controller/AutocompleteController.java +++ b/src/main/java/com/t3t/frontserver/elastic/controller/AutocompleteController.java @@ -14,7 +14,13 @@ @RequiredArgsConstructor public class AutocompleteController { private final ElasticClient elasticAdaptor; - + /** + * + * elasticsearch 기반 실시간 자동완성 + * + * @param prefix text 검색어 + * @return 페이지로 정보를 가지고 이동 + */ @GetMapping("/autocomplete") public ResponseEntity>> proxyAutocomplete(@RequestParam String prefix) {