Skip to content

Commit 64de84d

Browse files
authored
템플릿 업로드 기능 (#6)
* refactor(components): LoginForm, Logout 컴포넌트 분리 * feat(popup): 카테고리 정보 불러오기 * feat(popup): 카테고리 선택, title 입력, filename 입력 후 템플릿 업로드 기능 * feat(icons): 아이콘 변경 * feat(types): css 타입 추가 * feat(popup): 컴포넌트 분리, style 적용 * refactor(popup): 스타일 변경 * refactor(LoginForm): 스타일 변경 * refactor(popup): DOM node 에러 해결 LoginForm 컴포넌트를 사용하면 다음과 같은 에러가 났음. 해당 컴포넌트 코드를 그대로 복붙하여 사용하면 에러가 나지 않음 Uncaught NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node. * feat(popup): 로그인에 form 태그 추가 * feat(popup): 소스코드 삭제 기능 * chore: v0.0.3으로 변경
1 parent f1d6bb8 commit 64de84d

File tree

19 files changed

+607
-154
lines changed

19 files changed

+607
-154
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "codezap-chrome-extension",
3-
"version": "0.0.2",
3+
"version": "0.0.3",
44
"description": "코드잽 크롬 익스텐션입니다",
55
"scripts": {
66
"start": "webpack --watch --progress --config webpack.dev.js",

src/background/background.ts

Lines changed: 6 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import config from '../../config';
1+
import { getStoredSourceCodes, setStoredSourceCodes } from '../utils/storage';
22

33
chrome.runtime.onInstalled.addListener(() => {
44
chrome.contextMenus.create({
@@ -8,80 +8,10 @@ chrome.runtime.onInstalled.addListener(() => {
88
});
99
});
1010

11-
chrome.contextMenus.onClicked.addListener((info, tab) => {
12-
if (info.menuItemId === 'uploadToCodeZap' && info.selectionText) {
13-
const selected = info.selectionText;
14-
15-
chrome.scripting.executeScript(
16-
{
17-
target: { tabId: tab.id },
18-
func: () => {
19-
console.log(
20-
'window.getSelection().toString()',
21-
window.getSelection().toString()
22-
);
23-
return window.getSelection().toString();
24-
},
25-
},
26-
(selectionArray) => {
27-
if (selectionArray) {
28-
const selectedText = selectionArray[0]?.result || '';
29-
30-
if (selected) {
31-
console.log('selectedText', selectedText);
32-
chrome.storage.local.get(['userInfo'], (result) => {
33-
if (result.userInfo) {
34-
fetch(`${config.API_BASE_URL}/templates`, {
35-
method: 'POST',
36-
headers: {
37-
'Content-Type': 'application/json',
38-
},
39-
credentials: 'include',
40-
body: JSON.stringify({
41-
title: '제목없음',
42-
description: '코드짱의 코드 템플릿',
43-
sourceCodes: [
44-
{
45-
filename: 'example.java',
46-
content: selected,
47-
ordinal: 1,
48-
},
49-
],
50-
thumbnailOrdinal: 1,
51-
categoryId: 115,
52-
tags: [],
53-
}),
54-
}).then((response) => {
55-
console.log('response', response);
56-
if (response.ok) {
57-
chrome.notifications.create({
58-
type: 'basic',
59-
iconUrl: 'icons/icon48.png',
60-
title: '코드잽',
61-
message: '소스코드 업로드가 성공했어요!',
62-
});
63-
} else {
64-
chrome.notifications.create({
65-
type: 'basic',
66-
iconUrl: 'icons/icon48.png',
67-
title: '코드잽',
68-
message:
69-
'소스코드 업로드에 실패했어요. 잠시 후 다시 시도해주세요',
70-
});
71-
}
72-
});
73-
} else {
74-
chrome.notifications.create({
75-
type: 'basic',
76-
iconUrl: 'icons/icon48.png',
77-
title: '코드잽',
78-
message: '로그인을 해주세요',
79-
});
80-
}
81-
});
82-
}
83-
}
84-
}
85-
);
11+
chrome.contextMenus.onClicked.addListener((event) => {
12+
if (event.menuItemId === 'uploadToCodeZap' && event.selectionText) {
13+
getStoredSourceCodes().then((codes) => {
14+
setStoredSourceCodes([...codes, event.selectionText]);
15+
});
8616
}
8717
});
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
.loginFormContainer {
2+
display: flex;
3+
flex-direction: column;
4+
align-items: flex-start;
5+
justify-content: center;
6+
gap: 16px;
7+
}
8+
9+
.loginFormTitle {
10+
font-size: 24px;
11+
font-weight: 700;
12+
line-height: 120%;
13+
}
14+
15+
.loginFormInput {
16+
height: 32px;
17+
width: 100%;
18+
19+
padding-left: 4px;
20+
border: 1px solid black;
21+
border-radius: 8px;
22+
}
23+
24+
.loginButton {
25+
background-color: #ff9500;
26+
color: white;
27+
border: none;
28+
cursor: pointer;
29+
30+
padding: 8px;
31+
border-radius: 4px;
32+
width: 100%;
33+
34+
&:hover {
35+
background-color: #f6a739;
36+
}
37+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { useState } from 'react';
2+
import styles from './LoginForm.module.css';
3+
4+
interface Props {
5+
onLogin: (username: string, password: string) => void;
6+
}
7+
8+
const LoginForm = ({ onLogin }: Props) => {
9+
const [username, setUsername] = useState('');
10+
const [password, setPassword] = useState('');
11+
12+
const handleLogin = () => {
13+
onLogin(username, password);
14+
};
15+
16+
return (
17+
<div className={styles.loginFormContainer}>
18+
<h2 className={styles.loginFormTitle}>코드잽 익스텐션</h2>
19+
<input
20+
id='name'
21+
type='text'
22+
placeholder='아이디'
23+
className={styles.loginFormInput}
24+
value={username}
25+
onChange={(e) => setUsername(e.target.value)}
26+
/>
27+
<input
28+
id='password'
29+
type='password'
30+
placeholder='비밀번호'
31+
className={styles.loginFormInput}
32+
value={password}
33+
onChange={(e) => setPassword(e.target.value)}
34+
/>
35+
<button className={styles.loginButton} onClick={handleLogin}>
36+
로그인
37+
</button>
38+
</div>
39+
);
40+
};
41+
42+
export default LoginForm;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
.logoutButton {
2+
background-color: #ff9500;
3+
color: white;
4+
border: none;
5+
cursor: pointer;
6+
7+
padding: 8px;
8+
border-radius: 4px;
9+
width: auto;
10+
11+
&:hover {
12+
background-color: #f6a739;
13+
}
14+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import styles from './LogoutButton.module.css';
2+
3+
interface Props {
4+
onLogout: () => void;
5+
}
6+
7+
const LogoutButton = ({ onLogout }: Props) => {
8+
return (
9+
<button className={styles.logoutButton} onClick={onLogout}>
10+
로그아웃
11+
</button>
12+
);
13+
};
14+
15+
export default LogoutButton;

src/components/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default as LoginForm } from './LoginForm/LoginForm';
2+
export { default as LogoutButton } from './LogoutButton/LogoutButton';

src/popup/popup.html

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,8 @@
66
<title>코드잽에 로그인해보세요</title>
77
<style>
88
body {
9-
font-family: Arial, sans-serif;
10-
padding: 20px;
11-
width: 250px;
12-
}
13-
input,
14-
button {
15-
display: block;
16-
margin-bottom: 10px;
17-
width: 100%;
18-
padding: 8px;
19-
}
20-
button {
21-
background-color: #4caf50;
22-
color: white;
23-
border: none;
24-
cursor: pointer;
25-
}
26-
button:hover {
27-
background-color: #45a049;
9+
margin: 20px;
10+
width: 300px;
2811
}
2912
</style>
3013
</head>

src/popup/popup.module.css

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
.popupHeaderContainer {
2+
display: flex;
3+
justify-content: space-between;
4+
align-items: center;
5+
width: 100%;
6+
}
7+
8+
.popupTitle {
9+
font-size: 24px;
10+
font-weight: 700;
11+
line-height: 120%;
12+
}
13+
14+
.popupContainer {
15+
display: flex;
16+
flex-direction: column;
17+
align-items: flex-start;
18+
justify-content: center;
19+
20+
gap: 16px;
21+
}
22+
23+
.categorySelect {
24+
border: 1px solid black;
25+
padding: 4px;
26+
border-radius: 4px;
27+
}
28+
29+
.titleInput {
30+
height: 32px;
31+
width: 100%;
32+
33+
padding-left: 4px;
34+
border-bottom: 1px solid black;
35+
}
36+
37+
.fileNameInput {
38+
height: 16px;
39+
width: 100%;
40+
padding: 12px 8px;
41+
42+
border: 1px solid black;
43+
border-radius: 4px 4px 0 0;
44+
}
45+
46+
.sourceCodeTextArea {
47+
resize: none;
48+
cursor: auto;
49+
width: 100%;
50+
padding: 8px;
51+
52+
border: 1px solid black;
53+
border-top: 0;
54+
border-radius: 0 0 4px 4px;
55+
}
56+
57+
.uploadButton {
58+
background-color: #ff9500;
59+
color: white;
60+
border: none;
61+
cursor: pointer;
62+
63+
padding: 8px;
64+
border-radius: 4px;
65+
width: 100%;
66+
67+
&:hover {
68+
background-color: #f6a739;
69+
}
70+
}
71+
72+
.loginFormContainer {
73+
display: flex;
74+
flex-direction: column;
75+
align-items: flex-start;
76+
justify-content: center;
77+
gap: 16px;
78+
}
79+
80+
.loginFormTitle {
81+
font-size: 24px;
82+
font-weight: 700;
83+
line-height: 120%;
84+
}
85+
86+
.loginFormInput {
87+
height: 32px;
88+
width: 100%;
89+
90+
padding-left: 4px;
91+
border: 1px solid black;
92+
border-radius: 8px;
93+
}
94+
95+
.loginButton {
96+
background-color: #ff9500;
97+
color: white;
98+
border: none;
99+
cursor: pointer;
100+
101+
padding: 8px;
102+
border-radius: 4px;
103+
width: 100%;
104+
105+
&:hover {
106+
background-color: #f6a739;
107+
}
108+
}
109+
110+
.sourceCodeContainer {
111+
position: relative;
112+
}
113+
114+
.removeButton {
115+
cursor: pointer;
116+
position: absolute;
117+
right: -6px;
118+
top: -6px;
119+
padding: 4px 6px;
120+
border-radius: 4px;
121+
background-color: #ff9500;
122+
color: white;
123+
}

0 commit comments

Comments
 (0)