github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/ui/src/views/cluster/containers/clusterOverview/capacity.tsx (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 import d3 from "d3"; 12 13 import { ComputeByteScale } from "src/util/format"; 14 15 const LOW_DISK_SPACE_RATIO = 0.15; 16 17 interface CapacityChartProps { 18 used: number; 19 usable: number; 20 } 21 22 /** 23 * capacityChart is the small bar chart showing capacity usage displayed on the 24 * cluster summary panel of the cluster overview page. 25 */ 26 function capacityChart() { 27 const size = { 28 width: 250, 29 height: 20, 30 }; 31 32 const margin = { 33 top: 12, 34 right: 20, 35 bottom: 25, 36 left: 20, 37 }; 38 39 const TICK_SIZE = 6; 40 const AXIS_MARGIN = 4; 41 42 const scale = d3.scale.linear() 43 .range([0, size.width]); 44 45 const axis = d3.svg.axis() 46 .scale(scale) 47 .tickSize(TICK_SIZE) 48 .ticks(5); 49 50 function recomputeScale(capacity: CapacityChartProps) { 51 // Compute the appropriate scale factor for a value slightly smaller than the 52 // usable capacity, so that if the usable capacity is exactly 1 {MiB,GiB,etc} 53 // we show the scale in the next-smaller unit. 54 const byteScale = ComputeByteScale(capacity.usable - 1); 55 56 const scaled = { 57 used: capacity.used / byteScale.value, 58 usable: capacity.usable / byteScale.value, 59 }; 60 61 axis.tickFormat(function (d) { 62 return d + " " + byteScale.units; 63 }); 64 scale.domain([0, scaled.usable]); 65 66 return scaled; 67 } 68 69 return function chart(svg: d3.Selection<CapacityChartProps>) { 70 const rect = (svg.node().parentNode as HTMLElement).getBoundingClientRect(); 71 size.width = rect.width; 72 73 scale.range([0, size.width]); 74 75 svg 76 .attr("width", size.width + margin.left + margin.right) 77 .attr("height", size.height + margin.top + margin.bottom); 78 79 const el = svg.selectAll(".main") 80 .data((d: CapacityChartProps) => [recomputeScale(d)]); 81 82 el.enter() 83 .append("g") 84 .attr("class", "main") 85 .attr("transform", `translate(${margin.left},${margin.top})`); 86 87 const axisGroup = el.selectAll("g.axis") 88 .data(() => [0]); 89 90 axisGroup.enter() 91 .append("g") 92 .attr("class", "axis") 93 .attr("transform", `translate(0,${size.height + AXIS_MARGIN})`); 94 95 axisGroup.call(axis); 96 axisGroup.selectAll("text").attr("y", AXIS_MARGIN + TICK_SIZE); 97 98 const lowDiskSpaceWidth = size.width * LOW_DISK_SPACE_RATIO; 99 const lowDiskSpacePosition = size.width - lowDiskSpaceWidth; 100 101 const bgNormal = el.selectAll(".bg-normal") 102 .data((d: CapacityChartProps) => [d]); 103 104 bgNormal.enter() 105 .append("rect") 106 .attr("class", "bg-normal"); 107 108 bgNormal 109 .attr("width", lowDiskSpacePosition) 110 .attr("height", size.height); 111 112 const bgLowDiskSpace = el.selectAll(".bg-low-disk-space") 113 .data((d: CapacityChartProps) => [d]); 114 115 bgLowDiskSpace.enter() 116 .append("rect") 117 .attr("class", "bg-low-disk-space"); 118 119 bgLowDiskSpace 120 .attr("x", lowDiskSpacePosition) 121 .attr("width", lowDiskSpaceWidth) 122 .attr("height", size.height); 123 124 const bar = el.selectAll(".bar") 125 .data((d: CapacityChartProps) => [d]); 126 127 bar.enter() 128 .append("rect") 129 .attr("class", "bar") 130 .attr("height", 10) 131 .attr("y", 5); 132 133 bar 134 .attr("width", (d: CapacityChartProps) => scale(d.used)); 135 136 }; 137 } 138 139 export default capacityChart;