Cesium too much recursion error on using CallbackProperty to fetch entity description - callback

The entities are updated multiple times in a second. I want to fetch description details at each position and using callback property. The same code is working if I return time or any constant value but gives too much recursion error when I return the description of the entity.
viewer.selectedEntityChanged.addEventListener(function(selectedEntity) {
if (Cesium.defined(selectedEntity)) {
if (Cesium.defined(selectedEntity.description)) {
console.log('Selected ' + selectedEntity.id);
selectedEntity.description = new Cesium.CallbackProperty(function(time) {
var currentDescription = selectedEntity.description.getValue(time);
console.log(currentDescription);
return currentDescription;
// return time;
}, false);
} else {
console.log('Unknown entity selected.');
}
} else {
console.log('Deselected.');
}
});

Related

Angular 2 correct way to get data from server

I want to get data from the database. I'm following the examples at angular.io webpage but I don't know if I'm doing right.
I have a form and when a user fills the postal code field, I call the database to get the name of the city or, if it doesn't exist, ask the user to fill it.
My problem is I don't know how to correctly do it.
In my service.
checkCp(city: City): Observable<any> {
return this.http.get<any>(this.backendUrl + 'api/city/' + city.cp).pipe(
tap(city => console.log("fetched"))
);
}
and this is in my component.js
checkCp(): void {
this.modal.header = 'Searching city';
this.modal.text = 'Please wait';
this.openWaitModal();
this.studentService.checkCp(this.city)
.subscribe(cityFromDb => {
if(cityFromDb ===null) {
this.closeWaitModal();
this.modal.header = 'Postal code not found';
this.modal.text = 'Insert the name of the city';
this.modal.no = 'Cancel';
this.modal.yes = 'Insert';
this.modal.action = 'newCity';
this.modal.enableInput = true;
this.openModal();
}else{
this.closeWaitModal();
this.city = cityFromDb.city; // I can't access cityFromDb.name
// i access via cityFromDb.city.name
}
}, err => {
this.errorHandler(err);
})
}
You would call your service as follows:
checkCp(city: City): Observable<any> {
return this.http.get<any>(this.backendUrl + 'api/city/' + city.cp);
};
This will return an Observable to your component.ts
The code in your component.ts should work now

Collection find method doesn't work on Angular 2 recursive function

I'm developing Angular2 with Meteor.
When I make a little component with a recursive function, it has some weird error.
Here is my part of codes.
Not recursive - return a result
ngOnInit() {
//this.current_canvas return the right results
this.current_canvas = this.get_canvase(1);
}
get_canvase(which_canvas): Canvas[] {
if (!isNaN(which_canvas)) {
this.current_canvas_id = which_canvas;
return CanvasContents.find().map((messages: Canvas[]) => { return messages; })[0].content;
return '';
} else if(which_canvas == 'most-recent') {
this.get_canvase(1);
}
}
Recursive - Don't return a result
ngOnInit() {
//this.current_canvas Goes to NUll
this.current_canvas = this.get_canvase('most-recent');
}
get_canvase(which_canvas): Canvas[] {
if (!isNaN(which_canvas)) {
this.current_canvas_id = which_canvas;
console.log('this.current_canvas_id : ' + this.current_canvas_id);
return CanvasContents.find().map((messages: Canvas[]) => { return messages; })[0].content;
return '';
} else if(which_canvas == 'most-recent') {
this.get_canvase(1);
}
}
Have I used a wrong syntax? or is it on wrong Angular2 state to get right result?

How can a range be used across different Word.run contexts?

