blob: f8a39854a42f821722b73b410fa3b55f1b49580a [file] [log] [blame]
Matteo Scandoloa5d03d52016-07-21 11:35:46 -07001/**
2 * © OpenCORD
3 *
4 * Visit http://guide.xosproject.org/devguide/addview/ for more information
5 *
6 * Created by teone on 3/24/16.
7 */
8
9(function () {
10 'use strict';
11
12 angular.module('xos.uiComponents')
13 /**
14 * @ngdoc directive
15 * @name xos.uiComponents.directive:xosSmartPie
16 * @restrict E
17 * @description The xos-table directive
18 * @param {Object} config The configuration for the component,
19 * it is composed by the name of an angular [$resource](https://docs.angularjs.org/api/ngResource/service/$resource)
20 * and a field name that is used to group the data.
21 * ```
22 * {
23 resource: 'Users',
24 groupBy: 'fieldName',
25 classes: 'my-custom-class',
26 labelFormatter: (labels) => {
27 // here you can format your label,
28 // you should return an array with the same order
29 return labels;
30 }
31 }
32 * ```
33 * @scope
34 * @example
35
36 Displaying Local data
37
38 <example module="sampleSmartPieLocal">
39 <file name="index.html">
40 <div ng-controller="SampleCtrlLocal as vm">
41 <xos-smart-pie config="vm.configLocal"></xos-smart-pie>
42 </div>
43 </file>
44 <file name="script.js">
45 angular.module('sampleSmartPieLocal', ['xos.uiComponents'])
46 .factory('_', function($window){
47 return $window._;
48 })
49 .controller('SampleCtrlLocal', function($timeout){
50
51 this.datas = [
52 {id: 1, first_name: 'Jon', last_name: 'aaa', category: 2},
53 {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 1},
54 {id: 3, first_name: 'Aria', last_name: 'Stark', category: 2}
55 ];
56
57 this.configLocal = {
58 data: [],
59 groupBy: 'category',
60 classes: 'local',
61 labelFormatter: (labels) => {
62 return labels.map(l => l === '1' ? 'North' : 'Dragon');
63 }
64 };
65
66 $timeout(() => {
67 // this need to be triggered in this way just because of ngDoc,
68 // otherwise you can assign data directly in the config
69 this.configLocal.data = this.datas;
70 }, 1)
71 });
72 </file>
73 </example>
74
75 Fetching data from API
76
77 <example module="sampleSmartPieResource">
78 <file name="index.html">
79 <div ng-controller="SampleCtrl as vm">
80 <xos-smart-pie config="vm.config"></xos-smart-pie>
81 </div>
82 </file>
83 <file name="script.js">
84 angular.module('sampleSmartPieResource', ['xos.uiComponents', 'ngResource', 'ngMockE2E'])
85 .controller('SampleCtrl', function(){
86 this.config = {
87 resource: 'SampleResource',
88 groupBy: 'category',
89 classes: 'resource',
90 labelFormatter: (labels) => {
91 return labels.map(l => l === '1' ? 'North' : 'Dragon');
92 }
93 };
94 });
95 </file>
96 <file name="backendPoll.js">
97 angular.module('sampleSmartPieResource')
98 .run(function($httpBackend, _){
99 let datas = [
100 {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
101 {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
102 {id: 3, first_name: 'Aria', last_name: 'Stark', category: 1}
103 ];
104
105 $httpBackend.whenGET('/test').respond(200, datas)
106 })
107 .factory('_', function($window){
108 return $window._;
109 })
110 .service('SampleResource', function($resource){
111 return $resource('/test/:id', {id: '@id'});
112 })
113 </file>
114 </example>
115
116 Polling data from API
117
118 <example module="sampleSmartPiePoll">
119 <file name="index.html">
120 <div ng-controller="SampleCtrl as vm">
121 <xos-smart-pie config="vm.config"></xos-smart-pie>
122 </div>
123 </file>
124 <file name="script.js">
125 angular.module('sampleSmartPiePoll', ['xos.uiComponents', 'ngResource', 'ngMockE2E'])
126 .controller('SampleCtrl', function(){
127 this.config = {
128 resource: 'SampleResource',
129 groupBy: 'category',
130 poll: 2,
131 labelFormatter: (labels) => {
132 return labels.map(l => l === '1' ? 'Active' : 'Banned');
133 }
134 };
135 });
136 </file>
137 <file name="backend.js">
138 angular.module('sampleSmartPiePoll')
139 .run(function($httpBackend, _){
140 let mock = [
141 [
142 {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
143 {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
144 {id: 3, first_name: 'Aria', last_name: 'Stark', category: 1},
145 {id: 3, first_name: 'Tyrion', last_name: 'Lannister', category: 1}
146 ],
147
148 [
149 {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
150 {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
151 {id: 3, first_name: 'Aria', last_name: 'Stark', category: 2},
152 {id: 3, first_name: 'Tyrion', last_name: 'Lannister', category: 2}
153 ],
154
155 [
156 {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
157 {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
158 {id: 3, first_name: 'Aria', last_name: 'Stark', category: 1},
159 {id: 3, first_name: 'Tyrion', last_name: 'Lannister', category: 2}
160 ]
161 ];
162 $httpBackend.whenGET('/test').respond(function(method, url, data, headers, params) {
163 return [200, mock[Math.round(Math.random() * 3)]];
164 });
165 })
166 .factory('_', function($window){
167 return $window._;
168 })
169 .service('SampleResource', function($resource){
170 return $resource('/test/:id', {id: '@id'});
171 })
172 </file>
173 </example>
174 */
175 .directive('xosSmartPie', function(){
176 return {
177 restrict: 'E',
178 scope: {
179 config: '='
180 },
181 template: `
182 <canvas
183 class="chart chart-pie {{vm.config.classes}}"
184 chart-data="vm.data" chart-labels="vm.labels"
185 chart-legend="{{vm.config.legend}}">
186 </canvas>
187 `,
188 bindToController: true,
189 controllerAs: 'vm',
190 controller: function($injector, $interval, $scope, $timeout, _){
191
192 if(!this.config.resource && !this.config.data){
193 throw new Error('[xosSmartPie] Please provide a resource or an array of data in the configuration');
194 }
195
196 const groupData = (data) => _.groupBy(data, this.config.groupBy);
197 const formatData = (data) => _.reduce(Object.keys(data), (list, group) => list.concat(data[group].length), []);
198 const formatLabels = (data) => angular.isFunction(this.config.labelFormatter) ? this.config.labelFormatter(Object.keys(data)) : Object.keys(data);
199
200 const prepareData = (data) => {
201 // group data
202 let grouped = groupData(data);
203 this.data = formatData(grouped);
204 // create labels
205 this.labels = formatLabels(grouped);
206 }
207
208 if(this.config.resource){
209
210 this.Resource = $injector.get(this.config.resource);
211 const getData = () => {
212 this.Resource.query().$promise
213 .then((res) => {
214
215 if(!res[0]){
216 return;
217 }
218
219 prepareData(res);
220 });
221 }
222
223 getData();
224
225 if(this.config.poll){
226 $interval(() => {getData()}, this.config.poll * 1000)
227 }
228 }
229 else {
230 $scope.$watch(() => this.config.data, (data) => {
231 if(data){
232 prepareData(this.config.data);
233 }
234 }, true);
235 }
236
237 $scope.$on('create', function (event, chart) {
238 console.log(`create: ${chart.id}`);
239 });
240
241 $scope.$on('destroy', function (event, chart) {
242 console.log(`destroy: ${chart.id}`);
243 });
244
245 }
246 };
247 });
248})();