SuiteCommerce Advance: Create Custom Service to fetch the custom record from Netsuite's backend to backbone view - backbone.js

I have custom record created in netsuite's backend named Webstore Landing Data. Record is having below structure & columns
Record Id: customrecord_webstore_category_landing
Coloumns:
i. custrecord_collection_name
ii. custrecord_collection_sub_category
iii. custrecord_collection_url
And need to create service to fetch this record on backbone view. Help appreciated.

Ok, Good question. This is the most important and required thing in SCA check below details-->
Note: Below steps is for SuiteCOmmerce Advance Vision(2016-17) release
You need to created below things-->
i. SuiteScript Model
ii. SuiteScript Service
iii.JavaScript Model
iv. JavaScript view
v. JavaScript Template
vi. Update distro.json
Create custom folder(our custom module) under custom folder as
Modules/custom/Categorylanding#1.0.0
Create SuiteScript folder under above module
Create SuiteScript Service under 'SuiteScript' Folder as below-->
FileName & Path: Modules/custom/Categorylanding#1.0.0/SuiteScript/Categorylanding.ServiceController.js
Code:
define(
'Categorylanding.ServiceController'
, [
'ServiceController'
, 'Categorylanding.Model'
]
, function(
ServiceController
, Categorylanding
)
{
'use strict';
return ServiceController.extend({
name: 'Categorylanding.ServiceController'
, get: function()
{
return Categorylanding.get();
}
});
}
);
Create SuiteScript Model under SuiteScript folder as below-->
FileName & Path:
Modules/custom/Categorylanding#1.0.0/SuiteScript/Categorylanding.Model.js
Code:
define('Categorylanding.Model',
[
'SC.Model'
],
function (SCModel) {
return SCModel.extend({
name: 'Categorylanding',
get: function()
{
var filters = new Array();
var columns = new Array();
columns[0] = new nlobjSearchColumn('custrecord_collection_name');
columns[2] = new nlobjSearchColumn('custrecord_collection_url');
var results = nlapiSearchRecord('customrecord_webstore_category_landing', null, filters, columns);
var results_ = JSON.stringify(results);
return results_;
}
});
}
)
Created ns package file
Filename & Path:
Modules/custom/Categorylanding#1.0.0/ns.package.json
Code:
{
"gulp": {
"javascript": [
"JavaScript/*"
],
"ssp-libraries": [
"SuiteScript/*.js"
],
"autogenerated-services": {
"Categorylanding.Service.ss": "Categorylanding.ServiceController"
},
"templates": [
"Templates/*"
],
"images": [
"Images/*"
],
"sass": [
"Sass/*.scss"
],
"configuration": [
"Configuration/*.json"
]
}
}
Update distro. json file as below
add your module under modules section as
"custom/Categorylanding": "1.0.0",
and dependencies in
"ssp-libraries": {
"entryPoint": "SCA",
"dependencies": [
"CategoryLanguage.ServiceController",
"CategoryLanguage.Model",
],
Deploy your code and once this is done you can able to see your data when in return call, you can call your service as below
http://yoursite.com/sca-dev-vinson/services/Categorylanding.Service.ss?c=4515330
Now the remaining part is how you can get this data on backbone view, to do this go to your view where you want this data
Before that create Javascript model under Same folder as below
Filename & Path :
Modules/custom/Categorylanding#1.0.0/JavaScript/Categorylanding.Model.js
Code:
define('Categorylanding.Model',
[
'Backbone',
'underscore'
],
function (Backbone, _) {
return Backbone.Model.extend(
{
url: function()
{ var urlRoot = _.getAbsoluteUrl('services/Categorylanding.Service.ss');
return urlRoot;
}
});
}
);
Once this is done, you can call above javascript model on any view/router file to get the record data on backbone view
Define mode and use below code
var collection = new CategorylandingModel();
var view = new BrowseView({
translator: translator
, translatorConfig: self.translatorConfig
, application: self.application
, collection: collection
});
collection.fetch().done(function(data) //again fetch Instagram service
{
console.log(data) //your service data will log here
});
Now you can able to access your data on BrowseView(){} as
var recorddata = this.collection.attributes;
console.log(recorddata);
and Pass it handlebar. That's it.
Let me know if you want any help....

Related

getconfig() for Community Connectors, how to employ user input

The Community Connector feature is very new, and I have searched, there isn't much information. We are building a Community Connector to enable Data Studio to pull API data from Google My Business Insights.
the getconfig() function is described here: https://developers.google.com/datastudio/connector/reference#getconfig
We can display our configuration options to the user, that was easy, but the API reference is unclear what the next step is: how to pass the user input to the next step. Pardon me if I am not using the proper terms here.
var config = {
configParams: [
{
"type": "SELECT_SINGLE",
"name": "SELECT_SINGLE",
"displayName": "Select a Location",
"helpText": "Pick One!",
"options": [
{
"label": locationName,
"value": name
},
{
"label": "altLocationName",
"value": "altName"
}
]
},
]
};
return config;
}
The preceding code displays properly to the user and the user can make a selection from the pull-down in Data Studio when making an initial data connection. But to repeat the question another way: how do we access the selection that the user chose?
The getData(), getSchema(), and getConfig() functions are all called with a parameter (which is called "request" in the documentation). The parameter is an object containing various info at each stage.
At the getConfig() stage, it includes a property called languageCode, in my case set to 'en-GB'.
The getSchema() stage is provided a property called configParams, which is essentially the result of all the settings in getConfig() after the user has set them.
Finally, getData() gets the most info, including whether this request is for extracting sample data for google to run heuristics on, and most importantly: again the configParams.
Here's what a sample request object might look like:
{ //------ Present in:
languageCode: en-GB, //////-Only getConfig()
configParams: { //////-getSchema() + getData()
SELECT_SINGLE: altName ////-+
}, //
scriptParams: { //////-Only getData()
sampleExtraction: true ////-|
lastRefresh: 'new Date()' ////-+
}, //
fields: [ //////-Only getData()
{ name: FooAwesomeness }, ////-|
{ name: BarMagicality }, ////-|
{ name: BazPizzazz } ////-+
] //
dimensionsFilters: [ //////-Only getData()
[{ // |
fieldName: "string", ////-|
values: ["string", ...], ////-|
type: DimensionsFilterType, ////-|
operator: Operator ////-+
}] //
] //
} //------
Do note
that the name field in your code, currently set to SELECT_SINGLE, would be better suited to be called location because that it how you'll access it later on.
In this way you would
access:
request.configParams.location
rather than
request.configParams.SELECT_SINGLE
:)
Also note
that the format for specifying a configuration screen has been updated. Your configuration would now be able to be done as follows:
function getConfig(request) {
var cc = DataStudioApp.createCommunityConnector();
var config = cc.getConfig();
config
.newSelectSingle()
.setId('location') // You can call this "location"
.setName('Select a Location')
.setHelpText('Pick One!')
.addOption(config.newOptionBuilder()
.setLabel('Location Name')
.setValue('value'))
.addOption(config.newOptionBuilder()
.setLabel('Alternate Location Name')
.setValue('altValue'))
config.setDateRangeRequired(true);
config.setIsSteppedConfig(false);
return config.build();
}
See: Connector API Reference
See: Build a Connector Guide
The user selections will be passed to getSchema() and getData() requests under configParams object.
Using your example, let's assume the user selects altLocationName in the configuration screen. In your getSchema() and getData() functions, request.configParams.SELECT_SINGLE should return altName.