I have created a taskpane addin for word that runs a search and displays information about the results as a list to the user.
When the user clicks on an item in the list I want to select the range in word to show the user the location of the item.
The addin will then allow the user to perform additional tasks on the range, for example change the font colour.
I am able to run the search and get ranges for display using the function below:
function runSearch(textToFind) {
var items = [];
return Word.run(function(context) {
var options = Word.SearchOptions.newObject(context);
options.matchWildCards = false;
var rangesFind = context.document.body.search(textToFind, options);
context.load(rangesFind, 'text, font, style');
return context.sync().then(function() {
for (var i = 0; i < rangesFind.items.length; i++) {
items.push(rangesFind.items[i]);
context.trackedObjects.add(rangesFind.items[i]);
}
return context.sync();
});
})
.then(function() {
return items;
});
};
However I am having difficulty selecting the range on user click.
I have tried using the ranges context:
function selectRange(range){
range.select();
return range.context.sync();
}
Or using the range in a new Word.run context:
function selectRange(range){
return Word.run(function(context) {
context.load(range);
return context.sync().then(function(){
range.select();
return context.sync();
});
});
}
I have come across a potential method that involves creating a content control for each search result and then reloading all the content controls in the selectRangefunction in the new context and finding the matching control, but that seems very inefficient when I have the range already.
What is the best method for reusing a range across different Word.run contexts?
You cannot use an object across Word.run invocations. Word.run creates a new context every time that it's invoked, whereas the original object is tied to its own context, creating a mismatch.
That being said, you absolutely can, from within a Word.run, add the objects you desire to context.trackedObjects.add(obj), and they will remain as working objects even after Word.run finishes executing. By "working objects" I mean that their path will not get invalidated (think something similar to garbage collection, but for remote objects).
Once you have such object (and it looks above like you do), you should be able to call
range.select();
range.context.sync().catch(...);
If it's not working for you, can you provide an example of the error you're getting?
For completeness sake, I should note that once you add objects to the trackedObjects collection, you're effectively taking memory management of those objects into your own hands. This means that if you don't properly release the memory, you will be slowing down Word by bogging down its memory / range-adjustment chain. So once you're done using the tracked object(s), you should call obj.context.trackedObjects.remove(obj), followed by obj.context.sync(). Don't forget the last part - if you don't do a sync, your request to remove the tracked objects will not be dispatched, and you'll continue to use up the memory.
======= Update 1 =======
Tom, thanks for providing the error message. It looks like this might be a bug in the Word implementation of the APIs -- I'll follow up on that, and someone might reach out to you if there's more questions.
From a conceptual standpoint, you are absolutely on the right path -- and the following does work in Excel, for example:
var range;
Excel.run(function (ctx) {
var sheet = ctx.workbook.worksheets.getActiveWorksheet();
range = sheet.getRange("A5");
range.values = [[5]];
ctx.trackedObjects.add(range);
return ctx.sync();
})
.then(function(){
setTimeout(function() {
range.select();
range.context.trackedObjects.remove(range);
range.context.sync();
}, 2000);
})
.catch(function (error) {
showMessage("Error: " + error);
});
======= Update 2 =======
It turns out there is indeed a bug in the product. However, the good news is that it's easy to fix with a JavaScript-only fix, and in fact we'll do so in the next couple of weeks, updating the CDN.
With the fix, the following code works:
var paragraph;
Word.run(function (ctx) {
var p = ctx.document.body.paragraphs.first;
paragraph = p.next;
ctx.trackedObjects.add(paragraph);
return ctx.sync();
})
.then(function(){
setTimeout(function() {
paragraph.select();
paragraph.context.trackedObjects.remove(paragraph);
paragraph.context.sync()
.then(function() {
console.log("Done");
})
.catch(handleError);
}, 2000);
})
.catch(handleError);
function handleError (error) {
console.log('Error: ' + JSON.stringify(error));
if (error instanceof OfficeExtension.Error) {
console.log('Debug info: ' + JSON.stringify(error.debugInfo));
}
}
Want even better news? Until the CDN is updated, you can use the code below to "patch" the JavaScript library and make the code above run. You should run this code some time after Office.js has already loaded (i.e., within your Office.initialize function), and before you do a Word.run.
var TrackedObjects = (function () {
function TrackedObjects(context) {
this._autoCleanupList = {};
this.m_context = context;
}
TrackedObjects.prototype.add = function (param) {
var _this = this;
if (Array.isArray(param)) {
param.forEach(function (item) { return _this._addCommon(item, true); });
}
else {
this._addCommon(param, true);
}
};
TrackedObjects.prototype._autoAdd = function (object) {
this._addCommon(object, false);
this._autoCleanupList[object._objectPath.objectPathInfo.Id] = object;
};
TrackedObjects.prototype._addCommon = function (object, isExplicitlyAdded) {
if (object[OfficeExtension.Constants.isTracked]) {
if (isExplicitlyAdded && this.m_context._autoCleanup) {
delete this._autoCleanupList[object._objectPath.objectPathInfo.Id];
}
return;
}
var referenceId = object[OfficeExtension.Constants.referenceId];
if (OfficeExtension.Utility.isNullOrEmptyString(referenceId) && object._KeepReference) {
object._KeepReference();
OfficeExtension.ActionFactory.createInstantiateAction(this.m_context, object);
if (isExplicitlyAdded && this.m_context._autoCleanup) {
delete this._autoCleanupList[object._objectPath.objectPathInfo.Id];
}
object[OfficeExtension.Constants.isTracked] = true;
}
};
TrackedObjects.prototype.remove = function (param) {
var _this = this;
if (Array.isArray(param)) {
param.forEach(function (item) { return _this._removeCommon(item); });
}
else {
this._removeCommon(param);
}
};
TrackedObjects.prototype._removeCommon = function (object) {
var referenceId = object[OfficeExtension.Constants.referenceId];
if (!OfficeExtension.Utility.isNullOrEmptyString(referenceId)) {
var rootObject = this.m_context._rootObject;
if (rootObject._RemoveReference) {
rootObject._RemoveReference(referenceId);
}
delete object[OfficeExtension.Constants.isTracked];
}
};
TrackedObjects.prototype._retrieveAndClearAutoCleanupList = function () {
var list = this._autoCleanupList;
this._autoCleanupList = {};
return list;
};
return TrackedObjects;
}());
OfficeExtension.TrackedObjects = TrackedObjects;
Hope this helps!
~ Michael Zlatkovsky, developer on Office Extensibility team, MSFT
In addition to the TrackedObjects fix the runSearch method needed updating to get the range of the searchResult rather than using the searchResult directly.
function runSearch(textToFind) {
var items = [];
return Word.run(function(context) {
var options = Word.SearchOptions.newObject(context);
options.matchWildCards = false;
var rangesFind = context.document.body.search(textToFind, options);
context.load(rangesFind);
return context.sync().then(function() {
for (var i = 0; i < rangesFind.items.length; i++) {
var range = rangesFind.items[i].getRange();
context.load(range, 'text');
items.push(range);
context.trackedObjects.add(items[items.length-1]);
}
return context.sync();
});
})
.then(function() {
return items;
});
};

