안형욱

Merge branch 'feat/advanced-search' into 'develop'

Feat/advanced search



See merge request !16
......@@ -126,7 +126,11 @@ const Header = () => {
float="left"
fontsize="20px"
height="50px"
options={[{ id: 1, name: '전체' }]}
options={[
{ id: 0, name: '전체' },
{ id: 1, name: '작성자' },
{ id: 2, name: '내용' },
]}
/>
</DropDownWrap>
</DropDownContainer>
......
......@@ -8,7 +8,7 @@ const Background = styled.div``;
const ModalWrapper = styled.div`
width: 400px;
height: 300px;
height: 194px;
`;
const ModalContent = styled.div`
......@@ -23,13 +23,13 @@ const ModalContent = styled.div`
const SearchWrap = styled.div`
position: absolute;
top: 80%;
left: 20%;
right: 20%;
`;
const CloseWrap = styled.div`
position: absolute;
top: 80%;
right: 20%;
left: 20%;
`;
const StandardWrap = styled.div`
......@@ -51,7 +51,6 @@ const TextWrap = styled.div`
width: 360px;
top: ${props => props.top};
right: ${props => props.right};
border-bottom: 2px solid #dee2e6;
padding-left: 20px;
padding-bottom: ${props => props.bottom};
`;
......@@ -59,8 +58,7 @@ const TextWrap = styled.div`
const Modal = ({ showModal, setShowModal }) => {
const [query, setQuery] = useState('');
const [keywordQuery, setKeywordQuery] = useState('');
const [writerQuery, setWriterQuery] = useState('');
const [dateQuery, setDateQuery] = useState('');
const [writer, setWriter] = useState('');
const history = useHistory();
const modalRef = useRef();
const closeModal = e => {
......@@ -76,7 +74,7 @@ const Modal = ({ showModal, setShowModal }) => {
<Card shadow="lg">
<ModalWrapper>
<ModalContent>
<TextWrap top="6%" right="10%" bottom="4%" height="40px">
<TextWrap top="8%" right="10%" bottom="4%" height="40px">
기본검색
</TextWrap>
<StandardWrap>
......@@ -103,7 +101,7 @@ const Modal = ({ showModal, setShowModal }) => {
}}
/>
</StandardWrap>
<TextWrap top="24%" right="10%" bottom="31%">
<TextWrap top="34%" right="10%" bottom="31%">
고급검색
</TextWrap>
<AdvancedWrap>
......@@ -124,28 +122,29 @@ const Modal = ({ showModal, setShowModal }) => {
}}
placeholder="작성자"
type="text"
value={decodeURIComponent(writerQuery)}
onChange={e => setWriterQuery(e.target.value)}
/>
<TextInput
inputStyle={{
marginBottom: 18,
fontSize: 15,
}}
placeholder="생성 날짜"
type="text"
value={decodeURIComponent(dateQuery)}
onChange={e => setDateQuery(e.target.value)}
value={decodeURIComponent(writer)}
onChange={e => setWriter(e.target.value)}
/>
</AdvancedWrap>
</ModalContent>
<CloseWrap onClick={() => setShowModal(prev => !prev)}>
<Button width="100px" color="blue">
<Button width="100px" color="gray">
닫기
</Button>
</CloseWrap>
<SearchWrap>
<Button width="100px" color="gray">
<SearchWrap
onClick={() => {
const searchQuery = {};
if (query !== '') searchQuery.query = query;
if (keywordQuery !== '') searchQuery.keyword = keywordQuery;
if (writer !== '') searchQuery.writer = writer;
const params = new URLSearchParams(searchQuery);
history.push(
`search?${decodeURIComponent(params.toString())}`
);
}}
>
<Button width="100px" color="blue">
검색
</Button>
</SearchWrap>
......
......@@ -18,10 +18,16 @@ const Buttons = ({
width,
fontsize,
icon = '',
onClick,
}) => {
return (
<ButtonBlock float={float} width={width} fontsize={fontsize}>
<Button size={size} color={color || 'blue'} rightIcon={icon}>
<Button
onClick={onClick}
size={size}
color={color || 'blue'}
rightIcon={icon}
>
{children}
</Button>
</ButtonBlock>
......
import React, { useState, useEffect } from 'react';
import { TiArrowSortedDown } from 'react-icons/ti';
import { Menu, MenuItem } from '@mantine/core';
import { useDispatch } from 'react-redux';
import styled from 'styled-components';
import { dropdownHeaderColorMap } from '../../lib/styles/palette';
import { setSearchOption } from '../../features/searchOption';
const DropDownBlock = styled.div`
margin: 0 auto;
......@@ -41,6 +43,7 @@ const DropDown = ({
size,
}) => {
const [menuTitle, setTitle] = useState('');
const dispatch = useDispatch();
useEffect(() => {
setTitle(title);
}, []);
......@@ -62,14 +65,15 @@ const DropDown = ({
</DropDownWrap>
}
>
{options.map(friend => (
{options.map(option => (
<MenuItem
value={friend.id}
value={option.id}
onClick={() => {
setTitle(friend.name);
dispatch(setSearchOption(option.id));
setTitle(option.name);
}}
>
{friend.name}
{option.name}
</MenuItem>
))}
</DropDownHeader>
......
......@@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react';
import { TextInput } from '@mantine/core';
import styled from 'styled-components';
import { useHistory, useLocation } from 'react-router-dom';
import { useDispatch } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import SearchBox from './SearchBox';
import { inputColorMap } from '../../lib/styles/palette';
import { esApi } from '../../lib/api/elasticsearch';
......@@ -43,18 +43,31 @@ const MyInput = ({
}) => {
const [query, setQuery] = useState('');
const history = useHistory();
const search = useLocation();
const name = decodeURIComponent(search.search.substring(7));
const { search } = useLocation();
const name = decodeURIComponent(
new URLSearchParams(search).get('query') || ''
);
const option = decodeURIComponent(
new URLSearchParams(search).get('option') || ''
);
const dispatch = useDispatch();
const { option: currentSearchOption } = useSelector(
state => state.searchOption
);
useEffect(() => {
const setSearchDatas = async () => {
if (option === '') {
const { results } = await esApi.search(name);
dispatch(setParsedDocuments(results));
} else {
const { results } = await esApi.searchWithOption(name, option);
dispatch(setParsedDocuments(results));
}
};
setQuery(name);
setSearchDatas();
}, [name]);
}, [name, option]);
return (
<InputBlock
......@@ -82,7 +95,13 @@ const MyInput = ({
alert('검색어를 입력 해 주세요.');
return;
}
const params = new URLSearchParams({ query });
const searchRequest = {};
searchRequest.query = query;
if (currentSearchOption === 'WRITER')
searchRequest.option = 'writer';
if (currentSearchOption === 'CONTENT')
searchRequest.option = 'content';
const params = new URLSearchParams(searchRequest);
history.push(`search?${decodeURIComponent(params.toString())}`);
}
}}
......@@ -94,7 +113,13 @@ const MyInput = ({
alert('검색어를 입력 해 주세요.');
return;
}
const params = new URLSearchParams({ query });
const searchRequest = {};
searchRequest.query = query;
if (currentSearchOption === 'WRITER') searchRequest.option = 'writer';
if (currentSearchOption === 'CONTENT')
searchRequest.option = 'content';
const params = new URLSearchParams(searchRequest);
history.push(`search?${decodeURIComponent(params.toString())}`);
}}
>
......
......@@ -15,7 +15,6 @@ const ImageWrapper = styled.div`
`;
const Thumbnails = ({ srcs }) => {
const [lists, setLists] = useState([]);
console.log(srcs);
const placeholder = () => {
if (srcs.length < 4) {
const list = [];
......
import { createSlice } from '@reduxjs/toolkit';
const OPTION = ['ALL', 'WRITER', 'CONTENT'];
const searchOptionSlice = createSlice({
name: 'searchOption',
initialState: {
option: OPTION[0],
},
reducers: {
setSearchOption: (state, action) => {
state.option = OPTION[action.payload];
},
},
});
export const { setSearchOption } = searchOptionSlice.actions;
export default searchOptionSlice.reducer;
......@@ -19,4 +19,17 @@ export const esApi = {
return res.data;
},
searchWithOption: async (searchWord, option) => {
const res = await esInstance.post(
`/api/as/v1/engines/${process.env.REACT_APP_ENGINE_NAME}/search`,
{
query: searchWord,
search_fields: {
[option]: {},
},
}
);
return res.data;
},
};
......
......@@ -51,9 +51,9 @@ const HomePage = () => {
fontsize="20px"
height="50px"
options={[
{ id: 1, name: '전체' },
{ id: 2, name: '개인' },
{ id: 3, name: '부서' },
{ id: 0, name: '전체' },
{ id: 1, name: '작성자' },
{ id: 2, name: '내용' },
]}
/>
<Input color="blue" paddingsize="10px" width="100%" display />
......
import { combineReducers } from 'redux';
import parsedDocumentsReducer from '../features/parsedDocumentsSlice';
import searchOptionReducer from '../features/searchOption';
export default combineReducers({
parsedDocuments: parsedDocumentsReducer,
searchOption: searchOptionReducer,
});
......