I using igDoughnutChart for my web-page, I want a graph which shows the following hierarchy
source of attack (inside)
login abuse
dos
spyware
worm
outside attackers
spying
social attacks
The current object array looks like (also demo)
var data = [
{ "attacksource": 43, "attacktype": 60, "AT":"DoS","Label": "iNISDE" },
{ "attacksource": 29, "attacktype": 40, "AT":"login abuse","Label": "outside" }
];
I want to change this to do following:- (also shown above)
Where I have a parent and child values in 2d array so above code is to transform as
var data =
[
[{"attacksource": 43,"Label":"Inside"}],
[
{"attacktype": 13,"Label":"dos"},
{"attacktype": 13,"Label":"virus"}...
]
];
I'm not sure If I have initialized / assigned 2d using objects correctly.I appreciate If someone can look at the code, and let me know if I'm doing this right.
UPDATE
The jsbin example is just something to illustrate my requirements for the new code. For e.g "Label":"virus" is currently hardcoded, in real code (which I cannot do on jsbin) is I will get the values from DB.
VISUAL EXAMPLE
I don't think the chart you are trying to use support what you want to do. That being said there is somewhat of a hack to make it work:
$(function () {
var data = [
{ "label": "Inside", "attacks": 8 },
{ "label": "Outside", "attacks": 6 },
// Inside
{ "label": "Dos", vector: "Inside", "dummyValue": 6 },
{ "label": "siem", detect: "Dos", "detectValue": 3 },
{ "label": "user", detect: "Dos", "detectValue": 3 },
{ "label": "Worm", vector: "Inside", "dummyValue": 2 },
{ "label": "siem", detect: "Worm", "detectValue": 1 },
{ "label": "user", detect: "Worm", "detectValue": 1 },
// Outside
{ "label": "Spying", vector: "Outside", "dummyValue": 3 },
{ "label": "siem", detect: "Spying", "detectValue": 1.5 },
{ "label": "user", detect: "Spying", "detectValue": 1.5 },
{ "label": "Social", vector: "Outside", "dummyValue": 3},
{ "label": "siem", detect: "Social", "detectValue": 1.5 },
{ "label": "user", detect: "Social", "detectValue": 1.5 },
];
$("#chart").igDoughnutChart({
width: "100%",
height: "550px",
innerExtent: 6,
series:
[
{
name: "Attack Type",
labelMemberPath: "label",
valueMemberPath: "attacks",
dataSource: data,
labelsPosition: "center"
},
{
name: "Attack Vector",
labelMemberPath: "label",
valueMemberPath: "dummyValue",
dataSource: data,
labelsPosition: "center"
},
{
name: "detect Vector",
labelMemberPath: "label",
valueMemberPath: "detectValue",
dataSource: data,
labelsPosition: "center"
}
]
});
});
The order of the data and series arrays matter (not completely, just partially). Here is a jsFiddle that demonstrates this. Disclaimer: I'm not saying this will always work, as it makes the big assumption that igniteUI will always parse and display the data in the same way.
Also I'm not familiar with the library but I would bet there is a way to customize the colors of each section of the chart. If so you could just make the color a function that returns a color based on the vector property.
Some alternatives:
Highcharts
D3 - this would be my preferred approach. Browse the gallery, there a few examples that apply here.
Related
I'm writing here because I'm completely lost. I would like to do a findall based on association and nested [Op.and], but I can't do it. Let me explain.
I have two tables (car and properties) with an association between these two tables (one car, can have several properties). The data looks like this :
{
"car": "BMW M5",
"properties": [
{
"name": "make",
"value": "bmw"
},
{
"name": "color",
"value": "blue"
}
]
},
{
"car": "AUDI A3",
"properties": [
{
"name": "make",
"value": "audi"
},
{
"name": "color",
"value": "black"
}
]
},
What I'm trying to do is a "findAll" of all cars of make BMW and with blue color. Logically, I would see something like this :
( properties.name = make & properties.value = audi ) & ( properties.name = color & properties.value = blue )
From this logic, I therefore tried to create the sequelize command below, but without success :
const cars = await models.Car.findAll({
include: [{
model: models.Properties,
required: false,
}],
where: {
[Sequelize.Op.and]:[
{[Sequelize.Op.and]: [{"$properties.name$": "make"}, {"$properties.value$": "bmw"}]},
{[Sequelize.Op.and]: [{"$properties.name$": "color"}, {"$properties.value$": "blue"}]},
]
});
Apparently when I do this it only takes the last [Op.and] ([Sequelize.Op.and]: [{"$properties.name$": "color"}, {"$properties.value$": "blue"}]), the others don't seem to be taken into consideration.
Maybe I'm wrong, but I tried several possibilities, but I don't know how to do it. Any help would be very appreciated, thank you in advance to everyone.
It seems you over-complicated the where condition:
const cars = await models.Car.findAll({
include: [{
model: models.Properties,
required: false,
}],
where: {
[Sequelize.Op.and]:[
{
"$properties.name$": "make",
"$properties.value$": "bmw"
},
{
"$properties.name$": "color",
"$properties.value$": "blue"
},
]
}
});
If you have different props in the same group of conditions then you can just use an object to combine them with AND operator.
I'm using JSreport 3.4.1. and Chart.js 3.8.0. From a server API I'm getting a series of data to create n. charts. The problem is that the number of charts are never the same (they depend on various parameters in a database).
I cannot create n. static charts for the reason above, so I was trying to dynamically create and inject them in the DOM through jQuery, but I'm having some difficulties:
It successfully creates the first chart, but with incorrect data (like it isn't waiting for the trigger input), and the second chart isn't shown at all.
Any idea on how to create a dynamic number of charts based on the number of objects (inside an array) that arrives through an API?
const datasets = {
"datasets": [{
"dynamic_id": 0,
"NomeAnomalia": "MIT Appoggi",
"GruppiAnomalie": 199,
"anomalyList": [{
"GruppiAnomalie": 199,
"Code": "Classe 1\nApp1",
"Name": "Piastra di base deformata",
"Class": "Classe 1",
"Severity": "0 - Lieve",
"Value": 100
}],
"pieChartData": [{
"severityName": "Lieve",
"severityValue": 100
},
{
"severityName": "Media",
"severityValue": 0
},
{
"severityName": "Forte",
"severityValue": 0
}
]
},
{
"dynamic_id": 1,
"NomeAnomalia": "MIT Impalcati,Travi,Traversi CA CAP",
"GruppiAnomalie": 199,
"anomalyList": [{
"GruppiAnomalie": 199,
"Code": "Classe 1\nApp1",
"Name": "Piastra di base deformata",
"Class": "Classe 1",
"Severity": "0 - Lieve",
"Value": 100
}],
"pieChartData": [{
"severityName": "Lieve",
"severityValue": 100
},
{
"severityName": "Media",
"severityValue": 0
},
{
"severityName": "Forte",
"severityValue": 0
}
]
}
]
}
var content = document.getElementById('content');
for (dataset of datasets.datasets) {
var divPieChart = `
<div class="row">
<div class="col-sm-12">
<div class="chart-container">
<canvas id="bar_chart_${dataset.dynamic_id}"></canvas>
</div>
</div>
</div>`;
content.innerHTML += divPieChart;
var bar_chart_ctx = document.getElementById(`bar_chart_${dataset.dynamic_id}`).getContext('2d');
var bar_chart = new Chart(bar_chart_ctx, {
type: 'bar',
data: {
labels: [1, 2, 3],
datasets: [{
"label": "2017",
"data": [5, 3, 7.5],
"backgroundColor": ["rgba(215, 221, 234)"]
}]
},
options: {
maintainAspectRatio: false,
devicePixelRatio: 1.5,
plugins: {
legend: {
display: true,
position: "top"
}
},
scales: {
y: {
beginAtZero: true
}
},
animation: {
onComplete: function() {
// set the PDF printing trigger when the animation is done
// to have this working, the chrome-pdf menu in the left must
// have the wait for printing trigger option selected
window.JSREPORT_READY_TO_START = true
}
}
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#2.0.0"></script>
<div id="test"></div>
<div id="content"></div>
I've set a playground with mock data (not really needed cause I've put static data inside the charts) so you can see what I mean:
playground test
Thank you
EDIT
I figured out how to do it (JSReport specifically): in JSReport, window.JSREPORT_READY_TO_START = true tells the report that all the components in the page are done to print. Breaking down the "creation" of the html and the "creation" of the charts into two separates loop, using the length of the dataset as control, makes the work (only JSReport, I won't post a snippet cause it won't work the same as window.JSREPORT_READY_TO_START = true is not present).
Here's the playground if someone needs it: playground test
How can we call MSCRM action using some HTTP Client request (c#)?
Can any one please assist on this.
The documentation is not covering this action, and I was able to pull this payload from couple of references. But I could not test this in my environment, please test it yourself.
The sample will look like this:
{
"SearchText": "",
"UseInflection": false,
"RemoveDuplicates": false,
"StateCode": 3,
"QueryExpression": {
"#odata.type": "Microsoft.Dynamics.CRM.QueryExpression",
"EntityName": "knowledgearticle",
"ColumnSet": {
"AllColumns": true
},
"Distinct": false,
"NoLock": false,
"PageInfo": {
"PageNumber": 1,
"Count": 10,
"ReturnTotalRecordCount": true,
"PagingCookie": ""
},
"LinkEntities": [],
"Criteria": {
"FilterOperator": "And",
"Conditions": [
{
"EntityName": "knowledgearticle",
"AttributeName": "languagelocaleid",
"Operator": "Equal",
"Values": [
"56940B3E-300F-4070-A559-5A6A4D11A8A3"
]
}
]
}
}
}
Reference.
Make a POST request to the the following URL.
[Your organization root URL]/api/data/v9.1/FullTextSearchKnowledgeArticle
Here is one sample payload that works. You can optionally add additional filters to filter the search result.
{
"SearchText":"test",
"UseInflection":true,
"RemoveDuplicates":true,
"StateCode":3,
"QueryExpression":{
"#odata.type":"Microsoft.Dynamics.CRM.QueryExpression",
"EntityName":"knowledgearticle",
"ColumnSet":{
"AllColumns":true
},
"PageInfo":{
"PageNumber":1,
"Count":10
},
"Orders":[
{
"AttributeName":"modifiedon",
"OrderType":"Descending"
}
]
}
}
Refer the link below for sample code for connecting to Dynamics.
CDSWebApiService class library (C#)
I am using rails, and gathering some data to make pie charts. I am just using ruby objects (so no JSON), and using d3pie. First, I make a helper function. Then I make a javascript function using that helper, and pass it in the dom. Here's my code;
helper.rb
def options_data_to_d3(options_data)
d3_data = []
options_data.each do |key, value|
d3_data.push( { label: key.option.as_json, value: value.as_json } )
end
return JSON.pretty_generate(d3_data)
end
this takes the ruby hash, and makes it into json
js function
function dataPieChart(id, data) {
var config = {
"header": {
"title": {
"text": "Quiz Questions",
"fontSize": 18,
"font": "verdana"
},
"size": {
"canvasHeight": 400,
"canvasWidth": 500
},
"data": {
"content": data
},
"labels": {
"outer": {
"pieDistance": 32
}
}
}
}
var pie = new d3pie(id, config);
}
passing into the view
<div id="quizQuestionOptionPie<%= question.id %>"></div>
<script type="text/javascript">dataPieChart("quizQuestionOptionPie<%= question.id %>", <%= raw options_data_to_d3(data[:options]) %>);
</script>
when I call a console log in the javascript function to see what data is, I get the correct output that both d3pie and d3 are looking for, yet I am still getting the error
d3pie error: no data supplied.
does anyone see something wrong with my code, or something I am missing? any help is appreciated.
You config option is bracketed incorrectly (everything is a child of "header"). You really meant:
var config = {
"header": {
"title": {
"text": "Quiz Questions",
"fontSize": 18,
"font": "verdana"
},
},
"size": {
"canvasHeight": 400,
"canvasWidth": 500
},
"data": {
"content": data
},
"labels": {
"outer": {
"pieDistance": 32
}
}
};
I need to create a multi leveled that is dynamic because I have to drill down to hundreds or even thousands of data providers that will load from the database. The flow goes like this: I have 1, 2, 3, 4, and 5 years that will drill down to 16 Departments each and will drill down to Courses 10 or more courses. Doing it manually is tedious and I need it to be dynamic. Please help me.
The variables:
var ccs_final_data = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/final_ccs_data");
//VAR CCS AVERAGE_FINAL
var drill_down_to_ccs_courses_average_final = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/ccs_courses_data_average_final");
var drill_down_to_ccs_sections_BSIT_average_final = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/ccs_sections_data_BSIT_average_final");
var drill_down_to_ccs_sections_ACT_average_final = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/ccs_sections_data_ACT_average_final");
var drill_down_to_ccs_sections_BSCS_average_final = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/ccs_sections_data_BSCS_average_final");
The graph:
var chart2 = AmCharts.makeChart( "ccs2", {
"theme": "light",
type: "serial",
pathToImages: "http://cdn.amcharts.com/lib/3/images/",
dataProvider: ccs_final_data,
categoryField: "category",
categoryAxis: {
labelRotation: 0,
gridPosition: "start"
},
valueAxes: [ {
title: "CCS FINAL TERM - Passing"
} ],
graphs: [ {
valueField: "value",
colorField: "color",
type: "column",
lineAlpha: 100,
fillAlphas: 1
} ],
chartScrollbar: {
"updateOnReleaseOnly": true
},
chartCursor: {
bulletsEnabled: "enabled",
bulletSize: 15,
cursorAlpha: 100,
cursorColor: "#CC0000",
zoomable: true,
categoryBalloonEnabled: true
},
export: {
enabled: true
}
} );
Here's the drill down stuff:
chart2.addListener("clickGraphItem", function (event) {
if(event.item.category == "Average"){
event.chart.dataProvider = drill_down_to_ccs_courses_average_final;
event.chart.validateData();
chart2.addListener("clickGraphItem", function (event) {
if(event.item.category == "BSIT"){
event.chart.dataProvider = drill_down_to_ccs_sections_BSIT_average_final;
event.chart.validateData();
}
else if(event.item.category == "ACT"){
event.chart.dataProvider = drill_down_to_ccs_sections_ACT_average_final;
event.chart.validateData();
}
else if(event.item.category == "BSCS"){
event.chart.dataProvider = drill_down_to_ccs_sections_BSCS_average_final;
event.chart.validateData();
}
});
}
I'd say the best way to make it dynamic is to include some custom field for each data point in your data that would be passed in to server-side script so it knows which data to load.
I'm assuming your data looks like this now:
[ {
"category": "BSIT",
"value": 100
}, {
"category": "ACT",
"value": 200
}, {
"category": "BSCS",
"value": 150
} ]
You could easily add a third field to hold the information for drill-down data load:
[ {
"category": "BSIT",
"value": 100,
"drill": "ccs_sections_data_BSIT_average_final"
}, {
"category": "ACT",
"value": 200,
"drill": "ccs_sections_data_ACT_average_final"
}, {
"category": "BSCS",
"value": 150,
"drill": "ccs_sections_data_BSCS_average_final"
} ]
Then, when clickGraphItem event occurs, you could just take that info and pass it to load script dynamically:
chart2.addListener( "clickGraphItem", function( event ) {
if ( event.item.dataContext.drill !== undefined ) {
event.chart.dataProvider = AmCharts.loadJSON( "<?php echo base_url();?>index.php/osa/" + event.item.dataContext.drill );
event.chart.validateData();
}
} );
This way, you could have any number of drill-down levels, with each level data containing info about where to look for the data for the next level.
Also, I'm not sure as you haven't posted the code for it, so I'm assuming that AmCharts.loadJSON method is synchronous. If it's not (for example if you are using method from Data Loader), you will need to assign the chart's dataProvider after the data is loaded.