diff --git a/src/models/article.js b/src/models/article.js
index 550baf4..5cc4c10 100644
--- a/src/models/article.js
+++ b/src/models/article.js
@@ -11,6 +11,7 @@ const ArticleSchema = new Schema({
slug: { type: String, index: { unique: true } },
image: { type: String, required: true },
created_at: { type: Date, default: Date.now },
+ updated_at: { type: Date },
html: { type: String, required: true },
comments: [{
content: { type: String, required: true },
diff --git a/src/routes/a/[slug].json.js b/src/routes/a/[slug].json.js
index 22b1771..1abc16d 100644
--- a/src/routes/a/[slug].json.js
+++ b/src/routes/a/[slug].json.js
@@ -12,7 +12,9 @@ export async function get(req, res, next) {
});
if (article) {
- article.set({ views: article.views + 1 });
+ if (req.query.no_view !== '1') {
+ article.set({ views: article.views + 1 });
+ }
await article.save();
res.writeHead(200, {
'Content-Type': 'application/json'
diff --git a/src/routes/a/[slug].svelte b/src/routes/a/[slug].svelte
index 46d51bd..435a501 100644
--- a/src/routes/a/[slug].svelte
+++ b/src/routes/a/[slug].svelte
@@ -214,6 +214,9 @@
Author: {article.author.realname}
Category: {article.category.name}
Published: {new Date(article.created_at).toLocaleString()}
+ {#if article.updated_at}
+ Last Updated: {new Date(article.updated_at).toLocaleString()}
+ {/if}
Views: {article.views}
diff --git a/src/routes/cms/create.svelte b/src/routes/cms/create.svelte
index fec1d73..6cf6009 100644
--- a/src/routes/cms/create.svelte
+++ b/src/routes/cms/create.svelte
@@ -6,7 +6,9 @@
}
const res = await this.fetch('/c.json');
const categories = await res.json();
- return { user: session.user, categories };
+ const origRes = page.query.edit && await this.fetch(`/a/${page.query.edit}.json?no_view=1`)
+ const editArticle = origRes && await origRes.json();
+ return { user: session.user, categories, editArticle };
}
@@ -20,6 +22,7 @@
let editor, form, uploadForm;
let loading = false, loadingAttach = false;
let title = '', category = '';
+ export let editArticle = undefined;
export let categories;
let actions = [
@@ -55,9 +58,9 @@
];
onMount(function load() {
- title = window.localStorage['title'] || '';
- category = window.localStorage['category'] || '';
- editor.setHtml(window.localStorage['html'] || '', false);
+ title = editArticle ? editArticle.title : (window.localStorage['title'] || '');
+ category = editArticle ? editArticle.category.slug : (window.localStorage['category'] || '');
+ editor.setHtml(editArticle ? editArticle.html : (window.localStorage['html'] || ''), false);
});
async function submit()
@@ -67,7 +70,7 @@
fd.append('html', html);
loading = true;
try {
- const res = await fetch(`/cms/article`, {
+ const res = await fetch(editArticle ? `/cms/article/${editArticle.slug}` : `/cms/article`, {
method: 'POST',
headers: {
'Accept': 'application/json'
diff --git a/src/routes/cms/edit.svelte b/src/routes/cms/edit.svelte
new file mode 100644
index 0000000..f888651
--- /dev/null
+++ b/src/routes/cms/edit.svelte
@@ -0,0 +1,42 @@
+
+
+
+ Edit Article | HOWFEED.BIZ
+
+
+
+
+
+
< Back to Dashboard
+
Edit an Article
+
Choose an article to edit:
+
+
diff --git a/src/routes/cms/index.svelte b/src/routes/cms/index.svelte
index 8b5a522..7bc34d0 100644
--- a/src/routes/cms/index.svelte
+++ b/src/routes/cms/index.svelte
@@ -22,7 +22,7 @@
{#if user.author}
HowFeed Publisher Dashboard
Publish a new article
- Edit an existing article Coming soon!
+ Edit an existing article
Delete an article
Account Settings
Change your avatar
diff --git a/src/server.js b/src/server.js
index 804e4e2..91e12b7 100644
--- a/src/server.js
+++ b/src/server.js
@@ -251,13 +251,27 @@ express()
});
})
- .post('/cms/article',
+ .post('/cms/article/:edit?',
isAuthor,
async function(req, res, next) {
try {
+ let editArticle;
+ if (req.params.edit) {
+ editArticle = await Article.findOne({ slug: req.params.edit });
+ if (!editArticle) {
+ res.writeHead(404, {
+ 'Content-Type': 'application/json'
+ });
+ res.end(JSON.stringify({
+ message: `Article to edit not found`
+ }));
+ return false;
+ }
+ }
+
const { html, title, category } = req.body;
- const { image } = req.files;
- if (!title || !image || !html || !category) {
+ const image = req.files && req.files.image;
+ if (!title || (!editArticle && !image) || !html || !category) {
res.writeHead(422, {
'Content-Type': 'application/json'
});
@@ -266,23 +280,30 @@ express()
}));
return false;
}
- if (!/^image\//.test(image.mimetype)) {
- res.writeHead(422, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- message: `Invalid MIME type for the header image file.`
- }));
- return false;
- }
- if (image.truncated) {
- res.writeHead(422, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- message: `Received truncated image file. Try again with a smaller file.`
- }));
- return false;
+ let ext, filename, url;
+ if (image) {
+ if (!/^image\//.test(image.mimetype)) {
+ res.writeHead(422, {
+ 'Content-Type': 'application/json'
+ });
+ res.end(JSON.stringify({
+ message: `Invalid MIME type for the header image file.`
+ }));
+ return false;
+ }
+ if (image.truncated) {
+ res.writeHead(422, {
+ 'Content-Type': 'application/json'
+ });
+ res.end(JSON.stringify({
+ message: `Received truncated image file. Try again with a smaller file.`
+ }));
+ return false;
+ }
+ ext = image.name.match(/(\.[^.]+)$/)[0];
+ filename = crypto.randomBytes(20).toString('hex') + ext;
+ url = `/a/${filename}`;
+ await image.mv('./static' + url);
}
const cat = await Category.findOne({ slug: category });
if (!cat) {
@@ -294,18 +315,30 @@ express()
}));
return false;
}
- const ext = image.name.match(/(\.[^.]+)$/)[0];
- const filename = crypto.randomBytes(20).toString('hex') + ext;
- const url = `/a/${filename}`;
- await image.mv('./static' + url);
- const article = await new Article({ html, title, image: filename, category: cat, author: req.user._id });
- await article.save();
- res.writeHead(200, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- slug: article.slug
- }));
+ if (editArticle) {
+ let newObj = {
+ html, title, category: cat, updated_at: Date.now()
+ };
+ if (filename) {
+ newObj.image = filename;
+ }
+ await Article.updateOne({ slug: editArticle.slug }, { $set: newObj });
+ res.writeHead(200, {
+ 'Content-Type': 'application/json'
+ });
+ res.end(JSON.stringify({
+ slug: editArticle.slug
+ }));
+ } else {
+ const article = await new Article({ html, title, image: filename, category: cat, author: req.user._id });
+ await article.save();
+ res.writeHead(200, {
+ 'Content-Type': 'application/json'
+ });
+ res.end(JSON.stringify({
+ slug: article.slug
+ }));
+ }
} catch (err) {
res.writeHead(500, {
'Content-Type': 'application/json'