Skip to content

Commit

Permalink
14-9 [FE] [논문 상세 - 네트워크 차트] 그래프 사용 안내 tooltip을 표시한다. (#119)
Browse files Browse the repository at this point in the history
Co-authored-by: yeynii <yeynii@gmail.com>
  • Loading branch information
Palwol and yeynii committed Dec 12, 2022
1 parent 9a5b251 commit 5b4aee3
Show file tree
Hide file tree
Showing 13 changed files with 188 additions and 26 deletions.
2 changes: 1 addition & 1 deletion frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/components/IconButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/search/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
13 changes: 13 additions & 0 deletions frontend/src/icons/InfoIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const InfoIcon = () => {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="20" height="20">
<path
fill="#e4e4e4"
stroke="#e4e4e4"
d="M256 512c141.4 0 256-114.6 256-256S397.4 0 256 0S0 114.6 0 256S114.6 512 256 512zM216 336h24V272H216c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-144c-17.7 0-32-14.3-32-32s14.3-32 32-32s32 14.3 32 32s-14.3 32-32 32z"
/>
</svg>
);
};

export default InfoIcon;
9 changes: 9 additions & 0 deletions frontend/src/icons/XMark.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const XIcon = () => {
return (
<svg xmlns="http://www.w3.org/2000/svg" fill="#000000" width="15" height="15" viewBox="0 0 320 512">
<path d="M310.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L160 210.7 54.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L114.7 256 9.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 301.3 265.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L205.3 256 310.6 150.6z" />
</svg>
);
};

export default XMark;
2 changes: 2 additions & 0 deletions frontend/src/pages/Main/components/KeywordRanking.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
`;

Expand Down
119 changes: 119 additions & 0 deletions frontend/src/pages/PaperDetail/components/InfoTooltip.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<Container>
<IconButtonWrapper>
<IconButton icon={<InfoIcon />} onClick={handleInfoButtonClick} aria-label="정보" />
</IconButtonWrapper>
<InfoContainer isOpened={isOpened}>
<Title>그래프 사용법</Title>
<InfoList>
<li>• 그래프의 노드나 좌측의 레퍼런스 논문을 클릭하여 선택한 논문의 인용관계를 추가로 그릴 수 있습니다.</li>
<li>• 마우스 휠을 이용해 그래프를 확대, 축소할 수 있습니다.</li>
<li>• 마우스 드래그로 그래프의 위치를 옮길 수 있습니다.</li>
<li>• 노드색이 불투명한 논문은 정보가 완전하지 않은 논문으로, 선택 및 추가 인터랙션이 불가능합니다.</li>
<li>• 노드의 색상은 피인용수(citations)를 의미합니다. (오른쪽 아래 범례 참고)</li>
</InfoList>
<ButtonWrapper>
<Button onClick={handleCloseButtonClick}>닫기</Button>
</ButtonWrapper>
</InfoContainer>
</Container>
);
};

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<InfoContainerProps>`
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;
1 change: 1 addition & 0 deletions frontend/src/pages/PaperDetail/components/PaperInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ const InfoItem = styled.div`

const InfoAuthor = styled(Ellipsis)`
${({ theme }) => theme.TYPO.body2};
-webkit-line-clamp: 3;
`;

const DivideLine = styled.hr`
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/pages/PaperDetail/components/ReferenceGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -55,6 +56,7 @@ const ReferenceGraph = ({ data, addChildrensNodes, hoveredNode, changeHoveredNod

return (
<Container>
<InfoTooltip />
<Graph ref={svgRef}>
<Links ref={linkRef}></Links>
<Nodes ref={nodeRef}></Nodes>
Expand Down
31 changes: 18 additions & 13 deletions frontend/src/pages/SearchList/components/Paper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,23 @@ const Paper = ({ data, keyword }: PaperProps) => {
{title && <Title>{highlightKeyword(sliceTitle(removeTag(title)), keyword)}</Title>}
{authors && (
<Content>
<div>
<Bold>{authors.length > 1 ? 'Authors ' : 'Author '}</Bold>
<ContentItem>
<Bold>{authors.length > 1 ? 'Authors' : 'Author'}</Bold>
<Ellipsis>{highlightKeyword(authors?.join(', '), keyword)}</Ellipsis>
</div>
</ContentItem>
</Content>
)}
<Content>
<div>
<Bold>Published </Bold>
{year}
</div>
<div>
<Bold>cited by </Bold>
{citations}
<Bold> references </Bold>
{references}
</div>
<ContentItem>
<Bold>Published</Bold>
<span>{year}</span>
</ContentItem>
<ContentItem>
<Bold>cited by</Bold>
<span>{citations}</span>
<Bold>references</Bold>
<span>{references}</span>
</ContentItem>
</Content>
</Container>
);
Expand Down Expand Up @@ -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;
`;
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/style/styleUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
`;
Expand Down
9 changes: 0 additions & 9 deletions frontend/src/utils/localStorage.ts

This file was deleted.

19 changes: 19 additions & 0 deletions frontend/src/utils/storage.ts
Original file line number Diff line number Diff line change
@@ -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;
};

0 comments on commit 5b4aee3

Please sign in to comment.