Commit f0706d956f35903caf32f9edf149cefef8fbbb4b

Authored by hitier
1 parent 3c21ae9f

Add color legend

app/main/static/css/charges.css
... ... @@ -18,6 +18,15 @@
18 18 display: inline-block;
19 19 }
20 20  
  21 +text.legend {
  22 + font-size: 12px;
  23 +}
  24 +
  25 +rect.legend {
  26 + stroke: white;
  27 + stroke-width: 0.5pt;
  28 +}
  29 +
21 30 rect.bar {
22 31 stroke: white;
23 32 stroke-width: 0.5pt;
... ... @@ -27,7 +36,6 @@ rect.bar:hover {
27 36 -webkit-filter: brightness(1.5);
28 37 -moz-filter: brightness(1.5);
29 38 filter: brightness(1.5);
30   - stroke-width: 0;
31 39 }
32 40  
33 41 .tooltip {
... ...
app/main/static/js/charges.js
1   -var margin = {top: 60, right: 30, bottom: 130, left: 90},
2   - width = 1000 - margin.left - margin.right,
  1 +const margin = {top: 60, right: 270, bottom: 100, left: 90},
  2 + width = 1200 - margin.left - margin.right,
3 3 height = 500 - margin.top - margin.bottom;
4 4  
5 5 const tooltip_offset = {dx: 0, dy: 100}
6 6  
  7 +const color_scale = d3.scaleOrdinal(d3.schemeCategory10);
  8 +
  9 +const legend_cell_size = 15;
7 10  
8 11 // TODO: set main scales attr here then domain later
9 12 // const x = d3.scaleBand()
... ... @@ -14,19 +17,6 @@ const tooltip_offset = {dx: 0, dy: 100}
14 17 // .range([height, 0]);
15 18 //
16 19  
17   -var color = d3.scaleOrdinal()
18   - .range(["#4e79a7",
19   - "#f28e2c",
20   - "#e15759",
21   - "#76b7b2",
22   - "#59a14f",
23   - "#edc949",
24   - "#af7aa1",
25   - "#ff9da7",
26   - "#9c755f",
27   - "#bab0ab"
28   - ]);
29   -
30 20 function build_chart(div_selector, data_url, project_name, category) {
31 21  
32 22 if (category == 'capacity') {
... ... @@ -75,38 +65,99 @@ function build_chart(div_selector, data_url, project_name, category) {
75 65 .style("top", (e.pageY - tooltip_offset.dy) + "px")
76 66 }
77 67  
  68 + var addlegend = function (color_scale) {
  69 +
  70 + let reverse_keys = color_scale.domain().reverse();
  71 +
  72 + let legend = svg.append('g')
  73 + .attr('transform', 'translate(850, -30)');
  74 +
  75 + legend.selectAll()
  76 + .data(reverse_keys)
  77 + .enter().append('rect')
  78 + .attr('height', legend_cell_size + 'px')
  79 + .attr('width', legend_cell_size + 'px')
  80 + .attr('class', 'legend')
  81 + .attr('x', 5)
  82 + .attr('y', (d, i) => i * legend_cell_size)
  83 + .style("fill", d => color_scale(d));
  84 +
  85 + legend.selectAll()
  86 + .data(reverse_keys)
  87 + .enter().append('text')
  88 + .attr("transform", (d, i) => "translate(30, " + (i * legend_cell_size + legend_cell_size / 1.6) + ")")
  89 + .attr('class', 'legend')
  90 + // .style("font-size", "10px")
  91 + // .style("font-weight", "bold")
  92 + .style("fill", "black")
  93 + .text(d => d);
  94 + }
  95 +
78 96 d3.csv(data_url).then(data => {
79   - var services = data.columns.slice(1)
  97 + // var categories = data.columns.slice(1)
80 98 var periods = d3.map(data, d => d.period)
  99 + var categories_total_charge = {}
  100 +
  101 + // Get the charge sum for each categories over periods
  102 + // That will leave '0' to categories with no charge at all
  103 + data.forEach(function (d) {
  104 + Object.keys(d).forEach(function (k) {
  105 + if (categories_total_charge.hasOwnProperty(k)) {
  106 + categories_total_charge[k] += +d[k]
  107 + } else {
  108 + categories_total_charge[k] = 0
  109 + }
  110 + }
  111 + )
  112 + })
  113 +
  114 + // Now, filter only categories that have some charge
  115 + var categories = []
  116 + for (var key in categories_total_charge) {
  117 + if (categories_total_charge[key] > 0) {
  118 + categories.push(key)
  119 + }
  120 + }
  121 +
  122 + // This forme list is the color_scale domain.
  123 + // And that allows us to build the legend
  124 + color_scale.domain(categories)
  125 + addlegend(color_scale)
81 126  
  127 + // Build the stacked data for stacked bars
82 128 var stack = d3.stack()
83   - .keys(services)
  129 + .keys(categories)
84 130 // .order(d3.stackOrderNone)
85 131 // .offset(d3.stackOffsetNone);
86 132 var stacked_data = stack(data)
87 133  
  134 + // Xaxis
  135 + //
  136 + // x scale from the periods list
88 137 const x = d3.scaleBand()
89 138 .domain(periods)
90 139 .range([0, width])
91 140 .padding(0.2);
92 141  
  142 + const xAxis = d3.axisBottom(x)
  143 +
  144 + // Yaxis
  145 + //
93 146 // Get the max y to plot
94 147 y_max = d3.max(stacked_data[stacked_data.length - 1], d => d[1]);
95 148 if (y_max == 0) {
96 149 y_max = 100
97 150 }
98   - // Enhance it by 20% to leave room on the top of the graph
  151 + // Enhance it by 10% to leave room on the top of the graph
99 152 y_max = y_max * 1.1
100 153  
101 154 const y = d3.scaleLinear()
102 155 .range([height, 0])
103 156 .domain([0, y_max]);
104 157  
105   - // Sur l'axe horizontal, on filtre les dates afficher
106   - const xAxis = d3.axisBottom(x)
107   - // .tickValues(x.domain().filter(d => (d.includes("06/0") || d.includes("21/0"))));
108   -
109 158 const yAxis = d3.axisLeft(y)
  159 +
  160 + // Draw Xaxis
110 161 svg.append("g")
111 162 .attr("class", "x axis")
112 163 .attr("transform", "translate(0," + height + ")")
... ... @@ -117,17 +168,12 @@ function build_chart(div_selector, data_url, project_name, category) {
117 168 .attr("dy", ".15em")
118 169 .attr("transform", "rotate(-65)");
119 170  
  171 + // Draw Yaxis
120 172 svg.append("g")
121 173 .attr("class", "y axis")
122 174 .call(yAxis)
123   - // .append("text")
124   - // .attr("fill", "#000")
125   - // .attr("transform", "rotate(-90)")
126   - // .attr("y", 6)
127   - // .attr("dy", "0.91em")
128   - // .style("text-anchor", "end")
129   - // .text("rate");
130 175  
  176 + // Write Y axis title
131 177 svg.append("text")
132 178 .attr("text-anchor", "end")
133 179 .attr("transform", "rotate(-90)")
... ... @@ -135,14 +181,15 @@ function build_chart(div_selector, data_url, project_name, category) {
135 181 .attr("x", -margin.top - 70)
136 182 .text("Charge (% ETP)")
137 183  
  184 + // Write chart Title
  185 + // part 1
138 186 svg.append("text")
139 187 .attr("x", (width / 2))
140 188 .attr("y", 0 - (margin.top / 2) - 10)
141 189 .attr("text-anchor", "middle")
142 190 .style("font-size", "16px")
143 191 .text(project_name);
144   -
145   -
  192 + // part 2
146 193 svg.append("text")
147 194 .attr("x", (width / 2))
148 195 .attr("y", 0 - (margin.top / 2) + 10)
... ... @@ -150,11 +197,13 @@ function build_chart(div_selector, data_url, project_name, category) {
150 197 .style("font-size", "12px")
151 198 .text(chart_title);
152 199  
  200 + // Draw the stacked bars
  201 + //
153 202 let groups = svg.selectAll("g.category")
154 203 .data(stacked_data)
155 204 .enter()
156 205 .append("g")
157   - .style("fill", (d) => color(d.key));
  206 + .style("fill", (d) => color_scale(d.key));
158 207  
159 208 let rect = groups.selectAll("rect")
160 209 .data(d => d)
... ...