Comment app.js and server.js
This commit is contained in:
parent
30a618ad06
commit
14233b6954
27
server.js
27
server.js
@ -5,12 +5,8 @@ var bodyParser = require('body-parser'); // Data conversion, JSON parsing
|
|||||||
// Set up Express
|
// Set up Express
|
||||||
var app = express();
|
var app = express();
|
||||||
|
|
||||||
app.use(express.static("./static/")); // Serve static files from /static/
|
app.use(express.static("./static/")); // Serve static files from /static
|
||||||
app.use(express.json()); // Parse JSON in requests
|
app.use(express.json()); // Parse JSON in requests
|
||||||
// app.use("/", (req, res, next) => // Finally send a 404 page
|
|
||||||
// {
|
|
||||||
// res.status(404).sendFile("404.html", {"root": "./"});
|
|
||||||
// });
|
|
||||||
|
|
||||||
// Posts route, return posts.json
|
// Posts route, return posts.json
|
||||||
app.get("/api/posts", function(req, res)
|
app.get("/api/posts", function(req, res)
|
||||||
@ -18,32 +14,39 @@ app.get("/api/posts", function(req, res)
|
|||||||
res.json(JSON.parse(fs.readFileSync('./data/posts.json')));
|
res.json(JSON.parse(fs.readFileSync('./data/posts.json')));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Posts route, digest received post
|
// Posts route, digest incoming post
|
||||||
app.post("/api/posts", function(req, res)
|
app.post("/api/posts", function(req, res)
|
||||||
{
|
{
|
||||||
|
// Read in posts.json
|
||||||
var postsFile = fs.readFileSync('./data/posts.json');
|
var postsFile = fs.readFileSync('./data/posts.json');
|
||||||
var posts = JSON.parse(postsFile);
|
var posts = JSON.parse(postsFile);
|
||||||
|
|
||||||
|
// Verify incoming post matches expected schema
|
||||||
var incomingData = req.body;
|
var incomingData = req.body;
|
||||||
if (validatePost(incomingData))
|
if (validatePost(incomingData))
|
||||||
{
|
{
|
||||||
|
// Prepend the incoming post to the post list
|
||||||
posts.unshift(incomingData);
|
posts.unshift(incomingData);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Complain that we haven't been given what we're expecting
|
||||||
res.status(400).json({"error":"Failed to validate post"});
|
res.status(400).json({"error":"Failed to validate post"});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try to save the updated posts object
|
||||||
fs.writeFile('./data/posts.json', JSON.stringify(posts), (e) =>
|
fs.writeFile('./data/posts.json', JSON.stringify(posts), (e) =>
|
||||||
{
|
{
|
||||||
if (e)
|
if (e)
|
||||||
{
|
{
|
||||||
|
// Tell the client we've hit a snag and dump the error to the console
|
||||||
res.sendStatus(500);
|
res.sendStatus(500);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Tell the client all is good and that they shouldn't expect any content
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -71,7 +74,17 @@ app.listen(8080, function()
|
|||||||
console.log("Listening on port 8080");
|
console.log("Listening on port 8080");
|
||||||
});
|
});
|
||||||
|
|
||||||
// Validates a post object conforms to the standard we're expecting
|
// Verifies the post object conforms to the standard we're expecting
|
||||||
|
// Each post should conform to the following template:
|
||||||
|
// {
|
||||||
|
// "title":"",
|
||||||
|
// "author":"",
|
||||||
|
// "date":0,
|
||||||
|
// "tags":[
|
||||||
|
// ""
|
||||||
|
// ],
|
||||||
|
// "content":""
|
||||||
|
// }
|
||||||
function validatePost(post)
|
function validatePost(post)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
var app = angular.module("app", ["ngRoute", "ngSanitize", "ngTagsInput"]);
|
var app = angular.module("app", ["ngRoute", "ngSanitize", "ngTagsInput"]);
|
||||||
|
|
||||||
|
// Provider configuration
|
||||||
app.config(
|
app.config(
|
||||||
function ($routeProvider, $locationProvider)
|
function ($routeProvider, $locationProvider)
|
||||||
{
|
{
|
||||||
|
// Configure routes
|
||||||
$routeProvider
|
$routeProvider
|
||||||
.when("/", {templateUrl: "views/blog.html", controller: "blog"})
|
.when("/", {templateUrl: "views/blog.html", controller: "blog"})
|
||||||
.when("/create", {templateUrl: "views/create.html", controller: "create"})
|
.when("/create", {templateUrl: "views/create.html", controller: "create"})
|
||||||
@ -10,35 +12,45 @@ app.config(
|
|||||||
.when("/faq", {templateUrl: "views/faq.html", controller: "faq"})
|
.when("/faq", {templateUrl: "views/faq.html", controller: "faq"})
|
||||||
.otherwise({templateUrl: "404.html"});
|
.otherwise({templateUrl: "404.html"});
|
||||||
|
|
||||||
|
// Enable HTML5-style routing
|
||||||
|
// URLs will be shown as http://host/view instead of http://host/#!/view
|
||||||
$locationProvider.html5Mode({enabled: true, requireBase: false});
|
$locationProvider.html5Mode({enabled: true, requireBase: false});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Non-provider configuration
|
||||||
app.run(($anchorScroll) =>
|
app.run(($anchorScroll) =>
|
||||||
{
|
{
|
||||||
|
// Apply 100px scroll offset to compensate for fixed header
|
||||||
$anchorScroll.yOffset = 100;
|
$anchorScroll.yOffset = 100;
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Blog view controller
|
||||||
app.controller("blog", ["$scope", "$http",
|
app.controller("blog", ["$scope", "$http",
|
||||||
function($scope, $http)
|
function($scope, $http)
|
||||||
{
|
{
|
||||||
$scope.posts = [];
|
$scope.posts = [];
|
||||||
|
|
||||||
|
// Retrieve posts from server and populate array
|
||||||
$http.get("/api/posts")
|
$http.get("/api/posts")
|
||||||
.then((r) => { $scope.posts = angular.fromJson(r.data); });
|
.then((r) => { $scope.posts = angular.fromJson(r.data); });
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Create view controller
|
||||||
app.controller("create", ["$scope", "$http",
|
app.controller("create", ["$scope", "$http",
|
||||||
function($scope, $http)
|
function($scope, $http)
|
||||||
{
|
{
|
||||||
|
// Initialise fields
|
||||||
$scope.title = "";
|
$scope.title = "";
|
||||||
$scope.author = "";
|
$scope.author = "";
|
||||||
$scope.content = "";
|
$scope.content = "";
|
||||||
$scope.tags = [];
|
$scope.tags = [];
|
||||||
|
|
||||||
|
// Disable preview by default
|
||||||
$scope.previewing = false;
|
$scope.previewing = false;
|
||||||
|
|
||||||
|
// Handle post submission
|
||||||
$scope.onSubmit = function()
|
$scope.onSubmit = function()
|
||||||
{
|
{
|
||||||
// Create the post object
|
// Create the post object
|
||||||
@ -59,24 +71,31 @@ app.controller("create", ["$scope", "$http",
|
|||||||
$scope.content = "";
|
$scope.content = "";
|
||||||
$scope.tags = [];
|
$scope.tags = [];
|
||||||
|
|
||||||
|
// Alert the user that it has been submitted
|
||||||
alert("Post has been submitted.");
|
alert("Post has been submitted.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle tag additions
|
||||||
$scope.onTagAdding = ($tag) =>
|
$scope.onTagAdding = ($tag) =>
|
||||||
{
|
{
|
||||||
|
// Prepend a hash if the tag doesn't already start with one
|
||||||
if (!$tag.text.startsWith("#"))
|
if (!$tag.text.startsWith("#"))
|
||||||
$tag.text = "#" + $tag.text;
|
$tag.text = "#" + $tag.text;
|
||||||
|
|
||||||
|
// Return whether the tag has already been added
|
||||||
return $scope.tags.indexOf($tag.text) === -1;
|
return $scope.tags.indexOf($tag.text) === -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Toggle post preview
|
||||||
$scope.onPreview = () =>
|
$scope.onPreview = () =>
|
||||||
{
|
{
|
||||||
|
// Invert preview switch
|
||||||
$scope.previewing = !$scope.previewing;
|
$scope.previewing = !$scope.previewing;
|
||||||
|
|
||||||
// Update HTML on preview to avoid parsing for each character change
|
// Update HTML on preview to avoid parsing for each character change
|
||||||
$scope.previewHtml = () =>
|
$scope.previewHtml = () =>
|
||||||
{
|
{
|
||||||
|
// Only parse if there is content and if the preview is toggling on
|
||||||
return $scope.content && $scope.previewing
|
return $scope.content && $scope.previewing
|
||||||
? marked($scope.content)
|
? marked($scope.content)
|
||||||
: "";
|
: "";
|
||||||
@ -85,46 +104,54 @@ app.controller("create", ["$scope", "$http",
|
|||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// About view controller
|
||||||
app.controller("about", ["$scope", "$http",
|
app.controller("about", ["$scope", "$http",
|
||||||
function($scope, $http)
|
function($scope, $http)
|
||||||
{
|
{
|
||||||
$scope.aboutContent = "";
|
$scope.aboutContent = "";
|
||||||
|
|
||||||
|
// Get about content from the server and populate the view
|
||||||
$http.get("/api/about")
|
$http.get("/api/about")
|
||||||
.then((r) => { $scope.aboutContent = angular.fromJson(r.data).content; });
|
.then((r) => { $scope.aboutContent = angular.fromJson(r.data).content; });
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// FAQ view controller
|
||||||
app.controller("faq", ["$scope", "$http", "$location", "$anchorScroll",
|
app.controller("faq", ["$scope", "$http", "$location", "$anchorScroll",
|
||||||
function($scope, $http, $location, $anchorScroll)
|
function($scope, $http, $location, $anchorScroll)
|
||||||
{
|
{
|
||||||
$scope.entries = []
|
$scope.entries = []
|
||||||
|
|
||||||
|
// Get FAQ entries from the server and populate the array
|
||||||
$http.get("/api/faq")
|
$http.get("/api/faq")
|
||||||
.then((r) => { $scope.entries = angular.fromJson(r.data) });
|
.then((r) => { $scope.entries = angular.fromJson(r.data) });
|
||||||
|
|
||||||
|
// Handle scrolling to different entries
|
||||||
$scope.scrollTo = (hash) =>
|
$scope.scrollTo = (hash) =>
|
||||||
{
|
{
|
||||||
|
// Use $anchorScroll to avoid weird issues with hashes in the URL
|
||||||
$anchorScroll(hash);
|
$anchorScroll(hash);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Navbar controller
|
||||||
app.controller("navButtons", ["$scope", "$location",
|
app.controller("navButtons", ["$scope", "$location",
|
||||||
function($scope, $location)
|
function($scope, $location)
|
||||||
{
|
{
|
||||||
// Set the current relative path
|
// Set the current relative path
|
||||||
// Helpful to set the navButtons appropriately when refreshing
|
// Useful for setting the navButtons appropriately when navigating to a deep linked view
|
||||||
$scope.current = $location.path();
|
$scope.current = $location.path();
|
||||||
|
|
||||||
// Changes location to the given target and sets the current path
|
// Handle navButton clicks
|
||||||
$scope.navClick = (target) =>
|
$scope.navClick = (target) =>
|
||||||
{
|
{
|
||||||
|
// Change location to the given target and set the current path
|
||||||
$location.path(target);
|
$location.path(target);
|
||||||
$scope.current = target;
|
$scope.current = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Applies the 'current' class if the target matches the current path
|
// Apply the 'current' class if the target matches the current path
|
||||||
$scope.isCurrent = (target) =>
|
$scope.isCurrent = (target) =>
|
||||||
{
|
{
|
||||||
return $scope.current == target ? "current" : "";
|
return $scope.current == target ? "current" : "";
|
||||||
@ -136,21 +163,26 @@ app.controller("navButtons", ["$scope", "$location",
|
|||||||
app.controller("head", ["$scope",
|
app.controller("head", ["$scope",
|
||||||
function($scope)
|
function($scope)
|
||||||
{
|
{
|
||||||
|
// Set the pag title
|
||||||
$scope.title = "Lemonblog";
|
$scope.title = "Lemonblog";
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Footer controller
|
||||||
app.controller("footer", ["$scope",
|
app.controller("footer", ["$scope",
|
||||||
function($scope)
|
function($scope)
|
||||||
{
|
{
|
||||||
|
// Set the current year for the copyright string
|
||||||
$scope.year = new Date().getFullYear();
|
$scope.year = new Date().getFullYear();
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Markdown filter
|
||||||
app.filter("markdown", () =>
|
app.filter("markdown", () =>
|
||||||
{
|
{
|
||||||
return function(input)
|
return function(input)
|
||||||
{
|
{
|
||||||
|
// Parse input as markdown and return resulting HTML
|
||||||
return marked(input);
|
return marked(input);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user