AnyChart 8.1.0 - Resource Gantt - Move periods from one resource to another - anychart

I am using the AnyChart 8.1.0 resource Gantt (anychart.ganttResource()) to show and edit planned data (car reservations).
I can edit / move a reservation horizontally to change the time / period of a reservation and also drag the start and/or enddate. But I would like to move a reservation from one car (row) to another - very similar to moving a task from one person to another.
Is that possible - and how?
Thanks!
Roel

I'm having the same issue, and as far as I can see you can use
tree.listen("treeItemMove", function (e) {
// do your stuff
});
Unfortunally, I think this will only work, if you only have one reservation in each row. If you have more than one, all reservations will be moved.
So far I haven't found a solution to get one reservation and move it to another row. But I hope it may help you in the rigth direction..
EDIT:
I have contacted Anychart support and asked if there is a way to move one period from one (child-) row and create a new row under another parent?
Here is the answer:
the current version of AnyGantt 8.1.0 doesn't provide this feature as an out-of-the-box or even with the extra code.
But you can modify the dataTree from the code as you need. This provides full control under the data, but without mouse interactivity.

That's too bad. I can manipulate the tree - even one period, using this code to delete and add a period. You can update a period as well, code should be similar.
function deletePeriod( pItemId, pPeriodId ){
var item = treeData.search("id", pItemId);
var periods = item.get("periods")
var i = periods.findIndex(function(e){ return e.id == pPeriodId; });
periods.splice(i,1);
item.set('periods', periods);
treeData.addChildAt( item, treeData.indexOfChild(item) );
}
and
function addPeriod( pItemId, pPeriodId, start, end){
var period = {
"id": pPeriodId,
"start": start,
"end": end,
"name": "Whatever name you want"
};
var item = treeData.search("id", pItemId);
var periods = item.get("periods");
periods.push(period);
item.set('periods', periods);
treeData.addChildAt( item, treeData.indexOfChild(item) );
}

Related

Listen for click / hover on individual axis labels

I'm looking for a way to change the value (or format) for an individual series label when hovering it in anycharts.
Currently I'm only able to access the entire axis and I can find no getter method for individual labels so as to attach a listener.
xAxis.labels().listen('mouseOver', function(e) {
console.log(this, e.target);
});
This jsfiddle is as far as I got (see console log), this as well as the event.target reference the entire axis but not the label:
https://jsfiddle.net/robstarbuck/pbhd4b7L/9/
Indeed, there was a little bug with cache and format() function, our dev team made the fix, so please check the working sample:
var labelIndex = e.labelIndex;
var label = this.getLabel(labelIndex);
var value = xAxis.scale().ticks().get()[labelIndex];
label.format(value * 2);
https://jsfiddle.net/pbhd4b7L/13/ – it also shows how to work with tick values:
Currently it takes the js from branch, but this fix will be included in the upcoming release – 7.14.0 version (ETA: May 2017)
Our API is a little bit complicated here, but we're working hard to improve it. Does this what you're looking for?
var labelIndex = e.labelIndex;
var label = this.getLabel(labelIndex);
label.fontColor('red');
label.draw();
https://jsfiddle.net/pbhd4b7L/10/
This issue was fixed in the 7.14.0 release, use this code:
xAxis.labels().listen('mouseOver', function(e) {
var labelIndex = e.labelIndex;
var label = this.getLabel(labelIndex);
var value = xAxis.scale().ticks().get()[labelIndex];
label.format(value * 2);
label.fontColor('red');
label.draw();
});
with the latest version: https://jsfiddle.net/2t08ahkg/3/

Devexpress: how to add points to Chart Control at runtime?