Handling concurrency exceptions when passing the objects ids and timestamps using jQuery

I have the following business scenario inside my Asp.net MVC 4 asset management system :-
Scenario 1) A user selects multiple servers , then he selects a Rack Tag ,and click on
assign . so the selected servers will be assigned to the new Rack.
Scenario 2) And i want to check for any concurrency exception , if for example the selected
servers have been modified by another user since they were retrieved .
so i have wrote the following jQuery which will send the object ids+timestamps to the action method:-
$('body').on("click", "#transferSelectedAssets", function () {
var boxData = [];
$("input[name='CheckBoxSelection']:checked").each(function () {
boxData.push($(this).val());
});
var URL = "#Url.Content("~/Server/TransferSelectedServers")";
$.ajax({
type: "POST",
url: URL,
data: { ids: boxData.join(","), rackTo: $("#rackIDTo").val()}
,
success: function (data) {
addserver(data); })});
and inside the action method i have the following code:-
public ActionResult TransferSelectedServers(string ids, int? rackTo)
{
if (ModelState.IsValid)
{
try
{
var serverIDs = ids.Split(',');
int i = 0;
foreach (var serverinfo in serverIDs)
{
var split = serverinfo.Split('~');
var name = split[0];
//System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
byte[] bytearray = Encoding.Default.GetBytes(split[1]);
i++;
var server = repository.FindServer_JTechnology(Int32.Parse(name));
if (server == null)
return Json(new { IsSuccess = false, reload = true, description = " Some Servers might have been deleted, Transferre process has been cancelled .", rackid = rackFrom }, JsonRequestBehavior.AllowGet);
server.RackID = rackTo;
server.timestamp = bytearray;
string ADusername = User.Identity.Name.Substring(User.Identity.Name.IndexOf("\\") + 1);
repository.InsertOrUpdateServer(server, ADusername, server.Technology.IT360ID.Value, server.IT360SiteID, new bool(), server.Technology);
}
repository.Save();
return Json(new { IsSuccess = true, description = i + " Server/s Transferred Successfully To Rack " + }, JsonRequestBehavior.AllowGet);
}
catch (DbUpdateConcurrencyException e)
{
return Json(new { IsSuccess = false, reload = true, description = "records has been modified by antoehr user" }, JsonRequestBehavior.AllowGet);
}
catch (Exception e)
{
return Json(new { IsSuccess = false, reload = true, description = " Server/s Can not Be Transferred to the Selected Rack " }, JsonRequestBehavior.AllowGet);
}
}
return RedirectToAction("Details", new { id = rackTo });
}
and the repository method looks as follow:-
public void InsertOrUpdateServer(TMSServer server, string username, long assetid, long? siteid = 0, bool isTDMHW = false, Technology t = null)
{
server.IT360SiteID = siteid.Value;
tms.Entry(server).State = EntityState.Modified;
var technology = tms.Technologies.Single(a => a.TechnologyID == server.TMSServerID);
technology.IsManaged = t.IsManaged;
tms.Entry(technology).State = EntityState.Modified;
InsertOrUpdateTechnologyAudit(auditinfo);
}
}
but currently if two users selects the same servers and assign them to tow different racks , no concurrency exception will be raised ?
Can anyone advice ? baring in mind that if two users edit single object then one of them will get an concurrent exception message. so my timestamp column is defined correctly.
Thanks

