NodeJS: Use a pug template to display results - node.js

I have a method in a NodeJS app that handles scraping a URL, and when successful, saving that data in a Mongo database, and showing the results.
Main method:
//url parameter
app.get('/urls/', function(req, res) {
var client = new MetaInspector(req.query.url, {
timeout: 5000
});
client.on("fetch", function() {
var imagesArray = [];
var keywordsArray = [];
var now = new Date();
var dateVal = dateFormat(now, "mm/dd/yyyy h:MM:ss");
for (var i = 0; i < client.images.length; i++) {
// we only want jpgs. nothing else.
if (client.images[i].indexOf('.jpg') > -1) {
imagesArray.push({
"image": client.images[i]
})
}
}
for (var i = 0; i < client.keywords.length; i++) {
keywordsArray.push({
"keyword": client.keywords[i]
})
}
var newUrls = Urls({
url: client.url,
date_added: dateVal,
keywords: req.body.keywords,
author: client.author,
description: client.description,
ogTitle: client.ogTitle,
ogDescription: client.ogDescription,
image: client.image,
images: imagesArray,
keywords: keywordsArray
});
newUrls.save(function(err) {
if (err) throw err;
res.send('Success' + newUrls);
});
});
client.on("error", function(err) {
console.log(err);
});
client.fetch();
});
This all works well and good. But I'm using Pug and Express and have specific routes setup. I'd like instead of sending the newUrls obj to the res.send, have it go to a particular route and pass it to a particular pug template I already have setup:
// Route.js
var express = require('express');
var router = express.Router();
var Urls = require('../models/urlModel');
var Footer = require('../models/footerModel');
/* URL Saved Success Page */
router.get('/saved', function (req, res) {});
});
module.exports = router;
My view lives in a pug file located at:
/views/saved.pug
div#body
include nav.pug
div.container.item-container
div.row
div.col-md-8
h1 Item successfully saved.
h5 {item}
h6 {description}
I've tried using the res.send method, but that doesn't work. Any suggestions on how to handle this?

For my understanding, you want the request redirected to /saved with payload after urls saved to database, in this scenario, you could user res.redirect with query string
newUrls.save(function(err){
var payload = JSON.stringify({
url: client.url,
date_added: dateVal,
keywords: req.body.keywords,
author: client.author,
description: client.description,
ogTitle: client.ogTitle,
ogDescription: client.ogDescription,
image: client.image,
images: imagesArray,
keywords: keywordsArray
})
//append the payload as a query string
res.redirect(`/saved?payload=${payload}`)
})
and in /saved route, you could parse the query and use res.render
router.get('/saved', function (req, res) {});
let payload = JSON.parse(req.query.payload);
if(payload){
res.render('saved', payload)
}
});

Related

Mongoose.create creating document but none of my data

