categories frontend
This commit is contained in:
parent
7fe7ddcfac
commit
03f01f65d3
@ -2,7 +2,20 @@ import mongoose from 'mongoose';
|
|||||||
|
|
||||||
const { Schema } = mongoose;
|
const { Schema } = mongoose;
|
||||||
const CategorySchema = new Schema({
|
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);
|
export default mongoose.model('Category', CategorySchema);
|
||||||
|
@ -7,6 +7,8 @@ export async function get(req, res, next) {
|
|||||||
const article = await Article.findOne({ slug }).populate({
|
const article = await Article.findOne({ slug }).populate({
|
||||||
path: 'author',
|
path: 'author',
|
||||||
select: 'realname'
|
select: 'realname'
|
||||||
|
}).populate({
|
||||||
|
path: 'category'
|
||||||
});
|
});
|
||||||
|
|
||||||
if (article) {
|
if (article) {
|
||||||
|
@ -138,6 +138,7 @@
|
|||||||
<h1 class="article-title">{article.title}</h1>
|
<h1 class="article-title">{article.title}</h1>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p>Author: <strong>{article.author.realname}</strong></p>
|
<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>Published: <strong>{new Date(article.created_at).toLocaleString()}</strong></p>
|
||||||
<p>Views: <strong>{article.views}</strong></p>
|
<p>Views: <strong>{article.views}</strong></p>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
28
src/routes/c/[slug].json.js
Normal file
28
src/routes/c/[slug].json.js
Normal 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));
|
||||||
|
}
|
0
src/routes/c/[slug].svelte
Normal file
0
src/routes/c/[slug].svelte
Normal file
10
src/routes/c/index.json.js
Normal file
10
src/routes/c/index.json.js
Normal 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));
|
||||||
|
}
|
@ -4,7 +4,9 @@
|
|||||||
if (!session.user || !session.user.author) {
|
if (!session.user || !session.user.author) {
|
||||||
return this.redirect(302, '/cms');
|
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>
|
</script>
|
||||||
|
|
||||||
@ -17,6 +19,7 @@
|
|||||||
|
|
||||||
let editor;
|
let editor;
|
||||||
let title = '', image = '', category = '';
|
let title = '', image = '', category = '';
|
||||||
|
export let categories;
|
||||||
|
|
||||||
let actions = [
|
let actions = [
|
||||||
{
|
{
|
||||||
@ -72,6 +75,22 @@
|
|||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
goto(`/a/${json.slug}`);
|
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>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@ -90,15 +109,15 @@
|
|||||||
<form method="POST" action="/cms/article">
|
<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 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 Author: <strong>{$session.user.realname}</strong></p>
|
||||||
<p>Article Category: <select>
|
<p>Article Category:
|
||||||
{#await fetch('/c').then(r => r.json())}
|
{#if categories.length}
|
||||||
Loading...
|
<select bind:value={category}>
|
||||||
{:then categories}
|
{#each categories as { name, slug }}
|
||||||
{#each categories as category}
|
<option value={slug}>{name}</option>
|
||||||
<option value={category}>{category}</option>
|
|
||||||
{/each}
|
{/each}
|
||||||
{/await}
|
</select>
|
||||||
</select></p>
|
{/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>
|
<p>Article Header Image URL: <input type="text" name="image" bind:value={image} required placeholder="http:// ..."></p>
|
||||||
</form>
|
</form>
|
||||||
<Editor bind:this={editor} {actions} />
|
<Editor bind:this={editor} {actions} />
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
if (!session.user || !session.user.author) {
|
if (!session.user || !session.user.author) {
|
||||||
return this.redirect(302, '/cms');
|
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();
|
const articles = await res.json();
|
||||||
return { articles, user: session.user };
|
return { articles, user: session.user };
|
||||||
}
|
}
|
||||||
@ -24,7 +24,7 @@
|
|||||||
await fetch(`/a/${article.slug}.json`, {
|
await fetch(`/a/${article.slug}.json`, {
|
||||||
method: 'DELETE'
|
method: 'DELETE'
|
||||||
});
|
});
|
||||||
const res = await fetch(`/a/all`);
|
const res = await fetch(`/c/all.json`);
|
||||||
articles = await res.json();
|
articles = await res.json();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script context="module">
|
<script context="module">
|
||||||
export async function preload()
|
export async function preload()
|
||||||
{
|
{
|
||||||
const res = await this.fetch(`/a/all`);
|
const res = await this.fetch(`/c/all.json`);
|
||||||
const articles = await res.json();
|
const articles = await res.json();
|
||||||
return { articles };
|
return { articles };
|
||||||
}
|
}
|
||||||
|
@ -214,7 +214,7 @@ express()
|
|||||||
message: `You must supply an article title, image URL, category, and content.`
|
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) {
|
if (!cat) {
|
||||||
res.writeHead(404, {
|
res.writeHead(404, {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
@ -260,9 +260,8 @@ express()
|
|||||||
res.writeHead(200, {
|
res.writeHead(200, {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
});
|
});
|
||||||
res.end(JSON.stringify({
|
const categories = await Category.find();
|
||||||
category: cat.name
|
res.end(JSON.stringify(categories));
|
||||||
}));
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
res.writeHead(500, {
|
res.writeHead(500, {
|
||||||
'Content-Type': 'application/json'
|
'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) {
|
.get('/me', function(req, res, next) {
|
||||||
if (req.user) {
|
if (req.user) {
|
||||||
res.writeHead(200, {
|
res.writeHead(200, {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user