Pagination not working for a Lazy Loaded Data Table on First Loading

I am using JPA named queries for Loading a Lazy Loaded DataTable. and setting first and Max results as shown below.
Query query = entityManager.createNamedQuery("StudyplanCategory.findByStatusAndLimit");
int end=(start*pageNumber);
query.setParameter("status", status);
query.setParameter("start", start);
query.setParameter("end", end);
query.setMaxResults(end - start);
The load method is given below:
public List<StudyplanCategory> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String,String> filters) {
List<StudyplanCategory> data = new ArrayList<StudyplanCategory>();
//System.out.println("Page First Value:"+first+"PageSize Value:"+pageSize);
datasource=categoryService.findDynaEditStudyPlan("NOT_USER_SPECIFIC",first,pageSize);
//filter
for(StudyplanCategory studyplanCategory : datasource) {
boolean match = true;
for(Iterator<String> it = filters.keySet().iterator(); it.hasNext();) {
try {
String filterProperty = it.next();
String filterValue = filters.get(filterProperty).toLowerCase();
String fieldValue = String.valueOf(studyplanCategory.getClass().getDeclaredField(filterProperty).get(studyplanCategory)).toLowerCase();
//System.out.println("fieldValue............."+fieldValue);
if(filterValue == null || fieldValue.startsWith(filterValue)) {
match = true;
}
else {
match = false;
break;
}
} catch(Exception e) {
match = false;
System.out.println("The Exception occured at"+e);
}
}
if(match) {
data.add(studyplanCategory);
}
}
//sort
if(sortField != null) {
Collections.sort(data, new LazySorter(sortField, sortOrder));
}
//rowCount
int dataSize = data.size();
this.setRowCount(dataSize);
//paginate
if(dataSize > pageSize) {
try {
return data.subList(first, first + pageSize);
}
catch(IndexOutOfBoundsException e) {
return data.subList(first, first + (dataSize % pageSize));
}
}
else {
return data;
}
}
But when the table is loaded Next Buttons are not active because I am loading only those data required to load the first page. How can I Solve this.
You need to fire another query which sets the total rowcount. Basically, in LazyDataModel#load():
public List<StudyplanCategory> load(...) {
setRowCount(studyplanCategoryService.count());
return studyplanCategoryService.list(...);
}
Unrelated to the concrete problem, you should actually be using Query#setFirstResult() to set the first record index.