i'm trying to build a telemetry software using Winform and Devexpress library. Specifically i'm working on a Line Chart Control and what i would like to do is to configure the chart so that it is able to display a data changing in real time.
The graph is generated reading some external sensors that send informations at a rate of 10 values per second.
This is my code for initialize the chart:
series1 = new Series("test test", ViewType.Line);
chartControl1.Series.Add(series1);
series1.ArgumentScaleType = ScaleType.Numerical;
((LineSeriesView)series1.View).LineMarkerOptions.Kind = MarkerKind.Triangle;
((LineSeriesView)series1.View).LineStyle.DashStyle = DashStyle.Dash;
((XYDiagram)chartControl1.Diagram).EnableAxisXZooming = true;
chartControl1.Legend.Visibility = DefaultBoolean.False;
chartControl1.Titles.Add(new ChartTitle());
chartControl1.Titles[0].Text = "A Line Chart";
chartControl1.Dock = DockStyle.Fill;
And this is the one that add a new point and remove the first point available so that the amount of points in my chart is always the same (after a minimum amount of points is reached) and it keeps updating itself displaying the last X seconds of values and discarding the old values.
series1.Points.RemoveRange(0, 1);
series1.Points.Add(new SeriesPoint(time, value));
...
AxisXRange.SetMinMaxValues(newFirstTime, time);
AxisRange is the following
Range AxisXRange
{
get
{
SwiftPlotDiagram diagram = chartControl1.Diagram as SwiftPlotDiagram;
if (diagram != null)
return diagram.AxisX.VisualRange;
return null;
}
}
**The problem ** is that this code works temporarily. After some seconds, the chart stop working and a big red cross is displayed over it.
Is there something that i'm missing with its configuration?
Do you know any better way to realize my task?
Any help would be appreciated.
Thank you
I think you doing it nearly right. Devexpress has an Article about RealTime-Charts. They doing it the same way but using a timer for updating the data. Maybe this would fix your painting problems.

ListCollectionView's live shaping bug

