Skip to content

Commit

Permalink
implement delete post in api & intregrate it in app b00tc4mp#136
Browse files Browse the repository at this point in the history
  • Loading branch information
Eduardolans committed May 30, 2024
1 parent 705050b commit fe9b41f
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 25 deletions.
6 changes: 6 additions & 0 deletions staff/eduardo-sanchez/socialcode/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,10 @@ xhr.send()

```sh
🐖 curl -X POST http://localhost:8080/posts -H "Authorization: Basic peterpan" -H "Content-Type: application/json" -d '{"title":"blah","image":"https://upload.wikimedia.org/wikipedia/commons/1/1d/Blah_Blah_Blah.jpg","description":"blah blah"}' -v
```

- delete post

```sh
🐖 curl -X DELETE http://localhost:8080/posts/4007381802005925-1717082344121 -H "Authorization: Basic peterpan" -v
```
18 changes: 18 additions & 0 deletions staff/eduardo-sanchez/socialcode/api/data/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,24 @@ data.findPosts = (condition, callback) => {
})
}

data.findPost = (condition, callback) => {
fs.readFile('./data/posts.json', 'utf8', (error, json) => {
if (error) {
callback(new SystemError(error.message))

return
}

if (!json) json = '[]'

const posts = JSON.parse(json)

const post = posts.find(condition)

callback(null, post)
})
}

