1 (function (angular
, $, _
) {
4 // FIXME: This code is long and hasn't been fully working for me, but I've moved it into a spot
5 // where it at least fits in a bit better.
7 // example: <div crm-mailing-ab-stats="{split_count: 6, criteria:'Open'}" crm-abtest="myabtest" />
8 // options (see also: Mailing.graph_stats API)
11 // - target_date: string, date
12 // - target_url: string
13 angular
.module('crmMailingAB').directive('crmMailingAbStats', function (crmApi
, $parse
) {
16 crmMailingAbStats
: '@',
19 template
: '<div class="crm-mailing-ab-stats"></div>',
20 link: function (scope
, element
, attrs
) {
21 var abtestModel
= $parse(attrs
.crmAbtest
);
22 var optionModel
= $parse(attrs
.crmMailingAbStats
);
23 var options
= angular
.extend({}, optionModel(scope
.$parent
), {
24 criteria
: 'Open', // e.g. 'Open', 'Total Unique Clicks'
28 scope
.$watch(attrs
.crmAbtest
, refresh
);
30 var abtest
= abtestModel(scope
.$parent
);
32 console
.log('failed to draw stats - missing abtest');
45 for (var i
= 1; i
<= options
.split_count
; i
++) {
46 var result
= crmApi('MailingAB', 'graph_stats', {
48 target_date
: abtest
.ab
.declare_winning_time
? abtest
.ab
.declare_winning_time
: 'now',
49 target_url
: null, // FIXME
50 criteria
: options
.criteria
,
51 split_count
: options
.split_count
,
55 result
.then(function (data
) {
58 for (var key
in data
.values
.A
) {
61 var t
= data
.values
.A
[temp
].time
.split(" ");
64 var day
= t
[1].substr(0, t
[1].length
- 3);
65 var t1
, hur
, hour
, min
;
66 if (_
.isEmpty(t
[3])) {
76 hour
= parseInt(hur
) + 12;
90 hour
= parseInt(hur
) + 12;
134 var tp
= new Date(year
, month
, day
, hour
, min
, 0, 0);
135 scope
.graph_data
[temp
- 1] = {
137 x
: data
.values
.A
[temp
].count
,
138 y
: data
.values
.B
[temp
].count
141 if (keep_cnt
== options
.split_count
) {
142 scope
.graphload
= true;
143 data
= scope
.graph_data
;
145 // set up a colour variable
146 var color
= d3
.scale
.category10();
148 // map one colour each to x, y and z
149 // keys grabs the key value or heading of each key value pair in the json
151 color
.domain(d3
.keys(data
[0]).filter(function (key
) {
152 return key
!== "time";
155 // create a nested series for passing to the line generator
156 // it's best understood by console logging the data
157 var series
= color
.domain().map(function (name
) {
160 values
: data
.map(function (d
) {
169 // Set the dimensions of the canvas / graph
176 width
= 550 - margin
.left
- margin
.right
,
177 height
= 350 - margin
.top
- margin
.bottom
;
180 //var x = d3.time.scale().range([0, width]).domain([0,10]);
181 var x
= d3
.time
.scale().range([0, width
]);
182 var y
= d3
.scale
.linear().range([height
, 0]);
185 var xAxis
= d3
.svg
.axis().scale(x
)
186 .orient("bottom").ticks(10);
188 var yAxis
= d3
.svg
.axis().scale(y
)
189 .orient("left").ticks(5);
192 // Note you plot the time / score pair from each key you created earlier
193 var valueline
= d3
.svg
.line()
201 // Adds the svg canvas
202 var svg
= d3
.select($('.crm-mailing-ab-stats', element
)[0])
204 .attr("width", width
+ margin
.left
+ margin
.right
)
205 .attr("height", height
+ margin
.top
+ margin
.bottom
)
207 .attr("transform", "translate(" + margin
.left
+ "," + margin
.top
+ ")");
209 // Scale the range of the data
210 x
.domain(d3
.extent(data
, function (d
) {
214 // note the nested nature of this you need to dig an additional level
216 d3
.min(series
, function (c
) {
217 return d3
.min(c
.values
, function (v
) {
221 d3
.max(series
, function (c
) {
222 return d3
.max(c
.values
, function (v
) {
227 svg
.append("text") // text label for the x axis
228 .attr("x", width
/ 2)
229 .attr("y", height
+ margin
.bottom
)
230 .style("text-anchor", "middle")
233 svg
.append("text") // text label for the x axis
234 .style("text-anchor", "middle")
235 .text(scope
.winnercriteria
).attr("transform",function (d
) {
236 return "rotate(-90)";
237 }).attr("x", -height
/ 2)
240 // create a variable called series and bind the date
241 // for each series append a g element and class it as series for css styling
242 series
= svg
.selectAll(".series")
245 .attr("class", "series");
247 // create the path for each series in the variable series i.e. x, y and z
248 // pass each object called x, y nad z to the lne generator
249 series
.append("path")
250 .attr("class", "line")
251 .attr("d", function (d
) {
252 // console.log(d); // to see how d3 iterates through series
253 return valueline(d
.values
);
255 .style("stroke", function (d
) {
256 return color(d
.name
);
260 svg
.append("g") // Add the X Axis
261 .attr("class", "x axis")
262 .attr("transform", "translate(0," + height
+ ")")
265 .attr("transform", function (d
) {
266 return "rotate(-30)";
270 svg
.append("g") // Add the Y Axis
271 .attr("class", "y axis")
280 })(angular
, CRM
.$, CRM
._
);