-
Notifications
You must be signed in to change notification settings - Fork 29
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
[Mission5/우현지] Project_Notion_VanilaJs 과제 #58
base: 4/#5_woohyunji
Are you sure you want to change the base?
Changes from all commits
b6f21cb
6acc8d3
17369a5
3fe3e4e
d73d0a5
74e1024
08125a5
241fa82
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
body { | ||
margin: 0; | ||
} | ||
#app { | ||
width: 100%; | ||
display: flex; | ||
} | ||
.sidebar { | ||
width: 25%; | ||
min-width: 250px; | ||
background-color: rgb(247, 247, 245); | ||
padding: 5px; | ||
} | ||
.sidebar_header { | ||
padding: 8px; | ||
border-bottom: 1px solid black; | ||
} | ||
.sidebar_newDocument { | ||
cursor: pointer; | ||
box-sizing: border-box; | ||
padding: 3px; | ||
} | ||
.sidebar_newDocument:hover { | ||
background-color: rgb(232, 232, 230); | ||
} | ||
|
||
.document_list > ul { | ||
padding-left: 8px; | ||
} | ||
.document_li { | ||
list-style: none; | ||
cursor: pointer; | ||
} | ||
|
||
section { | ||
width: 100%; | ||
padding: 8px; | ||
} | ||
.editor { | ||
display: flex; | ||
flex-direction: column; | ||
width: 100%; | ||
height: 100vh; | ||
} | ||
.title { | ||
flex-grow: 1; | ||
width: 100%; | ||
height: 50px; | ||
margin-bottom: 10px; | ||
padding: 5px 20px; | ||
outline: none; | ||
} | ||
.content { | ||
width: 100%; | ||
height: 100%; | ||
padding: 20px; | ||
outline: none; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>노션 클로닝</title> | ||
<link rel="stylesheet" href="/index.css" /> | ||
</head> | ||
<body> | ||
<div id="app"></div> | ||
<script src="/src/main.js" type="module"></script> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
export const API_END_POINT = 'https://kdt-frontend.programmers.co.kr'; | ||
|
||
export const request = async (url, options = {}) => { | ||
try { | ||
const res = await fetch(`${API_END_POINT}${url}`, { | ||
...options, | ||
headers: { | ||
'x-username': 'whj', | ||
'Content-Type': 'application/json', | ||
}, | ||
}); | ||
if (res.ok) { | ||
return await res.json(); | ||
} | ||
throw new Error('API처리중 문제 발생!!'); | ||
} catch (e) { | ||
console.log(e.message); | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import DocumentListPage from './Sidebar/DocumentListPage.js'; | ||
import EditPage from './Editor/EditPage.js'; | ||
import ListHeader from './Sidebar/ListHeader.js'; | ||
import { request } from '../api.js'; | ||
|
||
export default function App({ $target }) { | ||
const $sidebar = document.createElement('aside'); | ||
$sidebar.className = 'sidebar'; | ||
const $editor = document.createElement('section'); | ||
|
||
new ListHeader({ | ||
$target: $sidebar, | ||
onNewDocument: () => { | ||
console.log('새로운 문서'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. p3; |
||
const nextState = { | ||
documentId: 'new', | ||
parent: null, | ||
}; | ||
editPage.setState(nextState); | ||
}, | ||
}); | ||
|
||
const documentListPage = new DocumentListPage({ | ||
$target: $sidebar, | ||
Comment on lines
+11
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. p3; |
||
onSelectDocument: (documentId) => { | ||
const nextState = { documentId }; | ||
console.log(nextState); | ||
editPage.setState(nextState); | ||
}, | ||
onCreateDocument: (documentId) => { | ||
const parent = documentId; | ||
const nextState = { | ||
documentId: 'new', | ||
parent, | ||
}; | ||
editPage.setState(nextState); | ||
}, | ||
onRemoveDocument: async (documentId) => { | ||
console.log('remove'); | ||
await request(`/documents/${documentId}`, { | ||
method: 'DELETE', | ||
}); | ||
documentListPage.setState(); | ||
}, | ||
Comment on lines
+25
to
+44
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 함수명 설정이 너무 좋은 것 같습니다! 저도 좀 더 구체적으로 정해야겠네요ㅎㅎ 배워가요! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍👍👍👍👍 함수명 덕분에 코드를 이해하기 좋았습니당!! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 👍 👍 👍 👍 👍 👍 👍 |
||
}); | ||
|
||
const editPage = new EditPage({ | ||
$target: $editor, | ||
initialState: { | ||
documentId: 'new', | ||
document: { | ||
title: '', | ||
content: '', | ||
}, | ||
parent: null, | ||
}, | ||
onChange: () => { | ||
documentListPage.setState(); | ||
}, | ||
}); | ||
|
||
this.route = () => { | ||
$target.append($sidebar, $editor); | ||
const { pathname } = window.location; | ||
if (pathname === '/') { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. p4; |
||
documentListPage.setState(); | ||
editPage.render(); | ||
} | ||
}; | ||
this.route(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import { request } from '../../api.js'; | ||
import Editor from './Editor.js'; | ||
|
||
export default function EditPage({ $target, initialState, onChange }) { | ||
const $page = document.createElement('div'); | ||
|
||
this.state = initialState; | ||
|
||
const fetchDocument = async () => { | ||
const { documentId } = this.state; | ||
if (documentId !== 'new') { | ||
const document = await request(`/documents/${documentId}`); //api GET | ||
this.setState({ | ||
...this.state, | ||
document, | ||
}); | ||
} | ||
}; | ||
|
||
let timer = null; | ||
const editor = new Editor({ | ||
$target: $page, | ||
initialState: this.state.document, | ||
onEditing: (document) => { | ||
if (timer !== null) { | ||
clearTimeout(timer); | ||
} | ||
timer = setTimeout(async () => { | ||
const isNew = this.state.documentId === 'new'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 변수명 좋습니다 👍 |
||
if (isNew) { | ||
const createdDocument = await request('/documents', { | ||
method: 'POST', | ||
body: JSON.stringify({ | ||
title: document.title, | ||
parent: this.state.parent, | ||
}), | ||
}); | ||
this.setState({ | ||
documentId: createdDocument.id, | ||
document, | ||
}); | ||
onChange(); | ||
} else { | ||
await request(`/documents/${this.state.documentId}`, { | ||
method: 'PUT', | ||
body: JSON.stringify(document), | ||
}); | ||
} | ||
onChange(); | ||
}, 1000); | ||
}, | ||
}); | ||
|
||
this.setState = async (nextState) => { | ||
if (this.state.documentId !== nextState.documentId) { | ||
this.state = nextState; | ||
if (this.state.documentId === 'new') { | ||
this.render(); | ||
editor.setState({ title: '', content: '' }); | ||
} else { | ||
await fetchDocument(); | ||
} | ||
return; | ||
} | ||
Comment on lines
+55
to
+64
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if가 이중중첩이네요 🤔 |
||
this.state = nextState; | ||
editor.setState(this.state.document || { title: '', content: '' }); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OR연산자 사용하신 거 좋습니당!!! 👍 |
||
}; | ||
|
||
this.render = () => { | ||
$target.appendChild($page); | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,45 @@ | ||||||
export default function Editor({ $target, initialState, onEditing }) { | ||||||
const $editor = document.createElement('form'); | ||||||
$editor.className = 'editor'; | ||||||
$target.appendChild($editor); | ||||||
|
||||||
const $title = document.createElement('input'); | ||||||
$title.className = 'title'; | ||||||
$title.name = 'title'; | ||||||
$title.placeholder = '제목을 작성하세요...'; | ||||||
|
||||||
const $content = document.createElement('textarea'); | ||||||
$content.className = 'content'; | ||||||
$content.name = 'content'; | ||||||
$content.placeholder = '내용을 입력하세요...'; | ||||||
|
||||||
let isInitialize = false; | ||||||
|
||||||
this.state = initialState; | ||||||
this.setState = (nextState) => { | ||||||
this.state = nextState; | ||||||
this.render(); | ||||||
}; | ||||||
|
||||||
$editor.addEventListener('keyup', (e) => { | ||||||
const name = e.target.getAttribute('name'); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이벤트 위임을 잘해주신 것 같아 좋습니다 👍 |
||||||
if (this.state[name] !== undefined) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. p3;
Suggested change
truthy로 처리 가능할 것 같네요 |
||||||
const nextState = { | ||||||
...this.state, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||||||
[name]: e.target.value, | ||||||
}; | ||||||
this.setState(nextState); | ||||||
onEditing(this.state); | ||||||
} | ||||||
}); | ||||||
|
||||||
this.render = () => { | ||||||
if (!isInitialize) { | ||||||
$editor.append($title, $content); | ||||||
isInitialize = true; | ||||||
} | ||||||
$title.value = this.state.title; | ||||||
$content.value = this.state.content; | ||||||
}; | ||||||
this.render(); | ||||||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,73 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export default function DocumentList({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$target, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
initialState, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onSelectDocument, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onCreateDocument, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onRemoveDocument, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const $list = document.createElement('div'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$list.className = 'document_list'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$target.appendChild($list); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (Array.isArray(initialState)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.state = initialState; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+12
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. initialState validation 과정 잊었는데 저도 추가해야겠네요! 👍👍👍 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.setState = (nextState) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.state = nextState; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.render(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.render = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const $ul = document.createElement('ul'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.state.map((documentInfo) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const $li = document.createElement('li'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$li.className = 'document_li'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$li.setAttribute('data-id', documentInfo.id); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const $title = document.createElement('span'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$title.textContent = documentInfo.title; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$title.className = 'title'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$li.appendChild($title); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const $createBtn = document.createElement('button'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$createBtn.textContent = '+'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$createBtn.className = 'createBtn'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$li.appendChild($createBtn); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const $removeBtn = document.createElement('button'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$removeBtn.textContent = '-'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$removeBtn.className = 'removeBtn'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$li.appendChild($removeBtn); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (documentInfo.documents.length > 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
new DocumentList({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$target: $li, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
initialState: documentInfo.documents, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$ul.appendChild($li); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+19
to
+48
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. innerHTML 대신에 appendChild 너무 잘 쓰시는 것 같아요... 저는 피드백 받아도 아직 익숙하지 않네요ㅠㅠ 나중에 기회가 된다면 배워보고 싶네요! |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$list.replaceChildren($ul); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$ul.addEventListener('click', (e) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const $li = e.target.closest('li'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if ($li !== null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const documentId = $li.dataset.id; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// document 선택 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (e.target.className === 'title') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onSelectDocument(documentId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//하위 document 생성 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (e.target.className === 'createBtn') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onCreateDocument(documentId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// document 삭제 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
else if (e.target.className === 'removeBtn') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onRemoveDocument(documentId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+52
to
+70
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이벤트 위임 깔끔하게 잘 된것 같습니다!!
Comment on lines
+53
to
+70
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.render(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { request } from '../../api.js'; | ||
import DocumentList from './DocumentList.js'; | ||
export default function DocumentListPage({ | ||
$target, | ||
onSelectDocument, | ||
onCreateDocument, | ||
onRemoveDocument, | ||
}) { | ||
const $page = document.createElement('div'); | ||
$target.appendChild($page); | ||
|
||
const documentList = new DocumentList({ | ||
$target: $page, | ||
initialState: [], | ||
onSelectDocument, | ||
onCreateDocument, | ||
onRemoveDocument, | ||
}); | ||
|
||
this.setState = async () => { | ||
const documents = await request('/documents'); | ||
documentList.setState(documents); | ||
}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p3;
네이밍 컨벤션을 하나로 통일하면 좋을 듯 합니다.
현재는 snake케이스와 camel케이스가 혼용되어있네요!