-
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_VanillaJs 과제 #46
base: 4/#5_colorkite10_working
Are you sure you want to change the base?
Changes from all commits
194e851
4255ac7
d709e0e
2bc808d
2f75227
1c54656
ba96536
b2d4e9d
4be8e7f
912686c
1f23e72
c9c8484
1223509
d25017c
58316f9
2adfa7b
b3776ca
9b40e5c
495a583
5f3c043
98a5d09
95c463a
76afe40
46ff36b
58df77b
fcdca72
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,13 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head lang="ko"> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, height=device-height" /> | ||
<title>채연스 Notion cloning</title> | ||
</head> | ||
<body> | ||
<main id="notion-app"> | ||
<script src="/src/main.js" type="module"></script> | ||
</main> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { push } from "../routes/router.js"; | ||
|
||
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: { | ||
"Content-Type": "application/json", | ||
"x-username": "colorkite10", | ||
}, | ||
}); | ||
if (res.ok) { | ||
return await res.json(); | ||
} | ||
|
||
throw new Error("API 연결에 오류가 발생했습니다."); | ||
} catch (e) { | ||
Comment on lines
+14
to
+19
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; res.ok가 아닌 경우에는 어떻게 핸들링 하나요? ask; 퀴즈 request 함수 관점에서 |
||
alert(e); | ||
push("/"); | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,74 @@ | ||||||
import { request } from "../api/api.js"; | ||||||
import DocumentPage from "./DocumentPage.js"; | ||||||
import DocumentEditPage from "./DocumentEditPage.js"; | ||||||
import { initRouter } from "../routes/router.js"; | ||||||
|
||||||
export default function App({ $target }) { | ||||||
this.state = { | ||||||
docId: null, | ||||||
docs: [], | ||||||
}; | ||||||
|
||||||
this.setState = (nextState) => { | ||||||
this.state = nextState; | ||||||
documentPage.setState(nextState); | ||||||
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
|
||||||
}; | ||||||
|
||||||
const documentPage = new DocumentPage({ | ||||||
$target, | ||||||
initialState: { | ||||||
docId: null, | ||||||
docs: [], | ||||||
}, | ||||||
}); | ||||||
|
||||||
const documentEditPage = new DocumentEditPage({ | ||||||
$target, | ||||||
initialState: { | ||||||
docId: "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. 이 new라는 부분 때문에 그런건지 모르겠는데, add a document 버튼을 누르면 id가 string 타입으로 들어가고 하위 문서 생성을 하면 id가 number 타입으로 들어가는 것 같은데요! 한 번 확인해보시면 좋을 것 같습니다! 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; docId의 ID가 주로 가지는 의미를 생각해보면 "중복되지 않는 유니크한 값" 이라고 생각돼요. 만약 id 값을 만드는게 막연하다면 uuid 같은 값을 만들어서 부여해보면 어떨까요? |
||||||
doc: { | ||||||
title: "", | ||||||
content: "", | ||||||
}, | ||||||
}, | ||||||
}); | ||||||
|
||||||
this.route = async () => { | ||||||
await fetchDocuments(); | ||||||
|
||||||
const { pathname } = window.location; | ||||||
|
||||||
if (pathname === "/") { | ||||||
$target.innerHTML = ""; | ||||||
documentPage.render(); | ||||||
|
||||||
this.setState({ ...this.state }); | ||||||
} else if (pathname.indexOf("/documents/") === 0) { | ||||||
const [, , docId] = pathname.split("/"); | ||||||
|
||||||
documentEditPage.setState({ docId }); | ||||||
|
||||||
this.setState({ | ||||||
...this.state, | ||||||
docId, | ||||||
}); | ||||||
} | ||||||
}; | ||||||
Comment on lines
+46
to
+56
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. p2; route의 역할을 생각해보면 만약 edit 뿐 아니라 또 다른 페이지들이 생겨난다면..? 이 안에서 if문과 state가 쌓이게 될 것 같은데 그랬을 때 가독성이 나빠질 것 같아요. 여기서는 documentEditPage를 띄우는 것 까지만 하고. |
||||||
|
||||||
const fetchDocuments = async () => { | ||||||
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. P5; fetch라는 의미를 생각해보면 "무언가를 가져온다" 라는 의미를 가지고 있다고 생각해요. 개발적으론 API 등에서 요청해서 가져온다 라는 의미를 가지고 있죠. 그렇다보니 fetch 함수를 호출한다고 했을 때 response 값이 return 될 것이라 기대가 되는데 여기서는 setState 도 하다보니 기대와 정말 같은 행동일까? 하는 생각이 들었어요. 사용하는 곳에서 |
||||||
const docs = await request("/documents", { | ||||||
method: "GET", | ||||||
}); | ||||||
Comment on lines
+59
to
+61
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. fetch 전역 함수에서 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. 생략 가능한 줄 몰랐는데 덕분에 하나 더 알고 갑니다! |
||||||
|
||||||
this.setState({ | ||||||
...this.state, | ||||||
docs, | ||||||
}); | ||||||
}; | ||||||
|
||||||
this.route(); | ||||||
|
||||||
initRouter(() => this.route()); | ||||||
|
||||||
window.addEventListener("popstate", () => this.route()); | ||||||
} |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,168 @@ | ||||||||||
import Editor from "./Editor.js"; | ||||||||||
import { request } from "../api/api.js"; | ||||||||||
import { push } from "../routes/router.js"; | ||||||||||
import { getItem, setItem, removeItem } from "../utils/storage.js"; | ||||||||||
|
||||||||||
export default function DocumentEditPage({ $target, initialState }) { | ||||||||||
const $documentEditPage = document.createElement("div"); | ||||||||||
|
||||||||||
$documentEditPage.className = "documentEditPage"; | ||||||||||
|
||||||||||
$documentEditPage.style.width = "60%"; | ||||||||||
$documentEditPage.style.margin = "auto"; | ||||||||||
|
||||||||||
this.state = initialState; | ||||||||||
|
||||||||||
let docLocalSaveKey = `temp-document-${this.state.docId}`; | ||||||||||
let timer = null; | ||||||||||
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; 이런 timer는 자주 사용되기도 하고 맥락을 명확하게 구분 지으면 좋을 것 같은데! |
||||||||||
|
||||||||||
const editor = new Editor({ | ||||||||||
$target: $documentEditPage, | ||||||||||
initialState: { | ||||||||||
title: "Untitled", | ||||||||||
content: "", | ||||||||||
}, | ||||||||||
onEditing: (doc) => { | ||||||||||
setItem(docLocalSaveKey, { | ||||||||||
...doc, | ||||||||||
tempSaveDate: new Date(), | ||||||||||
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. P5; ask; 제가 잘 몰라서 여쭈어봐요!! 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. 강의에서 임시저장값의 date를 나타내기 위해 사용한 변수명으로 알고 있습니다! |
||||||||||
}); | ||||||||||
|
||||||||||
if (timer !== null) { | ||||||||||
clearTimeout(timer); | ||||||||||
} | ||||||||||
|
||||||||||
timer = setTimeout(async () => { | ||||||||||
const isNew = this.state.docId === "new"; | ||||||||||
if (isNew) { | ||||||||||
if (doc.title === "") { | ||||||||||
doc.title = "Untitled"; | ||||||||||
} | ||||||||||
|
||||||||||
const createDocument = await request("/documents", { | ||||||||||
method: "POST", | ||||||||||
body: JSON.stringify(doc), | ||||||||||
}); | ||||||||||
|
||||||||||
await request(`/documents/${createDocument.id}`, { | ||||||||||
method: "PUT", | ||||||||||
body: JSON.stringify(doc), | ||||||||||
}); | ||||||||||
Comment on lines
+42
to
+50
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. ask; 생성 이후 put를 바로 하는 이유는 무엇인가요? |
||||||||||
|
||||||||||
history.replaceState(null, null, `/documents/${createDocument.id}`); | ||||||||||
removeItem(docLocalSaveKey); | ||||||||||
|
||||||||||
this.setState({ | ||||||||||
docId: createDocument.id, | ||||||||||
}); | ||||||||||
|
||||||||||
push(createDocument.id); | ||||||||||
} else { | ||||||||||
if (doc.title === "") { | ||||||||||
doc.title = "Untitled"; | ||||||||||
} | ||||||||||
await request(`/documents/${doc.id}`, { | ||||||||||
method: "PUT", | ||||||||||
body: JSON.stringify(doc), | ||||||||||
}); | ||||||||||
|
||||||||||
removeItem(docLocalSaveKey); | ||||||||||
} | ||||||||||
}, 1000); | ||||||||||
}, | ||||||||||
}); | ||||||||||
|
||||||||||
this.setState = async (nextState) => { | ||||||||||
if (this.state.docId === "new" && nextState.docId === "new") { | ||||||||||
const tempDocument = await getItem(docLocalSaveKey, { | ||||||||||
title: "Untitled", | ||||||||||
content: "", | ||||||||||
}); | ||||||||||
|
||||||||||
if (tempDocument.title !== "" || tempDocument.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.
Suggested change
똑같이 동작하는 코드인 것 같아서 제안드려봅니다..! 🤔 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. @jgjgill 제 생각에는 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. 소소한 TMI 형변환을 통한 검증도 가능할 것 같아요!
Suggested change
|
||||||||||
this.state = { | ||||||||||
...this.state, | ||||||||||
doc: tempDocument, | ||||||||||
}; | ||||||||||
} else { | ||||||||||
this.state = nextState; | ||||||||||
} | ||||||||||
|
||||||||||
editor.setState(this.state.doc); | ||||||||||
|
||||||||||
this.render(); | ||||||||||
return; | ||||||||||
} | ||||||||||
|
||||||||||
if (this.state.docId !== nextState.docId) { | ||||||||||
docLocalSaveKey = `temp-document-${nextState.docId}`; | ||||||||||
this.state = nextState; | ||||||||||
|
||||||||||
if (this.state.docId === "new") { | ||||||||||
const doc = getItem(docLocalSaveKey, { | ||||||||||
title: "Untitled", | ||||||||||
content: "", | ||||||||||
}); | ||||||||||
|
||||||||||
editor.setState(doc); | ||||||||||
|
||||||||||
this.render(); | ||||||||||
} else { | ||||||||||
await fetchDocument(); | ||||||||||
} | ||||||||||
return; | ||||||||||
} | ||||||||||
|
||||||||||
this.state = nextState; | ||||||||||
|
||||||||||
this.render(); | ||||||||||
|
||||||||||
if (this.state.doc) { | ||||||||||
editor.setState( | ||||||||||
this.state.doc || { | ||||||||||
title: "Untitled", | ||||||||||
content: "", | ||||||||||
} | ||||||||||
); | ||||||||||
} | ||||||||||
}; | ||||||||||
|
||||||||||
const fetchDocument = async () => { | ||||||||||
const { docId } = this.state; | ||||||||||
|
||||||||||
if (this.state !== "new") { | ||||||||||
const doc = await request(`/documents/${docId}`, { | ||||||||||
metohd: "GET", | ||||||||||
}); | ||||||||||
|
||||||||||
if (doc.content === null) doc.content = ""; | ||||||||||
|
||||||||||
const tempDocument = await getItem(docLocalSaveKey, { | ||||||||||
title: "Untitled", | ||||||||||
content: "", | ||||||||||
}); | ||||||||||
|
||||||||||
if ( | ||||||||||
tempDocument.tempSaveDate && | ||||||||||
tempDocument.tempSaveDate > doc.updatedAt | ||||||||||
) { | ||||||||||
if (confirm("임시저장된 값을 불러올까요?")) { | ||||||||||
this.setState({ | ||||||||||
...this.state, | ||||||||||
doc: tempDocument, | ||||||||||
}); | ||||||||||
return; | ||||||||||
} | ||||||||||
Comment on lines
+149
to
+155
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. 저도 임시 저장 기능을 구현한 것은 매우 좋다고 생각돼요!!! 👍 다만 위에 적은 것 처럼 |
||||||||||
} | ||||||||||
|
||||||||||
this.setState({ | ||||||||||
...this.state, | ||||||||||
doc, | ||||||||||
}); | ||||||||||
} | ||||||||||
}; | ||||||||||
|
||||||||||
this.render = () => { | ||||||||||
$target.appendChild($documentEditPage); | ||||||||||
}; | ||||||||||
} |
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.
P1;
이렇게 하게 된다면 headers를 변경하고 싶어도 변경하지 못할 것 같아요.
아래와 같이 headers 또한 수정 가능하게 해두면 어떨까요?