Implement notifications through ajax in django - javascript

I have a feed stream in which users are shown activities, I have to notify users of new activity after the page is loaded through ajax call.
Below is the code
views.py
#login_required
def new_activity(request):
context = {}
response = {}
latest_activity = []
prev_activity_id = request.GET.get('activity_id')
#get the latest activity from news feed
time_stamp = Activity.objects.get(pk = prev_activity_id).created
latest_activity = Activity.objects.filter(created__gt = time_stamp)
activity_count = latest_activity.count()
#Handle multiple activities
if activity_count == 1:
updated_id = latest_activity.id
elif activity_count > 1:
updated_id = latest_activity[0].id
else:
updated_id = prev_activity_id
context['activities'] = latest_activity
template = render_to_string('activities/new_activity_template.html', context, context_instance=RequestContext(request))
response['template'] = template
response['updated_id'] = updated_id
response['activity_count'] = activity_count
response['success'] = 'success'
return HttpResponse(simplejson.dumps(response), mimetype='application/json')
ajax
(function new_activity() {
setTimeout(function() {
var activity_id = null
$.ajax({
url: "/activities/all/new_activity/?activity_id="+activity_id,
type: "GET",
success: function(response) {
$('#id_new_activity').empty();
$('#id_new_activity').append(response.template);
console.log(response.success);
//if activity_id is null get the activity id for first time
//if activity_id is not null update the activity_id from the response
activity_id = response.updated_id;
},
dataType: "json",
complete: new_activity,
timeout: 2000
})
}, 5000);
})();
I need to update the latest acitivity_id after each call to new_activity if any new object is created in my activity model. Also i need to pass the activity_id for the first time when page is loaded.
I am not sure how to do that in my ajax call.

Save not activity_id, but latest_activity date in user browser. When ajax queried and there is an new activity, save new date of latest activity in user browser, and for next ajax query send that date, so server-side app will send only activity after that date.

Related

How update data in JavaScript when flask send a josinify response

