We are facing a problem with our javascript application. We have the following method in an Angular 1.5 application. This method sometimes when called continues to run indefinitely. We have encountered situations where the function has continued to run and send requests to the server for hours and found the requests up to 4000.
How to make sure that the request is sent only once?
var normalVisitAuthorization = function(cardNo) {
$scope.authorizePromise =
$q.all([VerificationService.authorizeCardWithVisit(cardNo, $scope.logininfo.FacilityCode, $scope.logininfo.UserName, $scope.visitType.selected.TypeID, 1), VerificationService.getLastVisits(cardNo)])
.then(function(results) {
console.log(results[0]);
if (results[0].CardExistence.indexOf('MISSING') != -1) {
$scope.memberDetails = undefined;
DevExpress.ui.notify({
message: 'The card was not found in NHIF Database. The
beneficiary should submit the card to the nearby NHIF office
for
verification ',
position: {
my: "center center",
at: "center center"
}
}, "warning", 7500);
} else {
$scope.memberDetails = results[0];
$rootScope.memberDetails = results[0];
$scope.lastVisits = results[1];
}
$scope.imageSrc = ngAuthSettings.verificationUrl + "GetImage?CardNo=" + cardNo;
console.log($scope.imageSrc);
}, function(error) {
console.log(error);
DevExpress.ui.notify({
message: error.data.ExceptionMessage,
position: {
my: "center center",
at: "center center"
}
}, "warning", 4500);
});
}
Related
I tried to include a button (created from user event) on Sales order. Upon clicking it, Invoice will be generated. As soon as the button is hit, ther comes an error and invoice doesnt get generated. Can anyone help me with this?
//Client script
function pageInit() {
}
function csForButton(ctx) {
var rec = curr.get();
var customer = rec.getValue({ "fieldId": "customer" });
log.error({
title: 'customer',
details: customer
});
var scriptURL = url.resolveScript({
"scriptId": "customscript_button_task_sl",
"deploymentId": "customdeploy_button_task_sl"
});
console.log('scriptURL', scriptURL);
window.onbeforeunload = null;
window.open(scriptURL + '&id=' + rec.id);
}
return {
pageInit: pageInit,
csForButton: csForButton
};
//User Event Script
function beforeLoad(ctx) {
//if (context.type == context.UserEventType.VIEW) {
addbutton(ctx);
// }
}
function addbutton(ctx) {
try {
var rec = ctx.newRecord;//record object, now we can get its properties through it(e.g. fields)
var statusOfTrans = rec.getValue({ fieldId: 'status' });
log.error('statusOfTrans', statusOfTrans);
ctx.form.clientScriptFileId = "16474"
if (ctx.type == "view" && statusOfTrans == 'Pending Fulfillment') {
ctx.form.addButton({
id: 'custpage_make_invoice',
label: 'create invoice!',
functionName: 'csForButton'
});
}
}
catch (error) {
log.error('addbutton', error);
}
}
return {
beforeLoad: beforeLoad,
}
//Suitelet Script
function onRequest(ctx) {
try {
var req = ctx.request;
var res = ctx.response;
if (req.method == 'GET') {
var objRecord = rec.transform({
fromType: rec.Type.SALES_ORDER,
fromId: req.parameters.id,
toType: rec.Type.INVOICE,
isDynamic: true,
});
objRecord.save({
ignoreMandatoryFields: true
});
res.write({output: 'Invoice created'});
}
} catch (error) {
log.error('onRequest', error);
}
}
return {
'onRequest': onRequest
}
error (in suitelet):
{"type":"error.SuiteScriptError","name":"USER_ERROR","message":"You must enter at least one line item for this transaction.","stack":["anonymous(N/serverRecordService)","onRequest(/SuiteScripts/button SL.js:39)"],"cause":{"type":"internal error","code":"USER_ERROR","details":"You must enter at least one line item for this transaction.","userEvent":null,"stackTrace":["anonymous(N/serverRecordService)","onRequest(/SuiteScripts/button SL.js:39)"],"notifyOff":false},"id":"","notifyOff":false,"userFacing":false}
As Error says to include atleast 1 line but i wanted it to be generated automatically. I am new in suitescript and taking all the help from the documentation. Can anyone jst guide me what is wrong i m doing?
Thank u
You need the SO status to be Pending Billing. If the status of the SO is Pending Fulfillment, then no line items are ready to be invoiced.
with this code:
if (ionic.Platform.isIOS()) {
cordova.plugins.diagnostic.switchToSettings();
} else {
cordova.plugins.diagnostic.switchToLocationSettings();
}
I can open the native device configuration to mark the geolocation. but I do not know how to do it when the user turns on the geolocation, it simply executes that code but does not get an answer from that. I would like (if possible) to know if the user turned on the geolocation or not.
how can I do it?
I am using ionic1, although I suppose that the operation for this solution would apply to any version. thank you very much.
Unfortunately you can not get callback or response when user turn on/off location from device setting because there is no such way to communicate with Native settings.
But there is a workaround for this. Use isLocationEnabled() of cordova-diagnostic-plugin.
Below is complete working code:
$scope.$on("$ionicView.enter", function() {
cordova.plugins.diagnostic.isLocationEnabled(function(enabled) {
console.log("Location setting is " + (enabled ? "enabled" : "disabled"));
if (!enabled) {
var templateMsg = "Location is not enabled!\nDo you want to enable location service?"
var confirmPopup = $ionicPopup.confirm({
title: '<b>Location Service</b>',
template: '<input alert-enter-key style="position: absolute; left: -9999px;">' + templateMsg.replace(/\n/g, '<br>'),
okText: "Enable",
okType: 'ok-button',
cancelText: "Not now",
cancelType: 'cancel-button'
});
confirmPopup.then(function(res) {
if (res) {
if (ionic.Platform.isIOS()) {
if (window.cordova && window.cordova.plugins.settings) {
window.cordova.plugins.settings.open("settings", function() {
console.log('settings opened');
},
function() {
console.log('failed to open settings');
}
);
} else {
console.log('openNativeSettingsTest is not active!');
}
} else {
cordova.plugins.diagnostic.switchToLocationSettings();
} }
});
}
}, function(error) {
console.error("The following error occurred: " + error);
});
});
Note: To open location setting (Settings > Privacy > Location Services) on iOS there is plugin but There is change/ in iOS 11 platform due to which you can not open Settings > Privacy > Location Services.
Using react-notification-system, I am attempting to create a pop-up notification each time a JSON array is returned from the backend. For the sake of showing the issue I've manually added the array and parsed it in the below code.
As it appears I wish to trigger the event if the "type" of the alerts array is either "WARNING" or "ERROR", and furthermore print the message that comes along with it in the "message" part.
I'm pretty sure the issue I have is with the state and props. Right now, running this code, I am getting Uncaught TypeError: Cannot read property 'type' of undefined - Which leads me to the question, how do I access the information inside the array in React properly, and trigger it in the return function on the conditions?
Sample code:
var NotificationSystem = React.createClass({
_notificationSystem: null,
_addNotification: function(event) {
event.preventDefault();
this._notificationSystem.addNotification({
message: 'Danger!',
level: 'error',
position: 'tc'
});
},
componentDidMount: function() {
this._notificationSystem = this.refs.notificationSystem;
},
render: function() {
var mdata = {"alerts":[
{
"dateTime": 111111111,
"message": "This is a super serious warning",
"type": "WARNING"
}
]};
var mdataArr = Object.values(mdata);
console.log(JSON.stringify(mdataArr)); // It prints the JSON in console
if (this.props.mdataArr.type == "WARNING")
this._notificationSystem.addNotification({
message: this.props.mdataArr.message,
level: 'warning',
position: 'tc'
});
else if (this.props.mdataArr.type == "ERROR")
this._notificationSystem.addNotification({
message: this.props.mdataArr.message,
level: 'error',
position: 'tc'
});
return (
<div>
<NotificationSystem ref="notificationSystem" />
</div>
);
}
});
Actually you defined mdataArr in render() method itself, but you are looking for same in this.props
Try this in render method
if (mdataArr[0].type == "WARNING")
this._notificationSystem.addNotification({
message: mdataArr[0].message,
level: 'warning',
position: 'tc'
});
else if (mdataArr[0].type == "ERROR")
this._notificationSystem.addNotification({
message: mdataArr[0].message,
level: 'error',
position: 'tc'
});
I hope someone can help me with this.
I have a Backbone based SPA for a responsive website with a .net WebAPI providing all of the data.
I've recently found a weird problem. I've added a search box, which searches one of the catalogues on the system. This works fine on desktop browsers and on Android. On iOS, executing a search seems to take you back to the sign in page.
You can execute a search in various ways, you can either hit enter or you can click the search icon. Both of these then trigger a method that navigates the router to the URL for the search result.
My first thought was that it was some button weirdness, but I don't think that's the problem as both methods of search execution are causing the same problem.
The search results are displayed in a view that is secured (It requires a username to be present - this is stored in a hidden field on the page). There are two search boxes on the site - one on the home page and one on the search results page itself (it shows a default set when you load it first time - which it does load first time fine). Both search boxes are exhibiting the same behaviour.
My site is set up in such a way that when Backbone pulls back a model, if it gets a 401 back from the API then it will send you back to the login page, so I can only think it's happening here.
Here's my view code...
function (SiansPlan, ErrorManager, RecipeSearchResult, Header, Components, TemplateSource) {
var recipeSearchView = SiansPlan.SecureView.extend({
name: 'Recipe Search',
sectionName: 'Recipes',
queryText: '',
template: Handlebars.compile(TemplateSource),
headerView: new Header({ text: 'Recipes', swatch: 'e' }),
searchBoxRegion: undefined,
$searchWrapper: undefined,
$queryHeaderMobile: undefined,
$queryHeaderDesktop: undefined,
$searchButton: undefined,
$searchInput: undefined,
$recipeSearch : undefined,
events: {
'click .link-container': 'showRecipe',
'click #searchWrapper': 'showSearch',
'click #searchButton': 'showOrPerformSearch',
'keydown #searchButton': 'performSearchOnEnter',
'keydown #recipeSearch': 'performSearchOnEnter'
},
initialize: function (options) {
this.options = options || {};
SiansPlan.SecureView.prototype.initialize.call(this, options);
this.queryText = Object.exists(this.options.query) ? this.options.query : '';
},
bindData: function () {
this.$el.html(this.template({ results: this.collection.toJSON() }));
},
render: function () {
var that = this;
if (this.isSecured()) {
this.trigger('rendering');
var params = {
success: function () {
that.bindData();
that.trigger('rendered');
},
error: function (model, xhr) {
if (Object.exists(xhr) && xhr.status == 401) {
that.applyTimedOutSecureLoginPrompt();
} else {
that.$el.html('Unable to fetch search results');
ErrorManager.handleXhr('Search failed', xhr);
}
that.trigger('rendered');
}
};
if (!Object.exists(this.collection)) {
this.collection = new RecipeSearchResult.Collection({ username: SiansPlanApp.session.username(), query: this.queryText });
}
this.collection.fetch(params);
} else {
this.applySecureLoginPrompt();
}
return this;
},
postRender: function () {
var that = this;
var queryHeader = "All recipes";
if (Object.hasValue(this.queryText)) {
queryHeader = this.collection.length + " results for '" + this.queryText + "'";
}
this.$searchWrapper = $('#searchWrapper');
this.$queryHeaderMobile = $('#queryHeaderMobile');
this.$queryHeaderDesktop = $('#queryHeaderDesktop');
this.$searchButton = $('#searchWrapper');
this.$searchInput = $('#searchInput');
this.$recipeSearch = $('#recipeSearch');
this.$queryHeaderMobile.html(queryHeader);
this.$queryHeaderDesktop.html(queryHeader);
this.$recipeSearch.val(this.queryText);
SiansPlanApp.session.waitForLoad(30, function () {
that.searchBoxRegion = new SiansPlan.Region({ el: '.recipe-search-box-container' });
that.searchBoxRegion.renderView(new Components.RecipeSearchBox({ username: SiansPlanApp.session.username(), query: that.queryText, title: 'Search' }));
});
},
performSearchOnEnter: function (e) {
if (e.keyCode == 13) {
this.showOrPerformSearch(e);
}
},
showOrPerformSearch: function (e) {
if (!this.$searchInput.is(':visible')) {
this.showSearch(e);
} else {
e.preventDefault();
var url = '/recipes/search/' + this.$recipeSearch.val();
window.SiansPlanApp.router.navigate(url, true);
}
return false;
},
showRecipe: function (e) {
e.preventDefault();
var url = $(e.target).find('a').first().attr('href');
window.SiansPlanApp.router.navigate(url, true);
},
showSearch: function (e) {
e.preventDefault();
if (!this.$searchInput.is(':visible')) {
this.$queryHeaderMobile.hide();
this.$searchInput.show();
this.$recipeSearch.focus();
this.$recipeSearch.select();
}
return false;
}
});
return recipeSearchView;
});
UPDATES
I've set up some alerts as follows in the script to see what's going on and I've discovered the following...
render: function () {
var that = this;
if (this.isSecured()) {
this.trigger('rendering');
var params = {
success: function () {
alert('Bind has succeeded!');
that.bindData();
that.trigger('rendered');
},
error: function (model, xhr) {
alert('Bind has failed!');
if (Object.exists(xhr) && xhr.status == 401) {
that.applyTimedOutSecureLoginPrompt();
} else {
that.$el.html('Unable to fetch search results');
ErrorManager.handleXhr('Search failed', xhr);
}
that.trigger('rendered');
alert(xhr.status + ' ' + xhr.responseText);
}
};
if (!Object.exists(this.collection)) {
alert('Binding new collection: ' + SiansPlanApp.session.username() + ' - ' + this.queryText);
this.collection = new RecipeSearchResult.Collection({ username: SiansPlanApp.session.username(), query: this.queryText });
}
alert('About to fetch using ' + this.collection.url());
this.collection.fetch(params);
} else {
alert('I dont appear to be secured??');
this.applySecureLoginPrompt();
}
return this;
},
When I first load the page (to show all the results) it loads fine and 'Bind Succeeded!' appears. The API call made is /api/recipes/search/{username}/
When I submit search criteria it fails ('Bind failed!') with the API call of /api/recipes/search/{username}/{query} and returns a 401.
This has me even more befuddled than before as this now looks like an API issue, but other devices are working fine and if I submit the same queries into Fiddler everything is, as expected, fine.
I've found the answer in the smallest place...
The issue was that the search criteria had an upper case letter. So, for example, when searching with 'Fish', The API generated a 301 which redirected to /api/recipes/search/{username}/fish. iOS didn't like that and reported it as a 401 (Which truly sucks!)
I am using Azure Mobile Services for sending push notifications to my client app. I send both square and tile notification using the push.wns object (first square and then wide). Below is how the server-side code that sends push notifications looks like (this is basically called whenever a record is updated in my DB table):
function update(item, user, request) {
request.execute({
success: function() {
request.respond();
sendNotifications();
}
});
function sendNotifications() {
var channelTable = tables.getTable('channel');
channelTable.read({
success: function(channels) {
channels.forEach(function(channel) {
push.wns.sendTileSquarePeekImageAndText02(channel.pushuri,
{image1src: '<imgPath>',
text1: 'New Game',
text2: item.playername },
{
success: function(pushResponse) { console.log("Sent Square:", pushResponse); },
error: function(error) {
console.log("error sending push notification to ", channel.pushuri);
if (error.statusCode == 410) {
console.log("Deleting ", channel);
channelTable.del(channel.id);
}
}
});
push.wns.sendTileWidePeekImage01(channel.pushuri,
{image1src: <imgPath>,
text1: 'New Game',
text2: item.playername },
{
success: function(pushResponse) { console.log("Sent Square:", pushResponse); },
error: function(error) {
console.log("error sending push notification to ", channel.pushuri);
if (error.statusCode == 410) {
console.log("Deleting ", channel);
channelTable.del(channel.id);
}
}
});
});
}
});
}
}
I notice that the wide notification is displayed correctly when my app tile is wide. However, when I make the tile size of my app to square, the square notification is not displayed. How can I correct this?
Here's sample which you can use to send one update and update two kind of tiles at once.
push.wns.send(item.channel,
'<tile><visual>' +
'<binding template="TileSquarePeekImageAndText02">' +
'<image id="1" src="imageUri" />' +
'<text id="1">Template: TileSquarePeekImageAndText02</text>' +
'<text id="2">' + item.text + '</text>' +
'</binding>' +
'<binding template="TileWidePeekImage01">' +
'<image id="1" src="imageUri" />' +
'<text id="1">Template: TileWidePeekImage01</text>' +
'<text id="2">' + item.text + '</text>' +
'</binding>' +
'</visual></tile>',
"wns/toast", {
success: function(pushResponse) {
console.log("Sent push:", pushResponse);
}
}
);
The tile notification with the wide content is replacing the tile notification containing the square content. A single notification should be sent containing both square and wide tile content.