AngularJs, Django RESTful and Restangular: Consuming an array of hyperlinks

I'm having trouble configuring restangular to consume a list of api urls in my response object.
Currently, my object response looks like:
{
folders: ['http://localhost:8000/api/folder/1',
'http://localhost:8000/api/folder/2',
'http://localhost:8000/api/folder/3']
}
but i want it to return the folder objects
{
folders: [{
files: ['http://localhost:8000/api/file/1'
'http://localhost:8000/api/file/2']
},
{
files: ['http://localhost:8000/api/file/3']
},
{
files: ['http://localhost:8000/api/file/4']
}]
}
(and then eventually the file objects inside the folder objects):
{
folders: [{
files: [{},{}]
},
{
files: [{}]
},
{
files: [{}]
}]
}
How can I configure restangular through addResponseInterceptor or other means to consume the array of nested hyperlinks
I have not found a solution which performs a get() on all nested urls independently without doing it explicitly in the controller.
So for these twice nested jsons, I created three different objects rather than one full cabinet object. Restangular than can use its put and patch methods on the objects returned.
Then I iterate through each folder in the cabinet, and in turn each file in the folder to get all my objects into the view.
If anybody has a better way let me know!
vm.cabinet = {};
vm.folders = [];
vm.files = {}
Cabinet.get(id).then(cabinetSuccessFn, errorFn);
function cabinetSuccessFn(response) {
vm.cabinet = response;
vm.cabinet.folders.map(function(folder) {
return Folder.get(parseInt(folder.substr(folder.lastIndexOf('/', folder.length - 2) + 1).slice(0, -1))).then(folderSuccessFn, errorFn);
});
vm.loading = false;
}
function folderSuccessFn(response) {
vm.folders.push(response);
vm.files[response.id] = [];
response.files.map(function(file) {
return Files.get(parseInt(file.substr(file.lastIndexOf('/', file.length - 2) + 1).slice(0, -1))).then(fileSuccessFn, errorFn);
});
}
function fileSuccessFn(response) {
vm.filess[response.folder.substr(response.folder.lastIndexOf('/', response.folder.length - 2) + 1).slice(0, -1)].push(response);
}
function errorFn(response) {
$log.error('unable to load resource');
$log.error(response);
}