I am making a project with raspberry Pi, is a control and monitoring data through internet.
Finally I can make the communication with flask-html-JavaScript
In summary I want to update my chart js graph when the flask function response with jsonify data
I am using Ajax method with getjson but I am executing with setinterval and I don’t want to use setinterval, I want that the getjson function execute when flask function response with jsonify data
Exist any method that can make it?
this is my code in flask:
#app.route('/start', methods=['GET', 'POST'])
def start():
n = request.form['number']
print(int(n))
for i in range(int(n)):
GPIO.output(19, GPIO.LOW)
while gt.read_sensor() == 0:
pass
now0 = datetime.now()
for j in range(1):
value = adc.read( channel = 0 )
volt = (value/1023)*3.3
presure = ((volt/3.3)-0.1)*3/2
p1.append(presure)
global pon
pon = presure
time.sleep(0.25)
pon = -100
Here I capture the value sensor and I call update with global variable the function presson:
#app.route('/pon')
def presson():
return jsonify(result = presson)
and this is my javascript code:
var pon = 0;
var test = 0;
function sendData() {
$.ajax({
type: "POST",
url: "{{ url_for('start') }}",
data: { number : $('#number').val() }
});
setInterval(update_values,100);
}
function update_values() {
$.getJSON('/pon',
function(data) {
$('#result').text(data.result);
pon = data.result;
console.log(data)
});
currently that work good, but sometimes the value is not update, then I want that the function getJSON() run only when recieve a correct value (without setInterval method), what recommend me?

Javascript post request one key and multiple values

I have a script to submit an array of id's to be deleted. The script is not tied to a form.
The data is in the form of {'id': [1,2]}.
When I run the script, the form data is changed to id[]: 1
I have tried $.param(), but that just creates a single string.
I could join 1,2 into a string (i.e. {id: "1,2"}, but would prefer to avoid that. Any suggestions?
function delete_messages(event){
let data = {id: [1,2]};
event.preventDefault();
let parameters = {
url: '/message/delete'
type: "POST",
data: data,
dataType: "html"
};
addcsrf();
$.ajax(parameters).done(function(data){
alert("successfully deleted");
})
.fail(function(data){
alert("failed to delete");
});
}
Flask Code
#bp.route('/message/delete', methods=['POST'])
#login_required
def message_delete():
message_ids = request.form.get('msg_id')
deleted = []
for id in message_ids:
msg = RecipientData.query.get(id)
if msg is not None and msg.user_id == current_user.id:
msg.update(status='trash')
return redirect(url_for('main.view_messages', folder="inbox"))
var ids=[];
ids[0] = 1;
ids[1] = 2;
In the ajax request, change the data as given below:
data: {ids:ids},

JQuery/Ajax post in Razor page and redirect to returned view from MVC Action (aka form submitting)

I post a json array to the MVC Action via either JQuery or AJax, and Action handles the request correctly. However, then MVC Action is returning a View and I need to redirect to this View (or replace a body with it) but I don't know how.
So, the action is working well except probably for the returning value:
[HttpPost]
public ActionResult CreateGet(List<string> itemIds)
{
List<TempItem> items = new List<TempItem>();
foreach (string item in itemIds)
{
items.Add(CallApi.Get(Request.Cookies["jwt"], "tempitems", item.ToString()).Content.ReadAsAsync<TempItem>().Result);
}
Invoice inv = new Invoice()
{
IsSupplement = items[0].IsSupplement,
Date = DateTime.Now,
Employee = CallApi.Get(Request.Cookies["jwt"], "employees/getprofile").Content.ReadAsAsync<Employee>().Result,
InvoiceItems = new List<InvoiceItem>()
};
foreach(TempItem item in items)
{
inv.InvoiceItems.Add(new InvoiceItem { Amount = item.Amount, ProductId = item.ProductId, Product = item.Product });
}
return View(inv);
}
And the script inside razor page, that collects selected ids and posts them to the action.
After the post nothing else happens, even the alert is not being called, even though the View page exists and I don't see fails in console.
function CreateInvoice(id) {
var selected = $('#' + id).DataTable().rows('.selected').data();
var items = [];
for (i = 0; i < selected.length; i++) {
items.push(selected[i][0]);
}
var postData = { itemIds: items };
$.ajax({
type: "POST",
url: "/Invoices/CreateGet",
data: postData,
success: function (data) {
alert("success");
window.location.href = data.url;
},
dataType: "json",
traditional: true
});
}
Update
Well, I gave up that nonsense and stuck to GET request that passes array of ids in the URL. I think I just doing things wrong.
You should change ActionResult to JsonResult.
And return like this:
return Json(new {url: "yoururl", inv: yourdata}, JsonRequestBehavior.AllowGet);
If you don't need to do nothing in actual page with data returned from ajax call, you shouldn't use ajax call. You can use submit request and redirect page in backend to new page.

Autocomplete search taking too long to retrieve data from server

I have an AJAX autocomplete search in user control page, which gets called on document.ready. In that we makes an AJAX call to web service which takes the data (which is approx. 90,000) from the database, insert data into cache, returns the data to JavaScript and added to the array.
At first it takes the data from the database and after inserting the data into cache, every time it takes the data from cache. When we type something on textbox it matches the text of textbox with array and displays the list. To get 90,000 items from a stored procedure, it takes 2 sec in local server.
But on live server it takes approx 40 secs to take data from a stored procedure. Also for taking data from cache it takes the same time. How can I reduce the time and increase the performance?
AJAX call:
var locationSearchListData = [];
var termTemplate = "<span class='ui-autocomplete-term'>%s</span>";
var postData = '{cultureId : "DE"}';
// Ajax call to run webservice's methods.
$.ajax({
url: "/asmx/SearchLocations.asmx/GetAutoCompleteSearchLocations",
type: "POST",
data: postData,
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (responseData) {
if (responseData != undefined && responseData != null && responseData.d.length > 0) {
for (i = 0; i < responseData.d.length; i++) {
// Add resopnse data in location search lis, this list is used as a source for autocomplete textbox.
locationSearchListData.push({
label: responseData.d[i].locationData,
latitude: responseData.d[i].latitude,
longitude: responseData.d[i].longitude
});
}
}
Web-service:
[ScriptMethod]
[WebMethod(Description = "Provides instant search suggestions")]
public List<GeoLocationObject> GetAutoCompleteSearchLocations(string cultureId)
{
SqlDatabase database = new SqlDatabase(WebConfigurationManager.ConnectionStrings["MasterDB"].ConnectionString);
string databaseName = WebConfigurationManager.AppSettings["databaseName"];
// Key to identify location search data in cache
string cacheKey = "auto_complete_result";
// List to store locations
List<GeoLocationObject> lstGeolocationObject = new List<GeoLocationObject>();
// If location data is present in cache then return data from cache.
if (Context.Cache[cacheKey] is List<GeoLocationObject>)
{
return Context.Cache[cacheKey] as List<GeoLocationObject>;
}
else // If data is not present in cache, get data from db and add into cache.
{
// Call method GetAutoCompleteSearchLocations of LocationManager to get list of geo location object.
lstGeolocationObject = LocationManager.GetAutoCompleteSearchLocations(database, cultureId);
// Checking if lstGeolocationObject is not null
// If its not null then adding the lstGeolocationObject in the cache
if (lstGeolocationObject.Count > 0)
{
// Add locationdata in cache.
// Removed sqlcache dependency.
Context.Cache.Insert(cacheKey,
lstGeolocationObject,
null,
Cache.NoAbsoluteExpiration,
Cache.NoSlidingExpiration,
CacheItemPriority.NotRemovable,
null);
}
// Return geolocation data list
return lstGeolocationObject;
}
} // GetAutoCompleteSearchLocations
The main intention of autocomplete facility is to narrow down the search and bring to front only the nearly matching records to ease the user to select the exact record he wants. Try adding a debounceTime() if possible.
Other options are to fine tune the sql query, implementing the server side paging and checking the page render time in browser.
Sorry for my late reply.
Thanks all for helping me to find out the solution.
We have solved the issue by doing some changes in ajax call. We send the search text as:
// set auto complete textbox
$("#<%= txtOrtOderPlz.ClientID%>").autocomplete({
// Set required minimum length to display autocomplete list.
minLength: 3,
// Set source for textbox, this source is used in autocomplete search.
source: function (request, response) {
// Ajax call to run webservice's methods.
$.ajax({
url: "/asmx/SearchLocations.asmx/GetAutoCompleteSearchLocations",
type: "POST",
data: '{ searchText :\'' + request.term + '\' }',
dataType: "json",
contentType: "application/json; charset=utf-8",
Success: function (responseData) {
response(responseData.d);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
}
});
},
Every time we search anything, it takes the search text and call web services, send the search text to SP, get the data from SP and show in autocomplete search.

How do I get Mercury Editor to redirect to a new resource?

After watching RailsCast #296 about Mercury Editor, I am trying to get the editor to redirect to a newly created resource.
I can already redirect on the client-side using JS and window.location.href=. But for a new resource, I cannot "guess" its URL on the client-side. I need it to be in the server response.
However, the problem is that I don't see the possibility of using the server response in the editor. No matter what the controller renders, the server response is discarded by Mercury instead of used as an argument to my function for mercury:saved.
Is there a way to get around this?
I was able to do this on update by sending a valid JSON string back. I would assume create works the same way. check firebug to make sure you're not getting an error in the jQuery.ajax call that Mercury uses.
posts_controller.rb
def mercury_update
post = Post.find(params[:id])
post.title = params[:content][:post_title][:value]
post.body = params[:content][:post_body][:value]
post.save!
render text: '{"url":"'+ post_path(post.slug) +'"}'
end
mercury.js:
jQuery(window).on('mercury:ready', function() {
Mercury.on('saved', function() {
window.location.href = arguments[1].url
});
});
note: I'm using friendly_id to slug my posts
Redirecting on the server side doesn't work because the save button is just an jQuery.ajax call:
// page_editor.js
PageEditor.prototype.save = function(callback) {
var data, method, options, url, _ref, _ref1,
_this = this;
url = (_ref = (_ref1 = this.saveUrl) != null ? _ref1 : Mercury.saveUrl) != null ? _ref : this.iframeSrc();
data = this.serialize();
data = {
content: data
};
if (this.options.saveMethod === 'POST') {
method = 'POST';
} else {
method = 'PUT';
data['_method'] = method;
}
Mercury.log('saving', data);
options = {
headers: Mercury.ajaxHeaders(),
type: method,
dataType: this.options.saveDataType,
data: data,
success: function(response) {
Mercury.changes = false;
Mercury.trigger('saved', response);
if (typeof callback === 'function') {
return callback();
}
},
error: function(response) {
Mercury.trigger('save_failed', response);
return Mercury.notify('Mercury was unable to save to the url: %s', url);
}
};
if (this.options.saveStyle !== 'form') {
options['data'] = jQuery.toJSON(data);
options['contentType'] = 'application/json';
}
return jQuery.ajax(url, options);
};
So your redirect is sent to the success callback, but the page doesn't actually re-render, as with any successful AJAX request. The author discusses overriding this very function here. It also looks like there might be some room to maneuver here by passing a callback function to save.
Btw, another way to do what #corneliusk suggests is:
render { json: {url: post_path(post.slug)} }
Either way, the response body is passed as an argument to the function in the mercury:saved callback.

Categories

Resources