Skip to content

Commit

Permalink
Merge pull request #61 from boostcamp-2020/feat/VideoList
Browse files Browse the repository at this point in the history
[COMMON] User, Video Store구현, Modal 구현 및 리팩토링
  • Loading branch information
kyu9341 authored Dec 3, 2020
2 parents 35883d6 + 96c8ace commit 8c4df2c
Show file tree
Hide file tree
Showing 38 changed files with 653 additions and 74 deletions.
3 changes: 2 additions & 1 deletion client/src/api/video.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { requestPOST } from '@/api';
import { requestGET, requestPOST } from '@/api';

const VIDEO_BASE_URL = '/video';

const videoAPI = {
upload: (formData: FormData) =>
requestPOST(VIDEO_BASE_URL, formData, {}, true),
getList: () => requestGET(`${VIDEO_BASE_URL}/list`),
};

export default videoAPI;
8 changes: 0 additions & 8 deletions client/src/components/atoms/Canvas/Canvas.tsx

This file was deleted.

1 change: 0 additions & 1 deletion client/src/components/atoms/Canvas/index.ts

This file was deleted.

2 changes: 1 addition & 1 deletion client/src/components/atoms/TimeText/TimeText.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import styled from 'styled-components';
import parseTime from '@/utils/time';
import { parseTime } from '@/utils/time';

const StyledP = styled.p`
margin: 0;
Expand Down
51 changes: 51 additions & 0 deletions client/src/components/atoms/VideoList/VideoItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react';
import styled from 'styled-components';

import { Video } from '@/store/video/actions';
import color from '@/theme/colors';
import { parseDateString } from '@/utils/time';

const StyledDiv = styled.div`
display: flex;
align-items: center;
justify-content: space-around;
border-bottom: 1px solid ${color.BORDER};
${({ isChecked }) =>
`background-color: ${
isChecked ? `${color.DARK_PURPLE}` : `${color.MODAL}`
};`}
&:hover {
background-color: ${color.BORDER};
}
`;

const Image = styled.img`
width: 2.5rem;
height: 2rem;
`;

const Name = styled.p``;

const Timestamp = styled.p``;

interface Props {
video: Video;
selected: Video;
handleCheck: Function;
}

const VideoItem: React.FC<Props> = ({ video, handleCheck, selected }) => {
return (
<StyledDiv
onClick={() => handleCheck(video)}
isChecked={selected === video}
>
<Image src="https://user-images.githubusercontent.com/49153756/99666210-03b80600-2aae-11eb-95b9-f61f52694708.png" />
<Name>{video.name}</Name>
<Timestamp>{parseDateString(new Date(), video.updatedAt)}</Timestamp>
</StyledDiv>
);
};

export default VideoItem;
59 changes: 59 additions & 0 deletions client/src/components/atoms/VideoList/VideoList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React, { useEffect, useState } from 'react';
import styled from 'styled-components';
import { useSelector, useDispatch } from 'react-redux';

import { fetchListStart } from '@/store/video/actions';
import { getVideos } from '@/store/selectors';
import color from '@/theme/colors';
import VideoItem from './VideoItem';

const StyledDiv = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
background-color: ${color.MODAL};
border-radius: 12px 12px 0 0;
`;

const Header = styled.div`
display: flex;
align-items: center;
justify-content: center;
border-bottom: 1px solid ${color.BORDER};
padding: 10px;
`;

const List = styled.div`
height: 50vh;
overflow-y: auto;
`;

const VideoList: React.FC = () => {
const [selected, setSelected] = useState(null);
const videos = useSelector(getVideos);
const dispatch = useDispatch();

const handleCheck = video => setSelected(video);

useEffect(() => {
if (!videos) dispatch(fetchListStart());
}, [videos]);

return (
<StyledDiv>
<Header>Video List</Header>
<List>
{videos?.map(video => (
<VideoItem
key={video.name}
video={video}
handleCheck={handleCheck}
selected={selected}
/>
))}
</List>
</StyledDiv>
);
};

export default VideoList;
1 change: 1 addition & 0 deletions client/src/components/atoms/VideoList/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './VideoList';
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const CurrentTime: React.FC = () => {
if (newTime > end) video.setCurrentTime((newTime = end));
dispatch(moveTo(end));
}
newTime = Math.floor(newTime - start);
newTime = Math.floor(Number((newTime - start).toFixed(1)));
if (time !== newTime) setTime(newTime);
}, 50);
return () => clearInterval(timer);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React from 'react';
import React, { useState } from 'react';
import styled, { keyframes } from 'styled-components';