How to edit server stored JSON file with NodeJS

I have a web server hosting over localhost. The website I am accessing is a "Todo list app" written with AngularJS. To load the todo's, the browser gets a JSON file with the information. An example of this:
[
{"name":"Clean the house"},
{"name":"Water the dog"},
{"name":"Feed the lawn"},
{"name":"Pay dem bills"},
{"name":"Run"},
{"name":"Swim"}
]
It then loops through all the items and "prints" them out onto the website. I have various options like "Save" and "Delete". They work client-side, but that way does not allow me to properly save them, as when the browser is refreshed, all the content is reset with the server's static JSON file.
I was wondering if there was some way of using NodeJs to host the website and listen for incoming AJAX request and edit the content in the file based off that.
Writing a file asynchronously in nodejs can be done as follows.
var fs = require('fs');
var fileName = './file.json';
var file = require(fileName);
file.key = "new value"; // This will be coming as a http POST method from your view
fs.writeFile(fileName, JSON.stringify(file), function (err) {
if (err) return console.log(err);
console.log(JSON.stringify(file));
console.log('writing to ' + fileName);
});
The caveat is that json is written to the file on one line and not prettified. ex:
{
"key": "value"
}
will be...
{"key": "value"}
To avoid this, simply add these two extra arguments to JSON.stringify
JSON.stringify(file, null, 2)
null - represents the replacer function. (in this case we don't want to alter the process)
2 - represents the spaces to indent.
NodeJS does not persist data out of the box.
You want something like NodeJS + Express and special CRUD routes like POST for creating items or DELETE for deleting them.
In this routes you have to add a data persistance layer like mongoose if you want to use MongoDB or Sequelize if you want to add a SQL database behind it.
Each of this ORM requires to specify a Datamodel which can be saved.
Here an example for a mongoose implementation:
'use strict';
/**
* Module dependencies.
*/
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var plugins = require('./model.server.plugins');
/**
* Customer Schema
*/
var CustomerSchema = new Schema({
name: {
type: String,
default: '',
required: 'Please fill a name',
trim: true
},
created: {
type: Date,
default: Date.now
}
});
mongoose.model('Customer', CustomerSchema);
Here is the controller
'use strict';
/**
* Module dependencies.
*/
var mongoose = require('mongoose'),
errorHandler = require('./errors.server.controller'),
Customer = mongoose.model('Customer'),
_ = require('lodash');
/**
* Create a Customer
*/
exports.create = function(req, res) {
var customer = new Customer(req.depopulated);
customer.user = req.user;
customer.save(function(err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(customer);
}
});
};
Here the route
router.route('/')
.post(customers.create);

Fetch single field from mongodb in meteor

