Allowing a Route to Access Data from a Collection with Meteor - javascript

I'm using a route to create a PDF using meteor-pdfkit. Here is my current code which allows me to display my Calendars ID onto the PDF.
Router.route('/calendars/:_id/getPDF', function() {
var currentCalendar = this.params._id;
var doc = new PDFDocument({size: 'A4', margin: 50});
doc.fontSize(12);
doc.text(currentCalendar, 10, 30, {align: 'center', width: 200});
this.response.writeHead(200, {
'Content-type': 'application/pdf',
'Content-Disposition': "attachment; filename=test.pdf"
});
this.response.end( doc.outputSync() );
}, {where: 'server'});
However, when I try to include other information from the Calendars collection, the data comes back as undefined or creates an error. For example, if I try to call curentCalendar.name:
Router.route('/calendars/:_id/getPDF', function() {
var currentCalendar = this.params._id;
var doc = new PDFDocument({size: 'A4', margin: 50});
doc.fontSize(12);
doc.text(currentCalendar.name, 10, 30, {align: 'center', width: 200});
this.response.writeHead(200, {
'Content-type': 'application/pdf',
'Content-Disposition': "attachment; filename=test.pdf"
});
this.response.end( doc.outputSync() );
}, {where: 'server'});
I'm assuming this is because the route doesn't have access to the information from the collection. How do I allow the route to access the information from the Calendars collection?

In your code, currentCalendar is being set to an id. I think you want to write:
var currentCalendar = Calendars.findOnw(this.params._id);
Now currentCalendar will be a document with properties, e.g. currentCalendar.name.

currentCalendar.name is undefined because you are looking for a property name on the string currentCalendar which is nothing more than the id value supplied in the URL. Therefore, all it knows is a number.
What you would have to do is create some array with information about your calendars, ie:
global.calendars = [{name: "Holidays", data: ...}, {name: "Tests", data: ...}]
Then, in your route, you can then get the information based on the index as such:
doc.text(calendars[currentCalendar].name, 10, 30, {align: 'center', width: 200});
Because now calendars[currentCalendar].name is defined

Related

How to iterate through the result of a cloudinary query

I uploaded a video to cloudinary that's moderated with the "google video moderation". I want to save the public_Id and the url of the video if the video moderation status is approved. I've been able to successfully query cloudinary for the video, but I don't know how to iterate through the result of the query. I need to iterate and get only the public_Id and the url from the result with NodeJS.
I've not tried anything yet as I am new to NodeJS.
The result of the query:
{
resources: [
{
asset_id: '54598f6f952b934d45b9b8dfa3b9298f',
public_id: 'm7zp9okftllenzmigyng',
format: 'mp4',
version: 1629500308,
resource_type: 'video',
type: 'upload',
created_at: '2021-08-20T22:58:28Z',
bytes: 1004360,
width: 640,
height: 352,
url: 'http://res.cloudinary.com/dt3ic2vk7/video/upload/v1629500308/m7zp9okftllenzmigyng.mp4',
secure_url: 'https://res.cloudinary.com/dt3ic2vk7/video/upload/v1629500308/m7zp9okftllenzmigyng.mp4'
}
],
rate_limit_allowed: 500,
rate_limit_reset_at: 2021-08-21T00:00:00.000Z,
rate_limit_remaining: 490
}
We can use the Array.prototype.forEach() function to iterate through all the objects (videos) in the resources object and use Array.prototype.push() function to add the values into an array (as an example).
// initialize a new array called "results"
let results = [];
// for each object (initialized as "videoObject") in the "resources" object
result.resources.forEach(videoObject => {
// add the "public_id" and "url" keys into the "results" array.
results.push(videoObject.public_id, videoObject.url)
});

How to set the key value on a Go.js Node to create links

