Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[1단계 - 나만의 유튜브 강의실] 유조(조윤호) 미션 제출합니다. #1

Merged
merged 57 commits into from
Mar 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
57d366a
docs: 기능 및 테스트 구현 목록 작성
yujo11 Mar 2, 2021
efcf06c
chore: prettier, eslint, webpack, cypress 세팅
yujo11 Mar 2, 2021
9eff934
docs: 기능 및 테스트 구현목록 수정
yujo11 Mar 2, 2021
b904e7b
feat: index.html의 element에 data-js 속성 추가
yujo11 Mar 2, 2021
1146466
test: 검색 결과가 의도한대로 출력되는지 확인하는 테스트코드 작성
yujo11 Mar 2, 2021
d9a4327
test: 검색 후 웹 스토리지에 데이터가 저장되는지 확인하는 테스트 코드 작성
yujo11 Mar 2, 2021
cbed3e5
style: skeleton CSS 추가
yujo11 Mar 4, 2021
ea8017f
chore: package 명세 수정
yujo11 Mar 4, 2021
3e1fbdc
stlye: d-none(display none) 추가
yujo11 Mar 4, 2021
f706b2c
chore: 레거시 코드 추가
yujo11 Mar 4, 2021
152f584
feat: 검색 modal 창을 열고 닫는 기능
yujo11 Mar 4, 2021
a470ad7
feat: 최근 검색 키워드를 render하는 기능
yujo11 Mar 4, 2021
573fa65
feat: 최근 검색 키워드를 render하는 기능
yujo11 Mar 4, 2021
a153d65
feat: 최근 검색 결과를 render하는 기능
yujo11 Mar 4, 2021
5508c38
feat: 유튜브 클립 검색 기능
seojihwan Mar 4, 2021
c085479
fix: 검색결과가 없을 때 skeleton이 사라지지 않던 오류
yujo11 Mar 4, 2021
5ee7f08
feat: 스크롤을 끝까지 내렸을 때 클립들을 추가로 불러오는 기능
yujo11 Mar 4, 2021
85edbc3
feat: 클립을 저장하는 기능
seojihwan Mar 4, 2021
b63bf92
chore: 패키지 명세 수정
yujo11 Mar 4, 2021
c4ddc07
refactor: 매직넘버 상수로 변경 및 중복되는 코드 제거
yujo11 Mar 4, 2021
41429f4
test: HTML태그 변경에 따른 test코드의 선택자 변경
yujo11 Mar 4, 2021
f296149
refactor: Template의 데이터 속성 추가
yujo11 Mar 4, 2021
22f2e35
chore: package 명세 수정
yujo11 Mar 4, 2021
a37082c
docs: 구현한 기능 목록 체크
yujo11 Mar 4, 2021
1ae182f
docs: 코드 구조 시각화 파일 추가
yujo11 Mar 4, 2021
ce78787
refactor: form 에 requried 속성 추가
yujo11 Mar 6, 2021
6bdd02f
fix: 공백이 검색되던 오류 해결
seojihwan Mar 6, 2021
c840bdd
refactor: input태그를 event객체로 접근
seojihwan Mar 6, 2021
c569006
refactor: 불필요한 코드 제거
seojihwan Mar 6, 2021
5c8193d
chore: eslint babel parser option 추가
yujo11 Mar 6, 2021
3d8e59d
refactor: localstorage의 key값을 상수로 분리
yujo11 Mar 6, 2021
76a4a56
refactor: localstorage에 String, Array Type만 저장되도록 변경
yujo11 Mar 6, 2021
084b4dc
refactor: date 포맷팅 함수를 유틸로 분리
seojihwan Mar 6, 2021
ef8173c
refactor: 중복되는 template코드를 재사용 가능한 모듈로 분리
yujo11 Mar 6, 2021
6f4f229
refactor: 동적으로 추가되는 element를 HTML에 정적으로 삽입
seojihwan Mar 6, 2021
3214019
refactor: throttling함수 유틸로 분리
seojihwan Mar 6, 2021
1a59af8
refactor: dom element의 선택자를 데이터 속성으로 통일
seojihwan Mar 6, 2021
a6f2f54
refactor: 스크롤이벤트의 타겟을 모달로 변경
seojihwan Mar 6, 2021
863d935
refacor: 이벤트 등록의 일관성을 위해 closeModal -> onModalClose 변경
yujo11 Mar 6, 2021
64ea1bb
fix: 추가로 클립을 렌더할 때 기존 클립까지 재렌더 되던 오류 해결
yujo11 Mar 6, 2021
28137f1
refactor: onSearchClip 내부 함수 모듈화
yujo11 Mar 6, 2021
f06f586
refactor: <a>태그에 rel noopener, noreferer, nofollow 속성 추가
yujo11 Mar 6, 2021
eb2551b
fix: margin으로 인해 document의 스크롤이 생기는 오류 해결
seojihwan Mar 6, 2021
3fb4846
fix: 저장버튼과 클립이 짤리는 오류 해결
seojihwan Mar 6, 2021
829d971
feat: dimmed 클릭 시에 modal이 닫히는 기능
yujo11 Mar 6, 2021
0bf5036
style: 최근 검색어 session 밑에 margin 추가
yujo11 Mar 6, 2021
09b89bf
feat: 최근 검색어를 클릭했을 때 해당 검색어로 검색 되는 기능
yujo11 Mar 6, 2021
b698812
feat: 최근 키워드의 중복을 방지
seojihwan Mar 6, 2021
cdf3df5
feat: 저장 버튼을 클릭했을때 버튼을 숨기는 기능
seojihwan Mar 6, 2021
ddeee30
refactor: button 명시된 default type 제거
seojihwan Mar 6, 2021
8ab75f3
fix: 잘못된 코드 제거
seojihwan Mar 6, 2021
41a7b2d
fix: 새로 검색할 때 skeleton이 비디오 클립 아래에 보이던 오류 수정
seojihwan Mar 6, 2021
5095ab9
feat: queryString을 생성하는 함수 생성 및 적용
yujo11 Mar 6, 2021
95d8982
chore: gitignore 파일 EOL제거
yujo11 Mar 6, 2021
4024866
chore: gitignore 파일 EOL제거
yujo11 Mar 6, 2021
2c1ea44
fix: 저장된 영상 갯수의 text가 정렬되지 않았던 오류
yujo11 Mar 6, 2021
1034df4
Merge branch 'new-yujo-bran' of https://github.com/yujo11/javascript-…
yujo11 Mar 6, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"env": {
"browser": true
},
"extends": ["airbnb-base", "plugin:prettier/recommended"],
"plugins": ["prettier"],
"parserOptions": {
"sourceType": "module"
},
"ignorePatterns": ["cypress/", "dist/"],
"parser": "babel-eslint",
"rules": {
"no-new": "off",
"no-return-assign": "off",
"no-param-reassign": "off",
"import/extensions": "off",
"class-methods-use-this": "off",
"import/prefer-default-export": "off"
}
}
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,10 @@ dist

