Skip to content
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c1f2afb
initial commit project
Nov 16, 2022
250e899
chore : utils 파일 추가
Nov 16, 2022
940d3f8
feat : Navbar 구현
Nov 16, 2022
137d636
style : Navbar css 작업
Nov 16, 2022
2737c23
feat : Navbar documentList , Header title 구현
Nov 16, 2022
169014c
feat : Editor 컴포넌트 생성
Nov 16, 2022
803bd4f
feat : Editor title 구현
Nov 16, 2022
89ae913
fix : title 랜더링 될때 값 안변하는 현상
Nov 16, 2022
2355c53
feat : Editor Content 구현
Nov 16, 2022
014ee5f
style : 글 목록 , 버튼 css 작업
Nov 16, 2022
74b5a86
refactor : editor.css 버튼 클래스 두번 선언
Nov 16, 2022
409269c
refactor: 컴포넌트 네이밍 변경
Nov 16, 2022
c317732
fix : document 전부 삭제 안되는 현상
Nov 16, 2022
f55b762
docs : README 수정
Nov 16, 2022
bb3acae
fix: 렌더링 하면 2개행 이상부터 안보이는 현상
Nov 16, 2022
db21074
refactor: tabWidth 2로 설정
Nov 16, 2022
abd5f45
feat : 개행 추가
Nov 16, 2022
010431c
style : documentList 버튼 디자인 변경
Nov 17, 2022
7b74168
style : header button style 변경
Nov 17, 2022
27638ce
fix : 404 에러 해결
Nov 19, 2022
61f8ed4
chore : tabWidth 2 변경
Nov 19, 2022
b091456
refactor : tabWidth 2 적용
Nov 19, 2022
720cdfc
feat : 하위 문서 누르면 페이지 이동
Nov 19, 2022
0aa6450
refactor: EditorSubContent 이벤트 함수 분리,네이밍 변경
Nov 20, 2022
634e1a9
refactor: reset.css 모듈화
Nov 20, 2022
5f652f4
feat: EditorSubContent title 비어있을때 제목없음 추가
Nov 20, 2022
95ba0cc
refactor : 코드리뷰 반영
Nov 26, 2022
fd8744e
docs : README 수정
Nov 26, 2022
1c4d05f
refactor : render this 바인딩 제거
Nov 30, 2022
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
27 changes: 27 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# dependencies
/node_modules
/package-lock.json
/.pnp
.pnp.js
/url.js
# intellij configs
.idea/

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*


25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,33 @@

## 필수 프로젝트

글 단위를 Document라고 합니다. Document는 Document 여러개를 포함할 수 있습니다.
- [x] 화면 좌측에 Root Documents를 불러오는 API를 통해 root Documents를 렌더링합니다.
- [x] Root Documents를 클릭하면 오른쪽 편집기 영역에 해당 Docuement의 Content를 렌더링 합니다.
- [x] 해당 Root Document에 하위 Document가 있는 경우 , 해당 Document 아래에 트리 형태로 렌더링 합니다.
- [x] Document Tree에서 각 Document 우측에는 + 버튼이 있습니다. 해당 버튼을 클릭하면 , 클릭한 Document의 하위 Document로 새 Document를 생성하고 편집화면으로 넘깁니다.
- [x] 편집기에는 기본적으로 저장 버튼이 없습니다. Document Save API를 이용해 지속적으로 서버에 저장되도록 합니다.
- [x] History API를 이용해 SPA형태로 만듭니다.
- [x] 루트 URL 접속 시엔 별다른 편집기 선택이 안된 상태입니다.
- [x] /documents/{documentId} 로 접속시 , 해당 Document content를 불러와 편집기에 로딩합니다.
- [x] Header 버튼 클릭하면 정상적으로 새로운 Document 생성되는데 초기값 null 들어가는 현상
- [x] '제목없음' ,'내용없음' 초기에 grey color , input 들어오면 색 변경
- [x] putMethod 404 Error
- [x] Editor content 부분 textarea 값 변경 안되는 현상
- [x] Editor content 부분 입력할때 textarea 2 개행 이상부터 안보이는 현상
- [x] 상위 Document 삭제하면 하위 Document 같이 삭제가 되야 하는데 상위 Document 밑으로 이동 되는 현상
- [x] 상위 Document 삭제하면 최하위 Document 삭제 안되는 현상
- [x] 예외처리 작업, '/documents'-> documentsUrl 변경
- [x] Editor content 부분 textarea 렌더링 했을때 2 개행 이상부터 잘려서 안나오는 현상
- [x] Editor content 일정 개행 이상 넘어가면 title 안보이는 현상
- [x] 버튼 이미지 넣어서 관리 -> 현재 text로 들어가 있음
- [ ] 편집기 하단에는 Documents의 하위 Document 링크를 렌더링하도록 생성
- [ ] onDelete 리팩토링 필요

