From a1d7e7e2633f9cf6ef89e8a67875f176b1529009 Mon Sep 17 00:00:00 2001 From: JongHyeon Lee Date: Sun, 7 Apr 2024 00:33:37 +0900 Subject: [PATCH 1/3] Task #1 Done --- client/src/pages/feed.tsx | 21 ++++++++++++++++++++- seminar/src/routes/feed.js | 24 ++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/client/src/pages/feed.tsx b/client/src/pages/feed.tsx index b64c53b..a7b8eb7 100644 --- a/client/src/pages/feed.tsx +++ b/client/src/pages/feed.tsx @@ -8,9 +8,11 @@ interface IAPIResponse { id: number, title: string, content: string } const FeedPage = (props: {}) => { const [ LAPIResponse, setLAPIResponse ] = React.useState([]); - const [ NPostCount, setNPostCount ] = React.useState(0); + const [ NPostCount, setNPostCount ] = React.useState(1); + const [ NEditPostId, setNEditPostId ] = React.useState(0); const [ SNewPostTitle, setSNewPostTitle ] = React.useState(""); const [ SNewPostContent, setSNewPostContent ] = React.useState(""); + const [ SEditPostContent, setSEditPostContent ] = React.useState(""); React.useEffect( () => { let BComponentExited = false; @@ -35,6 +37,15 @@ const FeedPage = (props: {}) => { asyncFun().catch(e => window.alert(`AN ERROR OCCURED! ${e}`)); } + const editPost = () => { + const asyncFun = async () => { + await axios.post( SAPIBase + '/feed/updateFeed', { id: NEditPostId, content: SEditPostContent } ); + const { data } = await axios.get( SAPIBase + `/feed/getFeed?count=${ NPostCount }`); + setLAPIResponse(data); + } + asyncFun().catch(e => window.alert(`AN ERROR OCCURED! ${e}`)); + } + const deletePost = (id: string) => { const asyncFun = async () => { // One can set X-HTTP-Method header to DELETE to specify deletion as well @@ -53,6 +64,14 @@ const FeedPage = (props: {}) => { setNPostCount( parseInt(e.target.value) ) } /> +
+ Edit Post #id:    + setNEditPostId(parseInt(e.target.value))} /> +
+ New content:    + setSEditPostContent(e.target.value)} /> +
+
{ LAPIResponse.map( (val, i) => diff --git a/seminar/src/routes/feed.js b/seminar/src/routes/feed.js index f9c19d9..8c3ee94 100644 --- a/seminar/src/routes/feed.js +++ b/seminar/src/routes/feed.js @@ -26,6 +26,18 @@ class FeedDB { return true; } + updateItem = ( id, content ) => { + let BItemEdited = false; + this.#LDataDB = this.#LDataDB.map((value) => { + if (value.id === id) { + value.content = content; + BItemEdited = true; + } + return value; + }); + return BItemEdited; + } + deleteItem = ( id ) => { let BItemDeleted = false; this.#LDataDB = this.#LDataDB.filter((value) => { @@ -62,6 +74,18 @@ router.post('/addFeed', (req, res) => { } }); +router.post('/updateFeed', (req, res) => { + try { + const { id, content } = req.body; + const Nid = parseInt(id); + const updateResult = feedDBInst.updateItem( Nid, content ); + if (!updateResult) return res.status(500).json({ error: { Nid, content, updateResult } }) + else return res.status(200).json({ isOK: true }); + } catch (e) { + return res.status(500).json({ error: e }); + } + }); + router.post('/deleteFeed', (req, res) => { try { const { id } = req.body; From 602c709570507136f0056a55d669860061c52e42 Mon Sep 17 00:00:00 2001 From: JongHyeon Lee Date: Sun, 7 Apr 2024 00:41:03 +0900 Subject: [PATCH 2/3] Task #2 Done --- client/src/pages/account.tsx | 12 ++++++++---- seminar/.env.example | 4 +++- seminar/src/middleware/auth.js | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/client/src/pages/account.tsx b/client/src/pages/account.tsx index 37341f5..c5f896d 100644 --- a/client/src/pages/account.tsx +++ b/client/src/pages/account.tsx @@ -5,14 +5,15 @@ import {SAPIBase} from "../tools/api"; import "./css/account.css"; const AccountPage = () => { - const [ SAPIKEY, setSAPIKEY ] = React.useState(""); + const [ SUserId, setSUserId ] = React.useState(""); + const [ SUserPW, setSUserPW ] = React.useState(""); const [ NBalance, setNBalance ] = React.useState("Not Authorized"); const [ NTransaction, setNTransaction ] = React.useState(0); const getAccountInformation = () => { const asyncFun = async() => { interface IAPIResponse { balance: number }; - const { data } = await axios.post(SAPIBase + '/account/getInfo', { credential: SAPIKEY }); + const { data } = await axios.post(SAPIBase + '/account/getInfo', { credential: {SUserId, SUserPW} }); setNBalance(data.balance); } asyncFun().catch((e) => window.alert(`AN ERROR OCCURED: ${e}`)); @@ -22,7 +23,7 @@ const AccountPage = () => { const asyncFun = async() => { if (amount === '') return; interface IAPIResponse { success: boolean, balance: number, msg: string }; - const { data } = await axios.post(SAPIBase + '/account/transaction', { credential: SAPIKEY, amount: amount }); + const { data } = await axios.post(SAPIBase + '/account/transaction', { credential: {SUserId, SUserPW}, amount: amount }); setNTransaction(0); if (!data.success) { window.alert('Transaction Failed:' + data.msg); @@ -40,7 +41,10 @@ const AccountPage = () => {

Account

- Enter API Key: setSAPIKEY(e.target.value)}/> + Enter API Key: setSUserId(e.target.value)}/> +
+ Enter API Key: setSUserPW(e.target.value)}/> +
diff --git a/seminar/.env.example b/seminar/.env.example index f84e5b2..0b3bf4c 100644 --- a/seminar/.env.example +++ b/seminar/.env.example @@ -1,3 +1,5 @@ PORT=8080 NODE_ENV=DEVELOPMENT -API_KEY= \ No newline at end of file +API_KEY= +USER_ID=admin +USER_PW=password \ No newline at end of file diff --git a/seminar/src/middleware/auth.js b/seminar/src/middleware/auth.js index 480f41d..bc6c4bf 100644 --- a/seminar/src/middleware/auth.js +++ b/seminar/src/middleware/auth.js @@ -1,5 +1,5 @@ const authMiddleware = (req, res, next) => { - if (req.body.credential === process.env.API_KEY) { + if (req.body.credential.SUserId === process.env.USER_ID && req.body.credential.SUserPW === process.env.USER_PW) { console.log("[AUTH-MIDDLEWARE] Authorized User"); next(); } From 213e8303687ac4af72b3e510d52955da9bfac9f2 Mon Sep 17 00:00:00 2001 From: JongHyeon Lee Date: Sun, 7 Apr 2024 14:03:04 +0900 Subject: [PATCH 3/3] Add duplicate feature --- client/src/pages/css/feed.css | 13 +++++++++++++ client/src/pages/feed.tsx | 15 ++++++++++++++- seminar/src/routes/feed.js | 33 +++++++++++++++++++++++++++++++-- 3 files changed, 58 insertions(+), 3 deletions(-) diff --git a/client/src/pages/css/feed.css b/client/src/pages/css/feed.css index 53580df..6268252 100644 --- a/client/src/pages/css/feed.css +++ b/client/src/pages/css/feed.css @@ -30,6 +30,19 @@ font-weight: 700; } +.duplicate-item { + position: absolute; + right: 40px; + top: 15px; + color: blue; + font-size: 18px; +} + +.duplicate-item:hover { + font-weight: bold; + cursor: pointer; +} + .delete-item { position: absolute; right: 15px; diff --git a/client/src/pages/feed.tsx b/client/src/pages/feed.tsx index a7b8eb7..bd1f2f4 100644 --- a/client/src/pages/feed.tsx +++ b/client/src/pages/feed.tsx @@ -46,6 +46,18 @@ const FeedPage = (props: {}) => { asyncFun().catch(e => window.alert(`AN ERROR OCCURED! ${e}`)); } + const duplicatePost = (id: string) => { + const asyncFun = async () => { + await axios.post( SAPIBase + '/feed/duplicateFeed', { id: id } ); + setNPostCount(NPostCount + 1); + setSNewPostTitle(""); + setSNewPostContent(""); + const { data } = await axios.get( SAPIBase + `/feed/getFeed?count=${ NPostCount }`); + setLAPIResponse(data); + } + asyncFun().catch(e => window.alert(`AN ERROR OCCURED! ${e}`)); + } + const deletePost = (id: string) => { const asyncFun = async () => { // One can set X-HTTP-Method header to DELETE to specify deletion as well @@ -61,7 +73,7 @@ const FeedPage = (props: {}) => {

Feed

Number of posts to show:    - setNPostCount( parseInt(e.target.value) ) } />
@@ -76,6 +88,7 @@ const FeedPage = (props: {}) => {
{ LAPIResponse.map( (val, i) =>
+
duplicatePost(`${val.id}`)}>⎘
deletePost(`${val.id}`)}>ⓧ

{ val.title }

{ val.content }

diff --git a/seminar/src/routes/feed.js b/seminar/src/routes/feed.js index 8c3ee94..a6c2db7 100644 --- a/seminar/src/routes/feed.js +++ b/seminar/src/routes/feed.js @@ -38,6 +38,23 @@ class FeedDB { return BItemEdited; } + duplicateItem = ( id ) => { + let BItemFound = false; + let OItem = null; + this.#LDataDB = this.#LDataDB.map((value) => { + if (value.id === id) { + BItemFound = true; + OItem = value; + } + return value; + }); + if (BItemFound) { + this.#LDataDB.push({id: this.#id, title: OItem.title, content: OItem.content}); + this.#id++; this.#itemCount++; + } + return BItemFound; + } + deleteItem = ( id ) => { let BItemDeleted = false; this.#LDataDB = this.#LDataDB.filter((value) => { @@ -84,7 +101,19 @@ router.post('/updateFeed', (req, res) => { } catch (e) { return res.status(500).json({ error: e }); } - }); +}); + +router.post('/duplicateFeed', (req, res) => { + try { + const { id } = req.body; + const Nid = parseInt(id); + const updateResult = feedDBInst.duplicateItem( Nid ); + if (!updateResult) return res.status(500).json({ error: { Nid, updateResult } }) + else return res.status(200).json({ isOK: true }); + } catch (e) { + return res.status(500).json({ error: e }); + } +}); router.post('/deleteFeed', (req, res) => { try { @@ -95,6 +124,6 @@ router.post('/deleteFeed', (req, res) => { } catch (e) { return res.status(500).json({ error: e }); } -}) +}); module.exports = router; \ No newline at end of file