From 5b4aee36bd410fd411f322638cb39a10510343f2 Mon Sep 17 00:00:00 2001 From: Mirim Park Date: Tue, 13 Dec 2022 00:52:05 +0900 Subject: [PATCH] =?UTF-8?q?14-9=20[FE]=20[=EB=85=BC=EB=AC=B8=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20-=20=EB=84=A4=ED=8A=B8=EC=9B=8C=ED=81=AC=20?= =?UTF-8?q?=EC=B0=A8=ED=8A=B8]=20=EA=B7=B8=EB=9E=98=ED=94=84=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=20=EC=95=88=EB=82=B4=20tooltip=EC=9D=84=20=ED=91=9C?= =?UTF-8?q?=EC=8B=9C=ED=95=9C=EB=8B=A4.=20(#119)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: yeynii --- frontend/src/App.tsx | 2 +- frontend/src/components/IconButton.tsx | 3 +- frontend/src/components/search/Search.tsx | 2 +- frontend/src/icons/InfoIcon.tsx | 13 ++ frontend/src/icons/XMark.tsx | 9 ++ .../pages/Main/components/KeywordRanking.tsx | 2 + .../PaperDetail/components/InfoTooltip.tsx | 119 ++++++++++++++++++ .../PaperDetail/components/PaperInfo.tsx | 1 + .../PaperDetail/components/ReferenceGraph.tsx | 2 + .../src/pages/SearchList/components/Paper.tsx | 31 +++-- frontend/src/style/styleUtils.ts | 2 +- frontend/src/utils/localStorage.ts | 9 -- frontend/src/utils/storage.ts | 19 +++ 13 files changed, 188 insertions(+), 26 deletions(-) create mode 100644 frontend/src/icons/InfoIcon.tsx create mode 100644 frontend/src/icons/XMark.tsx create mode 100644 frontend/src/pages/PaperDetail/components/InfoTooltip.tsx delete mode 100644 frontend/src/utils/localStorage.ts create mode 100644 frontend/src/utils/storage.ts diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 41bb009..5a1d02b 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -22,7 +22,7 @@ const queryClient = new QueryClient({ refetchOnWindowFocus: false, refetchOnMount: false, refetchOnReconnect: false, - staleTime: 5 * 60 * 1000, + staleTime: 10 * 60 * 1000, retry: (failureCount, error) => { if (error instanceof AxiosError) { return error.response?.status === 408 && failureCount <= 1 ? true : false; diff --git a/frontend/src/components/IconButton.tsx b/frontend/src/components/IconButton.tsx index dc362ee..5f6caee 100644 --- a/frontend/src/components/IconButton.tsx +++ b/frontend/src/components/IconButton.tsx @@ -2,7 +2,8 @@ import styled from 'styled-components'; interface IProps { icon: JSX.Element; - onClick: React.MouseEventHandler; + onClick?: React.MouseEventHandler; + 'aria-label': string; } const IconButton = ({ icon, onClick, ...rest }: IProps) => { diff --git a/frontend/src/components/search/Search.tsx b/frontend/src/components/search/Search.tsx index f22199b..362098a 100644 --- a/frontend/src/components/search/Search.tsx +++ b/frontend/src/components/search/Search.tsx @@ -8,7 +8,7 @@ import useDebounceValue from '../../hooks/useDebouncedValue'; import MaginifyingGlassIcon from '../../icons/MagnifyingGlassIcon'; import { createDetailQuery } from '../../utils/createQuery'; import { getDoiKey, isDoiFormat } from '../../utils/format'; -import { getLocalStorage, setLocalStorage } from '../../utils/localStorage'; +import { getLocalStorage, setLocalStorage } from '../../utils/storage'; import IconButton from '../IconButton'; import MoonLoader from '../loader/MoonLoader'; import AutoCompletedList from './AutoCompletedList'; diff --git a/frontend/src/icons/InfoIcon.tsx b/frontend/src/icons/InfoIcon.tsx new file mode 100644 index 0000000..1799cfd --- /dev/null +++ b/frontend/src/icons/InfoIcon.tsx @@ -0,0 +1,13 @@ +const InfoIcon = () => { + return ( + + + + ); +}; + +export default InfoIcon; diff --git a/frontend/src/icons/XMark.tsx b/frontend/src/icons/XMark.tsx new file mode 100644 index 0000000..482e1e8 --- /dev/null +++ b/frontend/src/icons/XMark.tsx @@ -0,0 +1,9 @@ +const XIcon = () => { + return ( + + + + ); +}; + +export default XMark; diff --git a/frontend/src/pages/Main/components/KeywordRanking.tsx b/frontend/src/pages/Main/components/KeywordRanking.tsx index 0f6da13..9a226c6 100644 --- a/frontend/src/pages/Main/components/KeywordRanking.tsx +++ b/frontend/src/pages/Main/components/KeywordRanking.tsx @@ -108,6 +108,8 @@ const HeaderDivideLine = styled.hr` const DivideLine = styled.hr` width: 100%; + border: 1px solid ${({ theme }) => theme.COLOR.offWhite}; + fill: ${({ theme }) => theme.COLOR.offWhite}; margin-bottom: 10px; `; diff --git a/frontend/src/pages/PaperDetail/components/InfoTooltip.tsx b/frontend/src/pages/PaperDetail/components/InfoTooltip.tsx new file mode 100644 index 0000000..b5f06d1 --- /dev/null +++ b/frontend/src/pages/PaperDetail/components/InfoTooltip.tsx @@ -0,0 +1,119 @@ +import { useState } from 'react'; +import styled from 'styled-components'; +import IconButton from '../../../components/IconButton'; +import InfoIcon from '../../../icons/InfoIcon'; +import { getSessionStorage, setSessionStorage } from '../../../utils/storage'; + +interface InfoContainerProps { + isOpened: boolean; +} + +const InfoTooltip = () => { + const [isOpened, setisOpened] = useState(getSessionStorage('isTooltipClosed') ? false : true); + + const handleInfoButtonClick = () => { + setisOpened(true); + }; + + const handleCloseButtonClick = () => { + const isTooltipClosed = getSessionStorage('isTooltipClosed'); + if (!isTooltipClosed) { + setSessionStorage('isTooltipClosed', true); + } + setisOpened(false); + }; + + return ( + + + } onClick={handleInfoButtonClick} aria-label="정보" /> + + + 그래프 사용법 + +
  • • 그래프의 노드나 좌측의 레퍼런스 논문을 클릭하여 선택한 논문의 인용관계를 추가로 그릴 수 있습니다.
  • +
  • • 마우스 휠을 이용해 그래프를 확대, 축소할 수 있습니다.
  • +
  • • 마우스 드래그로 그래프의 위치를 옮길 수 있습니다.
  • +
  • • 노드색이 불투명한 논문은 정보가 완전하지 않은 논문으로, 선택 및 추가 인터랙션이 불가능합니다.
  • +
  • • 노드의 색상은 피인용수(citations)를 의미합니다. (오른쪽 아래 범례 참고)
  • +
    + + + +
    +
    + ); +}; + +const Container = styled.div` + display: flex; + flex-direction: column; + gap: 5px; + position: relative; + align-items: flex-start; + position: absolute; + top: 20px; + left: 320px; +`; + +const IconButtonWrapper = styled.div` + opacity: 0.3; + :hover { + opacity: 1; + } +`; + +const InfoContainer = styled.div` + display: flex; + flex-direction: column; + gap: 5px; + width: 400px; + padding: 15px 15px 10px 20px; + background-color: ${({ theme }) => theme.COLOR.gray1}; + border-radius: 10px; + position: absolute; + top: 0; + left: 0; + visibility: ${(props) => (props.isOpened ? 'visible' : 'hidden')}; +`; + +const Title = styled.h3` + ${({ theme }) => theme.TYPO.body_h}; +`; + +const InfoList = styled.ul` + display: flex; + flex-direction: column; + gap: 5px; + margin-top: 5px; + ${({ theme }) => theme.TYPO.body2}; + color: ${({ theme }) => theme.COLOR.primary4}; + line-height: 1rem; + li { + word-break: keep-all; + text-align: justify; + text-indent: -8px; + } +`; + +const ButtonWrapper = styled.div` + display: flex; + justify-content: flex-end; +`; + +const Button = styled.button` + width: 80px; + height: 30px; + margin-top: 10px; + ${({ theme }) => theme.TYPO.body2}; + color: ${({ theme }) => theme.COLOR.offWhite}; + background-color: ${({ theme }) => theme.COLOR.primary3}; + opacity: 0.9; + border-radius: 3px; + cursor: pointer; + :hover { + opacity: 1; + } +`; + +export default InfoTooltip; diff --git a/frontend/src/pages/PaperDetail/components/PaperInfo.tsx b/frontend/src/pages/PaperDetail/components/PaperInfo.tsx index 1f83a66..c588049 100644 --- a/frontend/src/pages/PaperDetail/components/PaperInfo.tsx +++ b/frontend/src/pages/PaperDetail/components/PaperInfo.tsx @@ -109,6 +109,7 @@ const InfoItem = styled.div` const InfoAuthor = styled(Ellipsis)` ${({ theme }) => theme.TYPO.body2}; + -webkit-line-clamp: 3; `; const DivideLine = styled.hr` diff --git a/frontend/src/pages/PaperDetail/components/ReferenceGraph.tsx b/frontend/src/pages/PaperDetail/components/ReferenceGraph.tsx index b050f49..505b849 100644 --- a/frontend/src/pages/PaperDetail/components/ReferenceGraph.tsx +++ b/frontend/src/pages/PaperDetail/components/ReferenceGraph.tsx @@ -7,6 +7,7 @@ import useGraphEmphasize from '../../../hooks/graph/useGraphEmphasize'; import useGraphZoom from '../../../hooks/graph/useGraphZoom'; import useLinkUpdate from '../../../hooks/graph/useLinkUpdate'; import useNodeUpdate from '../../../hooks/graph/useNodeUpdate'; +import InfoTooltip from './InfoTooltip'; interface ReferenceGraphProps { data: IPaperDetail; @@ -55,6 +56,7 @@ const ReferenceGraph = ({ data, addChildrensNodes, hoveredNode, changeHoveredNod return ( + diff --git a/frontend/src/pages/SearchList/components/Paper.tsx b/frontend/src/pages/SearchList/components/Paper.tsx index 02484a3..a4843e9 100644 --- a/frontend/src/pages/SearchList/components/Paper.tsx +++ b/frontend/src/pages/SearchList/components/Paper.tsx @@ -18,23 +18,23 @@ const Paper = ({ data, keyword }: PaperProps) => { {title && {highlightKeyword(sliceTitle(removeTag(title)), keyword)}} {authors && ( -
    - {authors.length > 1 ? 'Authors ' : 'Author '} + + {authors.length > 1 ? 'Authors' : 'Author'} {highlightKeyword(authors?.join(', '), keyword)} -
    +
    )} -
    - Published - {year} -
    -
    - cited by - {citations} - references - {references} -
    + + Published + {year} + + + cited by + {citations} + references + {references} +
    ); @@ -62,6 +62,11 @@ const Content = styled.div` justify-content: space-between; `; +const ContentItem = styled.div` + display: flex; + gap: 5px; +`; + const Bold = styled.b` font-weight: 700; `; diff --git a/frontend/src/style/styleUtils.ts b/frontend/src/style/styleUtils.ts index 9b55f69..8848ec7 100644 --- a/frontend/src/style/styleUtils.ts +++ b/frontend/src/style/styleUtils.ts @@ -5,7 +5,7 @@ export const Ellipsis = styled.span` overflow: hidden; text-overflow: ellipsis; display: -webkit-box; - -webkit-line-clamp: 3; + -webkit-line-clamp: 1; -webkit-box-orient: vertical; word-break: keep-all; `; diff --git a/frontend/src/utils/localStorage.ts b/frontend/src/utils/localStorage.ts deleted file mode 100644 index 4ab586c..0000000 --- a/frontend/src/utils/localStorage.ts +++ /dev/null @@ -1,9 +0,0 @@ -export const setLocalStorage = (key: string, value: unknown) => { - window.localStorage.setItem(key, JSON.stringify(value)); -}; - -export const getLocalStorage = (key: string) => { - const item = window.localStorage.getItem(key); - if (item) return JSON.parse(item); - return null; -}; diff --git a/frontend/src/utils/storage.ts b/frontend/src/utils/storage.ts new file mode 100644 index 0000000..7307a72 --- /dev/null +++ b/frontend/src/utils/storage.ts @@ -0,0 +1,19 @@ +export const setLocalStorage = (key: string, value: unknown) => { + window.localStorage.setItem(key, JSON.stringify(value)); +}; + +export const getLocalStorage = (key: string) => { + const item = window.localStorage.getItem(key); + if (item) return JSON.parse(item); + return null; +}; + +export const setSessionStorage = (key: string, value: unknown) => { + window.sessionStorage.setItem(key, JSON.stringify(value)); +}; + +export const getSessionStorage = (key: string) => { + const item = window.sessionStorage.getItem(key); + if (item) return JSON.parse(item); + return null; +};