categories frontend

This commit is contained in:
James Shiffer 2020-06-21 21:22:17 -07:00
parent 7fe7ddcfac
commit 03f01f65d3
No known key found for this signature in database
GPG Key ID: C0DB8774A1B3BA45
10 changed files with 91 additions and 52 deletions

View File

@ -2,7 +2,20 @@ import mongoose from 'mongoose';
const { Schema } = mongoose;
const CategorySchema = new Schema({
name: { type: String, index: { unique: true } }
name: { type: String, required: true, index: { unique: true } },
slug: { type: String, required: true, index: { unique: true } }
});
CategorySchema.methods.genSlug = name => name.toLowerCase().replace(/\W+/g, '-');
CategorySchema.pre('save', function (next) {
var cat = this;
// only gen the slug if name has been modified (or is new)
if (!cat.isModified('name')) return next();
cat.slug = cat.genSlug(cat.name);
next();
});
export default mongoose.model('Category', CategorySchema);

View File

@ -7,6 +7,8 @@ export async function get(req, res, next) {
const article = await Article.findOne({ slug }).populate({
path: 'author',
select: 'realname'
}).populate({
path: 'category'
});
if (article) {

View File

@ -116,7 +116,7 @@
padding: 1rem;
margin-bottom: 0.5rem;
}
p.comment-meta {
margin: 0;
}
@ -138,6 +138,7 @@
<h1 class="article-title">{article.title}</h1>
<blockquote>
<p>Author: <strong>{article.author.realname}</strong></p>
<p>Category: <strong><a href={`/c/${article.category.slug}`}>{article.category.name}</a></strong></p>
<p>Published: <strong>{new Date(article.created_at).toLocaleString()}</strong></p>
<p>Views: <strong>{article.views}</strong></p>
</blockquote>

View File

@ -0,0 +1,28 @@
import Article from '../../models/article.js';
import Category from '../../models/category.js';
export async function get(req, res)
{
let { slug } = req.params;
let articles;
if (slug === 'all') {
articles = await Article.find().sort({ created_at: 'desc' });
} else {
let cat = await Category.findOne({ slug });
if (!cat) {
res.writeHead(404, {
'Content-Type': 'application/json'
});
res.end(JSON.stringify({
message: `That category does not exist.`
}));
return;
} else {
articles = await Article.find({ category: cat.id }).sort({ created_at: 'desc' });
}
}
res.writeHead(200, {
'Content-Type': 'application/json'
});
res.end(JSON.stringify(articles));
}

View File

View File

@ -0,0 +1,10 @@
import Category from '../../models/category.js';
export async function get(req, res)
{
let categories = await Category.find();
res.writeHead(200, {
'Content-Type': 'application/json'
});
res.end(JSON.stringify(categories));
}

View File

@ -4,7 +4,9 @@
if (!session.user || !session.user.author) {
return this.redirect(302, '/cms');
}
return { user: session.user };
const res = await this.fetch('/c.json');
const categories = await res.json();
return { user: session.user, categories };
}
</script>
@ -17,6 +19,7 @@
let editor;
let title = '', image = '', category = '';
export let categories;
let actions = [
{
@ -72,6 +75,22 @@
const json = await res.json();
goto(`/a/${json.slug}`);
}
async function addCategory()
{
let name = prompt('Enter a category name');
if (name) {
const res = await fetch('/cms/category', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ name })
});
categories = await res.json();
}
}
</script>
<style>
@ -90,15 +109,15 @@
<form method="POST" action="/cms/article">
<p>Article Title: <input type="text" name="title" bind:value={title} required placeholder="How to Assassinate the Governor of California"></p>
<p>Article Author: <strong>{$session.user.realname}</strong></p>
<p>Article Category: <select>
{#await fetch('/c').then(r => r.json())}
Loading...
{:then categories}
{#each categories as category}
<option value={category}>{category}</option>
<p>Article Category:
{#if categories.length}
<select bind:value={category}>
{#each categories as { name, slug }}
<option value={slug}>{name}</option>
{/each}
{/await}
</select></p>
</select>
{/if}
<button on:click|preventDefault={addCategory}>+</button></p>
<p>Article Header Image URL: <input type="text" name="image" bind:value={image} required placeholder="http:// ..."></p>
</form>
<Editor bind:this={editor} {actions} />

View File

@ -4,7 +4,7 @@
if (!session.user || !session.user.author) {
return this.redirect(302, '/cms');
}
const res = await this.fetch(`/a/all`);
const res = await this.fetch(`/c/all.json`);
const articles = await res.json();
return { articles, user: session.user };
}
@ -24,7 +24,7 @@
await fetch(`/a/${article.slug}.json`, {
method: 'DELETE'
});
const res = await fetch(`/a/all`);
const res = await fetch(`/c/all.json`);
articles = await res.json();
}
}

View File

@ -1,7 +1,7 @@
<script context="module">
export async function preload()
{
const res = await this.fetch(`/a/all`);
const res = await this.fetch(`/c/all.json`);
const articles = await res.json();
return { articles };
}
@ -84,7 +84,7 @@
div.article-list {
box-shadow: 0 0 5px #000;
}
div.article-meta {
div.article-meta {
font-weight: bold;
}
</style>

View File

@ -214,7 +214,7 @@ express()
message: `You must supply an article title, image URL, category, and content.`
}));
}
const cat = await Category.findOne({ name: category });
const cat = await Category.findOne({ slug: category });
if (!cat) {
res.writeHead(404, {
'Content-Type': 'application/json'
@ -260,9 +260,8 @@ express()
res.writeHead(200, {
'Content-Type': 'application/json'
});
res.end(JSON.stringify({
category: cat.name
}));
const categories = await Category.find();
res.end(JSON.stringify(categories));
} catch (err) {
res.writeHead(500, {
'Content-Type': 'application/json'
@ -274,39 +273,6 @@ express()
}
)
.get('/a/:category', async function (req, res, next) {
let { category } = req.params;
let articles;
if (category === 'all') {
articles = await Article.find().sort({ created_at: 'desc' });
} else {
let cat = await Category.findOne({ name: category });
if (!cat) {
res.writeHead(404, {
'Content-Type': 'application/json'
});
res.end(JSON.stringify({
message: `That category does not exist.`
}));
return;
} else {
articles = await Article.find({ category: cat.id }).sort({ created_at: 'desc' });
}
}
res.writeHead(200, {
'Content-Type': 'application/json'
});
res.end(JSON.stringify(articles));
})
.get('/c', async function (req, res, next) {
let categories = await Category.find();
res.writeHead(200, {
'Content-Type': 'application/json'
});
res.end(JSON.stringify(categories));
})
.get('/me', function(req, res, next) {
if (req.user) {
res.writeHead(200, {