- 프로젝트 기한
- 프로젝트 수행 기간 : 2022년 11월 8일(화) ~ 2022년 11월 16일(수)
- 멘티 코드 리뷰 기간 : 2022년 11월 17일(목) ~ 2022년 11월 20일(일)
- 멘토 코드 리뷰 기간 : 2022년 11월 17일(목) ~ 2022년 11월 22일(화)
- 코드 리뷰 반영 기간 : 2022년 11월 23일(수) ~ 2022년 11월 25일(금)
- 내용
- **Day 17 [프로젝트] 노션 클로닝 요구사항** 확인 부탁드립니다.
- **Day 17 [프로젝트] 노션 클로닝 요구사항** 확인 부탁드립니다.
13 changes: 13 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
<link rel="stylesheet" href="src/style/index.css" />
</head>
<body>
<div class="app"></div>
<script src="main.js" type="module"></script>
<script src="https://kit.fontawesome.com/982b34221e.js" crossorigin="anonymous"></script>
</body>
</html>
5 changes: 5 additions & 0 deletions main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import App from './src/App.js';

const app = document.querySelector('.app');

new App({ target: app });
33 changes: 33 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "fedc3-4_project_notion_vanillajs",
"version": "1.0.0",
"description": "- 프로젝트 기한\r - 프로젝트 수행 기간 : 2022년 11월 8일(화) ~ 2022년 11월 16일(수)\r - 멘티 코드 리뷰 기간 : 2022년 11월 17일(목) ~ 2022년 11월 20일(일)\r - 멘토 코드 리뷰 기간 : 2022년 11월 17일(목) ~ 2022년 11월 22일(화)\r - 코드 리뷰 반영 기간 : 2022년 11월 23일(수) ~ 2022년 11월 25일(금)\r - 내용\r - **Day 17 [프로젝트] 노션 클로닝 요구사항** 확인 부탁드립니다.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/prgrms-fe-devcourse/FEDC3-4_Project_Notion_VanillaJS.git"
},
"keywords": [],
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/prgrms-fe-devcourse/FEDC3-4_Project_Notion_VanillaJS/issues"
},
"homepage": "https://github.com/prgrms-fe-devcourse/FEDC3-4_Project_Notion_VanillaJS#readme",
"devDependencies": {
"prettier": "2.7.1"
},
"prettier": {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

설정파일을 분리해서 사용하면 이후에 재사용하는데 있어서 용이할거에요 ㅎㅎ

"singleQuote": true,
"semi": true,
"useTabs": false,
"tabWidth": 2,
"trailingComma": "all",
"printWidth": 100,
"bracketSpacing": true,
"arrowParens": "always"
}
}
34 changes: 34 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import Navbar from './Navbar/Navbar.js';
import { documentsUrl } from './utils/util.js';
import { initRouter } from './utils/route.js';
import Editor from './Editor/Editor.js';

function App({ target }) {
const navbarPage = new Navbar({ target });
const postEditPage = new Editor({
target,
initialState: {
title: '',
content: '',
},
});

this.route = async () => {
target.innerHTML = '';
const { pathname } = location;

if (pathname === '/') {
navbarPage.setState();
} else if (pathname.indexOf(`${documentsUrl}/`) === 0) {
const [, , postId] = pathname.split('/');

await navbarPage.setState();
await postEditPage.setState({ postId });
}
};

this.route();
initRouter(() => this.route());
}

export default App;
60 changes: 60 additions & 0 deletions src/Editor/Editor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { createElement } from '../utils/dom.js';
import { isNew, isObject } from '../utils/errorHandler.js';
import { request } from '../utils/api.js';
import { putContentMethod, putTitleMethod } from '../utils/optionsMethod.js';
import EditorTitle from './EditorTitle.js';
import EditorContent from './EditorContent.js';
import { documentsUrl } from '../utils/util.js';
import EditorSubContetn from './EditorSubContetn.js';

function Editor({ target, initialState }) {
isNew(new.target);
const page = createElement('section');
page.className = 'content';

const editor = createElement('div');
editor.className = 'editor';

this.state = initialState;
const postTitle = new EditorTitle({
div: editor,
initialState: initialState,

onChangeTitle: async ({ id, title }) => {
setTimeout(await putTitleMethod(id, title), 2000);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요런 매직 넘버들도 상수로 관리해주세요~

Copy link
Author

@ghost ghost Nov 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

확실히 상수로 관리하니깐 코드가 가독성이 좋아지는 것 같습니다 👍 수정하겠습니다 : )

},
});