After digging deeper, why live shaping, in detail the automatic sorting of groups by name, is not working, I decided to wrote a small test application, solution download is here:
here
Following, a description of the problem: I use an ObservableCollection of Person objects, with Age and Name properties (with NPC). I create a ListCollectionView bound to a DataGrid with a custom GroupStyle to expose an Expander
For this view I set:
GroupDescription to Age
SortDescription to Age (to sort the groups)
SortDescription to Name
After start a DispatcherTimer recalculates all Ages of each Person to a random value between 30 and 45.
At runtime the fault: for about 60-70% of all dynamic resorts of the groups, the sorting order is right e.g. for example 31 before 34 before 41 before 45. But sometimes a 30th number is between two 40th numbers, and that's wrong. Where is the problem and how can I solve? By the way, the problem only occures for group ordering.
BTW: For what purpose is the LiveSortingProperties collection, setting a SortDescription and IsLiveSorting=True obviously activates live shaping, In which situation I should add a string to this collection?
Here is a screenshot of the wrong group sorting:
Example Picture of wrong sorting:
Groups are presented in order of discovery. In your case the data is sorted by Age (then by Name), so the initial scan of the data will discover the Age-31 group before the Age-34 group. However if none of the people have Age=37, there is no Age-37 group. Later on, if add a new Person (or change the Age of an existing Person, when Live-Grouping is enabled) with Age=37, a new Age-37 group is created. But since it is discovered after the initial groups, it gets added after all those groups.
At present (4.6.1) there is no way to declare a sort order for the groups themselves. We are considering adding this feature, as many people ask for it.
BTW: The purpose of LiveSortingProperties is for cases when you want to sort by properties A, B, and C, but you know that only property C will change. Declare all three properties in SortDescriptions, but declare only C in LiveSortingProperties. That way we won't waste effort setting up change listeners for A and B that would never be called.
I recently ran into this problem as well. Because my client's may not immediately upgrade to 4.6.2 I created a work around.
My application uses ReactiveUI (http://reactiveui.net/) which facilitates this solution. Adapting my solution to your Person example, basically I monitor any changes to the Age property, then count the number of groups (i.e. Ages) and only when the number of age groups change (DistinctUntilChanged) do I reconfigure the grouping and sorting.
Because this uses a reactive pattern it is pretty efficient, but also in my case there are only a few dozen elements at any one time.
// NB People is a ReactiveList<Person>
void SetupInterface()
{
People.ItemChanged.Select(p => p.PropertyName == "Age")
.Where(ageChanged => ageChanged)
.DistinctUntilChanged(_ => People.GroupBy(x => x.Age).Count())
.Subscribe(_ =>
{
ConfigureGrouping();
});
ConfigureGrouping();
}
void ConfigureGrouping()
{
using (_collectionView.DeferRefresh())
{
// code to reset and rebuild the group and sort descriptions...
}
}
Random rnd = new Random();
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(4000);
timer.Tick += (sender, args) =>
{
foreach (var person in Persons)
{
person.Age = rnd.Next(30, 45);
}
PersonsView.Refresh();
};
timer.IsEnabled = true;
View.Refresh did the trick for me

Update AngularJS data from separate source

I'm working on my first Angular project and I've been thinking of the best way to word this question for a while now but I'm going to give this a shot.
I'm building an app that uses the Veralite (MiOS) to return device data in json format. The first request returns all of the devices on the system (example below).
"devices":[
{
"name":"Bedroom Light",
"altid":"4",
"id":6,
"category":2,
"subcategory":0,
"room":0,
"parent":1,
"status":"0",
"level":"0",
"state":-1,
"comment":""
},
{
"name":"Office Light",
"altid":"6",
"id":18,
"category":2,
"subcategory":0,
"room":0,
"parent":1,
"level":"0",
"status":"0",
"state":-1,
"comment":""
}
Once all of the devices are returned, my script begins long polling the vera engine. Once a change to a device is made the results of the long poll are returned, but the results only include the devices that were changed (example below).
"devices":[
{
"altid":"6",
"id":"18",
"subcategory":"0",
"room":"0",
"parent":"1",
"level":"20",
"status":"1",
"state":"4",
"comment":"Office Light: Transmit was ok"
}
What I am trying to wrap my head around, is the proper way to update the existing devices array with the newly updated data. Would I need to convert them to arrays, then loop through each array and try to match them by keys?
Hopefully I asked this as clearly as possible.
EDIT: Just to update this a bit for anyone that stumbles across this, specifically people interested in developing for the Veralite. The ID returned from the original request will be returned as an integer, but when long polling the engine, the ID will be returned as a string. So even though the selected answer is correct, you'll need to either parse the updated device ID as an integer (parseInt), or only use a == instead of a === when filtering the devices.
You can loop through the object fields just like you can loop through an array with Object.keys.
Conceptually something like:
Step 1) Find the updated product, by the field id:
var previousVersionDevice = $scope.devices.filter(function(item) {
return item.id === updateDevice.id; // Keep only the one existing device that matches id
})[0];
Step 2) Loop through the keys in the product and overwrite the previous values with the ones received.
Object.keys(updatedDevice).forEach(function(key) {
previousVersionDevice[key] = updatedDevice[key]; // Overwrite/add all from updated version
});
yes, you can loop through and find the matching device via some sort of unique key (assuming id is unique and won't change, you can use that).

Some items in my ipod library have a NULL assturl property

When try to pick an item from my ipod library some items play and some dont.
Looking at my log some items have a NULL for assetURL.
Why would that be?
all item are DRM protected which return null assetURL. You can't access such item
I want to add something to this. There are three reasons that I know of why assetURL will be null
The item is in the cloud (in which case isCloudItem will return true).
As stated in another answer, if the track is DRM protected.
This is the kicker, tho: in some cases, and item downloaded on the device, which is not DRM, will play in Music (the built-in App), but will still have assetURL returning NULL.
This means that any non-Apple App that uses the MediaPlayer framework may encounter some media items that play in Music, but which cannot be played in the App. Your end user can usually "fix" this problem by deleting the offending track in Music, and downloading it again.
I find that if I download a complete album and see this issue, then downloading the album again (after deleting it) will lead to some different tracks having the problem, so that is not a good way to go.
I have entered an Apple bug-report for this (21477730). I also used a DTS to ask for a work-around: there is none. If you are encountering this too, a "me too" to the bug report. This may increase the chances of a fix.
If you want to try this out for yourself, below is the code that I sent in with the bug report.
MPMediaQuery *allAlbumsQuery = [MPMediaQuery albumsQuery];
NSArray *allAlbumsArray = [allAlbumsQuery collections];
for (MPMediaItemCollection *collection in allAlbumsArray)
{
NSArray* items = collection.items;
MPMediaItem* rep = collection.representativeItem;
NSString* name = rep.albumTitle;
for(MPMediaItem* item in items)
{
NSURL* url = item.assetURL;
BOOL isCloudItem = item.isCloudItem;
if(!isCloudItem && (url==nil))
{
NSString* albumTitle = item.albumTitle;
NSString* trackTitle = item.title;
NSLog(#"****Nil: %# %#",albumTitle,trackTitle);
}
}
}

Resources