I'm using Go.js to create a canvas a user can draw straight lines on. From the documentation, I've been able to create nodes. Node creation code looks like:
const node = this.goMake(go.Node, 'Horizontal',
{ position: new go.Point(point[0], point[1]) }, // set the Node.position
this.goMake(go.Shape, 'Circle', { width: 10, height: 10, fill: 'lightblue' })
);
As I understand the documentation, in order to create a line (non-directional link) between the two nodes, I need to use their key values like so:
this.myDiagram.model.addLinkData({ from: node1.key, to: node2.key });
When logging out my nodes, I see that key value is an empty string.
Question: When creating my nodes using the first snippet above, how do I inject the key value so the second code snippet properly links the two? Creating unique values for all points is not an issue, I just can't figure out how to attach the unique value to the node's key property.
keys are a property of Model data, where the model has an array of node data and link data. Keys are not properties of the Nodes themselves exactly. node.key is just a convenience for node.data.key.
So when you write:
myDiagram.model.addNodeData( { key: 'a' });
It is making a copy of the myDiagram.nodeTemplate, and assigning that Node the node.data of { key: 'a' }, so that node's key is 'a'
In other words, you can only relate these things by the model, not by the Node that you are creating.
If you are using models, you should be creating node templates on the Diagram, not stand-alone nodes, as it appears you are doing. So something like:
myDiagram.nodeTemplate = this.goMake(go.Node, 'Horizontal',
{ position: new go.Point(point[0], point[1]) }, // set the Node.position
this.goMake(go.Shape, 'Circle', { width: 10, height: 10, fill: 'lightblue' })
);
or if you have multiple templates:
myDiagram.nodeTemplateMap.add('newTemplate', this.goMake(go.Node, 'Horizontal',
{ position: new go.Point(point[0], point[1]) }, // set the Node.position
this.goMake(go.Shape, 'Circle', { width: 10, height: 10, fill: 'lightblue' })
));

How to get data from xml by using URL