import Modal from '@/components/molecules/Modal';
import VideoList from '@/components/atoms/VideoList';
import color from '@/theme/colors';

const slide = keyframes`
Expand Down Expand Up @@ -57,18 +59,43 @@ interface Props {
handleChange: () => void;
}

const modalLayout = `
top: 20vh;
left: 35vw;
width: 30vw;
height: 60vh;
`;

const FileInput = React.forwardRef<HTMLInputElement, Props>(
({ handleChange }, forwardedRef) => {
const [modalVisible, setModalVisible] = useState(false);

const handleClick = () => setModalVisible(true);
const handleCancel = () => setModalVisible(false);
const handleConfirm = () => setModalVisible(false);

const handleOverlay = () => setModalVisible(false);
return (
<StyledDiv>
{modalVisible && (
<Modal
styleProps={modalLayout}
handleOverlay={handleOverlay}
handleButton1={handleCancel}
handleButton2={handleConfirm}
buttonMessage1="취소"
buttonMessage2="확인"
component={VideoList}
/>
)}
<FromLocal htmlFor="local">로컬</FromLocal>
<StyledInput
type="file"
id="local"
ref={forwardedRef}
onChange={handleChange}
/>
<FromServer>서버</FromServer>
<FromServer onClick={handleClick}>서버</FromServer>
</StyledDiv>
);
}
Expand Down
93 changes: 93 additions & 0 deletions client/src/components/molecules/Modal/Modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import React from 'react';
import styled from 'styled-components';

import Button from '@/components/atoms/Button';
import color from '@/theme/colors';

const StyledModal = styled.div`
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 1;
`;

const StyledModalOverlay = styled.div`
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 2;
background-color: rgba(0, 0, 0, 0.3);
`;

const StyledModalSection = styled.div`
position: absolute;
top: 30%;
left: 50%;
${({ styleProps }) => styleProps}
background-color: ${color.MODAL};
border-radius: 12px;
box-shadow: 0 0 10px 8px rgba(255, 255, 255, 0.2);
color: ${color.WHITE};
z-index: 3;
`;

const StyledModalButtonRow = styled.div`
position: absolute;
width: 100%;
bottom: 1rem;
margin-top: 1rem;
text-align: center;
button {
color: ${color.WHITE};
}
`;

interface Props {
styleProps: string;
handleOverlay: () => void;
handleButton1: () => void;
handleButton2: () => void;
buttonMessage1: string;
buttonMessage2: string;
component: React.FC;
}

const Modal: React.FC<Props> = ({
styleProps,
handleOverlay,
handleButton1,
handleButton2,
buttonMessage1,
buttonMessage2,
component: Component,
}) => {
return (
<StyledModal>
<StyledModalOverlay onClick={handleOverlay} />
<StyledModalSection styleProps={styleProps}>
<Component />
<StyledModalButtonRow>
<Button
type="transparent"
message={buttonMessage1}
onClick={handleButton1}
disabled={false}
/>
<Button
type="transparent"
message={buttonMessage2}
onClick={handleButton2}
disabled={false}
/>
</StyledModalButtonRow>
</StyledModalSection>
</StyledModal>
);
};

export default Modal;
1 change: 1 addition & 0 deletions client/src/components/molecules/Modal/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './Modal';
2 changes: 1 addition & 1 deletion client/src/components/molecules/Thumbnail/Thumbnail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { shallowEqual, useDispatch, useSelector } from 'react-redux';

import { moveTo } from '@/store/currentVideo/actions';
import Slider from '@/components/atoms/Slider';
import HoverSlider from '@/components/atoms/HoverSlider';
import HoverSlider from '@/components/molecules/HoverSlider';
import video from '@/video';
import { getThumbnails, getIsCrop, getStartEnd } from '@/store/selectors';
import CropLayer from '@/components/molecules/CropLayer';
Expand Down
5 changes: 1 addition & 4 deletions client/src/components/molecules/UploadArea/UploadArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@ import { useDispatch, useSelector } from 'react-redux';
import styled from 'styled-components';

import Button from '@/components/atoms/Button';
import FileInput from '@/components/atoms/FileInput';
import FileInput from '@/components/molecules/FileInput';
import { setVideo } from '@/store/originalVideo/actions';
import { getName } from '@/store/selectors';
import { reset } from '@/store/actionTypes';

import webglController from '@/webgl/webglController';

const StyledDiv = styled.div`
display: flex;
Expand Down
Loading

0 comments on commit 8c4df2c

Please sign in to comment.