loads articles correctly, deleting is WIP
This commit is contained in:
parent
ffa8b5322a
commit
570c607e12
@ -7,7 +7,8 @@ const ArticleSchema = new Schema({
|
|||||||
type: mongoose.Schema.Types.ObjectId,
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
ref: 'User'
|
ref: 'User'
|
||||||
},
|
},
|
||||||
slug: { type: String, required: true, index: { unique: true } },
|
slug: { type: String, index: { unique: true } },
|
||||||
|
image: { type: String, required: true },
|
||||||
created_at: { type: Date, default: Date.now },
|
created_at: { type: Date, default: Date.now },
|
||||||
html: { type: String, required: true },
|
html: { type: String, required: true },
|
||||||
comments: [{
|
comments: [{
|
||||||
@ -21,7 +22,14 @@ const ArticleSchema = new Schema({
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
ArticleSchema.methods.genSlug = () => this.title.toLowerCase().replace(/\W+/g, '-');
|
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) {
|
ArticleSchema.pre('findOne', function (next) {
|
||||||
var article = this;
|
var article = this;
|
||||||
|
@ -1,26 +1,20 @@
|
|||||||
import articles from './_articles.js';
|
import Article from '../../models/article.js';
|
||||||
|
|
||||||
const lookup = new Map();
|
export async function get(req, res, next) {
|
||||||
articles.forEach(article => {
|
|
||||||
lookup.set(article.slug, JSON.stringify(article));
|
|
||||||
});
|
|
||||||
|
|
||||||
export function get(req, res, next) {
|
|
||||||
// the `slug` parameter is available because
|
// the `slug` parameter is available because
|
||||||
// this file is called [slug].json.js
|
// this file is called [slug].json.js
|
||||||
const { slug } = req.params;
|
const { slug } = req.params;
|
||||||
|
const article = await Article.findOne({ slug }).populate('author_user');
|
||||||
|
|
||||||
if (lookup.has(slug)) {
|
if (article) {
|
||||||
res.writeHead(200, {
|
res.writeHead(200, {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
});
|
});
|
||||||
|
res.end(JSON.stringify(article));
|
||||||
res.end(lookup.get(slug));
|
|
||||||
} else {
|
} else {
|
||||||
res.writeHead(404, {
|
res.writeHead(404, {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
});
|
});
|
||||||
|
|
||||||
res.end(JSON.stringify({
|
res.end(JSON.stringify({
|
||||||
message: `Not found`
|
message: `Not found`
|
||||||
}));
|
}));
|
||||||
|
@ -75,7 +75,7 @@
|
|||||||
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<figure class="article-image">
|
<figure class="article-image">
|
||||||
<img alt={article.title} src={`/a/${article.slug}.jpg`}>
|
<img alt={article.title} src={article.image}>
|
||||||
</figure>
|
</figure>
|
||||||
<div class="article-meta">
|
<div class="article-meta">
|
||||||
<h1 class="article-title">{article.title}</h1>
|
<h1 class="article-title">{article.title}</h1>
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
const articles = [
|
|
||||||
];
|
|
||||||
|
|
||||||
articles.forEach(article => {
|
|
||||||
article.slug = article.title.toLowerCase().replace(/\W+/g, '-');
|
|
||||||
article.html = article.html.replace(/^\t{3}/gm, '');
|
|
||||||
});
|
|
||||||
|
|
||||||
export default articles;
|
|
@ -1,8 +1,8 @@
|
|||||||
<script context="module">
|
<script context="module">
|
||||||
export async function preload(page, session)
|
export async function preload(page, session)
|
||||||
{
|
{
|
||||||
if (!session.user) {
|
if (!session.user || !session.user.author) {
|
||||||
return this.redirect(302, '/cms/login');
|
return this.redirect(302, '/cms');
|
||||||
}
|
}
|
||||||
return { user: session.user };
|
return { user: session.user };
|
||||||
}
|
}
|
||||||
@ -52,14 +52,14 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
<title>Publish | HOWFEED.BIZ</title>
|
<title>Publish Article | HOWFEED.BIZ</title>
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<a href="/cms">< Back to Dashboard</a>
|
<a href="/cms">< Back to Dashboard</a>
|
||||||
<h1>HowFeed Publisher</h1>
|
<h1>HowFeed Publisher</h1>
|
||||||
<form method="POST" action="/cms/article" bind:this={form}>
|
<form method="POST" action="/cms/article" bind:this={form}>
|
||||||
<input type="hidden" name="html" bind:value={html}>
|
<input type="hidden" name="html" value={html}>
|
||||||
<p>Article Title: <input type="text" name="title" required placeholder="How to Assassinate the Governor of California"></p>
|
<p>Article Title: <input type="text" name="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 Header Image URL: <input type="text" name="image" required placeholder="http:// ..."></p>
|
<p>Article Header Image URL: <input type="text" name="image" required placeholder="http:// ..."></p>
|
||||||
|
41
src/routes/cms/delete.svelte
Normal file
41
src/routes/cms/delete.svelte
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<script context="module">
|
||||||
|
export async function preload(page, session)
|
||||||
|
{
|
||||||
|
if (!session.user || !session.user.author) {
|
||||||
|
return this.redirect(302, '/cms');
|
||||||
|
}
|
||||||
|
const res = await this.fetch(`/a/all`);
|
||||||
|
const articles = await res.json();
|
||||||
|
return { articles, user: session.user };
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>Delete Article | HOWFEED.BIZ</title>
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export let articles;
|
||||||
|
|
||||||
|
function del(article)
|
||||||
|
{
|
||||||
|
if (confirm(`Are you sure you want to delete "${article.title}"?`)) {
|
||||||
|
alert('ok');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
<a href="/cms">< Back to Dashboard</a>
|
||||||
|
<h1>Delete an Article</h1>
|
||||||
|
<ul>
|
||||||
|
{#each articles as article}
|
||||||
|
<li>
|
||||||
|
<strong>{article.title}</strong> by <strong>{article.author_user}</strong>
|
||||||
|
<button on:click={() => { del(article) }}>Delete</button>
|
||||||
|
</li>
|
||||||
|
{:else}
|
||||||
|
<li>There are no published articles.</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
</div>
|
@ -1,7 +1,8 @@
|
|||||||
<script context="module">
|
<script context="module">
|
||||||
import articles from './a/_articles.js';
|
|
||||||
export async function preload()
|
export async function preload()
|
||||||
{
|
{
|
||||||
|
const res = await this.fetch(`/a/all`);
|
||||||
|
const articles = await res.json();
|
||||||
return { articles };
|
return { articles };
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -94,14 +95,14 @@
|
|||||||
<h1 class="welcome">Welcome</h1>
|
<h1 class="welcome">Welcome</h1>
|
||||||
<h2 class="desc">Find an Article</h2>
|
<h2 class="desc">Find an Article</h2>
|
||||||
<div class="article-list">
|
<div class="article-list">
|
||||||
{#each articles as {title, slug, date}}
|
{#each articles as {title, slug, image, created_at}}
|
||||||
<a rel="prefetch" href={`/a/${slug}`}>
|
<a rel="prefetch" href={`/a/${slug}`}>
|
||||||
<figure class="article-image">
|
<figure class="article-image">
|
||||||
<img src={`/a/${slug}.jpg` || '/logo.png'} alt={title}>
|
<img src={image || '/logo.png'} alt={title}>
|
||||||
</figure>
|
</figure>
|
||||||
<div class="article-meta">
|
<div class="article-meta">
|
||||||
<p class="article-title">{title}</p>
|
<p class="article-title">{title}</p>
|
||||||
<p class="article-date">{new Date(date).toLocaleDateString()}</p>
|
<p class="article-date">{new Date(created_at).toLocaleDateString()}</p>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
{:else}
|
{:else}
|
||||||
|
@ -199,16 +199,43 @@ express()
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
function(req, res, next) {
|
async function(req, res, next) {
|
||||||
res.writeHead(200, {
|
try {
|
||||||
|
const { html, title, image } = req.body;
|
||||||
|
if (!title || !image || !html) {
|
||||||
|
res.writeHead(422, {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
});
|
});
|
||||||
res.end(JSON.stringify({
|
res.end(JSON.stringify({
|
||||||
message: `ur a faget lol`
|
message: `You must supply an article title, image URL, and content.`
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
const article = await new Article({ html, title, image, author: req.user._id });
|
||||||
|
await article.save();
|
||||||
|
res.redirect(`/a/${article.slug}`);
|
||||||
|
} catch (err) {
|
||||||
|
res.writeHead(500, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify({
|
||||||
|
message: `Failed to add article: ${err}`
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
.get('/a/all', async function (req, res, next) {
|
||||||
|
let articles = await Article.find().populate('author_user');
|
||||||
|
articles.forEach(article => {
|
||||||
|
article.slug = article.title.toLowerCase().replace(/\W+/g, '-');
|
||||||
|
article.html = article.html.replace(/^\t{3}/gm, '');
|
||||||
|
});
|
||||||
|
res.writeHead(200, {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify(articles));
|
||||||
|
})
|
||||||
|
|
||||||
.use(compression({ threshold: 0 }))
|
.use(compression({ threshold: 0 }))
|
||||||
.use(sirv('static', { dev }))
|
.use(sirv('static', { dev }))
|
||||||
.use(sapper.middleware({
|
.use(sapper.middleware({
|
||||||
|
Loading…
x
Reference in New Issue
Block a user