So I have two stores that use the exact same model, they are exactly the same in every way (except for their names of course). I want two different stores.
app.stores.newsFeed = new Ext.data.Store({
model: 'app.models.feedData',
proxy: {
type: 'scripttag',
url: 'http://query.yahooapis.com/v1/public/yql',
extraParams: {
format: 'json'
},
reader: {
root: 'query.results.item'
}
}
});
app.stores.eventsFeed = new Ext.data.Store({
model: 'app.models.feedData',
proxy: {
type: 'scripttag',
url: 'http://query.yahooapis.com/v1/public/yql',
extraParams: {
format: 'json'
},
reader: {
root: 'query.results.item'
}
}
});
My question is can I save space by getting rid of code and use only one store instance so I don't have to re-declare another new Ext.data.Store again?
something like:
store = new Ext.data.Store(...);
app.stores.newsFeed = store;
app.stores.eventsFeed = store;
I tried this before but both were assigned to the same store so when one was changed so was the other.
Just extend extJS component and you can get fast instances of your component:
MyStore = Ext.extend(Ext.data.Store, {
constructor : function(config) {
config = Ext.apply({
model: 'app.models.feedData',
proxy: {
type: 'scripttag',
url: 'http://query.yahooapis.com/v1/public/yql',
extraParams: {
format: 'json'
},
reader: {
root: 'query.results.item'
}
}
}, config);
MyStore.superclass.constructor.call(this, config);
},
onDestroy : function(config) {
MyStore.superclass.onDestroy.apply(this, arguments);
}
});
And create as much independent instanses as you want:
app.stores.newsFeed = Ext.create(MyStore, {});
app.stores.eventsFeed = Ext.create(MyStore, {});
Related
There is an existing API described in a Coludformation template. Now I want to document the API using Swagger. Is there a way to parse the Cloudformation template to create the swagger.yaml specification file? I would like to avoid writing the API a second time, if possible.
Note: I am aware that you can define your API using Swagger, then import the API configuration in your Cloudformation template. This is not what I need. The Cloudformation already exists and will not be changed. Hence, I need the opposite: a Swagger configuration file based on an existing Cloudformation template.
There is no way to convert the template to a swagger file that I know about. But if you are looking for a way to keep service-spec in one place only (template) and you have it deployed, you can take swagger or OAS file from the stage (so to do it you must have a stage as well) in two ways at least:
By Web console. Use Amazon API Gateway->
APIs->Your API->Stages>Your Stage -> Export tab. See the picture: exporting Swagger or OAS as a file by Web console
aws apigateway get-export ... Here is an example:
aws apigateway get-export --rest-api-id ${API_ID} --stage-name ${STAGE_NAME} --export-type swagger swagger.json
I just made this, it is not setup for perfect plug/play, but will give you an idea what you need to adjust to get it working (also need to make sure you CF template is setup so it has the needed info, on mine I had to add some missing requestParams I was missing, also use this site to test your results from this code to see it works with swagger):
const yaml = require('js-yaml');
const fs = require('fs');
// Get document, or throw exception on error
try {
// loads file from local
const inputStr = fs.readFileSync('../template.yaml', { encoding: 'UTF-8' });
// creating a schema to handle custom tags (cloud formation) which then js-yaml can handle when parsing
const CF_SCHEMA = yaml.DEFAULT_SCHEMA.extend([
new yaml.Type('!ImportValue', {
kind: 'scalar',
construct: function (data) {
return { 'Fn::ImportValue': data };
},
}),
new yaml.Type('!Ref', {
kind: 'scalar',
construct: function (data) {
return { Ref: data };
},
}),
new yaml.Type('!Equals', {
kind: 'sequence',
construct: function (data) {
return { 'Fn::Equals': data };
},
}),
new yaml.Type('!Not', {
kind: 'sequence',
construct: function (data) {
return { 'Fn::Not': data };
},
}),
new yaml.Type('!Sub', {
kind: 'scalar',
construct: function (data) {
return { 'Fn::Sub': data };
},
}),
new yaml.Type('!If', {
kind: 'sequence',
construct: function (data) {
return { 'Fn::If': data };
},
}),
new yaml.Type('!Join', {
kind: 'sequence',
construct: function (data) {
return { 'Fn::Join': data };
},
}),
new yaml.Type('!Select', {
kind: 'sequence',
construct: function (data) {
return { 'Fn::Select': data };
},
}),
new yaml.Type('!FindInMap', {
kind: 'sequence',
construct: function (data) {
return { 'Fn::FindInMap': data };
},
}),
new yaml.Type('!GetAtt', {
kind: 'scalar',
construct: function (data) {
return { 'Fn::GetAtt': data };
},
}),
new yaml.Type('!GetAZs', {
kind: 'scalar',
construct: function (data) {
return { 'Fn::GetAZs': data };
},
}),
new yaml.Type('!Base64', {
kind: 'mapping',
construct: function (data) {
return { 'Fn::Base64': data };
},
}),
]);
const input = yaml.load(inputStr, { schema: CF_SCHEMA });
// now that we have our AWS yaml copied and formatted into an object, lets pluck what we need to match up with the swagger.yaml format
const rawResources = input.Resources;
let guts = [];
// if an object does not contain a properties.path object then we need to remove it as a possible api to map for swagger
for (let i in rawResources) {
if (rawResources[i].Properties.Events) {
for (let key in rawResources[i].Properties.Events) {
// console.log(i, rawResources[i]);
if (rawResources[i].Properties.Events[key].Properties.Path) {
let tempResource = rawResources[i].Properties.Events[key].Properties;
tempResource.Name = key;
guts.push(tempResource);
}
}
}
} // console.log(guts);
const defaultResponses = {
'200': {
description: 'successful operation',
},
'400': {
description: 'Invalid ID supplied',
},
};
const formattedGuts = guts.map(function (x) {
if (x.RequestParameters) {
if (
Object.keys(x.RequestParameters[0])[0].includes('path') &&
x.RequestParameters.length > 1
) {
return {
[x.Path]: {
[x.Method]: {
tags: [x.RestApiId.Ref],
summary: x.Name,
parameters: [
{
name: Object.keys(x.RequestParameters[0])[0].split('method.request.path.')[1],
in: 'path',
type: 'string',
required: Object.values(x.RequestParameters[0])[0].Required,
},
{
name: Object.keys(x.RequestParameters[1])[0].split('method.request.path.')[1],
in: 'path',
type: 'string',
required: Object.values(x.RequestParameters[1])[0].Required,
},
],
responses: defaultResponses,
},
},
};
} else if (Object.keys(x.RequestParameters[0])[0].includes('path')) {
return {
[x.Path]: {
[x.Method]: {
tags: [x.RestApiId.Ref],
summary: x.Name,
parameters: [
{
name: Object.keys(x.RequestParameters[0])[0].split('method.request.path.')[1],
in: 'path',
type: 'string',
required: Object.values(x.RequestParameters[0])[0].Required,
},
],
responses: defaultResponses,
},
},
};
} else if (Object.keys(x.RequestParameters[0])[0].includes('querystring')) {
return {
[x.Path]: {
[x.Method]: {
tags: [x.RestApiId.Ref],
summary: x.Name,
parameters: [
{
name: Object.keys(x.RequestParameters[0])[0].split(
'method.request.querystring.'
)[1],
in: 'query',
type: 'string',
required: Object.values(x.RequestParameters[0])[0].Required,
},
],
responses: defaultResponses,
},
},
};
}
}
return {
[x.Path]: {
[x.Method]: {
tags: [x.RestApiId.Ref],
summary: x.Name,
responses: defaultResponses,
},
},
};
});
const swaggerYaml = yaml.dump(
{
swagger: '2.0',
info: {
description: '',
version: '1.0.0',
title: '',
},
paths: Object.assign({}, ...formattedGuts),
},
{ noRefs: true }
); // need to keep noRefs as true, otherwise you will see "*ref_0" instead of the response obj
// console.log(swaggerYaml);
fs.writeFile('../swagger.yaml', swaggerYaml, 'utf8', function (err) {
if (err) return console.log(err);
});
} catch (e) {
console.log(e);
console.log('error above');
}
I need to pass addition param to jersey server. But how do I submit my url like ..get/{param1}/{param2}/{param3}
Here is my js file
Ext.define('bluebutton.view.BlueButton.testing', {
extend: 'Ext.form.Panel',
xtype: 'testing',
requires: [
'bluebutton.view.BlueButton.TransactionList',
'bluebutton.view.BlueButton.MemberPopUp',
'bluebutton.view.BlueButton.MemberDetail',
'bluebutton.store.BlueButton.MemberList',
],
config: {
id:'register',
items :[
{
xtype: 'textfield',
name: 'name',
label: 'Name'
},
{
xtype: 'emailfield',
name: 'email',
label: 'Email'
},
{
xtype: 'button',
text: 'Send',
handler: function(button) {
var form = Ext.getCmp('register');
values = form.getValues();
// Select record
//If load data , restful will using "get", url will be /users/1
var User = Ext.ModelMgr.getModel('bluebutton.model.BlueButton.MemberList');
User.load(123,
{
success: function(user) {
alert(user.get('fullName'));
}
}
);
}
}
],
}
});
Model.js
Ext.define('bluebutton.model.BlueButton.MemberList', {
extend: 'Ext.data.Model',
config: {
idProperty: 'memberModel',
fields: [
{ name: 'fullName' },
{ name: 'singer' },
],
proxy: {
type: 'rest',
url: 'http://localhost:8080/RESTFulExample/rest/json/metallica/get',
reader: 'json',
actionMethods: {
create: 'GET',
read: 'POST',
update: 'PUT',
destroy: 'DELETE'
},
reader: {
type: 'json',
},
writer: {
type: 'json',
},
}
}
});
But now I only able to pass my url like ..get/123 Please guide me some solution.Thanks
2 things coming to my mind, First do not write proxy inside model definition, instead set it in initialize function of store where you can look at config data and create url on its basis. e.g.
initialize: function() {
var myId = this.config.uid;
this.setProxy({
type: 'rest',
url: 'http://localhost:8080/RESTFulExample/rest/json/metallica/get/'+myId,
reader: 'json',
actionMethods: {
create: 'GET',
read: 'POST',
update: 'PUT',
destroy: 'DELETE'
},
reader: {
type: 'json',
},
writer: {
type: 'json',
},
});
}
and you can pass id to load when you create the store like this:
var memberStore = Ext.create('bluebutton.store.BlueButton.MemberList', {
uid : 123
});
2nd way could be writing your own proxy extending Ext.data.proxy.Rest and implementing buildUrl such that it checks for data and append it to url. e.g.
buildUrl: function(request) {
var me = this,
url = me.callParent(arguments);
if(!Ext.isEmpty(someData)){
url = Ext.urlAppend(url, "data="+someData);
}
return url;
}
I hope it helps.
EDIT
Sample code for custom proxy which I have used in past to append some token to every request
Ext.define('myapp.proxy.CustomJsonpProxy', {
extend: 'Ext.data.proxy.JsonP',
alias: 'proxy.customjsonpproxy',
buildUrl: function(request) {
var me = this,
url = me.callParent(arguments);
if(!Ext.isEmpty(loggedInUserToken)){
url = Ext.urlAppend(url, "token="+loggedInUserToken);
}
return url;
}
});
the below code worked for me....to set a param to an url
myStore.getProxy().getApi().read = myStore.getProxy().getApi().read + param;
I tried to use model.save() to POST a new user. But I check request payload and found that it not only sent the data, but also sent other parts of the model. That makes my server cannot parse the payload.
The request payload generated :
{"phantom":true,"internalId":"ext-record-58","raw":{},"data":{"userId":0,"userName":"Amy"},"modified":{"userName":""},"hasListeners":{},"events":{},"stores":[],"dirty":true,"id":"AM.model.User-ext-record-58"}
But the desired request payload should be :
{"userId":0,"userName":"Amy"}
And I am aware that the "phantom" of my model is false before I call model.save(). But it becomes true in the request payload. Is it a clue?
Model:
Ext.define('AM.model.User',{
extend: 'Ext.data.Model',
fields: [
{ name: 'userId', type: 'int' },
{ name: 'userName', type: 'string' },
{ name: 'createdTime', type: 'string' },
],
idProperty: 'userId',
associations: [
{
type: 'hasOne',
model: 'AM.model.ModelA',
name:'modelA',
associationKey:'modelA',
getterName:'modelA'
},
{
type: 'hasOne',
model: 'AM.model.ModelB',
name:'modelB',
associationKey:'modelB',
getterName:'modelB'
}
],
proxy: {
type: 'rest',
success:true,
url:'../restful/users',
writer:{
type:'json',
getRecordData:function(record){ //parse createdTime to the format Y-m-d
record.set('createdTime', Ext.Date.format(new Date(record.get('createdTime')), "Y-m-d"));
return record;
}
},
reader: {
type: 'json'
}
}
});
This is the view which has the data to be posted. The view will fill the data to the model:
Ext.define('AM.view.UserRegisterForm',{
extend:'Ext.form.Panel.',
alias:'widget.userRegisterForm',
fields:new Array(), //I want to render the fields in xtemplate, so instead of adding the fields to items, I use an array to manage them.
retrieveData(model){
model.set('userName', this.fields[0].getValue());
model.set('createdTime',this.fields[1].getValue());
}
}
The function in the controller, which sends the POST request:
postUser:function(){
var userRegisterForm= this.getUserRegisterForm();
var userModel = this.getUserModel();
var user= new userModel();
var me = this;
userRegisterForm.retrieveFieldData(user);
console.log(user); //the data in console looks fine!
user.save({
success: function(response) {
//do something...
},failure:function(response) {
alert('fail');
}
});
}
You are returning the full record when you override getRecordData Where as you are just meant to return the records data. record.getData()
Some extra advice. Don't override getRecordData to set the models creation date. Use the models defaultValue property to give assign it a new Date if one doesn't exist.
My application grid is loading data using the webservice URL to fill grid with coming data. When Im giving URL like
function gridSectionResources()
{
Ext.define('Person', {
extend: 'Ext.data.Model',
fields: ['EmployeeID', 'FirstName', 'LastName','Designation','Role','BillingRate','SignedOn','SignedOff']
});
var store = Ext.create('Ext.data.Store', {
autoLoad: true,
//autoSync: true,
model: 'Person',
proxy: {
type: 'rest',
url:'http://localhost:2012/HBWebService/ws/employees',
// url:'js/Manager/data.json',
reader: {
type: 'json',
root: 'Project'
},
writer: {
type: 'json'
}
}
});
Working fine but
If I'm giving url:'http://172.166.11.9:2012/HBWebService/ws/employees'. It is not working
You must use JsonP proxy for getting data from another domain.
http://docs.sencha.com/ext-js/4-0/#!/api/Ext.data.proxy.JsonP
Ext.define('Person', {
extend: 'Ext.data.Model',
fields: ['EmployeeID', 'FirstName', 'LastName','Designation','Role','BillingRate','SignedOn','SignedOff']
});
var store = Ext.create('Ext.data.Store', {
autoLoad: true,
//autoSync: true,
model: 'Person',
proxy: {
type: 'jsonp',
url:'http://localhost:2012/HBWebService/ws/employees',
// url:'js/Manager/data.json',
reader: {
type: 'json',
root: 'Project'
},
writer: {
type: 'json'
}
}
});
i am trying to update records displayed in editor grid..but instead of updating same record, a new record gets inserted into the database...what am i missing??pllzz help..following is my JsonStore code :
Ext.data.Api.restActions = {
create : 'POST',
read : 'GET',
update : 'PUT',
destroy : 'DELETE' };
ProdStore = Ext.extend(Ext.data.JsonStore, {
constructor: function(cfg) {
cfg = cfg || {};
ProdStore.superclass.constructor.call(this, Ext.apply({
storeId: 'ProdStore',
id:'ProdStore',
url: 'products.json',
root: 'proddata',
restful:true,
idProperty:'id',
successProperty:'success',
autoLoad:true,
autoSave:false,
batch:true,
writer: new Ext.data.JsonWriter({
encode: false,
listful: false,
writeAllFields: false}),
fields: [
{ name:'customer_id'},{ name: 'prodnm'},
{ name: 'qty'}, { name: 'rate' }, { name: 'amt'}
]
}, cfg));
}
});
new ProdStore();
The idProperty set on the store should be the field that represents unique rows in the database. Perhaps customer_id in this case?
If this does not fix the issue, I would have to see the back end code to see how the save is being handled.