From 885603154094598a37b9f4d6efab6b14a6a7851d Mon Sep 17 00:00:00 2001 From: ChoiByeol Date: Tue, 15 Nov 2022 16:28:18 +0900 Subject: [PATCH 1/9] =?UTF-8?q?feat:=20=EA=B8=B0=EB=B3=B8=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 9 ++ src/App.js | 42 +++++++++ src/components/modal/modal.js | 0 src/components/posts/Editor.js | 51 +++++++++++ src/components/posts/PostEditPage.js | 130 +++++++++++++++++++++++++++ src/components/posts/PostList.js | 38 ++++++++ src/components/posts/PostsPage.js | 30 +++++++ src/components/sidebar/sidebar.js | 0 src/main.js | 5 ++ src/utils/LinkButton.js | 17 ++++ src/utils/api.js | 21 +++++ src/utils/router.js | 22 +++++ src/utils/storage.js | 18 ++++ 13 files changed, 383 insertions(+) create mode 100644 index.html create mode 100644 src/App.js create mode 100644 src/components/modal/modal.js create mode 100644 src/components/posts/Editor.js create mode 100644 src/components/posts/PostEditPage.js create mode 100644 src/components/posts/PostList.js create mode 100644 src/components/posts/PostsPage.js create mode 100644 src/components/sidebar/sidebar.js create mode 100644 src/main.js create mode 100644 src/utils/LinkButton.js create mode 100644 src/utils/api.js create mode 100644 src/utils/router.js create mode 100644 src/utils/storage.js diff --git a/index.html b/index.html new file mode 100644 index 00000000..d147bb2a --- /dev/null +++ b/index.html @@ -0,0 +1,9 @@ + + + Star notion + + +
+ + + diff --git a/src/App.js b/src/App.js new file mode 100644 index 00000000..74753790 --- /dev/null +++ b/src/App.js @@ -0,0 +1,42 @@ +import PostsPage from "./components/posts/PostsPage.js"; +import PostEditPage from "./components/posts/PostEditPage.js"; +import { initRouter } from "./utils/router.js"; + +/* url 규칙 + 루트: postsPage 그리기 + + /posts/{id} - id에 해당하는 post 생성 + /posts/new - 새 post 생성 +*/ +export default function App({ $target }) { + const postsPage = new PostsPage({ + $target, + }); + + const postEditPage = new PostEditPage({ + $target, + initialState: { + postId: "new", + post: { + title: "", + content: "", + }, + }, + }); + + this.route = () => { + $target.innerHTML = ""; + const { pathname } = window.location; + + if (pathname === "/") { + postsPage.setState(); + } else if (pathname.indexOf("/posts/") === 0) { + const [, , postId] = pathname.split("/"); + postEditPage.setState({ postId }); + } + }; + + this.route(); + + initRouter(() => this.route()); +} diff --git a/src/components/modal/modal.js b/src/components/modal/modal.js new file mode 100644 index 00000000..e69de29b diff --git a/src/components/posts/Editor.js b/src/components/posts/Editor.js new file mode 100644 index 00000000..789b625d --- /dev/null +++ b/src/components/posts/Editor.js @@ -0,0 +1,51 @@ +export default function Editor({ + $target, + initialState = { + title: "", + content: "", + }, + onEditing, +}) { + const $editor = document.createElement("div"); + + let isInitialize = false; + + this.state = initialState; + + $target.appendChild($editor); + + this.setState = (nextState) => { + this.state = nextState; + $editor.querySelector("[name=title]").value = this.state.title; + $editor.querySelector("[name=content]").innerHTML = this.state.content; + + this.render(); + }; + + this.render = () => { + if (!isInitialize) { + $editor.innerHTML = ` + + + `; + isInitialize = true; + } + }; + + this.render(); + + $editor.addEventListener("keyup", (e) => { + const { target } = e; + const name = target.getAttribute("name"); + + if (this.state[name] !== undefined) { + const nextState = { + ...this.state, + [name]: target.value, + }; + + this.setState(nextState); + onEditing(this.state); + } + }); +} diff --git a/src/components/posts/PostEditPage.js b/src/components/posts/PostEditPage.js new file mode 100644 index 00000000..29760298 --- /dev/null +++ b/src/components/posts/PostEditPage.js @@ -0,0 +1,130 @@ +import { request } from "../../utils/api.js"; +import { getItem, removeItem, setItem } from "../../utils/storage.js"; +import LinkButton from "../../utils/LinkButton.js"; +import Editor from "./Editor.js"; + +export default function PostEditPage({ $target, initialState }) { + const $page = document.createElement("div"); + + this.state = initialState; + + let postLocalSaveKey = `temp-post-${this.state.postId}`; + + const post = getItem(postLocalSaveKey, { + title: "", + content: "", + }); + + let timer = null; + + const editor = new Editor({ + $target: $page, + initialState: post, + onEditing: (post) => { + /* 연속으로 입력을 하고 있을 때는 계속 이벤트 발생을 지연시키다가 + 입력을 멈췄을 때, 즉, 마지막으로 이벤트가 발생하고 일정 시간이 지났을 때 + 지연시켰던 이벤트를 실행시키는 것 - 디바운스 + 디바운스를 이용하면 이벤트 발생하는 횟수를 줄일 수 있다. -> 성능, 최적화 + */ + if (timer !== null) { + clearTimeout(timer); + } + timer = setTimeout(async () => { + setItem(postLocalSaveKey, { + ...post, + tempSaveDate: new Date(), + }); + + const isNew = this.state.postId === "new"; + if (isNew) { + const createdPost = await request("/posts", { + method: "POST", + body: JSON.stringify(post), + }); + history.replaceState(null, null, `/posts/${createdPost.id}`); + removeItem(postLocalSaveKey); + + this.setState({ + postId: createdPost.id, + }); + } else { + await request(`/posts/${post.id}`, { + method: "PUT", + body: JSON.stringify(post), + }); + removeItem(postLocalSaveKey); + } + }, 2000); + }, + }); + + this.setState = async (nextState) => { + if (this.state.postId !== nextState.postId) { + postLocalSaveKey = `temp-post-${nextState.postId}`; + this.state = nextState; + + if (this.state.postId === "new") { + const post = getItem(postLocalSaveKey, { + title: "", + content: "", + }); + this.render(); + editor.setState(post); + } else { + await fetchPost(); + } + return; + } + + this.state = nextState; + this.render(); + + editor.setState( + this.state.post || { + title: "", + content: "", + } + ); + }; + + this.render = () => { + $target.appendChild($page); + }; + + const fetchPost = async () => { + const { postId } = this.state; + + if (postId !== "new") { + const post = await request(`/posts/${[postId]}`); + console.log(post); + + const tempPost = getItem(postLocalSaveKey, { + title: "", + content: "", + }); + + if (tempPost.tempSaveDate && tempPost.tempSaveDate > post.updated_at) { + if (confirm("저장되지 않은 임시 데이터가 있습니다. 불러올까요?")) { + this.setState({ + ...this.state, + post: tempPost, + }); + return; + } + } + + this.setState({ + ...this.state, + post, + }); + } + }; + + new LinkButton({ + $target: $page, + initialState: { + text: "목록으로 이동", + link: "/", + }, + }); +} diff --git a/src/components/posts/PostList.js b/src/components/posts/PostList.js new file mode 100644 index 00000000..ba4f3253 --- /dev/null +++ b/src/components/posts/PostList.js @@ -0,0 +1,38 @@ +import { push } from "../../utils/router.js"; + +export default function PostList({ $target, initialState }) { + const $postList = document.createElement("div"); + $target.appendChild($postList); + + this.state = initialState; + + this.setState = (nextState) => { + this.state = nextState; + this.render(); + }; + + this.render = () => { + $postList.innerHTML = ` + + `; + }; + + this.render(); + + $postList.addEventListener("click", (e) => { + const $li = e.target.closest("li"); + + if ($li) { + const { id } = $li.dataset; + push(`/posts/${id}`); + } + }); +} diff --git a/src/components/posts/PostsPage.js b/src/components/posts/PostsPage.js new file mode 100644 index 00000000..98365d65 --- /dev/null +++ b/src/components/posts/PostsPage.js @@ -0,0 +1,30 @@ +import { request } from "../../utils/api.js"; +import LinkButton from "../../utils/LinkButton.js"; +import PostList from "./PostList.js"; + +export default function PostsPage({ $target }) { + const $page = document.createElement("div"); + + const postList = new PostList({ + $target: $page, + initialState: [], + }); + + new LinkButton({ + $target: $page, + initialState: { + text: "New Post", + link: "/posts/new", + }, + }); + + this.setState = async () => { + const posts = await request("/posts"); + postList.setState(posts); + this.render(); + }; + + this.render = async () => { + $target.appendChild($page); + }; +} diff --git a/src/components/sidebar/sidebar.js b/src/components/sidebar/sidebar.js new file mode 100644 index 00000000..e69de29b diff --git a/src/main.js b/src/main.js new file mode 100644 index 00000000..3876e42a --- /dev/null +++ b/src/main.js @@ -0,0 +1,5 @@ +import App from "./App.js"; + +const $target = document.querySelector("#app"); + +new App({ $target }); diff --git a/src/utils/LinkButton.js b/src/utils/LinkButton.js new file mode 100644 index 00000000..d102e552 --- /dev/null +++ b/src/utils/LinkButton.js @@ -0,0 +1,17 @@ +import { push } from "./router.js"; + +export default function LinkButton({ $target, initialState }) { + this.state = initialState; + const $linkButton = document.createElement("button"); + $target.appendChild($linkButton); + + this.render = () => { + $linkButton.textContent = this.state.text; + }; + + this.render(); + + $linkButton.addEventListener("click", () => { + push(this.state.link); + }); +} diff --git a/src/utils/api.js b/src/utils/api.js new file mode 100644 index 00000000..1ce371a1 --- /dev/null +++ b/src/utils/api.js @@ -0,0 +1,21 @@ +import { API_END_POINT } from "./url.js"; + +export const request = async (url, options = {}) => { + try { + const res = await fetch(`${API_END_POINT}${url}`, { + ...options, + headers: { + "Content-Type": "application/json", + "x-username": "starchoi", + }, + }); + + if (res.ok) { + return await res.json(); + } + + throw new Error("API 처리 중 뭔가 이상합니다!"); + } catch (e) { + alert(e.message); + } +}; diff --git a/src/utils/router.js b/src/utils/router.js new file mode 100644 index 00000000..0193e3cd --- /dev/null +++ b/src/utils/router.js @@ -0,0 +1,22 @@ +const ROUTE_CHANGE_EVENT_NAME = "route-change"; + +export const initRouter = (onRoute) => { + window.addEventListener(ROUTE_CHANGE_EVENT_NAME, (e) => { + const { nextUrl } = e.detail; + + if (nextUrl) { + history.pushState(null, null, nextUrl); + onRoute(); + } + }); +}; + +export const push = (nextUrl) => { + window.dispatchEvent( + new CustomEvent("route-change", { + detail: { + nextUrl, + }, + }) + ); +}; diff --git a/src/utils/storage.js b/src/utils/storage.js new file mode 100644 index 00000000..5523516f --- /dev/null +++ b/src/utils/storage.js @@ -0,0 +1,18 @@ +const storage = window.localStorage; + +export const getItem = (key, defaultValue) => { + try { + const storedValue = storage.getItem(key); + return storedValue ? JSON.parse(storedValue) : defaultValue; + } catch (e) { + return defaultValue; + } +}; + +export const setItem = (key, value) => { + storage.setItem(key, JSON.stringify(value)); +}; + +export const removeItem = (key) => { + storage.removeItem(key); +}; From 65ba07abee7e4cdf7618660a9582cf9a1f1c497b Mon Sep 17 00:00:00 2001 From: ChoiByeol Date: Wed, 16 Nov 2022 09:44:38 +0900 Subject: [PATCH 2/9] =?UTF-8?q?feat:=20sidebar=20=EA=B5=AC=EC=A1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 1 + src/App.js | 67 +++++++++++++------------ src/components/modal/modalHeader.js | 0 src/components/posts/PostEditPage.js | 4 +- src/components/posts/PostsPage.js | 4 +- src/components/sidebar/sidebar.js | 36 +++++++++++++ src/components/sidebar/sidebarBody.js | 13 +++++ src/components/sidebar/sidebarFooter.js | 15 ++++++ src/components/sidebar/sidebarHeader.js | 15 ++++++ src/style/style.css | 58 +++++++++++++++++++++ 10 files changed, 177 insertions(+), 36 deletions(-) create mode 100644 src/components/modal/modalHeader.js create mode 100644 src/components/sidebar/sidebarBody.js create mode 100644 src/components/sidebar/sidebarFooter.js create mode 100644 src/components/sidebar/sidebarHeader.js create mode 100644 src/style/style.css diff --git a/index.html b/index.html index d147bb2a..129fe0b8 100644 --- a/index.html +++ b/index.html @@ -1,6 +1,7 @@ Star notion +
diff --git a/src/App.js b/src/App.js index 74753790..f13a59e1 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,6 @@ -import PostsPage from "./components/posts/PostsPage.js"; -import PostEditPage from "./components/posts/PostEditPage.js"; +import Sidebar from "./components/sidebar/sidebar.js"; +import PostsPage from "./components/posts/postsPage.js"; +import PostEditPage from "./components/posts/postEditPage.js"; import { initRouter } from "./utils/router.js"; /* url 규칙 @@ -9,34 +10,36 @@ import { initRouter } from "./utils/router.js"; /posts/new - 새 post 생성 */ export default function App({ $target }) { - const postsPage = new PostsPage({ - $target, - }); - - const postEditPage = new PostEditPage({ - $target, - initialState: { - postId: "new", - post: { - title: "", - content: "", - }, - }, - }); - - this.route = () => { - $target.innerHTML = ""; - const { pathname } = window.location; - - if (pathname === "/") { - postsPage.setState(); - } else if (pathname.indexOf("/posts/") === 0) { - const [, , postId] = pathname.split("/"); - postEditPage.setState({ postId }); - } - }; - - this.route(); - - initRouter(() => this.route()); + const sidebar = new Sidebar({ $target, initialState: [] }); + + // const postsPage = new PostsPage({ + // $target, + // }); + + // const postEditPage = new PostEditPage({ + // $target, + // initialState: { + // postId: "new", + // post: { + // title: "", + // content: "", + // }, + // }, + // }); + + // this.route = () => { + // $target.innerHTML = ""; + // const { pathname } = window.location; + + // if (pathname === "/") { + // postsPage.setState(); + // } else if (pathname.indexOf("/posts/") === 0) { + // const [, , postId] = pathname.split("/"); + // postEditPage.setState({ postId }); + // } + // }; + + // this.route(); + + // initRouter(() => this.route()); } diff --git a/src/components/modal/modalHeader.js b/src/components/modal/modalHeader.js new file mode 100644 index 00000000..e69de29b diff --git a/src/components/posts/PostEditPage.js b/src/components/posts/PostEditPage.js index 29760298..a7fdfd4e 100644 --- a/src/components/posts/PostEditPage.js +++ b/src/components/posts/PostEditPage.js @@ -1,7 +1,7 @@ import { request } from "../../utils/api.js"; import { getItem, removeItem, setItem } from "../../utils/storage.js"; -import LinkButton from "../../utils/LinkButton.js"; -import Editor from "./Editor.js"; +import LinkButton from "../../utils/linkButton.js"; +import Editor from "./editor.js"; export default function PostEditPage({ $target, initialState }) { const $page = document.createElement("div"); diff --git a/src/components/posts/PostsPage.js b/src/components/posts/PostsPage.js index 98365d65..0f62f731 100644 --- a/src/components/posts/PostsPage.js +++ b/src/components/posts/PostsPage.js @@ -1,6 +1,6 @@ import { request } from "../../utils/api.js"; -import LinkButton from "../../utils/LinkButton.js"; -import PostList from "./PostList.js"; +import LinkButton from "../../utils/linkButton.js"; +import PostList from "./postList.js"; export default function PostsPage({ $target }) { const $page = document.createElement("div"); diff --git a/src/components/sidebar/sidebar.js b/src/components/sidebar/sidebar.js index e69de29b..29461a70 100644 --- a/src/components/sidebar/sidebar.js +++ b/src/components/sidebar/sidebar.js @@ -0,0 +1,36 @@ +import sidebarHeader from "./sidebarHeader.js"; +import sidebarBody from "./sidebarBody.js"; +import sidebarFooter from "./sidebarFooter.js"; + +export default function Sidebar({ $target, initialState }) { + const $sidebar = document.createElement("div"); + $sidebar.className = "sidebar"; + const $sidebarHeader = document.createElement("div"); + const $sidebarBody = document.createElement("div"); + const $sidebarFooter = document.createElement("div"); + $target.appendChild($sidebar); + + this.state = initialState; + + new sidebarHeader({ + $target: $sidebarHeader, + }); + + new sidebarBody({ + $target: $sidebarBody, + }); + + new sidebarFooter({ + $target: $sidebarFooter, + }); + + this.render = () => { + $target.appendChild($sidebar); + $sidebar.appendChild($sidebarHeader); + $sidebar.appendChild($sidebarBody); + $sidebar.appendChild($sidebarFooter); + console.log("sidebar render"); + }; + + this.render(); +} diff --git a/src/components/sidebar/sidebarBody.js b/src/components/sidebar/sidebarBody.js new file mode 100644 index 00000000..45e2ea15 --- /dev/null +++ b/src/components/sidebar/sidebarBody.js @@ -0,0 +1,13 @@ +export default function sidebarBody({ $target }) { + const $sidebarBody = document.createElement("div"); + $sidebarBody.className = "sidebar-body"; + $target.appendChild($sidebarBody); + + this.render = () => { + $sidebarBody.innerHTML = ` +
document 로딩 예정
+ `; + }; + + this.render(); +} diff --git a/src/components/sidebar/sidebarFooter.js b/src/components/sidebar/sidebarFooter.js new file mode 100644 index 00000000..b44614d9 --- /dev/null +++ b/src/components/sidebar/sidebarFooter.js @@ -0,0 +1,15 @@ +export default function sidebarFooter({ $target }) { + const $sidebarFooter = document.createElement("div"); + $sidebarFooter.className = "sidebar-footer"; + $target.appendChild($sidebarFooter); + + this.render = () => { + $sidebarFooter.innerHTML = ` +
+ + 새 페이지 +
+ `; + }; + + this.render(); +} diff --git a/src/components/sidebar/sidebarHeader.js b/src/components/sidebar/sidebarHeader.js new file mode 100644 index 00000000..f5c46729 --- /dev/null +++ b/src/components/sidebar/sidebarHeader.js @@ -0,0 +1,15 @@ +export default function sidebarHeader({ $target }) { + const $sidebarHeader = document.createElement("div"); + $sidebarHeader.className = "sidebar-header"; + $target.appendChild($sidebarHeader); + + this.render = () => { + $sidebarHeader.innerHTML = ` +
+

최별의 Notion

+
+ `; + }; + + this.render(); +} diff --git a/src/style/style.css b/src/style/style.css new file mode 100644 index 00000000..90ef3fb3 --- /dev/null +++ b/src/style/style.css @@ -0,0 +1,58 @@ +html, +body { + box-sizing: border-box; + margin: 0; +} + +#app { + display: flex; + height: 100vh; +} + +button { + cursor: pointer; + padding: none; + user-select: none; +} + +/* + sidebar 배경색: rgb(250, 250, 249) + sidebar hover 색: rgb(230, 230, 239) + sidebar 눌러진 페이지: rgb(237, 238, 236) +*/ + +/* sidebar */ +.sidebar { + position: relative; + width: 240px; + margin: 0; + background-color: rgb(250, 250, 249); +} + +.sidebar-header { + /* position: fixed; */ + padding: 0 15; +} + +.sidebar-body { + position: relative; + padding: 0 15; +} + +.sidebar-footer { + position: fixed; + width: 240px; + cursor: pointer; + bottom: 0; + border-top: 1px solid rgb(228, 228, 225); + padding: 1.5rem 0; + z-index: 3; +} + +.sidebar-footer div { + padding: 0 15; +} + +.sidebar-footer:hover { + background-color: rgb(230, 230, 239); +} From 583f696807641689488710f85b95ebc8c36d4a49 Mon Sep 17 00:00:00 2001 From: ChoiByeol Date: Thu, 17 Nov 2022 11:25:28 +0900 Subject: [PATCH 3/9] =?UTF-8?q?feat:=20sidebar=20=EB=A0=8C=EB=8D=94?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 15 +++---- src/components/sidebar/sidebar.js | 29 +++++++++---- src/components/sidebar/sidebarBody.js | 58 +++++++++++++++++++++++-- src/components/sidebar/sidebarFooter.js | 15 ++++++- src/components/sidebar/sidebarHeader.js | 2 +- src/utils/api.js | 5 +-- 6 files changed, 97 insertions(+), 27 deletions(-) diff --git a/src/App.js b/src/App.js index f13a59e1..14ce29bb 100644 --- a/src/App.js +++ b/src/App.js @@ -1,16 +1,11 @@ -import Sidebar from "./components/sidebar/sidebar.js"; -import PostsPage from "./components/posts/postsPage.js"; -import PostEditPage from "./components/posts/postEditPage.js"; +import Sidebar from "./components/sidebar/Sidebar.js"; +import PostsPage from "./components/posts/PostsPage.js"; +import PostEditPage from "./components/posts/PostEditPage.js"; import { initRouter } from "./utils/router.js"; +import { request } from "./utils/api.js"; -/* url 규칙 - 루트: postsPage 그리기 - - /posts/{id} - id에 해당하는 post 생성 - /posts/new - 새 post 생성 -*/ export default function App({ $target }) { - const sidebar = new Sidebar({ $target, initialState: [] }); + const sidebar = new Sidebar({ $target }); // const postsPage = new PostsPage({ // $target, diff --git a/src/components/sidebar/sidebar.js b/src/components/sidebar/sidebar.js index 29461a70..e4d3d75e 100644 --- a/src/components/sidebar/sidebar.js +++ b/src/components/sidebar/sidebar.js @@ -1,8 +1,9 @@ -import sidebarHeader from "./sidebarHeader.js"; -import sidebarBody from "./sidebarBody.js"; -import sidebarFooter from "./sidebarFooter.js"; +import SidebarHeader from "./SidebarHeader.js"; +import SidebarBody from "./SidebarBody.js"; +import SidebarFooter from "./SidebarFooter.js"; +import { request } from "../../utils/api.js"; -export default function Sidebar({ $target, initialState }) { +export default function Sidebar({ $target }) { const $sidebar = document.createElement("div"); $sidebar.className = "sidebar"; const $sidebarHeader = document.createElement("div"); @@ -10,17 +11,28 @@ export default function Sidebar({ $target, initialState }) { const $sidebarFooter = document.createElement("div"); $target.appendChild($sidebar); - this.state = initialState; + this.init = async () => { + this.state = await request("/documents", { + method: "GET", + }); + sidebarBody.setState(this.state); + console.log("data GET", this.state); + }; + + this.init(); - new sidebarHeader({ + new SidebarHeader({ $target: $sidebarHeader, }); - new sidebarBody({ + const sidebarBody = new SidebarBody({ $target: $sidebarBody, + initialState: this.state, }); - new sidebarFooter({ + sidebarBody.setState(this.state); + + new SidebarFooter({ $target: $sidebarFooter, }); @@ -30,6 +42,7 @@ export default function Sidebar({ $target, initialState }) { $sidebar.appendChild($sidebarBody); $sidebar.appendChild($sidebarFooter); console.log("sidebar render"); + console.log(this.state); }; this.render(); diff --git a/src/components/sidebar/sidebarBody.js b/src/components/sidebar/sidebarBody.js index 45e2ea15..4d0afe21 100644 --- a/src/components/sidebar/sidebarBody.js +++ b/src/components/sidebar/sidebarBody.js @@ -1,13 +1,63 @@ -export default function sidebarBody({ $target }) { +export default function SidebarBody({ $target, initialState }) { const $sidebarBody = document.createElement("div"); + const $renderList = document.createElement("div"); $sidebarBody.className = "sidebar-body"; $target.appendChild($sidebarBody); + this.state = initialState; + + this.setState = (nextState) => { + this.state = nextState; + this.render(); + }; + + const renderDocuments = (documents, $renderList) => { + documents.map((e) => { + const $ul = document.createElement("ul"); + const $li = document.createElement("li"); + $li.className = "document-li"; + $li.setAttribute("data-id", e.id); + $li.textContent = e.title; + const $addBtn = document.createElement("button"); + $addBtn.className = "add-btn"; + $addBtn.innerHTML = "+"; + const $deleteBtn = document.createElement("button"); + $deleteBtn.className = "delete-btn"; + $deleteBtn.innerHTML = "x"; + + $renderList.appendChild($ul); + $ul.appendChild($li); + $li.appendChild($addBtn); + $li.appendChild($deleteBtn); + + if (e.documents) { + renderDocuments(e.documents, $ul); + } + }); + + return $renderList.innerHTML; + }; + this.render = () => { - $sidebarBody.innerHTML = ` -
document 로딩 예정
- `; + console.log("sidebarBody state", this.state); + if (this.state) { + $sidebarBody.innerHTML = renderDocuments(this.state, $renderList); + console.log($renderList); + } else { + $sidebarBody.innerHTML = "새 페이지를 눌러 문서를 작성해 주세요!"; + } }; this.render(); + + $sidebarBody.addEventListener("click", (e) => { + const target = e.target; + const dataId = target.closest("li").dataset.id; + console.log(dataId); + if (target.className === "add-btn") { + console.log("$addBtn clicked"); + } else if (target.className === "delete-btn") { + console.log("$deleteBtn clicked"); + } + }); } diff --git a/src/components/sidebar/sidebarFooter.js b/src/components/sidebar/sidebarFooter.js index b44614d9..31f66d9a 100644 --- a/src/components/sidebar/sidebarFooter.js +++ b/src/components/sidebar/sidebarFooter.js @@ -1,4 +1,6 @@ -export default function sidebarFooter({ $target }) { +import { request } from "../../utils/api.js"; + +export default function SidebarFooter({ $target }) { const $sidebarFooter = document.createElement("div"); $sidebarFooter.className = "sidebar-footer"; $target.appendChild($sidebarFooter); @@ -12,4 +14,15 @@ export default function sidebarFooter({ $target }) { }; this.render(); + + $sidebarFooter.addEventListener("click", async (e) => { + await request("/documents", { + method: "POST", + body: JSON.stringify({ + title: "test", + parent: null, + }), + }); + console.log("sidebarFooter clicked"); + }); } diff --git a/src/components/sidebar/sidebarHeader.js b/src/components/sidebar/sidebarHeader.js index f5c46729..aa7dabc4 100644 --- a/src/components/sidebar/sidebarHeader.js +++ b/src/components/sidebar/sidebarHeader.js @@ -1,4 +1,4 @@ -export default function sidebarHeader({ $target }) { +export default function SidebarHeader({ $target }) { const $sidebarHeader = document.createElement("div"); $sidebarHeader.className = "sidebar-header"; $target.appendChild($sidebarHeader); diff --git a/src/utils/api.js b/src/utils/api.js index 1ce371a1..f1067df9 100644 --- a/src/utils/api.js +++ b/src/utils/api.js @@ -1,8 +1,8 @@ -import { API_END_POINT } from "./url.js"; +import { NOTION_API } from "./url.js"; export const request = async (url, options = {}) => { try { - const res = await fetch(`${API_END_POINT}${url}`, { + const res = await fetch(`${NOTION_API}${url}`, { ...options, headers: { "Content-Type": "application/json", @@ -13,7 +13,6 @@ export const request = async (url, options = {}) => { if (res.ok) { return await res.json(); } - throw new Error("API 처리 중 뭔가 이상합니다!"); } catch (e) { alert(e.message); From 62281e6a492fc92c1dc56f338e9a010d0bbed62e Mon Sep 17 00:00:00 2001 From: ChoiByeol Date: Thu, 17 Nov 2022 11:27:02 +0900 Subject: [PATCH 4/9] design: sidebar style --- src/style/style.css | 47 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/src/style/style.css b/src/style/style.css index 90ef3fb3..c30c6a78 100644 --- a/src/style/style.css +++ b/src/style/style.css @@ -11,14 +11,22 @@ body { button { cursor: pointer; - padding: none; + border: 0; + padding: 0; + font-size: 1rem; + background: none; user-select: none; } +ul { + padding: 0 15; + margin: 5 0; +} + /* sidebar 배경색: rgb(250, 250, 249) - sidebar hover 색: rgb(230, 230, 239) - sidebar 눌러진 페이지: rgb(237, 238, 236) + sidebar hover 색: rgb(230, 230, 230) + sidebar 눌러진 페이지: rgb(238, 238, 238) */ /* sidebar */ @@ -26,17 +34,40 @@ button { position: relative; width: 240px; margin: 0; + overflow: hidden; background-color: rgb(250, 250, 249); } .sidebar-header { - /* position: fixed; */ + position: flex; padding: 0 15; } .sidebar-body { - position: relative; + overflow-y: scroll; + height: 80vh; padding: 0 15; + margin-top: -0.5rem; +} + +.document-li { + width: 100%; + padding: 5 10; +} + +.document-li:hover { + background-color: rgb(230, 230, 230); +} + +.add-btn { + margin-left: 6rem; + margin-right: 1rem; +} + +.delete-btn { + position: relative; + font-size: 0.9rem; + top: -1.5; } .sidebar-footer { @@ -44,9 +75,9 @@ button { width: 240px; cursor: pointer; bottom: 0; - border-top: 1px solid rgb(228, 228, 225); padding: 1.5rem 0; - z-index: 3; + border-top: 1px solid rgb(228, 228, 225); + background: rgb(250, 250, 249); } .sidebar-footer div { @@ -54,5 +85,5 @@ button { } .sidebar-footer:hover { - background-color: rgb(230, 230, 239); + background-color: rgb(230, 230, 230); } From 082788a079d64678873ca46de8987db10e3e616d Mon Sep 17 00:00:00 2001 From: ChoiByeol Date: Thu, 17 Nov 2022 13:39:21 +0900 Subject: [PATCH 5/9] =?UTF-8?q?feat:=20sidebar=20document=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/sidebar/sidebarBody.js | 26 ++++++++++++++++++++++--- src/components/sidebar/sidebarFooter.js | 7 ++++--- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/components/sidebar/sidebarBody.js b/src/components/sidebar/sidebarBody.js index 4d0afe21..63860adb 100644 --- a/src/components/sidebar/sidebarBody.js +++ b/src/components/sidebar/sidebarBody.js @@ -1,8 +1,9 @@ +import { request } from "../../utils/api.js"; + export default function SidebarBody({ $target, initialState }) { const $sidebarBody = document.createElement("div"); const $renderList = document.createElement("div"); $sidebarBody.className = "sidebar-body"; - $target.appendChild($sidebarBody); this.state = initialState; @@ -11,6 +12,22 @@ export default function SidebarBody({ $target, initialState }) { this.render(); }; + const addDocumnet = async (dataId) => { + await request("/documents", { + method: "POST", + body: JSON.stringify({ + title: "test", + parent: dataId, + }), + }); + }; + + const deleteDocument = async (dataId) => { + await request(`/documents/${dataId}`, { + method: "DELETE", + }); + }; + const renderDocuments = (documents, $renderList) => { documents.map((e) => { const $ul = document.createElement("ul"); @@ -40,6 +57,7 @@ export default function SidebarBody({ $target, initialState }) { this.render = () => { console.log("sidebarBody state", this.state); + $target.appendChild($sidebarBody); if (this.state) { $sidebarBody.innerHTML = renderDocuments(this.state, $renderList); console.log($renderList); @@ -55,9 +73,11 @@ export default function SidebarBody({ $target, initialState }) { const dataId = target.closest("li").dataset.id; console.log(dataId); if (target.className === "add-btn") { - console.log("$addBtn clicked"); + addDocumnet(dataId); + console.log("$addBtn clicked", dataId); } else if (target.className === "delete-btn") { - console.log("$deleteBtn clicked"); + deleteDocument(dataId); + console.log("$deleteBtn clicked", dataId); } }); } diff --git a/src/components/sidebar/sidebarFooter.js b/src/components/sidebar/sidebarFooter.js index 31f66d9a..9e67a8fe 100644 --- a/src/components/sidebar/sidebarFooter.js +++ b/src/components/sidebar/sidebarFooter.js @@ -15,7 +15,7 @@ export default function SidebarFooter({ $target }) { this.render(); - $sidebarFooter.addEventListener("click", async (e) => { + const addNewDocument = async () => { await request("/documents", { method: "POST", body: JSON.stringify({ @@ -23,6 +23,7 @@ export default function SidebarFooter({ $target }) { parent: null, }), }); - console.log("sidebarFooter clicked"); - }); + }; + + $sidebarFooter.addEventListener("click", addNewDocument); } From d30aff54e1fefb772c3503c1bb1e0a51113440c3 Mon Sep 17 00:00:00 2001 From: ChoiByeol Date: Thu, 17 Nov 2022 19:40:41 +0900 Subject: [PATCH 6/9] =?UTF-8?q?feat:=20editor=20=EB=A0=8C=EB=8D=94?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 55 ++++++++++++------------- src/components/posts/Editor.js | 17 +++----- src/components/posts/PostEditPage.js | 29 +++++-------- src/components/posts/PostList.js | 7 ++-- src/components/posts/PostsPage.js | 15 ++++--- src/components/sidebar/sidebar.js | 18 ++------ src/components/sidebar/sidebarBody.js | 27 +++++++----- src/components/sidebar/sidebarFooter.js | 9 +--- src/components/sidebar/sidebarHeader.js | 2 + src/style/style.css | 18 +++++++- src/utils/router.js | 3 +- 11 files changed, 97 insertions(+), 103 deletions(-) diff --git a/src/App.js b/src/App.js index 14ce29bb..980b9024 100644 --- a/src/App.js +++ b/src/App.js @@ -1,40 +1,39 @@ import Sidebar from "./components/sidebar/Sidebar.js"; -import PostsPage from "./components/posts/PostsPage.js"; import PostEditPage from "./components/posts/PostEditPage.js"; import { initRouter } from "./utils/router.js"; -import { request } from "./utils/api.js"; export default function App({ $target }) { - const sidebar = new Sidebar({ $target }); + const $sidebar = document.createElement("div"); + const $postEditPage = document.createElement("div"); - // const postsPage = new PostsPage({ - // $target, - // }); + $target.appendChild($sidebar); + $target.appendChild($postEditPage); - // const postEditPage = new PostEditPage({ - // $target, - // initialState: { - // postId: "new", - // post: { - // title: "", - // content: "", - // }, - // }, - // }); + const sidebar = new Sidebar({ $target: $sidebar }); - // this.route = () => { - // $target.innerHTML = ""; - // const { pathname } = window.location; + const postEditPage = new PostEditPage({ + $target: $postEditPage, + initialState: { + postId: "new", + post: { + title: "", + content: "", + }, + }, + }); - // if (pathname === "/") { - // postsPage.setState(); - // } else if (pathname.indexOf("/posts/") === 0) { - // const [, , postId] = pathname.split("/"); - // postEditPage.setState({ postId }); - // } - // }; + this.route = () => { + console.log("$sidebar", $sidebar); + const { pathname } = window.location; + if (pathname.indexOf("/documents/") === 0) { + const [, , postId] = pathname.split("/"); + postEditPage.setState({ postId }); + } else { + sidebar.setState(); + } + }; - // this.route(); + this.route(); - // initRouter(() => this.route()); + initRouter(() => this.route()); } diff --git a/src/components/posts/Editor.js b/src/components/posts/Editor.js index 789b625d..23d7de73 100644 --- a/src/components/posts/Editor.js +++ b/src/components/posts/Editor.js @@ -7,29 +7,22 @@ export default function Editor({ onEditing, }) { const $editor = document.createElement("div"); - - let isInitialize = false; + $editor.className = "editor"; + $target.appendChild($editor); this.state = initialState; - $target.appendChild($editor); - this.setState = (nextState) => { this.state = nextState; $editor.querySelector("[name=title]").value = this.state.title; $editor.querySelector("[name=content]").innerHTML = this.state.content; - - this.render(); }; this.render = () => { - if (!isInitialize) { - $editor.innerHTML = ` - - + $editor.innerHTML = ` + + `; - isInitialize = true; - } }; this.render(); diff --git a/src/components/posts/PostEditPage.js b/src/components/posts/PostEditPage.js index a7fdfd4e..a1ab1e87 100644 --- a/src/components/posts/PostEditPage.js +++ b/src/components/posts/PostEditPage.js @@ -1,10 +1,10 @@ import { request } from "../../utils/api.js"; import { getItem, removeItem, setItem } from "../../utils/storage.js"; -import LinkButton from "../../utils/linkButton.js"; -import Editor from "./editor.js"; +import Editor from "./Editor.js"; export default function PostEditPage({ $target, initialState }) { - const $page = document.createElement("div"); + const $postEditPage = document.createElement("div"); + $postEditPage.className = "post-edit-page"; this.state = initialState; @@ -18,8 +18,9 @@ export default function PostEditPage({ $target, initialState }) { let timer = null; const editor = new Editor({ - $target: $page, + $target: $postEditPage, initialState: post, + onEditing: (post) => { /* 연속으로 입력을 하고 있을 때는 계속 이벤트 발생을 지연시키다가 입력을 멈췄을 때, 즉, 마지막으로 이벤트가 발생하고 일정 시간이 지났을 때 @@ -37,24 +38,24 @@ export default function PostEditPage({ $target, initialState }) { const isNew = this.state.postId === "new"; if (isNew) { - const createdPost = await request("/posts", { + const createdPost = await request("/documents", { method: "POST", body: JSON.stringify(post), }); - history.replaceState(null, null, `/posts/${createdPost.id}`); + history.replaceState(null, null, `/documents/${createdPost.id}`); removeItem(postLocalSaveKey); this.setState({ postId: createdPost.id, }); } else { - await request(`/posts/${post.id}`, { + await request(`/documents/${post.id}`, { method: "PUT", body: JSON.stringify(post), }); removeItem(postLocalSaveKey); } - }, 2000); + }, 1000); }, }); @@ -88,14 +89,14 @@ export default function PostEditPage({ $target, initialState }) { }; this.render = () => { - $target.appendChild($page); + $target.appendChild($postEditPage); }; const fetchPost = async () => { const { postId } = this.state; if (postId !== "new") { - const post = await request(`/posts/${[postId]}`); + const post = await request(`/documents/${[postId]}`); console.log(post); const tempPost = getItem(postLocalSaveKey, { @@ -119,12 +120,4 @@ export default function PostEditPage({ $target, initialState }) { }); } }; - - new LinkButton({ - $target: $page, - initialState: { - text: "목록으로 이동", - link: "/", - }, - }); } diff --git a/src/components/posts/PostList.js b/src/components/posts/PostList.js index ba4f3253..66c2b02e 100644 --- a/src/components/posts/PostList.js +++ b/src/components/posts/PostList.js @@ -2,6 +2,7 @@ import { push } from "../../utils/router.js"; export default function PostList({ $target, initialState }) { const $postList = document.createElement("div"); + $postList.className = "post-list"; $target.appendChild($postList); this.state = initialState; @@ -16,8 +17,8 @@ export default function PostList({ $target, initialState }) {
    ${this.state .map( - (post) => ` -
  • ${post.title}
  • + (document) => ` +
  • ${document.title}
  • ` ) .join("")} @@ -32,7 +33,7 @@ export default function PostList({ $target, initialState }) { if ($li) { const { id } = $li.dataset; - push(`/posts/${id}`); + push(`/documents/${id}`); } }); } diff --git a/src/components/posts/PostsPage.js b/src/components/posts/PostsPage.js index 0f62f731..9be1a5a0 100644 --- a/src/components/posts/PostsPage.js +++ b/src/components/posts/PostsPage.js @@ -1,17 +1,20 @@ import { request } from "../../utils/api.js"; -import LinkButton from "../../utils/linkButton.js"; -import PostList from "./postList.js"; +import LinkButton from "../../utils/button.js"; +import PostList from "./PostList.js"; export default function PostsPage({ $target }) { - const $page = document.createElement("div"); + const $postsPage = document.createElement("div"); + $postsPage.className = "posts-page"; const postList = new PostList({ - $target: $page, + $target: $postsPage, initialState: [], }); + console.log("postsPage"); + new LinkButton({ - $target: $page, + $target: $postsPage, initialState: { text: "New Post", link: "/posts/new", @@ -25,6 +28,6 @@ export default function PostsPage({ $target }) { }; this.render = async () => { - $target.appendChild($page); + $target.appendChild($postsPage); }; } diff --git a/src/components/sidebar/sidebar.js b/src/components/sidebar/sidebar.js index e4d3d75e..9b264d6d 100644 --- a/src/components/sidebar/sidebar.js +++ b/src/components/sidebar/sidebar.js @@ -9,17 +9,6 @@ export default function Sidebar({ $target }) { const $sidebarHeader = document.createElement("div"); const $sidebarBody = document.createElement("div"); const $sidebarFooter = document.createElement("div"); - $target.appendChild($sidebar); - - this.init = async () => { - this.state = await request("/documents", { - method: "GET", - }); - sidebarBody.setState(this.state); - console.log("data GET", this.state); - }; - - this.init(); new SidebarHeader({ $target: $sidebarHeader, @@ -27,10 +16,11 @@ export default function Sidebar({ $target }) { const sidebarBody = new SidebarBody({ $target: $sidebarBody, - initialState: this.state, }); - sidebarBody.setState(this.state); + this.setState = () => { + sidebarBody.setState(); + }; new SidebarFooter({ $target: $sidebarFooter, @@ -41,8 +31,6 @@ export default function Sidebar({ $target }) { $sidebar.appendChild($sidebarHeader); $sidebar.appendChild($sidebarBody); $sidebar.appendChild($sidebarFooter); - console.log("sidebar render"); - console.log(this.state); }; this.render(); diff --git a/src/components/sidebar/sidebarBody.js b/src/components/sidebar/sidebarBody.js index 63860adb..4e34130f 100644 --- a/src/components/sidebar/sidebarBody.js +++ b/src/components/sidebar/sidebarBody.js @@ -1,31 +1,39 @@ import { request } from "../../utils/api.js"; +import { push } from "../../utils/router.js"; -export default function SidebarBody({ $target, initialState }) { +export default function SidebarBody({ $target }) { const $sidebarBody = document.createElement("div"); const $renderList = document.createElement("div"); $sidebarBody.className = "sidebar-body"; + $target.appendChild($sidebarBody); - this.state = initialState; - - this.setState = (nextState) => { - this.state = nextState; + this.setState = async () => { + this.state = await request("/documents", { + method: "GET", + }); + console.log("data GET", this.state); this.render(); }; const addDocumnet = async (dataId) => { - await request("/documents", { + const newDocument = await request("/documents", { method: "POST", body: JSON.stringify({ - title: "test", + title: "제목", parent: dataId, }), }); + $renderList.innerHTML = ""; + this.setState(); + push(`/documents/${newDocument.id}`); }; const deleteDocument = async (dataId) => { await request(`/documents/${dataId}`, { method: "DELETE", }); + $renderList.innerHTML = ""; + push("/"); }; const renderDocuments = (documents, $renderList) => { @@ -56,11 +64,8 @@ export default function SidebarBody({ $target, initialState }) { }; this.render = () => { - console.log("sidebarBody state", this.state); - $target.appendChild($sidebarBody); if (this.state) { $sidebarBody.innerHTML = renderDocuments(this.state, $renderList); - console.log($renderList); } else { $sidebarBody.innerHTML = "새 페이지를 눌러 문서를 작성해 주세요!"; } @@ -78,6 +83,8 @@ export default function SidebarBody({ $target, initialState }) { } else if (target.className === "delete-btn") { deleteDocument(dataId); console.log("$deleteBtn clicked", dataId); + } else if (dataId) { + push(`/documents/${dataId}`); } }); } diff --git a/src/components/sidebar/sidebarFooter.js b/src/components/sidebar/sidebarFooter.js index 9e67a8fe..f14fb4c0 100644 --- a/src/components/sidebar/sidebarFooter.js +++ b/src/components/sidebar/sidebarFooter.js @@ -1,4 +1,5 @@ import { request } from "../../utils/api.js"; +import { push } from "../../utils/router.js"; export default function SidebarFooter({ $target }) { const $sidebarFooter = document.createElement("div"); @@ -16,13 +17,7 @@ export default function SidebarFooter({ $target }) { this.render(); const addNewDocument = async () => { - await request("/documents", { - method: "POST", - body: JSON.stringify({ - title: "test", - parent: null, - }), - }); + push("/documents/new"); }; $sidebarFooter.addEventListener("click", addNewDocument); diff --git a/src/components/sidebar/sidebarHeader.js b/src/components/sidebar/sidebarHeader.js index aa7dabc4..ef9f515a 100644 --- a/src/components/sidebar/sidebarHeader.js +++ b/src/components/sidebar/sidebarHeader.js @@ -1,3 +1,5 @@ +import { push } from "../../utils/router.js"; + export default function SidebarHeader({ $target }) { const $sidebarHeader = document.createElement("div"); $sidebarHeader.className = "sidebar-header"; diff --git a/src/style/style.css b/src/style/style.css index c30c6a78..8ecf3d29 100644 --- a/src/style/style.css +++ b/src/style/style.css @@ -52,7 +52,7 @@ ul { .document-li { width: 100%; - padding: 5 10; + padding: 5 20; } .document-li:hover { @@ -60,7 +60,7 @@ ul { } .add-btn { - margin-left: 6rem; + margin-left: 6.5rem; margin-right: 1rem; } @@ -87,3 +87,17 @@ ul { .sidebar-footer:hover { background-color: rgb(230, 230, 230); } + +/* posts */ +.editor { + position: relative; + display: flex; + flex-direction: column; +} + +.post-edit-page { + flex-direction: row; + justify-content: center; + width: 1200px; + background: white; +} diff --git a/src/utils/router.js b/src/utils/router.js index 0193e3cd..145f6caa 100644 --- a/src/utils/router.js +++ b/src/utils/router.js @@ -3,7 +3,6 @@ const ROUTE_CHANGE_EVENT_NAME = "route-change"; export const initRouter = (onRoute) => { window.addEventListener(ROUTE_CHANGE_EVENT_NAME, (e) => { const { nextUrl } = e.detail; - if (nextUrl) { history.pushState(null, null, nextUrl); onRoute(); @@ -13,7 +12,7 @@ export const initRouter = (onRoute) => { export const push = (nextUrl) => { window.dispatchEvent( - new CustomEvent("route-change", { + new CustomEvent(ROUTE_CHANGE_EVENT_NAME, { detail: { nextUrl, }, From 6fa22652542c905a27cedbcad3f8020483995fcc Mon Sep 17 00:00:00 2001 From: ChoiByeol Date: Thu, 17 Nov 2022 20:48:11 +0900 Subject: [PATCH 7/9] =?UTF-8?q?design:=20style=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/posts/Editor.js | 4 +-- src/style/style.css | 53 ++++++++++++++++++++++++++-------- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/components/posts/Editor.js b/src/components/posts/Editor.js index 23d7de73..ae8551d7 100644 --- a/src/components/posts/Editor.js +++ b/src/components/posts/Editor.js @@ -20,8 +20,8 @@ export default function Editor({ this.render = () => { $editor.innerHTML = ` - - + + `; }; diff --git a/src/style/style.css b/src/style/style.css index 8ecf3d29..5d00457b 100644 --- a/src/style/style.css +++ b/src/style/style.css @@ -10,6 +10,7 @@ body { } button { + display: relative; cursor: pointer; border: 0; padding: 0; @@ -45,9 +46,10 @@ ul { .sidebar-body { overflow-y: scroll; + overflow-x: hidden; height: 80vh; - padding: 0 15; - margin-top: -0.5rem; + padding: 1rem 15; + padding-top: 1rem; } .document-li { @@ -60,14 +62,19 @@ ul { } .add-btn { - margin-left: 6.5rem; - margin-right: 1rem; + position: absolute; + padding: 0.5rem 1rem; + right: 0; + margin-top: -0.5rem; + margin-right: 0.5rem; } .delete-btn { - position: relative; + position: absolute; + padding: 0.5rem 1rem; + right: 1.7rem; + margin-top: -0.5rem; font-size: 0.9rem; - top: -1.5; } .sidebar-footer { @@ -89,15 +96,37 @@ ul { } /* posts */ +.post-edit-page { + display: flex; + flex-direction: row; + justify-content: center; + width: 100vh; + background: white; +} + .editor { position: relative; - display: flex; + border: 0; + cursor: text; flex-direction: column; + margin-left: 1rem; } -.post-edit-page { - flex-direction: row; - justify-content: center; - width: 1200px; - background: white; +.editor-title { + position: relative; + border: 0; + width: 100%; + font-size: 3.5rem; + font-weight: 500; + text-align: center; + padding: 3rem; + margin-top: 2rem; +} + +.editor-content { + border: 0; + width: 100%; + font-size: 1rem; + margin-top: 5vh; + padding: 3rem; } From 022a5bbdbcd887e021ac7b6add764942d01e3e03 Mon Sep 17 00:00:00 2001 From: ChoiByeol Date: Thu, 17 Nov 2022 20:58:41 +0900 Subject: [PATCH 8/9] =?UTF-8?q?refactor:=20=EC=BD=94=EB=93=9C,=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 1 - src/components/modal/modal.js | 0 src/components/modal/modalHeader.js | 0 src/components/posts/PostEditPage.js | 1 - src/components/posts/PostList.js | 39 --------------------------- src/components/posts/PostsPage.js | 33 ----------------------- src/components/sidebar/sidebarBody.js | 4 --- src/utils/LinkButton.js | 17 ------------ 8 files changed, 95 deletions(-) delete mode 100644 src/components/modal/modal.js delete mode 100644 src/components/modal/modalHeader.js delete mode 100644 src/components/posts/PostList.js delete mode 100644 src/components/posts/PostsPage.js delete mode 100644 src/utils/LinkButton.js diff --git a/src/App.js b/src/App.js index 980b9024..34cb3d16 100644 --- a/src/App.js +++ b/src/App.js @@ -23,7 +23,6 @@ export default function App({ $target }) { }); this.route = () => { - console.log("$sidebar", $sidebar); const { pathname } = window.location; if (pathname.indexOf("/documents/") === 0) { const [, , postId] = pathname.split("/"); diff --git a/src/components/modal/modal.js b/src/components/modal/modal.js deleted file mode 100644 index e69de29b..00000000 diff --git a/src/components/modal/modalHeader.js b/src/components/modal/modalHeader.js deleted file mode 100644 index e69de29b..00000000 diff --git a/src/components/posts/PostEditPage.js b/src/components/posts/PostEditPage.js index a1ab1e87..9edac232 100644 --- a/src/components/posts/PostEditPage.js +++ b/src/components/posts/PostEditPage.js @@ -97,7 +97,6 @@ export default function PostEditPage({ $target, initialState }) { if (postId !== "new") { const post = await request(`/documents/${[postId]}`); - console.log(post); const tempPost = getItem(postLocalSaveKey, { title: "", diff --git a/src/components/posts/PostList.js b/src/components/posts/PostList.js deleted file mode 100644 index 66c2b02e..00000000 --- a/src/components/posts/PostList.js +++ /dev/null @@ -1,39 +0,0 @@ -import { push } from "../../utils/router.js"; - -export default function PostList({ $target, initialState }) { - const $postList = document.createElement("div"); - $postList.className = "post-list"; - $target.appendChild($postList); - - this.state = initialState; - - this.setState = (nextState) => { - this.state = nextState; - this.render(); - }; - - this.render = () => { - $postList.innerHTML = ` -
      - ${this.state - .map( - (document) => ` -
    • ${document.title}
    • - ` - ) - .join("")} -
    - `; - }; - - this.render(); - - $postList.addEventListener("click", (e) => { - const $li = e.target.closest("li"); - - if ($li) { - const { id } = $li.dataset; - push(`/documents/${id}`); - } - }); -} diff --git a/src/components/posts/PostsPage.js b/src/components/posts/PostsPage.js deleted file mode 100644 index 9be1a5a0..00000000 --- a/src/components/posts/PostsPage.js +++ /dev/null @@ -1,33 +0,0 @@ -import { request } from "../../utils/api.js"; -import LinkButton from "../../utils/button.js"; -import PostList from "./PostList.js"; - -export default function PostsPage({ $target }) { - const $postsPage = document.createElement("div"); - $postsPage.className = "posts-page"; - - const postList = new PostList({ - $target: $postsPage, - initialState: [], - }); - - console.log("postsPage"); - - new LinkButton({ - $target: $postsPage, - initialState: { - text: "New Post", - link: "/posts/new", - }, - }); - - this.setState = async () => { - const posts = await request("/posts"); - postList.setState(posts); - this.render(); - }; - - this.render = async () => { - $target.appendChild($postsPage); - }; -} diff --git a/src/components/sidebar/sidebarBody.js b/src/components/sidebar/sidebarBody.js index 4e34130f..a10876b7 100644 --- a/src/components/sidebar/sidebarBody.js +++ b/src/components/sidebar/sidebarBody.js @@ -11,7 +11,6 @@ export default function SidebarBody({ $target }) { this.state = await request("/documents", { method: "GET", }); - console.log("data GET", this.state); this.render(); }; @@ -76,13 +75,10 @@ export default function SidebarBody({ $target }) { $sidebarBody.addEventListener("click", (e) => { const target = e.target; const dataId = target.closest("li").dataset.id; - console.log(dataId); if (target.className === "add-btn") { addDocumnet(dataId); - console.log("$addBtn clicked", dataId); } else if (target.className === "delete-btn") { deleteDocument(dataId); - console.log("$deleteBtn clicked", dataId); } else if (dataId) { push(`/documents/${dataId}`); } diff --git a/src/utils/LinkButton.js b/src/utils/LinkButton.js deleted file mode 100644 index d102e552..00000000 --- a/src/utils/LinkButton.js +++ /dev/null @@ -1,17 +0,0 @@ -import { push } from "./router.js"; - -export default function LinkButton({ $target, initialState }) { - this.state = initialState; - const $linkButton = document.createElement("button"); - $target.appendChild($linkButton); - - this.render = () => { - $linkButton.textContent = this.state.text; - }; - - this.render(); - - $linkButton.addEventListener("click", () => { - push(this.state.link); - }); -} From 00114a78ccfc57490f4563aacd5b977f840f0c89 Mon Sep 17 00:00:00 2001 From: ChoiByeol Date: Thu, 17 Nov 2022 21:56:03 +0900 Subject: [PATCH 9/9] =?UTF-8?q?fix:=20style=20=EB=B0=8F=20=EB=B2=84?= =?UTF-8?q?=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 6 +++++- src/components/sidebar/sidebar.js | 10 ++++++---- src/components/sidebar/sidebarBody.js | 1 + src/components/sidebar/sidebarFooter.js | 13 +++++++++++-- src/components/sidebar/sidebarHeader.js | 7 ++++++- src/style/style.css | 1 + 6 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/App.js b/src/App.js index 34cb3d16..a929108e 100644 --- a/src/App.js +++ b/src/App.js @@ -1,6 +1,6 @@ import Sidebar from "./components/sidebar/Sidebar.js"; import PostEditPage from "./components/posts/PostEditPage.js"; -import { initRouter } from "./utils/router.js"; +import { initRouter, push } from "./utils/router.js"; export default function App({ $target }) { const $sidebar = document.createElement("div"); @@ -22,6 +22,10 @@ export default function App({ $target }) { }, }); + // const fetchNewPost = async (postId) => { + // push(`/documents/${postId}`); + // }; + this.route = () => { const { pathname } = window.location; if (pathname.indexOf("/documents/") === 0) { diff --git a/src/components/sidebar/sidebar.js b/src/components/sidebar/sidebar.js index 9b264d6d..28a8bbca 100644 --- a/src/components/sidebar/sidebar.js +++ b/src/components/sidebar/sidebar.js @@ -10,10 +10,6 @@ export default function Sidebar({ $target }) { const $sidebarBody = document.createElement("div"); const $sidebarFooter = document.createElement("div"); - new SidebarHeader({ - $target: $sidebarHeader, - }); - const sidebarBody = new SidebarBody({ $target: $sidebarBody, }); @@ -22,8 +18,14 @@ export default function Sidebar({ $target }) { sidebarBody.setState(); }; + new SidebarHeader({ + $target: $sidebarHeader, + setState: this.setState(), + }); + new SidebarFooter({ $target: $sidebarFooter, + setState: this.setState(), }); this.render = () => { diff --git a/src/components/sidebar/sidebarBody.js b/src/components/sidebar/sidebarBody.js index a10876b7..5c89d095 100644 --- a/src/components/sidebar/sidebarBody.js +++ b/src/components/sidebar/sidebarBody.js @@ -11,6 +11,7 @@ export default function SidebarBody({ $target }) { this.state = await request("/documents", { method: "GET", }); + $renderList.innerHTML = ""; this.render(); }; diff --git a/src/components/sidebar/sidebarFooter.js b/src/components/sidebar/sidebarFooter.js index f14fb4c0..484e7b86 100644 --- a/src/components/sidebar/sidebarFooter.js +++ b/src/components/sidebar/sidebarFooter.js @@ -1,7 +1,7 @@ import { request } from "../../utils/api.js"; import { push } from "../../utils/router.js"; -export default function SidebarFooter({ $target }) { +export default function SidebarFooter({ $target, setState }) { const $sidebarFooter = document.createElement("div"); $sidebarFooter.className = "sidebar-footer"; $target.appendChild($sidebarFooter); @@ -17,7 +17,16 @@ export default function SidebarFooter({ $target }) { this.render(); const addNewDocument = async () => { - push("/documents/new"); + const newDocument = await request("/documents", { + method: "POST", + body: JSON.stringify({ + title: "제목", + parent: null, + }), + }); + setState; + push("/"); + push(`/documents/${newDocument.id}`); }; $sidebarFooter.addEventListener("click", addNewDocument); diff --git a/src/components/sidebar/sidebarHeader.js b/src/components/sidebar/sidebarHeader.js index ef9f515a..7a6ad7ab 100644 --- a/src/components/sidebar/sidebarHeader.js +++ b/src/components/sidebar/sidebarHeader.js @@ -1,6 +1,6 @@ import { push } from "../../utils/router.js"; -export default function SidebarHeader({ $target }) { +export default function SidebarHeader({ $target, setState }) { const $sidebarHeader = document.createElement("div"); $sidebarHeader.className = "sidebar-header"; $target.appendChild($sidebarHeader); @@ -14,4 +14,9 @@ export default function SidebarHeader({ $target }) { }; this.render(); + + $sidebarHeader.addEventListener("click", (e) => { + setState; + push("/"); + }); } diff --git a/src/style/style.css b/src/style/style.css index 5d00457b..7555a9e2 100644 --- a/src/style/style.css +++ b/src/style/style.css @@ -42,6 +42,7 @@ ul { .sidebar-header { position: flex; padding: 0 15; + cursor: pointer; } .sidebar-body {