deleting, view count, realname for articles
This commit is contained in:
		
							parent
							
								
									80b8a28c36
								
							
						
					
					
						commit
						c0214eef58
					
				| @ -22,21 +22,8 @@ const ArticleSchema = new Schema({ | ||||
| }); | ||||
| 
 | ||||
| 
 | ||||
| ArticleSchema.virtual('author_user', { | ||||
|     ref: 'User', | ||||
|     localField: 'author', | ||||
|     foreignField: '_id', | ||||
|     justOne: true | ||||
| }); | ||||
| 
 | ||||
| ArticleSchema.methods.genSlug = title => title.toLowerCase().replace(/\W+/g, '-'); | ||||
| 
 | ||||
| ArticleSchema.pre('findOne', function (next) { | ||||
|     var article = this; | ||||
|     article.views++; | ||||
|     next(); | ||||
| }); | ||||
| 
 | ||||
| ArticleSchema.pre('save', function (next) { | ||||
|     var article = this; | ||||
|     // only gen the slug if title has been modified (or is new)
 | ||||
|  | ||||
| @ -1,3 +1,11 @@ | ||||
| <script context="module"> | ||||
|     export async function preload({ user }, page) | ||||
|     { | ||||
|         const res = await this.fetch(`/me`); | ||||
|         user = await res.json(); | ||||
|     } | ||||
| </script> | ||||
| 
 | ||||
| <script> | ||||
|     import Footer from '../components/Footer.svelte'; | ||||
|     import Nav from '../components/Nav.svelte'; | ||||
| @ -5,20 +13,9 @@ | ||||
| 
 | ||||
| <style> | ||||
|     main { | ||||
|         max-width: 100vw; | ||||
|         max-width: 100%; | ||||
|         box-sizing: border-box; | ||||
|     } | ||||
|     footer { | ||||
|         box-sizing: border-box; | ||||
|         text-align: center; | ||||
|         position: fixed; | ||||
|         bottom: 0; | ||||
|         width: 100%; | ||||
|         background: #fff; | ||||
|         box-shadow: 0 2px 5px #000; | ||||
|         padding: 1rem; | ||||
|         z-index: 1; | ||||
|     } | ||||
| </style> | ||||
| 
 | ||||
| <Nav /> | ||||
|  | ||||
| @ -4,9 +4,14 @@ export async function get(req, res, next) { | ||||
|     // the `slug` parameter is available because
 | ||||
|     // this file is called [slug].json.js
 | ||||
|     const { slug } = req.params; | ||||
|     const article = await Article.findOne({ slug }).populate('author_user'); | ||||
|     const article = await Article.findOne({ slug }).populate({ | ||||
|         path: 'author', | ||||
|         select: 'realname' | ||||
|     }); | ||||
| 
 | ||||
|     if (article) { | ||||
|         article.set({ views: article.views + 1 }); | ||||
|         article.save(); | ||||
|         res.writeHead(200, { | ||||
|             'Content-Type': 'application/json' | ||||
|         }); | ||||
| @ -20,3 +25,20 @@ export async function get(req, res, next) { | ||||
|         })); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export async function del(req, res, next) { | ||||
|     const { slug } = req.params; | ||||
|     const article = await Article.findOneAndDelete({ slug }); | ||||
| 
 | ||||
|     if (article) { | ||||
|         res.writeHead(204); | ||||
|         res.end(); | ||||
|     } else { | ||||
|         res.writeHead(404, { | ||||
|             'Content-Type': 'application/json' | ||||
|         }); | ||||
|         res.end(JSON.stringify({ | ||||
|             message: `Not found` | ||||
|         })); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -64,9 +64,13 @@ | ||||
|     } | ||||
| 
 | ||||
|     div.article-meta { | ||||
|         margin: 0; | ||||
|         margin: 0 0 4rem 0; | ||||
|         padding: 0; | ||||
|     } | ||||
| 
 | ||||
|     div.article-meta h1 { | ||||
|         margin-bottom: 0; | ||||
|     } | ||||
| </style> | ||||
| 
 | ||||
| <svelte:head> | ||||
| @ -79,6 +83,9 @@ | ||||
|     </figure> | ||||
|     <div class="article-meta"> | ||||
|         <h1 class="article-title">{article.title}</h1> | ||||
|         <p>Author: <strong>{article.author.realname}</strong></p> | ||||
|         <p>Published: <strong>{new Date(article.created_at).toLocaleString()}</strong></p> | ||||
|         <p>Views: <strong>{article.views}</strong></p> | ||||
|     </div> | ||||
|     {@html article.html} | ||||
| </div> | ||||
|  | ||||
| @ -15,12 +15,17 @@ | ||||
| </svelte:head> | ||||
| 
 | ||||
| <script> | ||||
|     import { goto } from '@sapper/app'; | ||||
|     export let articles; | ||||
| 
 | ||||
|     function del(article) | ||||
|     async function del(article) | ||||
|     { | ||||
|         if (confirm(`Are you sure you want to delete "${article.title}"?`)) { | ||||
|             alert('ok'); | ||||
|             await fetch(`/a/${article.slug}.json`, { | ||||
|                 method: 'DELETE' | ||||
|             }); | ||||
|             const res = await fetch(`/a/all`); | ||||
|             articles = await res.json(); | ||||
|         } | ||||
|     } | ||||
| </script> | ||||
| @ -31,7 +36,8 @@ | ||||
|     <ul> | ||||
|     {#each articles as article} | ||||
|         <li> | ||||
|             <strong>{article.title}</strong> by <strong>{article.author_user}</strong> | ||||
|             <strong>{article.title}</strong> by <strong>{article.author.realname}</strong> | ||||
|             ({article.views} views) | ||||
|             <button on:click={() => { del(article) }}>Delete</button> | ||||
|         </li> | ||||
|     {:else} | ||||
|  | ||||
| @ -212,7 +212,12 @@ express() | ||||
|                 } | ||||
|                 const article = await new Article({ html, title, image, author: req.user._id }); | ||||
|                 await article.save(); | ||||
|                 res.redirect(`/a/${article.slug}`); | ||||
|                 res.writeHead(200, { | ||||
|                     'Content-Type': 'application/json' | ||||
|                 }); | ||||
|                 res.end(JSON.stringify({ | ||||
|                     slug: article.slug | ||||
|                 })); | ||||
|             } catch (err) { | ||||
|                 res.writeHead(500, { | ||||
|                     'Content-Type': 'application/json' | ||||
| @ -225,7 +230,10 @@ express() | ||||
|     ) | ||||
| 
 | ||||
|     .get('/a/all', async function (req, res, next) { | ||||
|         let articles = await Article.find().populate('author_user'); | ||||
|         let articles = await Article.find().sort({ created_at: 'desc' }).populate({ | ||||
|             path: 'author', | ||||
|             select: 'realname' | ||||
|         }); | ||||
|         articles.forEach(article => { | ||||
|             article.slug = article.title.toLowerCase().replace(/\W+/g, '-'); | ||||
|             article.html = article.html.replace(/^\t{3}/gm, ''); | ||||
| @ -236,6 +244,22 @@ express() | ||||
|         res.end(JSON.stringify(articles)); | ||||
|     }) | ||||
| 
 | ||||
|     .get('/me', function(req, res, next) { | ||||
|         if (req.user) { | ||||
|             res.writeHead(200, { | ||||
|                 'Content-Type': 'application/json' | ||||
|             }); | ||||
|             res.end(JSON.stringify(req.user)); | ||||
|         } else { | ||||
|             res.writeHead(401, { | ||||
|                 'Content-Type': 'application/json' | ||||
|             }); | ||||
|             res.end(JSON.stringify({ | ||||
|                 message: `You are not logged in` | ||||
|             })); | ||||
|         } | ||||
|     }) | ||||
| 
 | ||||
|     .use(compression({ threshold: 0 })) | ||||
|     .use(sirv('static', { dev })) | ||||
|     .use(sapper.middleware({ | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user