need to know if i can call a specific part of the following script
chrome.identity.getAuthToken({
interactive: true
}, function(token) {
if (chrome.runtime.lastError) {
alert(chrome.runtime.lastError.message);
return;
}
var x = new XMLHttpRequest();
x.open('GET', 'https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token=' + token);
x.onload = function() {
alert(x.response);
};
x.send();
});
I currently use document.write(x.response) which writes out the users information but would like to call only the id
{ "id": "XXX",
"email": "XXX",
"verified_email": true,
"name": "XXX", }
what I would like to do is turn the id into a variable.
var user_id = x.response['id']... Or something like that.
the original code can be found
chrome.identity User Authentication in a Chrome Extension
Try :
var user_id = JSON.parse(x.response).id;
Related
I have an api which gives the following data as response:
{
"status": 200,
"msg": "Data Found",
"data": {
"id": 104,
"firstName": "aaa",
"lastName": "aaa",
"surname": "aaa",
"email": "email#email.care",
"phone": "090909090",
"age": "23",
"gender": "M",
"height": "163",
"bloodGroup": null,
"weight": "72",
"status": null,
"fileId": 228,
"password": "pass",
"file": {
"id": 228,
"filename": "images.jpg",
"path": "user/images1613558976577.jpg",
"alt": "shafa care"
}
},
"success": true,
"token": "some token",
"userAccess": "some data"
}
The "file" parameter in the response is used to hold the image that the user uploads. For my update method, the user needs to pass their token as header for the update api. For updating the file parameter i have tried many different ways just to update the user image. The below code is using multipart form data to update the existing file image.
Future<AuthModel> updateImage(File imageFile, AuthModel authModel) async{
final String _accessToken = '${authModel.token}';
final String url =
'${GlobalConfiguration().getString('api_base_url')}auth/user/update';
var stream = new http.ByteStream(imageFile.openRead());
var length = await imageFile.length();
var uri = Uri.parse(url);
var request = new http.MultipartRequest("POST", uri);
request.headers['Authorization'] = _accessToken;
// request.headers['Content-Type'] = 'multipart/form-data';
var multipartFile = new http.MultipartFile('file', stream, length, filename: basename(imageFile.path));
request.files.add(multipartFile);
var response = await request.send();
print("updating: " + response.statusCode.toString());
response.stream.transform(utf8.decoder).listen((event) {
currentUser = authModelFromJson(event);
print("updating img: " + event);
});
return currentUser;
}
The above function does not update my file parameter even when the data is found. I just get the same old response. filepicker is also sending the correct image path that the user chooses from the gallery. I have also tried using http.client.post method using a token as the header and 'file' parameter as the body but then data is not found as the api only accepts form-data when an image is being uploaded.
It works in postman using form-data post method.
I am new to flutter and still learning. I have been stuck here for days without any solution. How can i update the file parameter from my flutter application? Any help is appreciated.
This is sample code. I hope this may help you !
static Future<bool> uploadFileAsFormData(
String url, File file) async {
try {
var uri = Uri.parse(_buildUrl(url));
var request = http.MultipartRequest('POST', uri);
request.files.add(await http.MultipartFile.fromPath('file', file.path));
var res = await request.send();
if (res.statusCode == 200) {
return true;
} else {
return false;
}
} catch (err) {
return false;
}
}
You can use this Dio to upload the image as shown by the following code:
Dio dio = Dio();
var formData = FormData();
for (var file in filePath) {
formData.files.addAll([MapEntry("files", await MultipartFile.fromFile(file)),]);
print(formData.length);
}
var response = await dio.post(url
data: formData,
options: Options(headers: {
'Authorization': _accessToken
}));
if(response.statusCode == 200){
print(response.data.toString();
}
I'm struggling with trying to figure out what I'm doing wrong, mostly down to not having a good understanding of AngularJS due to being new. The main goal is that I'm trying to list out all the values in the additionalText list out on the front-end, but it seems to be causing issue with this error:
Error: [$http:badreq] Http request configuration url must be a string or a $sce trusted object. Received: []
Context:
I have table in my application that relies on the API, this variable contains a list and outputs the following:
{
"name": "TEST",
"description": "TEST",
"additionalText": [
{
"name": "TEST",
"description": "TEST",
"lockId": 0
}
{
"name": "TEST",
"description": "TEST",
"lockId": 0
}
],
"lockId": 0
}
The API is working as expected, I can carry out all the necessary REST calls successfully. So I'm not struggling with that, the front-end is where I am having some difficulty.
HTML:
<td data-title="'additionalTexts'" sortable="'additionalTexts'">
<span ng-repeat="additionalText in additionalTextList[entity.name]">
<i>{{additionalText.name}}</i><br>
</span>
</td>
AngularJS:
$scope.refreshTextTable= function() {
SpringDataRestService.query(
{
collection: "APIURL"
},
function (response) {
var additionalTextRoles = response;
$scope.textTableOptions = new NgTableParams({}, {
dataset: additionalTextRoles,
counts: [],
});
// Also populate a list of all linked roles
for (var i = 0; i < additionalTextRoles.length; i++) {
var additionalTextRole = additionalTextRoles[i];
// This approach allows you to inject data into the callback
$http.get(additionalTextRole.additionalText).then((function (additionalTextRole) {
return function(response) {
$scope.additionalTextList[additionalTextRole.name] = response.additionalText;
};
})(additionalTextRole));
}
},
function (response) {
// TODO: Error Handling
}
);
};
Any help would be greatly appreciated, I'm really struggling with this one.
Can you try this below code:
$scope.refreshTextTable = function() {
SpringDataRestService.query({
collection: "APIURL"
},
function(response) {
var additionalTextRoles = response;
$scope.textTableOptions = new NgTableParams({}, {
dataset: additionalTextRoles,
counts: [],
});
// Also populate a list of all linked roles
for (var i = 0; i < additionalTextRoles.length; i++) {
var additionalTextRole = additionalTextRoles[i];
// This approach allows you to inject data into the callback
$http.get(additionalTextRole.additionalText).then((function(additionalTextRole) {
return function(response) {
$scope.additionalTextList = response.additionalText;
};
})(additionalTextRole));
}
},
function(response) {
// TODO: Error Handling
}
);
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.3/angular.min.js"></script>
<td data-title="'additionalTexts'" sortable="'additionalTexts'">
<span ng-repeat="additionalText in additionalTextList">
<i>{{additionalText.name}}</i><br>
</span>
</td>
The error message says the url must be a string.
For debugging purposes, console.log the URL:
for (var i = 0; i < additionalTextRoles.length; i++) {
var additionalTextRole = additionalTextRoles[i];
// This approach allows you to inject data into the callback
var url = additionalTextRole.additionalText;
console.log(i, url);
$http.get(url).then((function (additionalTextRole) {
return function(response) {
$scope.additionalTextList[additionalTextRole.name] = response.additionalText;
};
})(additionalTextRole));
}
Also note that the response object returned by the $http service does not have a property named additionalText. So it is likely that the intention is response.data.additionalText. To avoid the IIFE, use the forEach method:
additionalTextRoles.forEach( role => {
var url = role.additionalText;
console.log(url);
$http.get(url).then((function(response) {
$scope.additionalTextList[role.name] = response.data.additionalText;
});
});
I have a web socket service that I need it to fetch multiple requests.
I init the web socket with a url and need to send about 200 json requests.
So my question is,
What is the best way to do it?
Do I need open a web socket separatelly for each request?
CODE:
var ws = new WebSocket("wss://api.example.com/api/");
ws.onopen = function() {
ws.send(
JSON.stringify({
"method": "getItem",
"params": {
"color": "WHITE"
}
})
);
};
ws.onmessage = function(evt) {
var received_msg = evt.data;
console.log(received_msg);
};
So in this example I need more 200 times this JSON request:
JSON.stringify({
"method": "getItem",
"params": {
"color": "WHITE"
}
})
I would consider adding a message queue (this could be a simple Array) and sending the messages in the queue whenever you can.
i.e.:
ws.queue = []
ws.onmessage = function(evt) {
var received_msg = evt.data;
console.log(received_msg);
while(evt.target.queue.length) {
evt.target.send(evt.target.queue.pop());
}
};
ws.onopen = function(evt) {
while(evt.target.queue.length) {
evt.target.send(evt.target.queue.pop());
}
}
ws.queue.push( JSON.stringify({
"method": "getItem",
"params": {
"color": "WHITE"
}
}) );
This is quick and dirty example, but I'm sure a similar approach could work.
I'm able to successfully connect and query data from a mySql db via a Breeze/Angular client, following the todo-angular example. I switched out the db table and the GUI and was still ok. The problem starts when I try to use a naming convention. (I don't have control over the db that I have to connect to & I really don't want to use Uppercase_Underscored_Words in my client!)
I'm getting the following exception:
/Users/Sherri/Sites/awdb-web/node_modules/breeze-sequelize/node_modules/breeze-client/breeze.debug.js:1852
throw new Error("Unable to locate a registered object by the name: " + k
^
Error: Unable to locate a registered object by the name: NamingConvention.underscoreCamelCase
at Object.__config._fetchObject (/Users/Sherri/Sites/awdb-web/node_modules/breeze-sequelize/node_modules/breeze-client/breeze.debug.js:1852:13)
at MetadataStore.proto.importMetadata (/Users/Sherri/Sites/awdb-web/node_modules/breeze-sequelize/node_modules/breeze-client/breeze.debug.js:6517:40)
at new module.exports.MetadataMapper (/Users/Sherri/Sites/awdb-web/node_modules/breeze-sequelize/MetadataMapper.js:19:8)
at SequelizeManager.importMetadata (/Users/Sherri/Sites/awdb-web/node_modules/breeze-sequelize/SequelizeManager.js:46:24)
at createSequelizeManager (/Users/Sherri/Sites/awdb-web/server/routes.js:114:8)
at /Users/Sherri/Sites/awdb-web/server/routes.js:23:27
When I take the "namingConvention": "camelCase" line out of the metadata.json file, the error goes away, but of course, the database property is not able to be correctly converted.
Here is the relevant code I use to set up the Entity Manager: (EDIT: I'm pretty sure my problem is server side and has nothing to do with this code, though)
var namingConvention = new UnderscoreCamelCaseConvention();
namingConvention.setAsDefault();
breeze.core.config.initializeAdapterInstance("uriBuilder", "json");
var serviceName = 'breeze/awdb';
var manager = new breeze.EntityManager(serviceName);
// Take any server property name and make it camelCase for the client to use.
// also, save it so that we can convert from the client back to the server's name
function UnderscoreCamelCaseConvention() {
var serverNames = {
netPoints: 'netPoints',
netPointsSpent: 'netPointsSpent'
}; // every translated server name
return new breeze.NamingConvention({
name: 'underscoreCamelCase',
clientPropertyNameToServer: clientPropertyNameToServer,
serverPropertyNameToClient: serverPropertyNameToClient
});
function clientPropertyNameToServer(clientPropertyName) {
return serverNames[clientPropertyName];
}
function serverPropertyNameToClient(serverPropertyName) {
var clientName = _.camelCase(serverPropertyName);
serverNames[clientName] = serverPropertyName;
return clientName;
}
}
And here is a snippet of my metadata.json file:
{
"metadataVersion": "1.0.5",
"namingConvention": "underscoreCamelCase",
"localQueryComparisonOptions": "caseInsensitiveSQL",
"dataServices": [
{
"serviceName": "breeze/awdb/",
"hasServerMetadata": true,
"jsonResultsAdapter": "webApi_default",
"useJsonp": false
}
],
"structuralTypes": [
{
"shortName": "person",
"namespace": "AWdb.Models",
"autoGeneratedKeyType": "Identity",
"defaultResourceName": "people",
"dataProperties": [
{
"name": "Person_ID",
"dataType": "Int32",
"isNullable": false,
"defaultValue": 0,
"isPartOfKey": true,
"validators": [
{
"name": "required"
},
{
"min": -2147483648,
"max": 2147483647,
"name": "int32"
}
]
},
{
"name": "Household_ID",
"dataType": "Int32",
"validators": [
{
"min": -2147483648,
"max": 2147483647,
"name": "int32"
}
]
},
....
]
}
],
"resourceEntityTypeMap": {"people": "person:#AWdb.Models"}
}
EDIT:
Here is code from my routes.js file that gets the metadata.
var fs = require('fs');
var breezeSequelize = require('breeze-sequelize');
var SequelizeManager = breezeSequelize.SequelizeManager;
var SequelizeQuery = breezeSequelize.SequelizeQuery;
var SequelizeSaveHandler = breezeSequelize.SequelizeSaveHandler;
var breeze = breezeSequelize.breeze;
var EntityQuery = breeze.EntityQuery;
var dbConfig = {
host: 'localhost',
user: 'xx',
password: 'xx',
dbName: 'xx'
};
var _sequelizeManager = createSequelizeManager();
// _sequelizeManager.sync(true).then(seed).then(function(){
// console.log('db init successful');
// });
exports.init = init;
function init(app) {
app.get('/breeze/awdb/Metadata', function (req, res, next) {
try {
var metadata = readMetadata();
res.send(metadata);
} catch(e){
next(e);
}
});
function createSequelizeManager() {
var metadata = readMetadata();
var sm = new SequelizeManager(dbConfig);
sm.importMetadata(metadata);
return sm;
}
function readMetadata() {
var filename = "server/AWdbMetadata.json";
if (!fs.existsSync(filename)) {
filename = "AWdbMetadata.json";
if (!fs.existsSync(filename)) {
throw new Error("Unable to locate file: " + filename);
}
}
var metadata = fs.readFileSync(filename, 'utf8');
return JSON.parse(metadata);
}
Any ideas? Should I be able to use a custom naming convention when I'm on a node.js server, using a metadata.json file instead of a .net entity framework?
If I'm looking at this correctly, then I think your issue is the metadata on the server. If I understand correctly, your table and column names follow the Uppercase_Underscored_Word pattern. The Breeze/Sequelize stack on the server currently doesn't have the ability to convert names, so you must use the names of entities and properties exactly as they are in the DB schema. Otherwise, the Breeze to Sequelize translation will fail. You can still use a naming convention on the client to turn the underscored server names into whatever you want them to be on the client.
So, you need two metadata files. One for the server that is used by the Breeze/Sequelize stack and that uses names exactly as they are in the DB and then a separate metadata file for the client, where you can do the translation.
I am a complete n00b to Backbone.js, and have only been working with it for a few days. I am attempting to fetch JSON data to populate the model, and in this scenario I have two models that I need to generate. Here is the sample JSON I have been working with:
JSON
{
"status": "200",
"total": "2",
"items":
[{
"id": "1",
"name": "Here is another name",
"label": "Label for test",
"description": "A description for more information.",
"dataAdded": "123456789",
"lastModified": "987654321"
},
{
"id": "2",
"name": "Name of item",
"label": "Test Label",
"description": "This is just a long description.",
"dataAdded": "147258369",
"lastModified": "963852741"
}]
}
Backbone JS
// MODEL
var Service = Backbone.Model.extend({
defaults: {
id: '',
name: '',
label: '',
description: '',
dateAdded: '',
dateModified: ''
}
});
var service = new Service();
// COLLECTION
var ServiceList = Backbone.Collection.extend({
model: Service,
url: "./api/service.php",
parse: function(response) {
return response.items;
}
});
//
var serviceList = new ServiceList();
var jqXHR = serviceList.fetch({
success: function() {
console.log("Working!");
console.log(serviceList.length);
},
error: function() {
console.log("Failed to fetch!");
}
});
// VIEW for each Model
var ServiceView = Backbone.View.extend({
el: $('.widget-content'),
tagName: 'div',
template: _.template($('#service-template').html()),
initialize: function() {
this.collection.bind("reset", this.render, this);
},
render: function() {
console.log(this.collection);
this.$el.html('');
var self = this;
this.collection.each(function(model) {
self.$el.append(self.template(model.toJSON()));
});
return this;
}
});
//
var serviceView = new ServiceView({
collection: serviceList
});
console.log(serviceView.render().el);
html
<div class="widget-content">
<!-- Template -->
<script type="text/template" id="service-template">
<div><%= name %></div>
</script>
</div>
When I console log the serviceList.length I get the value 2, so I believe the JSON object is fetched successfully. I also get the "Working!" response for success too. However, in the view I am showing an empty object, which gives me an empty model.
I am still trying to understand the best way to do this too. Maybe I should be using collections for the "items" and then mapping over the collection for each model data? What am I doing wrong? Any advice or help is greatly appreciated.
I can see two problems. First, you want to remove serviceList.reset(list). Your collection should be populated automatically by the call to fetch. (In any case the return value of fetch is not the data result from the server, it is the "jqXHR" object).
var serviceList = new ServiceList();
var jqXHR = serviceList.fetch({
success: function(collection, response) {
console.log("Working!");
// this is the asynchronous callback, where "serviceList" should have data
console.log(serviceList.length);
console.log("Collection populated: " + JSON.stringify(collection.toJSON()));
},
error: function() {
console.log("Failed to fetch!");
}
});
// here, "serviceList" will not be populated yet
Second, you probably want to pass the serviceList instance into the view as its "collection". As it is, you're passing an empty model instance into the view.
var serviceView = new ServiceView({
collection: serviceList
});
And for the view, render using the collection:
var ServiceView = Backbone.View.extend({
// ...
initialize: function() {
// render when the collection is reset
this.collection.bind("reset", this.render, this);
},
render: function() {
console.log("Collection rendering: " + JSON.stringify(this.collection.toJSON()));
// start by clearing the view
this.$el.html('');
// loop through the collection and render each model
var self = this;
this.collection.each(function(model) {
self.$el.append(self.template(model.toJSON()));
});
return this;
}
});
Here's a Fiddle demo.
The call serviceList.fetch is made asynchronously, so when you try console.log(serviceList.length); the server has not yet send it's response that's why you get the the value 1, try this :
var list = serviceList.fetch({
success: function() {
console.log(serviceList.length);
console.log("Working!");
},
error: function() {
console.log("Failed to fetch!");
}
});