import { Component, Input, OnInit, ElementRef, ViewChild, Output, EventEmitter, NgZone } from '@angular/core'; import { Router } from '@angular/router'; import * as d3 from 'd3'; import { SessionService } from '@shared/services/session.service'; import { ApiService } from '@shared/services/api.service'; import { AppConstants } from '../../app.constants'; @Component({ selector: 'app-categories-chart', templateUrl: './categories-chart.component.html', styleUrls: ['./categories-chart.component.sass'] }) export class CategoriesChartComponent implements OnInit { public type: any; public heading: string; @Input() category: string; public pieData: any = {}; @ViewChild('chart') elementView: ElementRef; @Output() onApiSuccess: EventEmitter<any> = new EventEmitter(); public dataSet: Object[]; public colorCodes: Array<any> = ["#1d1e52", "#008b8f", "#ff9c2b", "#f65a38", "#d11d55"]; public margin = {top: 20, right: 20, bottom: 30, left: 50}; public width: number; public height: number; public radius: number; public arc: any; public labelArc: any; public pie: any; public color: any; public svg: any; constructor(private zone:NgZone, private route: Router, private SessionService: SessionService, public _apiCallService: ApiService) {} ngOnInit() { this.type = AppConstants.HTML_MODERATE; ( this.category === "user" ) ? this.getCategoryData("driveCategory") : this.getCategoryData("riskCategory"); } getCategoryData(apiName) { this._apiCallService.getCategoryData(apiName) .subscribe( (response: any) => { if(this.category === "user"){ this.pieData = { dataSet: response.data.drive_category, legends: AppConstants.USER_LEGENDS, dataSetMap: AppConstants.USER_DATASETMAP, totalVal: response.data.drive_category.total_users } } else { this.pieData = { dataSet: response.data.risk_category, legends: AppConstants.COMMON_LEGENDS, dataSetMap: AppConstants.COMMON_DATASETMAP, totalVal: response.data.risk_category.total_users } } this.buildChart(); this.onApiSuccess.next(true); }, (error: any) => { this.onApiSuccess.next(true); }); } buildData() { let newDataCollection: Array<any> = []; this.pieData.dataSetMap.forEach( (key, i) => { let obj: Object = { val: this.pieData.dataSet[key], perCentVal: ((this.pieData.dataSet[key] / this.pieData.totalVal) * 100), label: this.pieData.legends[i].toUpperCase() }; newDataCollection.push(obj); }); return newDataCollection; } buildChart() { this.dataSet = this.buildData(); this.width = this.elementView.nativeElement.offsetWidth - this.margin.left - this.margin.right ; this.height = this.elementView.nativeElement.offsetHeight - this.margin.top - this.margin.bottom; this.radius = Math.min(this.width, this.height) / 2 - 13; this.heading = ( this.category === "user" ) ? "User Categories" : "Risk Categories"; setTimeout(() => { this.initSvg() this.drawPie(); }, 10); } public initSvg() { this.color = d3.scaleOrdinal() .range(this.colorCodes); this.arc = d3.arc() .outerRadius(this.radius - 10) .innerRadius(0); this.labelArc = d3.arc() .outerRadius(this.radius - 40) .innerRadius(this.radius - 40); this.pie = d3.pie() .sort(null) .value((d: any) => d.perCentVal); this.svg = d3.select("#" + this.category) .append("g") .attr("class", "parent-g") .attr("transform", "translate(" + ((this.width / 2)+35) + "," + this.height / 2 + ")"); } public drawPie() { let g = this.svg.selectAll(".arc") .data(this.pie(this.dataSet)) .enter().append("g") .attr("class", "arc"); g.append("path").attr("d", this.arc) .style("fill", (d: any) => this.colorCodes[d.index] ); g.append("text").attr("font-weight", "bold") .attr("fill", "#ffffff") .attr("font-size", "12") .attr("transform", (d: any) => "translate(" + this.labelArc.centroid(d) + ")") .attr("dy", "-0.2em") .attr("dx", "-0.6em") .text((d: any) => { if(d.data.perCentVal > 0) { if(d.data.perCentVal == 0) return " " else if(d.data.perCentVal > 0 && d.data.perCentVal < 1){ return d.data.perCentVal.toFixed(2)+ "%" } else if(d.data.perCentVal >= 1) return Math.round(d.data.perCentVal)+ "%" } }); g.on("mouseover", (d) => { d3.select("#" + this.category + "-tooltip") .attr("class", "") .style("position", "absolute") .style("left", d3.event.pageX - 70 + "px") .style("top", d3.event.pageY - 580 + "px") .style("opacity", 1) .select("#" + this.category + "-value") .text(d.data.val); }).on("mouseout", () => { d3.select("#" + this.category + "-tooltip") .style("opacity", 0);; }) if(this.category === "user") { g.attr("cursor", "pointer") .on("click", (d) => { this.SessionService.deleteCategory() let label = d.data.label === "NEW USERS" ? "UNCATEGORIZED" : d.data.label; localStorage.setItem('userType', label); // this.route.navigate(["user-categories/categories"]); this.route.navigate(["dashboard/categories"]); // this.route.navigate(["user-categories/categories"], { queryParams: {type: label, page: "1"} }); }); } } onResize(e){ let width = this.elementView.nativeElement.offsetWidth - this.margin.left - this.margin.right ; let height = this.elementView.nativeElement.offsetHeight - this.margin.top - this.margin.bottom; let g = d3.select("#" + this.category).select("g.parent-g").attr("transform", "translate("+ width/2 +", " + height/2 + ")"); } }