diff --git a/search-engine/public/icons/dxicons.ttf b/search-engine/public/icons/dxicons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..89d555e078e6cdaf3b98aac34184a371a976f77e Binary files /dev/null and b/search-engine/public/icons/dxicons.ttf differ diff --git a/search-engine/public/icons/dxicons.woff b/search-engine/public/icons/dxicons.woff new file mode 100644 index 0000000000000000000000000000000000000000..01551f0f83c68002c27cd51820faa40fba041c03 Binary files /dev/null and b/search-engine/public/icons/dxicons.woff differ diff --git a/search-engine/public/icons/dxicons.woff2 b/search-engine/public/icons/dxicons.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..2db645644b1c9cfb6a5653be788cdd12ae0444d3 Binary files /dev/null and b/search-engine/public/icons/dxicons.woff2 differ diff --git a/search-engine/src/component/search.js b/search-engine/src/component/search.js index 7661b0319c0584fffefa4ecfe83d7fce93c0c55c..8fcb1d6269e916ae9fa6d710fa2fa8e4860e23f5 100644 --- a/search-engine/src/component/search.js +++ b/search-engine/src/component/search.js @@ -1,25 +1,46 @@ import React, { useState } from 'react'; -import DataGrid, { Scrolling, Sorting, LoadPanel, Column } from 'devextreme-react/data-grid'; +import DataGrid, { Scrolling, Sorting, LoadPanel, Column, MasterDetail, Paging } from 'devextreme-react/data-grid'; import TextBox from 'devextreme-react/text-box'; import "./search.css" import axios from "axios"; import { LoadIndicator } from 'devextreme-react/load-indicator'; +import TextArea from 'devextreme-react/text-area'; -function search(query) { +const PAGE_SIZE = 25 + +function search(query, startIdx=0, endIdx=PAGE_SIZE+1) { const config = { method: 'get', - url: '/api/search?q=' + query + url: '/api/search?q=' + query + "&startIdx=" + startIdx + "&endIdx=" + endIdx }; return axios(config); } +let TextView = function (e) { + + let result = e.data.data + + return ( + <div> + <TextArea + height={350} + value={JSON.stringify(result, null, 4)} + /> + <Scrolling mode="virtual" rowRenderingMode="virtual" /> + </div> + ) +} + let SearchEngine = function () { const [queryResult, setQueryResult] = useState([]); + const [query, setQuery] = useState(""); const [isLoading, setIsLoading] = useState(false); + const [prevPage, setPrevPage] = useState(0); + const [maxPage, setMaxPage] = useState(0); const parseESData = (data) => { @@ -31,6 +52,11 @@ let SearchEngine = function () { newObj["title"] = row["_source"]["title"] newObj["authors"] = row["_source"]["authors"] newObj["score"] = row["_score"] + newObj["country"] = row["_source"]["country"] + newObj["doi"] = row["_source"]["doi"] + newObj["journal"] = row["_source"]["journal"] + newObj["pmid"] = row["_source"]["pmid"] + newObj["published_at"] = row["_source"]["published_at"] parsedData.push(newObj) } return parsedData @@ -39,15 +65,37 @@ let SearchEngine = function () { const handleSubmit = (e) => { e.preventDefault(); setIsLoading(true) - search(e.target[0].value).then((res) => { + let query = e.target[0].value + search(query).then((res) => { let parsedRes = parseESData(res.data) + setQuery(query) setQueryResult(parsedRes) setIsLoading(false) }).catch((error) => { console.log(error) setIsLoading(false) }) + } + + const handlePageChange = (e) => { + let curPage = e.component.pageIndex() + if (curPage < prevPage){ + setPrevPage(curPage) + return + } else if (curPage > prevPage && curPage > maxPage){ + setIsLoading(true) + search(query, curPage*PAGE_SIZE+1, ((curPage+1)*PAGE_SIZE)+1).then((res) => { + let parsedRes = parseESData(res.data) + setQueryResult(queryResult.concat(parsedRes)) + setIsLoading(false) + setMaxPage(curPage) + }).catch((error) => { + console.log(error) + setIsLoading(false) + }) + setPrevPage(curPage) + } } return ( @@ -78,13 +126,18 @@ let SearchEngine = function () { keyExpr="id" showBorders={false} allowColumnResizing={true} + onContentReady={handlePageChange} > + <MasterDetail + enabled={true} + component={TextView} + /> <Column dataField="id" width={75}/> <Column dataField="title" caption={"Title"} dataType="string" /> <Column dataField="authors" caption={"Authors"} dataType="string" /> <Column dataField="score" caption={"Score"} width={75} dataType="string" /> <Sorting mode="none" /> - <Scrolling mode="virtual" /> + <Paging pageSize={PAGE_SIZE} visible={true}/> <LoadPanel enabled={true} /> </DataGrid> </div> diff --git a/server.py b/server.py index 44eb9c21801a0e3a0f4bf0e41d746b63be1adc25..b144d1996c242578e38a49524e4ea96132d7345c 100644 --- a/server.py +++ b/server.py @@ -30,8 +30,10 @@ def search(): keywords = request.args.get('q', default = "", type = str) + start_idx = request.args.get('startIdx', default = 0, type = int) + end_idx = request.args.get('endIdx', default = 25, type = int) query = { - "from" : 0, "size" : 25, + "from" : start_idx, "size" : end_idx, "query": { "multi_match" : { "query": keywords,