Commit 22c5ff6001e904dc39ce49849db3ce677326a21f

Authored by hitier
1 parent 2cb0a345

New stacked_charge function used for agent display

app/db_mgr.py
... ... @@ -13,6 +13,21 @@ def agents():
13 13 return all_agents
14 14  
15 15  
  16 +def stacked_charges_by_agent(agent_id):
  17 + all_charges = {}
  18 + for (period_id, period_name) in db.session.execute("select id, name from period order by id"):
  19 + charge_by_project_req = """select p.name, c.charge_rate from project p left join
  20 + charge c on p.id = c.project_id and agent_id = {} and period_id={}
  21 + order by p.id""".format(agent_id, period_id)
  22 + period_charge = {}
  23 + for project_name, project_rate in db.session.execute(charge_by_project_req):
  24 + period_charge[project_name] = project_rate
  25 + all_charges[period_name]=period_charge
  26 +
  27 + pprint(all_charges)
  28 + return all_charges
  29 +
  30 +
16 31 def charges_by_agent(agent_id):
17 32 # all_charges = db.session.query(Charge).all()
18 33 periods = db.session.execute("select name from period")
... ...
app/main/routes.py
... ... @@ -94,11 +94,7 @@ def charge_add():
94 94 @bp.route('/charge/agent/<agent_id>')
95 95 @role_required('service')
96 96 def charge_agent(agent_id):
97   - agent_charges = []
98   - for [period, charge] in db_mgr.charges_by_agent(agent_id):
99   - agent_charges.append({"charge": charge, "periode": period})
100   - # agent_charges = [["charge", "periode"]]+db_mgr.charges_by_agent(agent_id)#agent_charges
101   - resp = make_response(json.dumps(agent_charges))
  97 + resp = make_response(json.dumps(db_mgr.stacked_charges_by_agent(agent_id)))
102 98 resp.headers['Content-Type'] = 'application/json'
103 99 return resp
104 100  
... ...
app/main/templates/agent.html
... ... @@ -67,57 +67,98 @@
67 67  
68 68 // On demande à D3JS de charger notre fichier
69 69 d3.json("{{url_for('main.charge_agent', agent_id=agent.id)}}").then(data => {
70   - // Conversion des caractères en nombres
71   - data.forEach(d => d.charge = +d.charge);
72   -
73   - // Mise en relation du scale avec les données de notre fichier
74   - // Pour l'axe X, c'est la liste des periodes
75   - // Pour l'axe Y, c'est le max des charge
76   - x.domain(data.map(d => d.periode));
77   - y.domain([0, 100]);
78   -
79   - // Ajout de l'axe X au SVG
80   - // Déplacement de l'axe horizontal et du futur texte (via la fonction translate) au bas du SVG
81   - // Selection des noeuds text, positionnement puis rotation
82   - svg.append("g")
83   - .attr("transform", "translate(0," + height + ")")
84   - .call(d3.axisBottom(x).tickSize(5))
85   - .selectAll("text")
86   - .style("text-anchor", "end")
87   - .attr("dx", "-.8em")
88   - .attr("dy", ".15em")
89   - .attr("transform", "rotate(-65)");
90   -
91   -
92   - svg.append("text")
93   - .attr("text-anchor", "end")
94   - .attr("transform", "rotate(-90)")
95   - .attr("y", -margin.left+60)
96   - .attr("x", -margin.top-70)
97   - .text("Charge (ETP)")
98   -
99   -
100   - // Ajout de l'axe Y au SVG avec 6 éléments de légende en utilisant la fonction ticks (sinon D3JS en place autant qu'il peut).
101   - svg.append("g")
102   - .call(d3.axisLeft(y).ticks(6));
103   -
104   - // Ajout des bars en utilisant les données de notre fichier data.tsv
105   - // La largeur de la barre est déterminée par la fonction x
106   - // La hauteur par la fonction y en tenant compte de la charge
107   - // La gestion des events de la souris pour le popup
108   - svg.selectAll(".bar")
109   - .data(data)
  70 +
  71 + // waiting for structure of the form:
  72 + //
  73 + var periods = Object.keys(data)
  74 + var first_stacked_charges = Object.values(data)[0]
  75 + var projects = Object.keys(first_stacked_charges)
  76 + console.log(projects)
  77 +
  78 + // periods = data
  79 + var x = d3.scaleBand()
  80 + .domain(periods)
  81 + .range([0, width])
  82 + .padding(0.2)
  83 +
  84 + svg.append('g')
  85 + .attr('transform', 'translate(20, ' + height + ')')
  86 + .call(d3.axisBottom(x).tickSizeOuter(0));
  87 +
  88 + var y = d3.scaleLinear()
  89 + .domain([0, 100])
  90 + .range([height, 0])
  91 +
  92 + svg.append('g')
  93 + .attr('transform', 'translate(20, 0)')
  94 + .call(d3.axisLeft(y))
  95 +
  96 + var color = d3.scaleOrdinal()
  97 + .domain(projects)
  98 + .range(['#e41a1c', '#377eb8', '#4daf4a',
  99 + "#800000",
  100 + "#FFFF00",
  101 + "#808000",
  102 + "#00FF00",
  103 + "#008000",
  104 + "#00FFFF",
  105 + "#008080",
  106 + "#0000FF",
  107 + "#000080",
  108 + "#FF00FF",
  109 + "#800080",
  110 + ]);
  111 +
  112 + var stack_generator = d3.stack()
  113 + .keys(projects)
  114 +
  115 + var stackable_data = []
  116 + Object.keys(data).forEach( function (period){
  117 + line = data[period];
  118 + line['period']=period;
  119 + stackable_data.push(line)
  120 + });
  121 +
  122 + var stacked_data = stack_generator(stackable_data)
  123 +
  124 + // var sel = d3.select("#demo2")
  125 + // .select('g')
  126 + // .selectAll('g.series')
  127 + // .data(stackedSeries)
  128 + // .join('g')
  129 + // .classed('series', true)
  130 + // .style('fill', (d) => colorScale(d.key));
  131 + //
  132 + // sel.selectAll('rect')
  133 + // .data((d) => d)
  134 + // .join('rect')
  135 + // .attr('width', 40)
  136 + // .attr('y', (d) => yScale(d[1]))
  137 + // .attr('x', (d) => xScale(d.data.month) - 20)
  138 + // .attr('height', (d) => yScale(d[0]) - yScale(d[1]));
  139 +
  140 + svg.append('g')
  141 + .selectAll('g')
  142 + .data(stacked_data)
  143 + .enter().append('g')
  144 + .attr("fill", function (d) {
  145 + return color(d.key);
  146 + })
  147 + .selectAll("rect")
  148 + // enter a second time = loop subgroup per subgroup to add all rectangles
  149 + .data(d => d)
110 150 .enter().append("rect")
111   - .attr("class", "bar")
112   - .attr("x", d => x(d.periode))
  151 + .attr("x", d => x(d.data.period) + 20)
  152 + .attr("y", d => y(d[1]))
  153 + .attr("height", d => y(d[0]) - y(d[1]))
113 154 .attr("width", x.bandwidth())
114   - .attr("y", d => y(d.charge))
115   - .attr("height", d => height - y(d.charge))
  155 +
116 156 .on("mouseover", function (e, d) {
  157 + console.log(d)
117 158 div.transition()
118 159 .duration(200)
119 160 .style("opacity", .9);
120   - div.html("Charge: " + d.charge)
  161 + div.html("Charge: " + d)
121 162 .style("left", (e.x + 10) + "px")
122 163 .style("top", (e.y - 50) + "px");
123 164 })
... ...