mirror of
https://github.com/sergeyyarkov/node-docker-example.git
synced 2026-10-11 10:19:41 +03:00
feat: deleting article
This commit is contained in:
parent
9c84c17308
commit
3266939fdc
@ -0,0 +1,8 @@
|
||||
# node-docker-example
|
||||
|
||||
This app showcases a website built with NodeJS. The site has a set of
|
||||
articles, each article has a separate page, all data about the article
|
||||
is stored in the PostgreSQL database. Docker is used to deploy the
|
||||
application.
|
||||
|
||||
## How to deploy
|
||||
@ -40,8 +40,7 @@ class ArticleController {
|
||||
/**
|
||||
* Validate url `id` param
|
||||
*/
|
||||
const id = req.params.id;
|
||||
if (!/^\d+$/.test(id)) {
|
||||
if (!req.params || !/^\d+$/.test(req.params.id)) {
|
||||
res.render(
|
||||
'./views/404.hbs',
|
||||
{ title: '404 | Article not found.' },
|
||||
@ -50,7 +49,7 @@ class ArticleController {
|
||||
return;
|
||||
}
|
||||
|
||||
const article = await ArticleModel.getById(id);
|
||||
const article = await ArticleModel.getById(req.params.id);
|
||||
|
||||
/**
|
||||
* Not found
|
||||
@ -94,6 +93,29 @@ class ArticleController {
|
||||
res.serverError(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete article by `id`
|
||||
*
|
||||
* @param {http.ClientRequest} req
|
||||
* @param {Response} res
|
||||
*/
|
||||
static async delete(req, res) {
|
||||
try {
|
||||
/**
|
||||
* Validate url `id` param
|
||||
*/
|
||||
if (!req.params || !/^\d+$/.test(req.params.id)) {
|
||||
res.render('./views/403.hbs', { title: '403 | Bad request.' }, 403);
|
||||
return;
|
||||
}
|
||||
|
||||
await ArticleModel.delete(req.params.id);
|
||||
res.redirect(`/`);
|
||||
} catch (error) {
|
||||
res.serverError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default ArticleController;
|
||||
|
||||
@ -14,6 +14,7 @@ import db from '#app/db';
|
||||
class ArticleModel {
|
||||
/**
|
||||
* Get list of articles
|
||||
*
|
||||
* @returns {Promise<Array<Article>>} List of articles
|
||||
*/
|
||||
static async getAll() {
|
||||
@ -73,6 +74,19 @@ class ArticleModel {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete article by `id`
|
||||
*
|
||||
* @param {string} id
|
||||
*/
|
||||
static async delete(id) {
|
||||
try {
|
||||
await db.client.query(`DELETE FROM "articles" WHERE id = $1`, [id]);
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default ArticleModel;
|
||||
|
||||
@ -17,4 +17,5 @@ import WaitMiddleware from '#middlewares/WaitMiddleware';
|
||||
router.get('/', ArticleController.index).middleware([WaitMiddleware.handle]);
|
||||
router.get('/articles/:id', ArticleController.show);
|
||||
router.post('/articles', ArticleController.create);
|
||||
router.post('/articles/:id', ArticleController.delete);
|
||||
router.get('/editor/create', EditorController.create);
|
||||
|
||||
@ -55,6 +55,16 @@ textarea {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.app article .article-heading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.app article .article-heading button {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.app .app-footer {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
10
router.js
10
router.js
@ -179,6 +179,16 @@ class Router {
|
||||
post(url, handler) {
|
||||
return this.define('POST', url, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE Method route
|
||||
*
|
||||
* @param {*} url
|
||||
* @param {*} handler
|
||||
*/
|
||||
delete(url, handler) {
|
||||
return this.define('DELETE', url, handler);
|
||||
}
|
||||
}
|
||||
|
||||
export default new Router();
|
||||
|
||||
7
views/403.hbs
Normal file
7
views/403.hbs
Normal file
@ -0,0 +1,7 @@
|
||||
<html lang='en'>
|
||||
{{> head }}
|
||||
<body>
|
||||
<h1>{{ title }}</h1>
|
||||
<a href="/">< return to home</a>
|
||||
</body>
|
||||
</html>
|
||||
@ -23,13 +23,22 @@
|
||||
{{/unless}}
|
||||
{{#each articles}}
|
||||
<article>
|
||||
<div class="article-heading">
|
||||
<h2>
|
||||
<a href='articles/{{ this.id }}'>
|
||||
{{ this.title }}
|
||||
</a>
|
||||
</h2>
|
||||
<form method='post' action='/articles/{{ this.id }}'>
|
||||
<button type="submit">✕</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="article-description">
|
||||
<p>{{ this.description }}</p>
|
||||
</div>
|
||||
<div class="article-time">
|
||||
<time>{{ this.created_at }}</time>
|
||||
</div>
|
||||
</article>
|
||||
<hr />
|
||||
{{/each}}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user