import {Component, OnInit} from 'angular2/core'; import {HighlightType, EstimateDirection} from '../../enums'; import {PlanService} from '../../services/plan-service'; /// @Component({ selector: 'plan-node', inputs: ['node', 'planStats', 'viewOptions'], templateUrl: './components/plan-node/plan-node.html', directives: [PlanNode], providers: [PlanService] }) export class PlanNode { // consts MAX_WIDTH: number = 220; MIN_ESTIMATE_MISS: number = 100; COSTLY_TAG: string = 'costliest'; SLOW_TAG: string = 'slowest'; LARGE_TAG: string = 'largest'; ESTIMATE_TAG: string = 'bad estimate'; // inputs node: any; planStats: any; viewOptions: any; // calculated properties duration: string; durationUnit: string; executionTimePercent: number; backgroundColor: string; highlightValue: number; width: number; props: Array; tags: Array; plannerRowEstimateValue: number; plannerRowEstimateDirection: EstimateDirection; currentHighlightType: string; // expose enum to view estimateDirections = EstimateDirection; highlightTypes = HighlightType; constructor(private _planService: PlanService) { } ngOnInit() { this.currentHighlightType = this.viewOptions.highlightType; this.calculateBar(); this.calculateProps(); this.calculateDuration(); this.calculateTags(); this.plannerRowEstimateDirection = this.node[this._planService.PLANNER_ESIMATE_DIRECTION]; this.plannerRowEstimateValue = _.round(this.node[this._planService.PLANNER_ESTIMATE_FACTOR]); } ngDoCheck() { // console.log("check", this.currentHighlightType, this.viewOptions.highlightType); if (this.currentHighlightType !== this.viewOptions.highlightType) { this.currentHighlightType = this.viewOptions.highlightType; this.calculateBar(); } } calculateBar() { switch (this.currentHighlightType) { case HighlightType.DURATION: this.highlightValue = (this.node[this._planService.ACTUAL_DURATION_PROP]); this.width = Math.round((this.highlightValue / this.planStats.maxDuration) * this.MAX_WIDTH); break; case HighlightType.ROWS: this.highlightValue = (this.node[this._planService.ACTUAL_ROWS_PROP]); this.width = Math.round((this.highlightValue / this.planStats.maxRows) * this.MAX_WIDTH); break; case HighlightType.COST: this.highlightValue = (this.node[this._planService.ACTUAL_COST_PROP]); this.width = Math.round((this.highlightValue / this.planStats.maxCost) * this.MAX_WIDTH); break; } if (this.width < 1) { this.width = 1 } this.backgroundColor = this.numberToColorHsl(1 - this.width / this.MAX_WIDTH); } calculateDuration() { var dur: number = _.round(this.node[this._planService.ACTUAL_DURATION_PROP]); // convert duration into approriate units if (dur < 1) { this.duration = "<1"; this.durationUnit = 'ms'; } else if (dur > 1 && dur < 1000) { this.duration = dur.toString(); this.durationUnit = 'ms'; } else { this.duration = _.round(dur / 1000, 2).toString(); this.durationUnit = 'mins'; } this.executionTimePercent = (_.round((dur / this.planStats.executionTime) * 100)); } // create an array of node propeties so that they can be displayed in the view calculateProps() { this.props = _.chain(this.node) .omit('Plans') .map((value, key) => { return { key: key, value: value }; }) .value(); } calculateTags() { this.tags = []; if (this.node[this._planService.SLOWEST_NODE_PROP]) { this.tags.push(this.SLOW_TAG); } if (this.node[this._planService.COSTLIEST_NODE_PROP]) { this.tags.push(this.COSTLY_TAG); } if (this.node[this._planService.LARGEST_NODE_PROP]) { this.tags.push(this.LARGE_TAG); } if (this.node[this._planService.PLANNER_ESTIMATE_FACTOR] >= this.MIN_ESTIMATE_MISS) { this.tags.push(this.ESTIMATE_TAG); } } /** * http://stackoverflow.com/questions/2353211/hsl-to-rgb-color-conversion * * Converts an HSL color value to RGB. Conversion formula * adapted from http://en.wikipedia.org/wiki/HSL_color_space. * Assumes h, s, and l are contained in the set [0, 1] and * returns r, g, and b in the set [0, 255]. * * @param Number h The hue * @param Number s The saturation * @param Number l The lightness * @return Array The RGB representation */ hslToRgb(h, s, l) { var r, g, b; if (s == 0) { r = g = b = l; // achromatic } else { function hue2rgb(p, q, t) { if (t < 0) t += 1; if (t > 1) t -= 1; if (t < 1 / 6) return p + (q - p) * 6 * t; if (t < 1 / 2) return q; if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; return p; } var q = l < 0.5 ? l * (1 + s) : l + s - l * s; var p = 2 * l - q; r = hue2rgb(p, q, h + 1 / 3); g = hue2rgb(p, q, h); b = hue2rgb(p, q, h - 1 / 3); } return [Math.floor(r * 255), Math.floor(g * 255), Math.floor(b * 255)]; } // convert a number to a color using hsl numberToColorHsl(i) { // as the function expects a value between 0 and 1, and red = 0° and green = 120° // we convert the input to the appropriate hue value var hue = i * 100 * 1.2 / 360; // we convert hsl to rgb (saturation 100%, lightness 50%) var rgb = this.hslToRgb(hue, .9, .4); // we format to css value and return return 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')'; } }