data.insertPost = (post, callback) => {
fs.readFile('./data/posts.json', 'utf8', (error, json) => {
if (error) {
Expand Down
2 changes: 1 addition & 1 deletion staff/eduardo-sanchez/socialcode/api/data/posts.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
[{"id":"8375259641077482-1716319512771","author":"peterpan","title":"smile","image":"https://m.media-amazon.com/images/I/41xsPjrM-pL._AC_UF350,350_QL50_.jpg","description":"hi","date":"2024-05-21T19:25:12.770Z"},{"author":"pepitogrillo","title":"blah","image":"https://m.media-amazon.com/images/I/41xsPjrM-pL._AC_UF350,350_QL50_.jpg","description":"blah blah","id":"5879244716997389-1716667549269","date":"2024-05-25T20:05:49.269Z"},{"id":"7820462492406723-1716996283274","author":"ManoloC","title":"gjsfgjxfjg","image":"https://media.giphy.com/media/xTiTntKyFNFbCNuqkw/giphy.gif?cid=790b76117ksklq64slgwdawn5cmtm14enobheew3nkecwdq1&ep=v1_gifs_trending&rid=giphy.gif&ct=g","description":"dSGDG","date":"2024-05-29T15:24:43.274Z"},{"id":"5424401351689265-1716995937318","author":"WendyD","title":"asfaF","image":"https://media.giphy.com/media/xTiTntKyFNFbCNuqkw/giphy.gif?cid=790b76117ksklq64slgwdawn5cmtm14enobheew3nkecwdq1&ep=v1_gifs_trending&rid=giphy.gif&ct=g","description":"ASAFA","date":"2024-05-29T15:18:57.318Z"},{"author":"peterpan","title":"hello world","image":"https://miro.medium.com/v2/resize:fit:1024/1*OohqW5DGh9CQS4hLY5FXzA.png","description":"console.log(\"hello world\")","date":"2024-05-30T13:46:33.345Z","id":"2575794271140359-1717076793345"},{"author":"peterpan","title":"blah","image":"https://upload.wikimedia.org/wikipedia/commons/1/1d/Blah_Blah_Blah.jpg","description":"blah blah","date":"2024-05-30T14:07:06.222Z","id":"03238060139373644-1717078026222"},{"author":"peterpan","title":"i love js","image":"https://images-na.ssl-images-amazon.com/images/I/61VmREcLaFL._SLDPMOBCAROUSELAUTOCROP288221_MCnd_AC_SR462,693_.jpg","description":"t-shirt","date":"2024-05-30T15:07:38.101Z","id":"7052022051791447-1717081658101"},{"author":"ManoloC","title":"i love debugging","image":"https://ih1.redbubble.net/image.5079675350.2246/gptr,1400x,front,black-c,188,133,1000,1000-bg,f8f8f8.jpg","description":"otra tshirt","date":"2024-05-30T15:12:22.193Z","id":"3242603140750757-1717081942193"},{"author":"peterpan","title":"I hate onions","image":"https://res.cloudinary.com/teepublic/image/private/s--jk8hOZj1--/t_Resized%20Artwork/c_crop,x_10,y_10/c_fit,h_563/c_crop,g_north_west,h_626,w_470,x_-40,y_-15/g_north_west,u_upload:v1462829018:production:blanks:ekerz3afkzxin2pgqj8h,x_-435,y_-340/b_rgb:eeeeee/c_limit,f_auto,h_630,q_auto:good:420,w_630/v1704062586/production/designs/55814456_0.jpg","description":"camiseta","date":"2024-05-30T15:19:04.125Z","id":"4007381802005925-1717082344126"}]
[{"id":"8375259641077482-1716319512771","author":"peterpan","title":"smile","image":"https://m.media-amazon.com/images/I/41xsPjrM-pL._AC_UF350,350_QL50_.jpg","description":"hi","date":"2024-05-21T19:25:12.770Z"},{"author":"pepitogrillo","title":"blah","image":"https://m.media-amazon.com/images/I/41xsPjrM-pL._AC_UF350,350_QL50_.jpg","description":"blah blah","id":"5879244716997389-1716667549269","date":"2024-05-25T20:05:49.269Z"},{"id":"5424401351689265-1716995937318","author":"WendyD","title":"asfaF","image":"https://media.giphy.com/media/xTiTntKyFNFbCNuqkw/giphy.gif?cid=790b76117ksklq64slgwdawn5cmtm14enobheew3nkecwdq1&ep=v1_gifs_trending&rid=giphy.gif&ct=g","description":"ASAFA","date":"2024-05-29T15:18:57.318Z"},{"author":"peterpan","title":"hello world","image":"https://miro.medium.com/v2/resize:fit:1024/1*OohqW5DGh9CQS4hLY5FXzA.png","description":"console.log(\"hello world\")","date":"2024-05-30T13:46:33.345Z","id":"2575794271140359-1717076793345"},{"author":"peterpan","title":"blah","image":"https://upload.wikimedia.org/wikipedia/commons/1/1d/Blah_Blah_Blah.jpg","description":"blah blah","date":"2024-05-30T14:07:06.222Z","id":"03238060139373644-1717078026222"},{"author":"peterpan","title":"i love js","image":"https://images-na.ssl-images-amazon.com/images/I/61VmREcLaFL._SLDPMOBCAROUSELAUTOCROP288221_MCnd_AC_SR462,693_.jpg","description":"t-shirt","date":"2024-05-30T15:07:38.101Z","id":"7052022051791447-1717081658101"},{"author":"ManoloC","title":"i love debugging","image":"https://ih1.redbubble.net/image.5079675350.2246/gptr,1400x,front,black-c,188,133,1000,1000-bg,f8f8f8.jpg","description":"otra tshirt","date":"2024-05-30T15:12:22.193Z","id":"3242603140750757-1717081942193"},{"author":"peterpan","title":"I hate onions","image":"https://res.cloudinary.com/teepublic/image/private/s--jk8hOZj1--/t_Resized%20Artwork/c_crop,x_10,y_10/c_fit,h_563/c_crop,g_north_west,h_626,w_470,x_-40,y_-15/g_north_west,u_upload:v1462829018:production:blanks:ekerz3afkzxin2pgqj8h,x_-435,y_-340/b_rgb:eeeeee/c_limit,f_auto,h_630,q_auto:good:420,w_630/v1704062586/production/designs/55814456_0.jpg","description":"camiseta","date":"2024-05-30T15:19:04.125Z","id":"4007381802005925-1717082344121"}]
20 changes: 20 additions & 0 deletions staff/eduardo-sanchez/socialcode/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,24 @@ api.post('/posts', jsonBodyParser, (req, res) => {

})

api.delete('/posts/:postId', (req, res) => {
const username = req.headers.authorization.slice(6)

const { postId } = req.params

try {
logic.deletePost(username, postId, error => {
if (error) {
res.status(500).json({ error: error.constructor.name, message: error.message })

return
}

res.status(204).send()
})
} catch (error) {
res.status(500).json({ error: error.constructor.name, message: error.message })
}
})

api.listen(8080, () => console.log('api is up'))
66 changes: 65 additions & 1 deletion staff/eduardo-sanchez/socialcode/api/logic/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ const PASSWORD_REGEX = /^[\w-$%&=\[\]\{\}\<\>\(\)]{8,}$/

const NAME_REGEX = /^[a-zA-Z=\[\]\{\}\<\>\(\)]{1,}$/

const ID_REGEX = /^[0-9]+-[0-9]+$/

logic.registerUser = (name, surname, email, username, password, passwordRepeat, callback) => {
if (!NAME_REGEX.test(name))
throw new ContentError('name is not valid')
Expand All @@ -28,6 +30,9 @@ logic.registerUser = (name, surname, email, username, password, passwordRepeat,
if (password !== passwordRepeat)
throw new MatchError('passwords don\'t match')

if (typeof callback !== 'function')
throw new TypeError('callback is not a function')

data.findUser(user => user.email === email || user.username === username, (error, user) => {
if (error) {
callback(error)
Expand Down Expand Up @@ -68,6 +73,9 @@ logic.authenticateUser = (username, password, callback) => {
if (!PASSWORD_REGEX.test(password))
throw new ContentError('password is not valid')

if (typeof callback !== 'function')
throw new TypeError('callback is not a function')

data.findUser(user => user.username === username, (error, user) => {
if (error) {
callback(error)
Expand Down Expand Up @@ -117,6 +125,9 @@ logic.createPost = (username, title, image, description, callback) => {
if (typeof description !== 'string' || !description.length || description.length > 200)
throw new ContentError('description is not valid')

if (typeof callback !== 'function')
throw new TypeError('callback is not a function')

data.findUser(user => user.username === username, (error, user) => {
if (error) {
callback(error)
Expand Down Expand Up @@ -150,6 +161,59 @@ logic.createPost = (username, title, image, description, callback) => {
})
}

logic.deletePost = id => data.deletePost(post => post.id === id)
logic.deletePost = (username, postId, callback) => {
if (!USERNAME_REGEX.test(username))
throw new ContentError('username is not valid')

if (!ID_REGEX.test(postId))
throw new ContentError('postId is not valid')

if (typeof callback !== 'function')
throw new TypeError('callback is not a function')

data.findUser(user => user.username === username, (error, user) => {
if (error) {
callback(error)

return
}

if (!user) {
callback(new MatchError('user not found'))

return
}

data.findPost(post => post.id === postId, (error, post) => {
if (error) {
callback(error)

return
}

if (!post) {
callback(new MatchError('post not found'))

return
}

if (post.author !== username) {
callback(new MatchError('post author does not match user'))

return
}

data.deletePost(post => post.id === postId, error => {
if (error) {
callback(error)

return
}

callback(null)
})
})
})
}

export default logic
19 changes: 17 additions & 2 deletions staff/eduardo-sanchez/socialcode/api/logic/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,30 @@ import logic from './index.js'
// }


// try {
// logic.createPost('peterpan', 'hello world', 'https://miro.medium.com/v2/resize:fit:1024/1*OohqW5DGh9CQS4hLY5FXzA.png', 'console.log("hello world")', error => {
// if (error) {
// console.error(error)

// return
// }

// console.log('post created')
// })
// } catch (error) {
// console.error(error)
// }


try {
logic.createPost('peterpan', 'hello world', 'https://miro.medium.com/v2/resize:fit:1024/1*OohqW5DGh9CQS4hLY5FXzA.png', 'console.log("hello world")', error => {
logic.deletePost('peterpan', '4007381802005925-1717082344125', error => {
if (error) {
console.error(error)

return
}

console.log('post created')
console.log('post deleted')
})
} catch (error) {
console.error(error)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,36 +27,33 @@ class Post extends Component {
const deleteButton = new Button('Delete')

deleteButton.onClick(() => {
// const confirmed = confirm('Do you want to delete the Post?')

// if (confirmed) {


// }

const confirm = new Confirm()
confirm.setText('Delete the Post?')
confirm.setText('Delete Post?')

confirm.onConfirm(() => {
logic.deletePost(post.id)

this.onPostDeletedListener()

try {
logic.deletePost(post.id, error => {
if (error) {
alert(error.message)

return
}

this.onPostDeletedListener()
})
} catch (error) {
alert(error.message)
}
})

confirm.onCancel(() => this.remove(confirm))

this.add(confirm)

})

this.add(deleteButton)

}

}


onPostDeleted(listener) {
this.onPostDeletedListener = listener

Expand Down
53 changes: 49 additions & 4 deletions staff/eduardo-sanchez/socialcode/api/public/app/logic.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ const PASSWORD_REGEX = /^[\w-$%&=\[\]\{\}\<\>\(\)]{8,}$/

const NAME_REGEX = /^[a-zA-Z=\[\]\{\}\<\>\(\)]{1,}$/

const ID_REGEX = /^[0-9]+-[0-9]+$/

logic.registerUser = (name, surname, email, username, password, passwordRepeat, callback) => {
if (!NAME_REGEX.test(name))
throw new ContentError('name is not valid')
Expand All @@ -25,6 +27,9 @@ logic.registerUser = (name, surname, email, username, password, passwordRepeat,
if (password !== passwordRepeat)
throw new MatchError('passwords don\'t match')

if (typeof callback !== 'function')
throw new TypeError('callback is not a function')

const xhr = new XMLHttpRequest

xhr.onload = () => {
Expand Down Expand Up @@ -58,6 +63,9 @@ logic.loginUser = (username, password, callback) => {
if (!PASSWORD_REGEX.test(password))
throw new ContentError('password is not valid')

if (typeof callback !== 'function')
throw new TypeError('callback is not a function')

const xhr = new XMLHttpRequest

xhr.onload = () => {
Expand Down Expand Up @@ -97,6 +105,9 @@ logic.getUserName = () => {
}

logic.getAllPosts = callback => {
if (typeof callback !== 'function')
throw new TypeError('callback is not a function')

const xhr = new XMLHttpRequest

xhr.onload = () => {
Expand All @@ -121,10 +132,17 @@ logic.getAllPosts = callback => {
}

logic.createPost = (title, image, description, callback) => {
if (typeof title !== 'string' || !title.length || title.length > 50) throw new ContentError('title is not valid')
if (typeof image !== 'string' || !image.startsWith('http')) throw new ContentError('image is not valid')
if (typeof description !== 'string' || !description.length || description.length > 200) throw new ContentError('description is not valid')
if (typeof title !== 'string' || !title.length || title.length > 50)
throw new ContentError('title is not valid')

if (typeof image !== 'string' || !image.startsWith('http'))
throw new ContentError('image is not valid')

if (typeof description !== 'string' || !description.length || description.length > 200)
throw new ContentError('description is not valid')

if (typeof callback !== 'function')
throw new TypeError('callback is not a function')

const xhr = new XMLHttpRequest

Expand Down Expand Up @@ -160,4 +178,31 @@ logic.createPost = (title, image, description, callback) => {

logic.getLoggedInUsername = () => sessionStorage.username

logic.deletePost = id => data.deletePost(post => post.id === id)
logic.deletePost = (postId, callback) => {
if (!ID_REGEX.test(postId))
throw new ContentError('postId is not valid')

if (typeof callback !== 'function')
throw new TypeError('callback is not a function')

const xhr = new XMLHttpRequest

xhr.onload = () => {
if (xhr.status === 204) {
callback(null)

return
}

const { error, message } = JSON.parse(xhr.response)

const constructor = errors[error]

callback(new constructor(message))
}

xhr.open('DELETE', `http://localhost:8080/posts/${postId}`)

xhr.setRequestHeader('Authorization', `Basic ${sessionStorage.username}`)
xhr.send()
}

0 comments on commit fe9b41f

Please sign in to comment.