# TernJS port file
.tern-port

# custom
.DS_Store
.vscode/
cypress/fixtures/*
cypress/plugins/*
cypress/support/*
10 changes: 10 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"semi": true,
"useTabs": false,
"tabWidth": 2,
"printWidth": 80,
"endOfLine": "auto",
"singleQuote": true,
"arrowParens": "always",
"trailingComma": "all"
}
80 changes: 12 additions & 68 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,74 +21,18 @@

### 🎯 step1 검색 기능

- [ ] [유튜브 검색 API](https://developers.google.com/youtube/v3/getting-started?hl=ko)를 통해서, 내가 추가로 보고 싶은 영상들을 검색할 수 있다.
- [ ] 검색 시 엔터키를 눌렀을 때와 마우스로 검색 버튼을 눌렀을 때 검색 동작이 이루어진다.
- [ ] 로딩컴포넌트: 데이터를 불러오는 중일 때, 현재 데이터를 불러오는 중임을 skeleton UI로 보여준다.
- [ ] 검색 결과가 없는 경우 결과 없음 이미지를 추가하여, 사용자에게 메시지를 보여준다.
- [ ] 검색 결과 없음 이미지는 `src/images/status/not_found.png` 경로에 있다.
- [ ] 최초 검색결과는 10개까지만 보여준다. 더 많은 데이터는 스크롤을 내릴 때 추가로 불러온다.
- [x] [유튜브 검색 API](https://developers.google.com/youtube/v3/getting-started?hl=ko)를 통해서, 내가 추가로 보고 싶은 영상들을 검색할 수 있다.
- [x] 검색 시 엔터키를 눌렀을 때와 마우스로 검색 버튼을 눌렀을 때 검색 동작이 이루어진다.
- [x] 로딩컴포넌트: 데이터를 불러오는 중일 때, 현재 데이터를 불러오는 중임을 skeleton UI로 보여준다.
- [x] 검색 결과가 없는 경우 결과 없음 이미지를 추가하여, 사용자에게 메시지를 보여준다.
- [x] 검색 결과 없음 이미지는 `src/images/status/not_found.png` 경로에 있다.
- [x] 최초 검색결과는 10개까지만 보여준다. 더 많은 데이터는 스크롤을 내릴 때 추가로 불러온다.
- 검색 결과 화면에서 유저가 브라우저 스크롤 바를 끝까지 이동시켰을 경우, 그다음 10개 아이템을 추가로 api요청하여 불러온다.
- [ ] 내가 검색한 영상들의 json 데이터를 `저장`할 수 있다. (실제 저장이 아닌 영상 id를 Web Storage에 저장). 단 이미 저장된 경우는 저장 버튼이 보이지 않게 한다.
- [ ] 저장 가능한 최대 동영상의 갯수는 100개이다.
- [ ] 검색 모달에 다시 접근했을 때 가장 마지막에 검색한 키워드로 검색한 결과를 보여준다.
- [ ] 최근 검색 키워드를 3개까지 화면상에 검색창 하단에 보여준다.
- [x] 내가 검색한 영상들의 json 데이터를 `저장`할 수 있다. (실제 저장이 아닌 영상 id를 Web Storage에 저장). 단 이미 저장된 경우는 저장 버튼이 보이지 않게 한다.
- [x] 저장 가능한 최대 동영상의 갯수는 100개이다.
- [x] 검색 모달에 다시 접근했을 때 가장 마지막에 검색한 키워드로 검색한 결과를 보여준다.
- [x] 최근 검색 키워드를 3개까지 화면상에 검색창 하단에 보여준다.

### 🎯🎯 step2 강의실 관리 기능
### 🗂 코드 구조 시각화

- [ ] 가장 처음에는 저장된 영상이 없음으로, 비어있다는 것을 사용자에게 알려주는 상태를 보여준다.
- [ ] 이후 페이지를 방문했을 때 기본 메인 화면은 내가 **볼 영상**들의 리스트를 보여준다.
- [ ] 영상 카드의 이모지 버튼을 클릭하여 아래와 같은 상태 변경이 가능해야 한다.
- [ ] ✅ 본 영상으로 체크
- [ ] 🗑️ 버튼으로 저장된 리스트에서 삭제할 수 있습니다. (삭제 시 사용자에게 정말 삭제할 것인지 물어봅니다.)
- [ ] 사용자가 버튼을 클릭했을 때 해당 행위가 정상적으로 동작하거나, 실패하였음을 `snackbar`를 통해 보여준다.
- [ ] 본 영상, 볼 영상 버튼을 눌러 필터링 할 수 있다.

### 🎯🎯🎯 step3 유저 경험 증가 기능

- [ ] 내가 본 영상 중 좋은 영상에는 좋아요, 코멘트를 직접 추가할 수 있다. (실제 유튜브 영상에 추가하는 api 사용)
- [ ] 👍 좋아요 API를 이용하여 전송
- [ ] 💬 댓글 API를 이용하여 전송 (댓글 전송을 위한 modal과 form은 스스로 구현합니다.)
- [ ] 좋아요 버튼을 누른 데이터만 필터링해서 보여준다.
- [ ] 다크 모드를 위한 버튼을 만든다. 버튼 ui는 직접 만든다.
- [ ] 모든 글자 색상은 #FFFFFF, 배경 색상은 #000000 로 한정한다.
- [ ] 반응형 웹: 유저가 사용하는 디바이스의 가로 길이에 따라 검색 결과의 row 당 column 개수를 변경한다.
- 992px 이하: 4개
- 768px 이하: 2개
- 576px 이하: 1개
- [ ] 스크롤 페이징 방식을 이용해서 Lazy loading을 개선한다.

<br>

## ⚙️ Before Started

#### <img alt="Tip" src="https://img.shields.io/static/v1.svg?label=&message=Tip&style=flat-square&color=673ab8"> 로컬에서 서버 띄워서 손쉽게 static resources 변경 및 확인하는 방법

로컬에서 웹서버를 띄워 html, css, js 등을 실시간으로 손쉽게 테스트해 볼 수 있습니다. 이를 위해서는 우선 npm이 설치되어 있어야 합니다. 구글에 `npm install` 이란 키워드로 각자의 운영체제에 맞게끔 npm을 설치해주세요. 이후 아래의 명령어를 통해 실시간으로 웹페이지를 테스트해볼 수 있습니다.

```
npm install -g live-server
```

실행은 아래의 커맨드로 할 수 있습니다.

```
live-server 폴더명
```

<br>

## 👏 Contributing

만약 미션 수행 중에 개선사항이 보인다면, 언제든 자유롭게 PR을 보내주세요.

<br>

## 🐞 Bug Report

버그를 발견한다면, [Issues](https://github.com/woowacourse/javascript-youtube-classroom/issues)에 등록해주세요.

<br>

## 📝 License

This project is [MIT](https://github.com/woowacourse/javascript-youtube-classroom/blob/main/LICENSE) licensed.
![](./src/images/readme/youtube_step1.png)
3 changes: 3 additions & 0 deletions cypress.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"baseUrl": "http://localhost:5500"
}
56 changes: 56 additions & 0 deletions cypress/integration/search.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { YOUTUBE } from '../../src/js/utils/constant.js';

describe('유튜브 검색 테스트', () => {
beforeEach(() => {
cy.visit('/');
cy.get('#search-button').click();
});

const typeSearchKeywordAndClickToSubmitButton = (keyword) => {
cy.get('[data-js="youtube-search-modal__input"]').type(keyword);
cy.get('[data-js="youtube-search-modal__submit"]').click();
};

it('우테코를 검색하고 검색 결과가 나타나기 전에 로딩 컴포넌트가 나타나는지 테스트한다.', () => {
typeSearchKeywordAndClickToSubmitButton('우테코');
cy.get('[data-js="youtube-search-modal__skeleton-wrapper"]').should(
'be.visible',
);
});

it('우테코를 검색후 검색 결과가 10개까지 나타나는지 테스트한다.', () => {
typeSearchKeywordAndClickToSubmitButton('우테코');
cy.get('[data-js="youtube-search-modal__clip"]').should(
'have.length',
YOUTUBE.NUMBER_TO_LOAD,
);
});

it('우테코를 검색후 스크롤을 끝까지 내렸을 때 아이템이 추가로 나타나는지 테스트한다.', () => {
typeSearchKeywordAndClickToSubmitButton('우테코');
cy.scrollTo('0%', '100%');
cy.get('[data-js="youtube-search-modal__clip"]').then((clips) => {
expect(clips.length).to.be.greaterThan(YOUTUBE.NUMBER_TO_LOAD);
});
});

it('"8123579823476"를 검색했을 때 결과없음 이미지가 나타나는지 테스트한다.', () => {
typeSearchKeywordAndClickToSubmitButton('8123579823476');
cy.get('[data-js="youtube-search-modal__not-found"]').should('be.visible');
});

it('검색창을 다시 열었을 때 마지막 검색결과가 나오는지 테스트한다.', () => {
typeSearchKeywordAndClickToSubmitButton('우테코');
cy.get('[data-js="youtube-serach-modal__close"]').click();
cy.get('#search-button').click();
cy.get('[data-js="youtube-search-modal__clip"]').should('be.visible');
});

it('검색창의 하단에 최근 검색 키워드 3개가 표시되는지 테스트한다.', () => {
const keywords = ['우', '테', '코'];
keywords.forEach((keyword) => {
typeSearchKeywordAndClickToSubmitButton(keyword);
});
cy.get('[data-js="youtube-search-modal__chip"]').should('have.length', 3);
});
});
Loading