I have a grid where I am loading the data from the data store. Bu using some url. Code is something like that.
var store = new Ext.data.Store({
proxy : new Ext.data.HttpProxy({
method: 'GET',
url: SomeURL
}),
remoteSort:true,
method: 'GET',
baseParams: {start: 0, limit: 25},
sortInfo:{
field: 'UPDATEDON',
direction: 'DESC'
},
reader: new Ext.data.XmlReader({
totalProperty:'#Total',
record: 'ITEM'
}, [ {name:'name',type:'string', mapping:'#name',SortType:"asUCString"},
{name:'value', mapping:'#value'}
]),
grid:this,
listener : {
load:function(){
}
}
This is loading correctly. No problem in grid. I need to access grid data at some other place in my code. so for that I am call
`var xyz = new MyGrid({val:1,newval:2});`
val and newVal are the two para for grid. But I am not getting store and store value here. Is there anyway I can get store here or get the xml value by using the same url again.
You can set in your store autoLoad: true - if it is already binded/set with this new Grid.
Or just say xyz.store.reload();
Reloads the store using the last options passed to the load method.
You can get the data form xyz.store.
How to get the information from a store depends on you and what you have there stored. You can use 'find', 'findBy', 'each' and so on (senscha doc extjs V3.4)

jQuery MapSvg binding data to regions parameter

In my MVC application, I am trying to create a SVG Map with data that comes from a database. Using jQuery, I call an action in the controller which returns data in the format that is expected in the MapSvg region's parameter.
The format that is expected goes as follows:
regions : {
'Yemen': {disabled: true},
'USA': {tooltip: 'USA: Click to go to Google.com', attr: {fill: '#ff0000', href: 'http://google.com', 'cursor': 'help'}}},
'France': {tooltip: 'This is France!', attr: {'cursor': 'help'}},
'Kazakhstan': {tooltip: 'Kazakhstan - the ninth largest country in the world.'}
},
In my controller, I have an action that will be called in the view by a jQuery ajax request
public ActionResult GetCountries()
{
List<ScratchMap> allitems = this.Worker.GetAllItems();
var allItemsAsArray = allitems.Select(x => string.Format("'{0}': {{ tooltip: 'Test', attr: {{ fill: '{1}' }} }}", x.PluginCountryName, x.Color)).ToArray();
return Json(allItemsAsArray, JsonRequestBehavior.AllowGet);
}
In the View, the following code is executed after the jQuery plugins and the MapSvg plugins are loaded:
$.get('/ScratchMap/GetCountries', {},
function (data) {
var regionsData = '{' + data + '}';
$('#map').mapSvg(
{
source: '#Url.Content("~/Content/Maps/world_high.svg")',
loadingText: 'Loading map...',
tooltipsMode: 'names',
responsive: true,
zoom: true,
pan: true,
zoomButtons: {
'show': true,
'location': 'right'
},
regions: regionsData
});
}), 'json';
When the page is rendered, the map does not fill any countries that were retrieved from the database. However, when I copy and assign the output of the regionsData variable directly to the regions parameter, the map loads everything correctly.
The following article teaches me that this could have something to do with the input data type. However, if I parse the regionsData to JSON, it tells me it is in a wrong format. But the given example by the creators of MapSvg is also in a wrong format.
Does anybody have any ideas for a workaround?
Thanks.
The problem is that even if the regions variable is edited the map plugin doesnt watch the change in its object contents so you must either wait till the data is returned before graphing the contents. Or re-graph with the method below.
If you wish to wait to graph till the data has been returned from your database call you can use a promise to delay the graphing of the object. Also important to know is the format in which the OPTS variables needs to have here is a sample.
var OPTS = {
source: sourcepath, // Path to SVG map
colors: {background: '#fff',base: '#0066FF', stroke: '#fff', selected: 10, disabled: '#ff0000'},
tooltipsMode: 'combined',
zoom: true,
pan: true,
responsive: true,
width: 1170,
zoomLimit: [0,100],
onClick: function (e, m) {
//do something here on each map click
},
regions:{
id_of_svg_path(the actual region you want to add data for):{
disabled:true,/*or whatever you need*/
tooltip:'<h4>Something to say</h4>'
}
}
}
In-order to re-graph I used the return object:
OPTS are just your specific chart options.
A variable javascript object that contains a regions variable.
var chartObj = $('#chart_container').mapSvg(OPTS);
chartObj.destroy();
This call will destroy then you re-graph it with OPTS that you have passed in.
Once you have destroyed it and passed in the new data you can just call.
var chartObj = $('#chart_container').mapSvg(OPTS);
Re-graphing it with the new data.
It turns out that it was an issue with the way I created the javascript output. The answer to this question can be found in this article.

AngularJS/Restangular indexed JSON data extraction

I've got and app that takes quote input (purity, weight, total), and it pushes to $scope.quote:
// Controller action //
$scope.quote.push({
total: ((($scope.karat * $scope.spot) * $scope.percentage) / 20) * $scope.estimatedWeight,
karat: $scope.karat * 100,
description: $scope.description,
actualWeight: $scope.actualWeight,
estimatedWeight: $scope.estimatedWeight,
percent: $scope.percentage * 100,
spot: $scope.spot
})
and
// Factory //
app.factory('quoteFactory', function() {
var quote = [];
var factory = {};
factory.getQuote = function () {
return quote;
};
return factory;
})
and the post/save upon quote completion
$scope.save = function() {
var now = $scope.getDate();
$scope.quote.push({
createdOn: $scope.getDate()
})
Restangular.all('quote').post($scope.quote).then(function(quote){
$location.path('#/scrap')
});
};
When trying to access the quote JSON for list or edit I can't access all the information needed because of the JSON structure.
{
"0": {
"total": 401.79040000000003,
"karat": 74,
"description": "Rings",
"actualWeight": 12,
"estimatedWeight": 11,
"percent": 80,
"spot": 1234
},
"1": {
"total": 560.7296,
"karat": 56.8,
"description": "Test",
"actualWeight": 22,
"estimatedWeight": 20,
"percent": 80,
"spot": 1234
},
"2": {
"total": 48.5625,
"karat": 92.5,
"description": "Testing",
"actualWeight": 80,
"estimatedWeight": 75,
"percent": 70,
"spot": 20
},
"3": {
"createdOn": "2013-11-26T21:26:42.253Z"
},
"_id": {
"$oid": "52951213e4b05f03172f14e7"
}
}
Each index represents a line item of the quote and the createdOn info. What I'm trying to figure out is if there is a way to be able to access all the line item information without having to call each individual index?
I've looked into some lodash/underscore, thought about restructuring the backend... Not really sure where to go from here.
Complete project code at github
Since there is not much details available as to how your backend works or is handling the data I am assuming the problem is with generating the JSON.
What I would do is change the way Angular posts the data to the server, for example:
the Save function:
$scope.save = function() {
var url = 'http:127.0.0.1:3000/url/you/send/your/data/to',
json = JSON.stringify($scope.quote);
$http({
method: 'POST',
url: url,
data: json,
headers: {
'Content-Type': 'application/json'
}
}).then(function(response) {
$location.path('#/scrap');
});
};
This will give you more control, and will make sure you control how the data gets turned into proper JSON, in this case using the .stringify() method of the JSON object.
I see from your comments that you are concerned with indexing; conventionally objects that sync with the server have a property id that represents their database id's NOT their client array index. This is a good way to keep the model data on the client a representation of the truth on your server side.
There are quite some libraries out there that help with this process client side, I would suggest - since you are using Angular already - reading into Angular Resource.
NOTE: if you want to support older browsers with the JSON.stringify() method, make sure you use Crockford's JSON2.js

Categories