const postContent = new EditorContent({
div: editor,
initialState: initialState,

onChangeContent: async ({ id, content }) => {
setTimeout(await putContentMethod(id, content), 2000);
},
});
Comment on lines +32 to +38

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p5) keyup 시 들어있는 벨류 값이 api 통신으로 들아가게 작성하신 것 같습니다. 제대로 작성이 안됬는지
타이핑하는 순간 바로 키가 누른 숫자만큼 통신을 일으키고 있습니다 😥

Debounce 혹은 Throttle을 적용시켜서 통신의 간격을 두는 법 혹은
LocalData에 저장 후 일정 주기마다 Api와 통신하는 방법 등을 고려하면 좋을 것 같습니다. 👍

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋습니다~ Debounce 들어만 봤는데 한번 공부해보고 적용 시켜보겠습니다 👍


const postSub = new EditorSubContetn({
div: editor,
initialState: initialState,
});

this.setState = async (nextState) => {
const post = await request(`${documentsUrl}/${nextState.postId}`);
isObject(post);
postTitle.setState(post);
postContent.setState(post);
postSub.setState(post);
this.render();
};

this.render = () => {
// editor2.innerHTML = createSubDoucuments();
page.appendChild(editor);
target.appendChild(page);
};

this.render();
}

export default Editor;
47 changes: 47 additions & 0 deletions src/Editor/EditorContent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { createElement } from '../utils/dom.js';
import { isNew, isString } from '../utils/errorHandler.js';

function EditorContent({ div, initialState, onChangeContent }) {
isNew(new.target);
const editorContent = createElement('div');
editorContent.className = 'editor-content';

this.state = initialState;

this.setState = (nextState) => {
this.state = nextState;
const { content } = this.state;

this.render();
editorContent.querySelector('.content').value = content && content;
};

this.render = () => {
const { content } = this.state;
editorContent.innerHTML = `<textarea name="content" placeholder="내용 없음"
class="
content
">${content}</textarea>`;

div.appendChild(editorContent);
};

const onKeyUpContent = () => {
editorContent.addEventListener('keyup', (e) => {
const { name } = e.target;
const contentValue = e.target.value;
isString(contentValue);
const nextState = {
...this.state,
[name]: contentValue,
};

onChangeContent(nextState);
});
};

this.render();
onKeyUpContent();
}

export default EditorContent;
26 changes: 26 additions & 0 deletions src/Editor/EditorSubContetn.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { createElement } from '../utils/dom.js';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

파일명 오타가 있네요 ㅎㅎ


function EditorSubContetn({ div, initialState }) {
const editorDocuments = createElement('div');
editorDocuments.className = 'editor-documents';

this.state = initialState;

this.setState = (nextState) => {
this.state = nextState;
this.render();
};

const createSubDocuments = (documents) => {
console.log(documents);
};

this.render = () => {
// editorDocuments.innerHTML = createSubDocuments(this.state);
// div.appendChild(editorDocuments);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기 주석처리된 이유가 있을까요?_?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

엇 이거는 아직 기능 개발이 안되었는데 커밋을 진행해서 같이 올라간 것 같습니다!

};

this.render();
}

export default EditorSubContetn;
44 changes: 44 additions & 0 deletions src/Editor/EditorTitle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { createElement } from '../utils/dom.js';
import { isNew, isString } from '../utils/errorHandler.js';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p5) 👍


function EditorTitle({ div, initialState, onChangeTitle }) {
isNew(new.target);
const editorTitle = createElement('div');
editorTitle.className = 'editor-title';
this.state = initialState;

div.appendChild(editorTitle);

this.setState = (nextState) => {
this.state = nextState;
const { title } = this.state;
this.render();
editorTitle.querySelector('.title').value = title && title;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

title && title은 뭘까요?_? ㅎㅎ

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

zzzzㅋㅋ 다른 분들 코드보고 만들다가 삼항연산자 대신에 사용했는데 없어도 되겠네요!

};

this.render = () => {
const { title } = this.state;
editorTitle.innerHTML = `<input type="text" name="title" class="title" placeholder="제목 없음" value="${title}"/>`;
div.appendChild(editorTitle);
};

const onKeyupEditorTitle = () => {
editorTitle.addEventListener('keyup', (e) => {
const { name } = e.target;
const titleValue = e.target.value;

isString(titleValue);

const nextState = {
...this.state,
[name]: titleValue,
};

onChangeTitle(nextState);
});
};
this.render();
onKeyupEditorTitle();
}

export default EditorTitle;
Loading