I'm learning to use the mean stack and trying to build a url shortener. I've got a module that takes the req.params.UserUrl checks and makes sure it's a valid url then creates a random number that I want to use as the short route. I can't seem to find a way to save the random number so that I can check their next url request against it. After a google search it seemed maybe the most effecient way would be to save an object in the database with the long_url and the short_url:randomNumber. My code doesn't throw any errors but when I check my heroku database it has a new entry but only has the _id and __v that mLabs generates itself. Can someone tell me where I'm going wrong.
Route File
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var URLShortener = require(process.cwd()+'/public/Modules/urlShortener.module.js');
var ShortURL = require('../models/shortUrl.js');
router.get('/', function(req, res) {
res.render('index', { title: 'FreeCodeCamp Projects' });
});
router.get('/urlShortener', function(req, res){
res.render('freecodecamp/urlShortener', { title: 'Url Shortener Site'});
});
router.get('/urlShortener/:userUrl', function(req, res){
if(URLShortener.checkValidUrl(req.params.userUrl))
{
var UserUrl = req.params.userUrl;
var randNbr = URLShortener.assignRanNbr();
ShortURL.create(URLShortener.createUrlObj(UserUrl, randNbr), function (err, smallUrl) {
if (err) return console.log(err);
else res.json(smallUrl);
});
}
else
{
res.send('Invalid url');
}
});
router.get('/:short', function(req, res){
if(randNbr == req.params.short)
{
res.redirect(userUrl);
}
else
{
res.send('Not the correct shortcut');
}
});
module.exports = router;
Url Schema
var mongoose = require('mongoose')
var Schema = mongoose.Schema
var shortUrlSchema = new Schema({
long_id:String,
short_id:Number
}, {collection: 'shortUrl'});
module.exports = mongoose.model('shortUrl', shortUrlSchema);
urlShortener Module
'use strict'
module.exports.checkValidUrl = function(url){
var pattern = new RegExp(/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+#)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+#)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%#.\w_]*)#?(?:[\w]*))?)/);
return pattern.test(url);
}
module.exports.assignRanNbr = function(){
var randNbr = Math.floor(Math.random() * (9999 - 1 + 1)) + 1;
return randNbr;
}
module.exports.createUrlObj = function(url, num){
var urlObj = {};
urlObj.original_url = url;
urlObj.short_url = 'https://rawlejuglal-me-rawlejuglal-1.c9users.io/freecodecamp/'+num;
return urlObj;
}
Your createUrlObj method is returning an object with the properties original_url and short_url, but your shortUrlSchema properties are long_id and short_id. The property names in your create method need to match your schema. The property value types must also match your schema types (currently short_url is a string and short_id is a number). I think what you really want is for your createUrlObj method to be
module.exports.createUrlObj = function(url, num){
var urlObj = {};
urlObj.long_url = url;
urlObj.short_id = num;
return urlObj;
}
and your schema to be
var shortUrlSchema = new mongoose.Schema({
long_url: String,
short_id: Number
}, {collection: 'shortUrl'});
Additionally, your '/:short' route should have a call to the database since the randNbr and userUrl variables are not defined in that route.
router.get('/:short', function(req, res){
ShortUrl.findOne({short_id: req.params.short}, function(err, shortUrl){
if(err) res.send('Invalid Url');
res.redirect(shortUrl.long_url)
})
});

How to Auto-refresh the list of all imported data in MEAN stack. Nodejs+Mongodb+Openshift

I have a form, which a user inserts product data in the databse. When the save button is pressed, the method POST occurs. After the Post, the GET method, is called. Apparently, this works in localhost but on Openshift the POST is executed but the list does't auto refresh.
Server.js (GET, POST method)
var ResourcesSchema = new mongoose.Schema({
name: String,
serialnumber: String,
modelno: String,
description: String
});
var Resources = mongoose.model("Resources", ResourcesSchema);
app.get("/resources", function(req, res){
Resources.find(function(err, resources)
{
res.send(resources);
});
});
app.post("/resources", function(req, res){
var resources = new Resources(req.body);
resources.save(function(err, doc){
console.log(doc);
res.json(doc);
});
});
resources.js
app.controller("ResCtrl", function($scope, $http) {
$http.get('/resources')
.success(function(response) {
var resource = "";
$scope.resources = response;
$scope.resource = "";
});
$scope.addResource = function() {
console.log($scope.resource);
$http.post('/resources', $scope.resource)
.success(function(response){
$scope.resources.push(response);
});
$http.get('/resources')
.success(function(response) {
var resource = "";
$scope.resources = response;
$scope.resource = "";
});
};
});
Found the solution:
Had to do a function named $scope.all to retrieve data from the database and i had to call it from inside the $scope.addResource function:
$scope.addResource = function() {
console.log($scope.resource);
$http.post('/resources', $scope.resource)
.success(function(response){
$scope.resources.push(response);
$scope.all();
});
};
$scope.all = function(){
$http.get('/resources')
.success(function(response) {
var resource = "";
$scope.resources = response;
$scope.resource = "";
});
};
so if i make a post to db, the $scope.all(); will auto-refresh the list
I would suggest to make GET request after successful POST. You may get not updated data because GET request happens before data saved into database (we are dealing with asynchronous behavior here).
app.controller("ResCtrl", function($scope, $http) {
$http.get('/resources')
.success(function(response) {
var resource = "";
$scope.resources = response;
$scope.resource = "";
});
$scope.addResource = function() {
console.log($scope.resource);
$http.post('/resources', $scope.resource)
.success(function(response){
//$scope.resources.push(response); /*not sure we need this*/
// will make get call only after data saved successfully
$http.get('/resources')
.success(function(response) {
var resource = "";
$scope.resources = response;
$scope.resource = "";
});
}, function(err){console.log(err);});
};
});

angularjs error on server callback

I'm making a call to the server using resource and when I go to the base URL of
/viewEvent
It works fine. I receive all the database entries. However, when I go to
/viewEvent/1234
where 1234 is the eventID
I get a undefined is not a function and this is a crash from within angular. Stack trace is
TypeError: undefined is not a function
at copy (http://localhost:8000/js/lib/angular/angular.js:593:21)
at http://localhost:8000/js/lib/angular/angular-resource.js:410:19
at wrappedCallback (http://localhost:8000/js/lib/angular/angular.js:6846:59)
at http://localhost:8000/js/lib/angular/angular.js:6883:26
at Object.Scope.$eval (http://localhost:8000/js/lib/angular/angular.js:8057:28)
at Object.Scope.$digest (http://localhost:8000/js/lib/angular/angular.js:7922:25)
at Object.Scope.$apply (http://localhost:8000/js/lib/angular/angular.js:8143:24)
at done (http://localhost:8000/js/lib/angular/angular.js:9170:20)
at completeRequest (http://localhost:8000/js/lib/angular/angular.js:9333:7)
at XMLHttpRequest.xhr.onreadystatechange (http://localhost:8000/js/lib/angular/angular.js:9303:11) angular.js:575
When I examine the server, the request was made correctly. I can see that it got 1234 and it pulls the correct entry from the mongo database.
This is the controller logic
.controller("viewEventsController", ["$scope", 'EventService', '$location', function($scope, EventService, $location){
var path = $location.path().split('/');
var pathSize = path.length;
$scope.events = [];
if(pathSize === 2){
console.log("No event ID");
$scope.events = EventService.query();
}
else{
console.log("Event ID specified");
EventService.get({"eventID": path[pathSize - 1]}, function(data){
//$scope.events.push(data);
console.log(data);
}, function(error){
console.log(error);
});
}
}]);
and the service logic
service.factory('EventService', function($resource){
return $resource('api/viewEvent/:eventID');
});
It never makes it back to the controller so I'm "confident" it's not that. (watch it be that)
Not sure if the best way, but I got it working by doing
In service:
service.factory('EventService', function($resource){
return $resource('api/viewEvent/:eventID',
{eventID:"#eventID"},
{
'getSingleEvent': {
url: "api/viewEvent/:eventID",
method: "GET",
isArray: true
}
}
);
controller
var path = $location.path().split('/');
var pathSize = path.length;
EventService.getSingleEvent({"eventID":path[pathSize - 1]}, function(result){
$scope.updateEvent();
});
Server
routes = require('./routes')
var router = express.Router();
router.get('/api/viewEvent/:eventID', routes.viewEvent);
and in the routes directory I have a js file with
var mongoose = require('mongoose');
var db = mongoose.createConnection('localhost', 'eventApp');
var eventSchema = require('../models/createEvent.js').eventSchema;
var event = db.model('events', eventSchema);
exports.viewEvent = function(req, res){
console.log(req.params.eventID);
if(req.params.eventID) {
event.find({"_id": req.params.eventID}, function (error, events) {
console.log(events);
res.send(events);
});
}
else{
event.find({}, function (error, events) {
console.log(events);
res.send(events);
})
}
};

Send PDF file from AngularJS to NodeJS

i need to send a PDF file from angularjs client to NodeJS service.
I did the angularjs service, and when i receive the file its a string like this:
%PDF-1.3
3 0 obj
<</Type /Page
/Parent 1 0 R
/Reso
How can i reconvert this string to PDF in NodeJS?
This is the client code:
var sendByEmail = function () {
$scope.generatingPdf = true;
$('#budget').show();
var pdf = new JsPDF('p', 'pt', 'letter');
var source = $('#budget')[0];
pdf.addHTML(source, 0, 0, function () {
var resultPdf = pdf.output();
BillService.sendByEmail("rbrlnx#gmail.com", resultPdf).then(function () {
});
$('#budget').hide();
});
};
var sendByEmail = function (email, file) {
var deferred = $q.defer();
var data = {
email: email,
file: file
};
BillService.sendByEmail(data, function (result) {
deferred.resolve(result);
}, function () {
deferred.reject();
});
return deferred.promise;
};
The server code controller its empty:
var sendByEmail = function (req, res, next) {
var file = req.body.file;
};
I experimented with this a while ago, and I came up with this. It's not production ready by a long shot maybe you find it useful. It's free of front end libraries (except Angular ofcourse), but assumes you're using Express 4x and body-parser.
The result:
In the browser:
On the server:
What you're seeing:
You're seeing a tiny node server, serving static index.html and angular files, and a POST route receiving a PDF in base64 as delivered by the HTML FileReader API, and saves it to disk.
Instead of saving to disk, you can send it as an email attachment. See for instance here or here for some info on that.
The example below assumes uploading a PDF by a user through a file input, but the idea is the same for all other ways of sending a document to your back end system. The most important thing is to send the pdf data as BASE64, because this is the format that most file writers and email packages use (as opposed to straight up binary for instance..). This also goes for images, documents etc.
How did I do that:
In your HTML:
<div pdfs>Your browser doesn't support File API.</div>
A directive called pdfs:
myApp.directive('pdfs', ['upload', function(upload) {
return {
replace: true,
scope: function() {
files = null;
},
template: '<input id="files" type="file">',
link: function(scope,element) {
element.bind('change', function(evt) {
scope.$apply(function() {
scope.files = evt.target.files;
});
});
},
controller: function($scope, $attrs) {
$scope.$watch('files', function(files) {
//upload.put(files)
if(typeof files !== 'undefined' && files.length > 0) {
for(var i = 0; i<files.length;i++) {
readFile(files[i])
}
}
}, true);
function readFile(file) {
var reader = new FileReader();
reader.addEventListener("loadend", function(evt) {
upload.post({name: file.name, data: reader.result})
})
if(reader.type = 'application/pdf') {
reader.readAsDataURL(file);
}
}
}
}
}]);
A tiny service:
myApp.service('upload', function($http) {
this.post = function(file) {
$http.post('/pdf', file);
}
});
And a node server:
var express = require('express');
var bodyParser = require('body-parser')
var fs = require("fs");
var app = express();
app.use(express.static('.'));
app.use( bodyParser.json({limit: '1mb'}) );
app.post('/pdf', function(req, res){
var name = req.body.name;
var pdf = req.body.data;
var pdf = pdf.replace('data:application/pdf;base64,', '');
res.send('received');
fs.writeFile(name, pdf, 'base64', function(err) {
console.log(err);
});
});
var server = app.listen(3000, function() {
console.log('Listening on port %d', server.address().port);
});

RESTful CRUD for Angular and Express $resource

I have my JSON querying and creating correctly. I'm a bit stuck on how to remove items from the server. They are being removed in angular but I can't seem to get the connection right for removing them on the server.
My server.js:
var hcController = require('./server/controllers/services-controller.js')
//REST API
app.get('/api/hc', hcController.list);
app.post('/api/hc', hcController.create);
app.delete('/api/hc:_id', hcController.delete);
My server-side model
var mongoose = require('mongoose');
module.exports = mongoose.model('HealingCenterData',{
title: String,
shortname: String,
summary: String,
description: String
});
My server-side controller
var Hc = require('../models/healingcenter-model.js')
module.exports.create = function (req, res) {
var hc = new Hc(req.body);
hc.save(function (err, result){
res.json(result);
});
}
module.exports.list = function (req,res) {
Hc.find({}, function (err, results){
res.json(results);
});
}
module.exports.delete = function (req, res) {
???????
});
}
My angular service:
app.factory("HC", ["$resource", function($resource) {
return {
API: $resource('/api/hc/:id')
}
}]);
My angular controller:
app.controller('servicesController', ['$scope', 'HC','$resource', function ($scope, HC, $resource) {
HC.API.query(function(results) {
$scope.services = results;
});
$scope.createService = function() {
var service = new HC.API();
service.title = $scope.serviceTitle;
service.shortname = $scope.serviceShortname;
service.summary = $scope.serviceSummary;
service.description = $scope.serviceDescription;
service.$save(function(result){
$scope.services.push(result);
$scope.serviceTitle = '';
$scope.serviceShortname = '';
$scope.serviceSummary = '';
$scope.serviceDescription = '';
});
}
$scope.removeItem = function(index){
$scope.services.splice(index, 1);
}
}]);
My JSON structure
{ "_id" : ObjectId("53bea9366a03a66c2dad68bb"), "title" : "Auto Clinic", "shortname" : "auto_clinic", "summary" : "Volunteers evaluate car problems and make minor repairs. Labor is free, and the car owner pays for any needed parts. Oil changes are performed at a reduced cost. All services are performed on Saturdays.", "description" : "No additional information yet.", "__v" : 0 }
On the server side try (I'm assuming you are using moongose) :
exports.delete = function(req,res){
if(req.params.id !==null || req.params.id!==undefined){
Hc.remove({_id:req.params.id},function(err){
res.send(200);
});
}
};
on the client side:
angular controller:
var endPoint = $resource('/api/hc/:id', {id:'#tId'});
$scope.removeItem = function(id){
var ep = new endPoint({tId:id});
ep.$delete(function(res){
//TODO: update local array in scope
});
};
EDIT:
you can just use the resource directly in the controller or just the service as you have done in your case, that's totally fine.

Resources