i'm new to meteor framework
I want to fetch single from the collection
AccountNames = new Mongo.Collection("AccountTypeMaster");
I created a collection using
db.createCollection("AccountTypeMaster")
this.helpers({
AccountNames: () => {
return AccountNames.find({}, {fields: {name: 1}});
}
});
Using above query i'm unable to fetch single field "name" from collection.
I'm now sure what's wrong with my code.
You need to change how you instantiate your collection. The correct Meteor syntax would be:
AccountNames = new Mongo.Collection("AccountTypeMaster");
Helpers also need to be attached to a template. Remember, helpers only run on client-side code.
if (Meteor.isClient) {
// This code only runs on the client
Template.body.helpers({
tasks: function () {
return AccountNames.find({}, { fields: { name: 1 } });
}
});
}
Create Client folder in your project and put client side code into that folder.To create collection in mongodb
Template.name.helpers({
fun: function() {
return AccountNames.find({},{name: 1}).fetch();
})

extjs4 - is there a non json/xml writer for proxies?

I'm building some models to interact with an existing API from a previous project.
The API relies on standard POST methods to save the data.
I've configured a model and proxy up to the point where it does push the data onto the server but there only seems to be two writer types, json & xml.
proxy: {
/* ... */
reader: {
type: 'json',
root: 'results'
},
writer: {
type: '???' // <-- can only see json or xml in the docs
}
}
Isn't there a standard POST writer that simply submits data in post fields?
I'm surprised that wouldn't be a standard writer type.
(Parsing the json format wouldn't be too hard to implement but that would mean updating a lot of the old api files.)
Ok, I was able to create that writer quite easily by checking the existing writers' source code.
One thing those existing writers are able to do - and that may be why the dev team only implemented a json and xml version - is that they can push multiple records at once.
That could be implemented in POST but would be a bit more complicated.
This writer will work if you're trying to push a single model to an api using POST:
Ext.define('Ext.data.writer.SinglePost', {
extend: 'Ext.data.writer.Writer',
alternateClassName: 'Ext.data.SinglePostWriter',
alias: 'writer.singlepost',
writeRecords: function(request, data) {
request.params = data[0];
return request;
}
});
and the use this for the writer in the proxy:
writer: {
type: 'singlepost'
}
Based on Ben answer I've implemented my own writer that will collect all properties of all models into arrays.
For example if you have model like with some fields:
fields:[
{name:'id', type:'int'}
{name:'name', type:'string'}
{name:'age', type:'date'}
]
A request string will be
id=1&id=2&id=...&name=oleks&name=max&name=...&age=...
Code:
Ext.define('Ext.data.writer.SinglePost', {
extend: 'Ext.data.writer.Writer',
alternateClassName: 'Ext.data.SinglePostWriter',
alias: 'writer.singlepost',
writeRecords: function(request, data) {
if(data && data[0]){
var keys = [];
for(var key in data[0]){
keys.push(key);
}
for(var i=0;i<keys.length;i++){
request.params[keys[i]] = [];
for(var j=0;j<data.length;j++){
request.params[keys[i]].push((data[j])[keys[i]]);
}
}
}
return request;
}
});
For Sencha touch 2.0, change the writeRecords method to:
writeRecords: function (request, data) {
var params = request.getParams() || {};
Ext.apply(params, data[0]);
request.setParams(params);
return request;
}
Here's my version, adapted from answers above:
// Subclass the original XmlWriter
Ext.define('MyApp.utils.data.writer.XmlInAPostParameter', {
extend : 'Ext.data.writer.Xml',
// give it an alias to use in writer 'type' property
alias : 'writer.xml_in_a_post_parameter',
// override the original method
writeRecords : function(request, data) {
// call the overriden method - it will put the data that I
// want into request.xmlData
this.callParent(arguments);
// copy the data in request.xmlData. In this case the XML
// data will always be in the parameter called 'XML'
Ext.apply(request.params, {
XML: request.xmlData
});
// Already copied the request payload and will not send it,
// so we delete it from the request
delete request.xmlData;
// return the modified request object
return request;
}
});
Ext.define("MyApp.model.MyModel", {
extend : "Ext.data.Model",
requires : [
'MyApp.utils.data.writer.XmlInAPostParameter'
],
fields : [ 'field_A', 'field_B' ],
proxy : {
type : 'ajax',
api : {
read : '/mymodel/read.whatever',
update : '/mymodel/write.whatever'
},
reader : {
type : 'xml'
},
writer : {
// use the alias we registered before
type : 'xml_in_a_post_parameter'
}
}
});

Resources