blob: 23929301e9e96af48ff306f2c6bd5c4689b58f42 [file] [log] [blame]
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001'use strict';
2
3/**
4 * © OpenCORD
5 *
6 * Visit http://guide.xosproject.org/devguide/addview/ for more information
7 *
8 * Created by teone on 3/24/16.
9 */
10
11(function () {
12 'use strict';
13
14 /**
15 * @ngdoc overview
16 * @name xos.uiComponents
17 * @description
18 * # xos.uiComponents
19 * A collection of UI components useful for Dashboard development. <br/>
20 * Currently available components are:
21 * - [xosAlert](/#/module/xos.uiComponents.directive:xosAlert)
22 * - [xosForm](/#/module/xos.uiComponents.directive:xosForm)
23 * - [xosPagination](/#/module/xos.uiComponents.directive:xosPagination)
24 * - [xosSmartTable](/#/module/xos.uiComponents.directive:xosSmartTable)
25 * - [xosTable](/#/module/xos.uiComponents.directive:xosTable)
26 * - [xosValidation](/#/module/xos.uiComponents.directive:xosValidation)
27 **/
28
Matteo Scandolo65116c42016-09-21 17:06:23 -070029 angular.module('xos.uiComponents', ['chart.js', 'RecursionHelper', 'dndLists']);
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -070030})();
Matteo Scandolo1d689852016-09-29 09:42:12 -070031'use strict';
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -070032
Matteo Scandolo1d689852016-09-29 09:42:12 -070033/**
34 * © OpenCORD
35 *
36 * Visit http://guide.xosproject.org/devguide/addview/ for more information
37 *
38 * Created by teone on 3/24/16.
39 */
40
41(function () {
42 'use strict';
43
44 angular.module('xos.uiComponents')
45
46 /**
47 * @ngdoc directive
48 * @name xos.uiComponents.directive:xosSmartTable
49 * @link xos.uiComponents.directive:xosTable xosTable
50 * @link xos.uiComponents.directive:xosForm xosForm
51 * @restrict E
52 * @description The xos-table directive
53 * @param {Object} config The configuration for the component,
54 * it is composed by the name of an angular [$resource](https://docs.angularjs.org/api/ngResource/service/$resource)
55 * and an array of fields that shouldn't be printed.
56 * ```
57 * {
58 resource: 'Users',
59 hiddenFields: []
60 }
61 * ```
62 * @scope
63 * @example
64 <example module="sampleSmartTable">
65 <file name="index.html">
66 <div ng-controller="SampleCtrl as vm">
67 <xos-smart-table config="vm.config"></xos-smart-table>
68 </div>
69 </file>
70 <file name="script.js">
71 angular.module('sampleSmartTable', ['xos.uiComponents', 'ngResource', 'ngMockE2E'])
72 // This is only for documentation purpose
73 .run(function($httpBackend, _){
74 let datas = [{id: 1, name: 'Jhon', surname: 'Doe'}];
75 let count = 1;
76 let paramsUrl = new RegExp(/\/test\/(.+)/);
77 $httpBackend.whenDELETE(paramsUrl, undefined, ['id']).respond((method, url, data, headers, params) => {
78 data = angular.fromJson(data);
79 let id = url.match(paramsUrl)[1];
80 _.remove(datas, (d) => {
81 return d.id === parseInt(id);
82 })
83 return [204];
84 });
85 $httpBackend.whenGET('/test').respond(200, datas)
86 $httpBackend.whenPOST('/test').respond((method, url, data) => {
87 data = angular.fromJson(data);
88 data.id = ++count;
89 datas.push(data);
90 return [201, data, {}];
91 });
92 })
93 .factory('_', function($window){
94 return $window._;
95 })
96 .service('SampleResource', function($resource){
97 return $resource('/test/:id', {id: '@id'});
98 })
99 // End of documentation purpose, example start
100 .controller('SampleCtrl', function(){
101 this.config = {
102 resource: 'SampleResource'
103 };
104 });
105 </file>
106 </example>
107 */
108
109 .component('xosSmartTable', {
110 restrict: 'E',
111 bindings: {
112 config: '='
113 },
114 template: '\n <div class="row" ng-show="vm.data.length > 0">\n <div class="col-xs-12 text-right">\n <a href="" class="btn btn-success" ng-click="vm.createItem()">\n Add\n </a>\n </div>\n </div>\n <div class="row">\n <div class="col-xs-12 table-responsive">\n <xos-table config="vm.tableConfig" data="vm.data"></xos-table>\n </div>\n </div>\n <div class="panel panel-default" ng-show="vm.detailedItem">\n <div class="panel-heading">\n <div class="row">\n <div class="col-xs-11">\n <h3 class="panel-title" ng-show="vm.detailedItem.id">Update {{vm.config.resource}} {{vm.detailedItem.id}}</h3>\n <h3 class="panel-title" ng-show="!vm.detailedItem.id">Create {{vm.config.resource}} item</h3>\n </div>\n <div class="col-xs-1">\n <a href="" ng-click="vm.cleanForm()">\n <i class="glyphicon glyphicon-remove pull-right"></i>\n </a>\n </div>\n </div>\n </div>\n <div class="panel-body">\n <xos-form config="vm.formConfig" ng-model="vm.detailedItem"></xos-form>\n </div>\n </div>\n <xos-alert config="{type: \'success\', closeBtn: true}" show="vm.responseMsg">{{vm.responseMsg}}</xos-alert>\n <xos-alert config="{type: \'danger\', closeBtn: true}" show="vm.responseErr">{{vm.responseErr}}</xos-alert>\n ',
115 bindToController: true,
116 controllerAs: 'vm',
117 controller: ["$injector", "LabelFormatter", "_", "XosFormHelpers", function controller($injector, LabelFormatter, _, XosFormHelpers) {
118 var _this = this;
119
120 // TODO
121 // - Validate the config (what if resource does not exist?)
122
123 // NOTE
124 // Corner case
125 // - if response is empty, how can we generate a form ?
126
127 this.responseMsg = false;
128 this.responseErr = false;
129
130 this.tableConfig = {
131 columns: [],
132 actions: [{
133 label: 'delete',
134 icon: 'remove',
135 cb: function cb(item) {
136 _this.Resource.delete({ id: item.id }).$promise.then(function () {
137 _.remove(_this.data, function (d) {
138 return d.id === item.id;
139 });
140 _this.responseMsg = _this.config.resource + ' with id ' + item.id + ' successfully deleted';
141 }).catch(function (err) {
142 _this.responseErr = err.data.detail || 'Error while deleting ' + _this.config.resource + ' with id ' + item.id;
143 });
144 },
145 color: 'red'
146 }, {
147 label: 'details',
148 icon: 'search',
149 cb: function cb(item) {
150 _this.detailedItem = item;
151 }
152 }],
153 classes: 'table table-striped table-bordered table-responsive',
154 filter: 'field',
155 order: true,
156 pagination: {
157 pageSize: 10
158 }
159 };
160
161 this.formConfig = {
162 exclude: this.config.hiddenFields,
163 fields: {},
164 formName: this.config.resource + 'Form',
165 actions: [{
166 label: 'Save',
167 icon: 'ok',
168 cb: function cb(item) {
169 var p = void 0;
170 var isNew = true;
171
172 if (item.id) {
173 p = item.$update();
174 isNew = false;
175 } else {
176 p = item.$save();
177 }
178
179 p.then(function (res) {
180 if (isNew) {
181 _this.data.push(angular.copy(res));
182 }
183 delete _this.detailedItem;
184 _this.responseMsg = _this.config.resource + ' with id ' + item.id + ' successfully saved';
185 }).catch(function (err) {
186 _this.responseErr = err.data.detail || 'Error while saving ' + _this.config.resource + ' with id ' + item.id;
187 });
188 },
189 class: 'success'
190 }]
191 };
192
193 this.cleanForm = function () {
194 delete _this.detailedItem;
195 };
196
197 this.createItem = function () {
198 _this.detailedItem = new _this.Resource();
199 };
200
201 this.Resource = $injector.get(this.config.resource);
202
203 var getData = function getData() {
204 _this.Resource.query().$promise.then(function (res) {
205
206 if (!res[0]) {
207 _this.data = res;
208 return;
209 }
210
211 var item = res[0];
212 var props = Object.keys(item);
213
214 _.remove(props, function (p) {
215 return p === 'id' || p === 'validators';
216 });
217
218 // TODO move out cb, non sense triggering a lot of times
219 if (angular.isArray(_this.config.hiddenFields)) {
220 props = _.difference(props, _this.config.hiddenFields);
221 }
222
223 props.forEach(function (p) {
224 var fieldConfig = {
225 label: LabelFormatter.format(p),
226 prop: p
227 };
228
229 fieldConfig.type = XosFormHelpers._getFieldFormat(item[p]);
230
231 _this.tableConfig.columns.push(fieldConfig);
232 });
233
234 // build form structure
235 // TODO move in a pure function for testing purposes
Steven Burrows84818482016-09-29 15:33:46 -0700236 props.forEach(function (p) {
Matteo Scandolo1d689852016-09-29 09:42:12 -0700237 _this.formConfig.fields[p] = {
238 label: LabelFormatter.format(p).replace(':', ''),
239 type: XosFormHelpers._getFieldFormat(item[p])
240 };
241 });
242 _this.data = res;
243 });
244 };
245
246 getData();
247 }]
248 });
249})();
250'use strict';
251
252/**
253 * © OpenCORD
254 *
255 * Visit http://guide.xosproject.org/devguide/addview/ for more information
256 *
257 * Created by teone on 3/24/16.
258 */
259
260(function () {
261 'use strict';
262
263 angular.module('xos.uiComponents')
264 /**
265 * @ngdoc directive
266 * @name xos.uiComponents.directive:xosSmartPie
267 * @restrict E
268 * @description The xos-table directive
269 * @param {Object} config The configuration for the component,
270 * it is composed by the name of an angular [$resource](https://docs.angularjs.org/api/ngResource/service/$resource)
271 * and a field name that is used to group the data.
272 * ```
273 * {
274 resource: 'Users',
275 groupBy: 'fieldName',
276 classes: 'my-custom-class',
277 labelFormatter: (labels) => {
278 // here you can format your label,
279 // you should return an array with the same order
280 return labels;
281 }
282 }
283 * ```
284 * @scope
285 * @example
286
287 Displaying Local data
288 <example module="sampleSmartPieLocal">
289 <file name="index.html">
290 <div ng-controller="SampleCtrlLocal as vm">
291 <xos-smart-pie config="vm.configLocal"></xos-smart-pie>
292 </div>
293 </file>
294 <file name="script.js">
295 angular.module('sampleSmartPieLocal', ['xos.uiComponents'])
296 .factory('_', function($window){
297 return $window._;
298 })
299 .controller('SampleCtrlLocal', function($timeout){
300
301 this.datas = [
302 {id: 1, first_name: 'Jon', last_name: 'aaa', category: 2},
303 {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 1},
304 {id: 3, first_name: 'Aria', last_name: 'Stark', category: 2}
305 ];
306 this.configLocal = {
307 data: [],
308 groupBy: 'category',
309 classes: 'local',
310 labelFormatter: (labels) => {
311 return labels.map(l => l === '1' ? 'North' : 'Dragon');
312 }
313 };
314
315 $timeout(() => {
316 // this need to be triggered in this way just because of ngDoc,
317 // otherwise you can assign data directly in the config
318 this.configLocal.data = this.datas;
319 }, 1)
320 });
321 </file>
322 </example>
323 Fetching data from API
324 <example module="sampleSmartPieResource">
325 <file name="index.html">
326 <div ng-controller="SampleCtrl as vm">
327 <xos-smart-pie config="vm.config"></xos-smart-pie>
328 </div>
329 </file>
330 <file name="script.js">
331 angular.module('sampleSmartPieResource', ['xos.uiComponents', 'ngResource', 'ngMockE2E'])
332 .controller('SampleCtrl', function(){
333 this.config = {
334 resource: 'SampleResource',
335 groupBy: 'category',
336 classes: 'resource',
337 labelFormatter: (labels) => {
338 return labels.map(l => l === '1' ? 'North' : 'Dragon');
339 }
340 };
341 });
342 </file>
343 <file name="backendPoll.js">
344 angular.module('sampleSmartPieResource')
345 .run(function($httpBackend, _){
346 let datas = [
347 {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
348 {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
349 {id: 3, first_name: 'Aria', last_name: 'Stark', category: 1}
350 ];
351 $httpBackend.whenGET('/test').respond(200, datas)
352 })
353 .factory('_', function($window){
354 return $window._;
355 })
356 .service('SampleResource', function($resource){
357 return $resource('/test/:id', {id: '@id'});
358 })
359 </file>
360 </example>
361 Polling data from API
362 <example module="sampleSmartPiePoll">
363 <file name="index.html">
364 <div ng-controller="SampleCtrl as vm">
365 <xos-smart-pie config="vm.config"></xos-smart-pie>
366 </div>
367 </file>
368 <file name="script.js">
369 angular.module('sampleSmartPiePoll', ['xos.uiComponents', 'ngResource', 'ngMockE2E'])
370 .controller('SampleCtrl', function(){
371 this.config = {
372 resource: 'SampleResource',
373 groupBy: 'category',
374 poll: 2,
375 labelFormatter: (labels) => {
376 return labels.map(l => l === '1' ? 'Active' : 'Banned');
377 }
378 };
379 });
380 </file>
381 <file name="backend.js">
382 angular.module('sampleSmartPiePoll')
383 .run(function($httpBackend, _){
384 let mock = [
385 [
386 {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
387 {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
388 {id: 3, first_name: 'Aria', last_name: 'Stark', category: 1},
389 {id: 3, first_name: 'Tyrion', last_name: 'Lannister', category: 1}
390 ],
391 [
392 {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
393 {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
394 {id: 3, first_name: 'Aria', last_name: 'Stark', category: 2},
395 {id: 3, first_name: 'Tyrion', last_name: 'Lannister', category: 2}
396 ],
397 [
398 {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
399 {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
400 {id: 3, first_name: 'Aria', last_name: 'Stark', category: 1},
401 {id: 3, first_name: 'Tyrion', last_name: 'Lannister', category: 2}
402 ]
403 ];
404 $httpBackend.whenGET('/test').respond(function(method, url, data, headers, params) {
405 return [200, mock[Math.round(Math.random() * 3)]];
406 });
407 })
408 .factory('_', function($window){
409 return $window._;
410 })
411 .service('SampleResource', function($resource){
412 return $resource('/test/:id', {id: '@id'});
413 })
414 </file>
415 </example>
416 */
417 .component('xosSmartPie', {
418 restrict: 'E',
419 bindings: {
420 config: '='
421 },
422 template: '\n <canvas\n class="chart chart-pie {{vm.config.classes}}"\n chart-data="vm.data" chart-labels="vm.labels"\n chart-legend="{{vm.config.legend}}">\n </canvas>\n ',
423 bindToController: true,
424 controllerAs: 'vm',
425 controller: ["$injector", "$interval", "$scope", "$timeout", "_", function controller($injector, $interval, $scope, $timeout, _) {
426 var _this = this;
427
428 if (!this.config.resource && !this.config.data) {
429 throw new Error('[xosSmartPie] Please provide a resource or an array of data in the configuration');
430 }
431
432 var groupData = function groupData(data) {
433 return _.groupBy(data, _this.config.groupBy);
434 };
435 var formatData = function formatData(data) {
436 return _.reduce(Object.keys(data), function (list, group) {
437 return list.concat(data[group].length);
438 }, []);
439 };
440 var formatLabels = function formatLabels(data) {
441 return angular.isFunction(_this.config.labelFormatter) ? _this.config.labelFormatter(Object.keys(data)) : Object.keys(data);
442 };
443
444 var prepareData = function prepareData(data) {
445 // group data
446 var grouped = groupData(data);
447 _this.data = formatData(grouped);
448 // create labels
449 _this.labels = formatLabels(grouped);
450 };
451
452 if (this.config.resource) {
453 (function () {
454
455 _this.Resource = $injector.get(_this.config.resource);
456 var getData = function getData() {
457 _this.Resource.query().$promise.then(function (res) {
458
459 if (!res[0]) {
460 return;
461 }
462
463 prepareData(res);
464 });
465 };
466
467 getData();
468
469 if (_this.config.poll) {
470 $interval(function () {
471 getData();
472 }, _this.config.poll * 1000);
473 }
474 })();
475 } else {
476 $scope.$watch(function () {
477 return _this.config.data;
478 }, function (data) {
479 if (data) {
480 prepareData(_this.config.data);
481 }
482 }, true);
483 }
484
485 $scope.$on('create', function (event, chart) {
486 console.log('create: ' + chart.id);
487 });
488
489 $scope.$on('destroy', function (event, chart) {
490 console.log('destroy: ' + chart.id);
491 });
492 }]
493 });
494})();
Matteo Scandoloe57712f2016-09-21 15:27:36 -0700495'use strict';
Arpit Agarwal34b63832016-08-08 11:59:45 -0700496
497/**
498 * © OpenCORD
499 *
500 * Visit http://guide.xosproject.org/devguide/addview/ for more information
501 *
Arpit Agarwal43978742016-08-09 15:38:25 -0700502 * Created by teone on 4/15/16.
Arpit Agarwal34b63832016-08-08 11:59:45 -0700503 */
504
505(function () {
506 'use strict';
507
508 angular.module('xos.uiComponents')
509
510 /**
Arpit Agarwal43978742016-08-09 15:38:25 -0700511 * @ngdoc directive
512 * @name xos.uiComponents.directive:xosValidation
513 * @restrict E
514 * @description The xos-validation directive
515 * @param {Object} errors The error object
516 * @element ANY
517 * @scope
Arpit Agarwal34b63832016-08-08 11:59:45 -0700518 * @example
Arpit Agarwal43978742016-08-09 15:38:25 -0700519 <example module="sampleValidation">
Arpit Agarwal34b63832016-08-08 11:59:45 -0700520 <file name="index.html">
521 <div ng-controller="SampleCtrl as vm">
Arpit Agarwal43978742016-08-09 15:38:25 -0700522 <div class="row">
523 <div class="col-xs-12">
524 <label>Set an error type:</label>
525 </div>
526 <div class="col-xs-2">
527 <a class="btn"
528 ng-click="vm.field.$error.required = !vm.field.$error.required"
529 ng-class="{'btn-default': !vm.field.$error.required, 'btn-success': vm.field.$error.required}">
530 Required
531 </a>
532 </div>
533 <div class="col-xs-2">
534 <a class="btn"
535 ng-click="vm.field.$error.email = !vm.field.$error.email"
536 ng-class="{'btn-default': !vm.field.$error.email, 'btn-success': vm.field.$error.email}">
537 Email
538 </a>
539 </div>
540 <div class="col-xs-2">
541 <a class="btn"
542 ng-click="vm.field.$error.minlength = !vm.field.$error.minlength"
543 ng-class="{'btn-default': !vm.field.$error.minlength, 'btn-success': vm.field.$error.minlength}">
544 Min Length
545 </a>
546 </div>
547 <div class="col-xs-2">
548 <a class="btn"
549 ng-click="vm.field.$error.maxlength = !vm.field.$error.maxlength"
550 ng-class="{'btn-default': !vm.field.$error.maxlength, 'btn-success': vm.field.$error.maxlength}">
551 Max Length
552 </a>
553 </div>
554 </div>
555 <xos-validation field ="vm.field" form = "vm.form"></xos-validation>
Arpit Agarwal34b63832016-08-08 11:59:45 -0700556 </div>
557 </file>
558 <file name="script.js">
Arpit Agarwal43978742016-08-09 15:38:25 -0700559 angular.module('sampleValidation', ['xos.uiComponents'])
Arpit Agarwal34b63832016-08-08 11:59:45 -0700560 .controller('SampleCtrl', function(){
Arpit Agarwal43978742016-08-09 15:38:25 -0700561 this.field = {
562 $error: {}
Arpit Agarwal34b63832016-08-08 11:59:45 -0700563 };
Arpit Agarwal43978742016-08-09 15:38:25 -0700564 this.form= {
565 $submitted:true
566 }
Arpit Agarwal34b63832016-08-08 11:59:45 -0700567 });
568 </file>
569 </example>
Arpit Agarwal43978742016-08-09 15:38:25 -0700570 */
Arpit Agarwal34b63832016-08-08 11:59:45 -0700571
Arpit Agarwal43978742016-08-09 15:38:25 -0700572 .component('xosValidation', {
Arpit Agarwal34b63832016-08-08 11:59:45 -0700573 restrict: 'E',
574 bindings: {
Arpit Agarwal43978742016-08-09 15:38:25 -0700575 field: '=',
576 form: '='
Arpit Agarwal34b63832016-08-08 11:59:45 -0700577 },
Arpit Agarwal43978742016-08-09 15:38:25 -0700578 template: '\n <div ng-cloak>\n <xos-alert config="vm.config" show="vm.field.$error.required !== undefined && vm.field.$error.required !== false && (vm.field.$touched || vm.form.$submitted)">\n Field required\n </xos-alert>\n <xos-alert config="vm.config" show="vm.field.$error.email !== undefined && vm.field.$error.email !== false && (vm.field.$touched || vm.form.$submitted)">\n This is not a valid email\n </xos-alert>\n <xos-alert config="vm.config" show="vm.field.$error.minlength !== undefined && vm.field.$error.minlength !== false && (vm.field.$touched || vm.form.$submitted)">\n Too short\n </xos-alert>\n <xos-alert config="vm.config" show="vm.field.$error.maxlength !== undefined && vm.field.$error.maxlength !== false && (vm.field.$touched || vm.form.$submitted)">\n Too long\n </xos-alert>\n <xos-alert config="vm.config" show="vm.field.$error.custom !== undefined && vm.field.$error.custom !== false && (vm.field.$touched || vm.form.$submitted)">\n Field invalid\n </xos-alert>\n </div>\n ',
579 transclude: true,
Arpit Agarwal34b63832016-08-08 11:59:45 -0700580 bindToController: true,
581 controllerAs: 'vm',
Arpit Agarwal43978742016-08-09 15:38:25 -0700582 controller: function controller() {
583 this.config = {
584 type: 'danger'
585 };
586 }
587 });
588})();
Arpit Agarwal34b63832016-08-08 11:59:45 -0700589'use strict';
590
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -0700591/**
592 * © OpenCORD
593 *
594 * Visit http://guide.xosproject.org/devguide/addview/ for more information
595 *
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -0700596 * Created by teone on 3/24/16.
597 */
598
599(function () {
600 'use strict';
601
602 angular.module('xos.uiComponents')
603
604 /**
605 * @ngdoc directive
606 * @name xos.uiComponents.directive:xosTable
607 * @restrict E
608 * @description The xos-table directive
609 * @param {Object} config The configuration for the component.
610 * ```
611 * {
612 * columns: [
613 * {
614 * label: 'Human readable name',
615 * prop: 'Property to read in the model object',
616 * type: 'boolean'| 'array'| 'object'| 'custom'| 'date' | 'icon' // see examples for more details
617 formatter: fn(), // receive the whole item if tipe is custom and return a string
618 link: fn() // receive the whole item and return an url
619 * }
620 * ],
621 * classes: 'table table-striped table-bordered',
622 * actions: [ // if defined add an action column
623 {
624 label: 'delete',
625 icon: 'remove', // refers to bootstraps glyphicon
626 cb: (user) => { // receive the model
627 console.log(user);
628 },
629 color: 'red'
630 }
631 ],
632 filter: 'field', // can be by `field` or `fulltext`
633 order: true | {field: 'property name', reverse: true | false} // whether to show ordering arrows, or a configuration for a default ordering
634 * }
635 * ```
636 * @param {Array} data The data that should be rendered
637 * @element ANY
638 * @scope
639 * @example
640 # Basic usage
641 <example module="sampleTable1">
642 <file name="index.html">
643 <div ng-controller="SampleCtrl1 as vm">
644 <xos-table data="vm.data" config="vm.config"></xos-table>
645 </div>
646 </file>
647 <file name="script.js">
648 angular.module('sampleTable1', ['xos.uiComponents'])
649 .factory('_', function($window){
650 return $window._;
651 })
652 .controller('SampleCtrl1', function(){
653 this.config = {
654 columns: [
655 {
656 label: 'First Name', // column title
657 prop: 'name' // property to read in the data array
658 },
659 {
660 label: 'Last Name',
661 prop: 'lastname'
662 }
663 ]
664 };
665 this.data = [
666 {
667 name: 'John',
668 lastname: 'Doe'
669 },
670 {
671 name: 'Gili',
672 lastname: 'Fereydoun'
673 }
674 ]
675 });
676 </file>
677 </example>
678 # Filtering
679 <example module="sampleTable2" animations="true">
680 <file name="index.html">
681 <div ng-controller="SampleCtrl2 as vm">
682 <xos-table data="vm.data" config="vm.config"></xos-table>
683 </div>
684 </file>
685 <file name="script.js">
686 angular.module('sampleTable2', ['xos.uiComponents', 'ngAnimate'])
687 .factory('_', function($window){
688 return $window._;
689 })
690 .controller('SampleCtrl2', function(){
691 this.config = {
692 columns: [
693 {
694 label: 'First Name', // column title
695 prop: 'name' // property to read in the data array
696 },
697 {
698 label: 'Last Name',
699 prop: 'lastname'
700 }
701 ],
702 classes: 'table table-striped table-condensed', // table classes, default to `table table-striped table-bordered`
703 actions: [ // if defined add an action column
704 {
705 label: 'delete', // label
706 icon: 'remove', // icons, refers to bootstraps glyphicon
707 cb: (user) => { // callback, get feeded with the full object
708 console.log(user);
709 },
710 color: 'red' // icon color
711 }
712 ],
713 filter: 'field', // can be by `field` or `fulltext`
714 order: true
715 };
716 this.data = [
717 {
718 name: 'John',
719 lastname: 'Doe'
720 },
721 {
722 name: 'Gili',
723 lastname: 'Fereydoun'
724 }
725 ]
726 });
727 </file>
728 </example>
729 # Pagination
730 <example module="sampleTable3">
731 <file name="index.html">
732 <div ng-controller="SampleCtrl3 as vm">
733 <xos-table data="vm.data" config="vm.config"></xos-table>
734 </div>
735 </file>
736 <file name="script.js">
737 angular.module('sampleTable3', ['xos.uiComponents'])
738 .factory('_', function($window){
739 return $window._;
740 })
741 .controller('SampleCtrl3', function(){
742 this.config = {
743 columns: [
744 {
745 label: 'First Name', // column title
746 prop: 'name' // property to read in the data array
747 },
748 {
749 label: 'Last Name',
750 prop: 'lastname'
751 }
752 ],
753 pagination: {
754 pageSize: 2
755 }
756 };
757 this.data = [
758 {
759 name: 'John',
760 lastname: 'Doe'
761 },
762 {
763 name: 'Gili',
764 lastname: 'Fereydoun'
765 },
766 {
767 name: 'Lucky',
768 lastname: 'Clarkson'
769 },
770 {
771 name: 'Tate',
772 lastname: 'Spalding'
773 }
774 ]
775 });
776 </file>
777 </example>
778 # Field formatter
779 <example module="sampleTable4">
780 <file name="index.html">
781 <div ng-controller="SampleCtrl as vm">
782 <xos-table data="vm.data" config="vm.config"></xos-table>
783 </div>
784 </file>
785 <file name="script.js">
786 angular.module('sampleTable4', ['xos.uiComponents'])
787 .factory('_', function($window){
788 return $window._;
789 })
790 .controller('SampleCtrl', function(){
791 this.config = {
792 columns: [
793 {
794 label: 'First Name',
795 prop: 'name',
796 link: item => `https://www.google.it/#q=${item.name}`
797 },
798 {
799 label: 'Enabled',
800 prop: 'enabled',
801 type: 'boolean'
802 },
803 {
804 label: 'Services',
805 prop: 'services',
806 type: 'array'
807 },
808 {
809 label: 'Details',
810 prop: 'details',
811 type: 'object'
812 },
813 {
814 label: 'Created',
815 prop: 'created',
816 type: 'date'
817 },
818 {
819 label: 'Icon',
820 type: 'icon',
821 formatter: item => item.icon //note that this refer to [Bootstrap Glyphicon](http://getbootstrap.com/components/#glyphicons)
822 }
823 ]
824 };
825 this.data = [
826 {
827 name: 'John',
828 enabled: true,
829 services: ['Cdn', 'IpTv'],
830 details: {
831 c_tag: '243',
832 s_tag: '444'
833 },
834 created: new Date('December 17, 1995 03:24:00'),
835 icon: 'music'
836 },
837 {
838 name: 'Gili',
839 enabled: false,
840 services: ['Cdn', 'IpTv', 'Cache'],
841 details: {
842 c_tag: '675',
843 s_tag: '893'
844 },
845 created: new Date(),
846 icon: 'camera'
847 }
848 ]
849 });
850 </file>
851 </example>
852 # Custom formatter
853 <example module="sampleTable5">
854 <file name="index.html">
855 <div ng-controller="SampleCtrl as vm">
856 <xos-table data="vm.data" config="vm.config"></xos-table>
857 </div>
858 </file>
859 <file name="script.js">
860 angular.module('sampleTable5', ['xos.uiComponents'])
861 .factory('_', function($window){
862 return $window._;
863 })
864 .controller('SampleCtrl', function(){
865 this.config = {
866 columns: [
867 {
868 label: 'Username',
869 prop: 'username'
870 },
871 {
872 label: 'Features',
873 type: 'custom',
874 formatter: (val) => {
875
876 let cdnEnabled = val.features.cdn ? 'enabled' : 'disabled';
877 return `
878 Cdn is ${cdnEnabled},
879 uplink speed is ${val.features.uplink_speed}
880 and downlink speed is ${val.features.downlink_speed}
881 `;
882 }
883 }
884 ]
885 };
886 this.data = [
887 {
888 username: 'John',
889 features: {
890 "cdn": false,
891 "uplink_speed": 1000000000,
892 "downlink_speed": 1000000000,
893 "uverse": true,
894 "status": "enabled"
895 }
896 },
897 {
898 username: 'Gili',
899 features: {
900 "cdn": true,
901 "uplink_speed": 3000000000,
902 "downlink_speed": 2000000000,
903 "uverse": true,
904 "status": "enabled"
905 }
906 }
907 ]
908 });
909 </file>
910 </example>
911 **/
912
Arpit Agarwal34b63832016-08-08 11:59:45 -0700913 .component('xosTable', {
914 restrict: 'E',
915 bindings: {
916 data: '=',
917 config: '='
918 },
Matteo Scandoloe57712f2016-09-21 15:27:36 -0700919 template: '\n <div ng-show="vm.data.length > 0 && vm.loader == false">\n <div class="row" ng-if="vm.config.filter == \'fulltext\'">\n <div class="col-xs-12">\n <input\n class="form-control"\n placeholder="Type to search.."\n type="text"\n ng-model="vm.query"/>\n </div>\n </div>\n <table ng-class="vm.classes" ng-hide="vm.data.length == 0">\n <thead>\n <tr>\n <th ng-repeat="col in vm.columns">\n {{col.label}}\n <span ng-if="vm.config.order">\n <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = false">\n <i class="glyphicon glyphicon-chevron-up"></i>\n </a>\n <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = true">\n <i class="glyphicon glyphicon-chevron-down"></i>\n </a>\n </span>\n </th>\n <th ng-if="vm.config.actions">Actions:</th>\n </tr>\n </thead>\n <tbody ng-if="vm.config.filter == \'field\'">\n <tr>\n <td ng-repeat="col in vm.columns">\n <input\n ng-if="col.type !== \'boolean\' && col.type !== \'array\' && col.type !== \'object\' && col.type !== \'custom\'"\n class="form-control"\n placeholder="Type to search by {{col.label}}"\n type="text"\n ng-model="vm.query[col.prop]"/>\n <select\n ng-if="col.type === \'boolean\'"\n class="form-control"\n ng-model="vm.query[col.prop]">\n <option value="">-</option>\n <option value="true">True</option>\n <option value="false">False</option>\n </select>\n </td>\n <td ng-if="vm.config.actions"></td>\n </tr>\n </tbody>\n <tbody>\n <tr ng-repeat="item in vm.data | filter:vm.query:vm.comparator | orderBy:vm.orderBy:vm.reverse | pagination:vm.currentPage * vm.config.pagination.pageSize | limitTo: (vm.config.pagination.pageSize || vm.data.length) track by $index">\n <td ng-repeat="col in vm.columns" xos-link-wrapper>\n <span ng-if="!col.type || col.type === \'text\'">{{item[col.prop]}}</span>\n <span ng-if="col.type === \'boolean\'">\n <i class="glyphicon"\n ng-class="{\'glyphicon-ok\': item[col.prop], \'glyphicon-remove\': !item[col.prop]}">\n </i>\n </span>\n <span ng-if="col.type === \'date\'">\n {{item[col.prop] | date:\'H:mm MMM d, yyyy\'}}\n </span>\n <span ng-if="col.type === \'array\'">\n {{item[col.prop] | arrayToList}}\n </span>\n <span ng-if="col.type === \'object\'">\n <dl class="dl-horizontal">\n <span ng-repeat="(k,v) in item[col.prop]">\n <dt>{{k}}</dt>\n <dd>{{v}}</dd>\n </span>\n </dl>\n </span>\n <span ng-if="col.type === \'custom\'">\n {{col.formatter(item)}}\n </span>\n <span ng-if="col.type === \'icon\'">\n <i class="glyphicon glyphicon-{{col.formatter(item)}}">\n </i>\n </span>\n </td>\n <td ng-if="vm.config.actions">\n <a href=""\n ng-repeat="action in vm.config.actions"\n ng-click="action.cb(item)"\n title="{{action.label}}">\n <i\n class="glyphicon glyphicon-{{action.icon}}"\n style="color: {{action.color}};"></i>\n </a>\n </td>\n </tr>\n </tbody>\n </table>\n <xos-pagination\n ng-if="vm.config.pagination"\n page-size="vm.config.pagination.pageSize"\n total-elements="vm.data.length"\n change="vm.goToPage">\n </xos-pagination>\n </div>\n <div ng-show="(vm.data.length == 0 || !vm.data) && vm.loader == false">\n <xos-alert config="{type: \'info\'}">\n No data to show.\n </xos-alert>\n </div>\n <div ng-show="vm.loader == true">\n <div class="loader"></div>\n </div>\n ',
Arpit Agarwal34b63832016-08-08 11:59:45 -0700920 bindToController: true,
921 controllerAs: 'vm',
922 controller: ["_", "$scope", "Comparator", function controller(_, $scope, Comparator) {
923 var _this = this;
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -0700924
Arpit Agarwal34b63832016-08-08 11:59:45 -0700925 this.comparator = Comparator;
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -0700926
Arpit Agarwal34b63832016-08-08 11:59:45 -0700927 this.loader = true;
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -0700928
Arpit Agarwal34b63832016-08-08 11:59:45 -0700929 $scope.$watch(function () {
930 return _this.data;
931 }, function (data) {
932 if (angular.isDefined(data)) {
933 _this.loader = false;
934 }
935 });
936
937 if (!this.config) {
938 throw new Error('[xosTable] Please provide a configuration via the "config" attribute');
939 }
940
941 if (!this.config.columns) {
942 throw new Error('[xosTable] Please provide a columns list in the configuration');
943 }
944
945 // handle default ordering
946 if (this.config.order && angular.isObject(this.config.order)) {
947 this.reverse = this.config.order.reverse || false;
948 this.orderBy = this.config.order.field || 'id';
949 }
950
951 // if columns with type 'custom' are provided
952 // check that a custom formatte3 is provided too
953 var customCols = _.filter(this.config.columns, { type: 'custom' });
954 if (angular.isArray(customCols) && customCols.length > 0) {
955 _.forEach(customCols, function (col) {
956 if (!col.formatter || !angular.isFunction(col.formatter)) {
957 throw new Error('[xosTable] You have provided a custom field type, a formatter function should provided too.');
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -0700958 }
959 });
Arpit Agarwal34b63832016-08-08 11:59:45 -0700960 }
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -0700961
Arpit Agarwal34b63832016-08-08 11:59:45 -0700962 // if columns with type 'icon' are provided
963 // check that a custom formatte3 is provided too
964 var iconCols = _.filter(this.config.columns, { type: 'icon' });
965 if (angular.isArray(iconCols) && iconCols.length > 0) {
966 _.forEach(iconCols, function (col) {
967 if (!col.formatter || !angular.isFunction(col.formatter)) {
968 throw new Error('[xosTable] You have provided an icon field type, a formatter function should provided too.');
969 }
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -0700970 });
Arpit Agarwal34b63832016-08-08 11:59:45 -0700971 }
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -0700972
Arpit Agarwal34b63832016-08-08 11:59:45 -0700973 // if a link property is passed,
974 // it should be a function
975 var linkedColumns = _.filter(this.config.columns, function (col) {
976 return angular.isDefined(col.link);
977 });
978 if (angular.isArray(linkedColumns) && linkedColumns.length > 0) {
979 _.forEach(linkedColumns, function (col) {
980 if (!angular.isFunction(col.link)) {
981 throw new Error('[xosTable] The link property should be a function.');
982 }
983 });
984 }
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -0700985
Arpit Agarwal34b63832016-08-08 11:59:45 -0700986 this.columns = this.config.columns;
987 this.classes = this.config.classes || 'table table-striped table-bordered';
988
989 if (this.config.actions) {
990 // TODO validate action format
991 }
992 if (this.config.pagination) {
993 this.currentPage = 0;
994 this.goToPage = function (n) {
995 _this.currentPage = n;
996 };
997 }
998 }]
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -0700999 })
1000 // TODO move in separate files
1001 // TODO test
1002 .filter('arrayToList', function () {
1003 return function (input) {
1004 if (!angular.isArray(input)) {
1005 return input;
1006 }
1007 return input.join(', ');
1008 };
1009 })
1010 // TODO test
1011 .directive('xosLinkWrapper', function () {
1012 return {
1013 restrict: 'A',
1014 transclude: true,
1015 template: '\n <a ng-if="col.link" href="{{col.link(item)}}">\n <div ng-transclude></div>\n </a>\n <div ng-transclude ng-if="!col.link"></div>\n '
1016 };
1017 });
1018})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001019'use strict';
1020
1021/**
1022 * © OpenCORD
1023 *
1024 * Visit http://guide.xosproject.org/devguide/addview/ for more information
1025 *
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001026 * Created by teone on 4/18/16.
1027 */
1028
1029(function () {
1030 'use strict';
1031
1032 angular.module('xos.uiComponents')
1033
1034 /**
1035 * @ngdoc directive
1036 * @name xos.uiComponents.directive:xosForm
1037 * @restrict E
1038 * @description The xos-form directive.
1039 * This components have two usage, given a model it is able to autogenerate a form or it can be configured to create a custom form.
1040 * @param {Object} config The configuration object
1041 * ```
1042 * {
1043 * exclude: ['id', 'validators', 'created', 'updated', 'deleted'], //field to be skipped in the form, the provide values are concatenated
Matteo Scandolobfb8ebd2016-10-28 17:53:05 +02001044 * order: ['field1', 'field2'], // ordering the fields (missing ones are attached at the end)
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001045 * actions: [ // define the form buttons with related callback
1046 * {
1047 label: 'save',
1048 icon: 'ok', // refers to bootstraps glyphicon
1049 cb: (user) => { // receive the model
1050 console.log(user);
1051 },
1052 class: 'success'
1053 }
1054 * ],
1055 * feedback: {
1056 show: false,
1057 message: 'Form submitted successfully !!!',
1058 type: 'success' //refers to bootstrap class
1059 },
1060 * fields: {
1061 * field_name: {
1062 * label: 'Field Label',
1063 * type: 'string' // options are: [date, boolean, number, email, string, select],
1064 * validators: {
1065 * minlength: number,
1066 maxlength: number,
1067 required: boolean,
1068 min: number,
1069 max: number,
1070 custom: (value) => {
1071 // do your validation here and return true | false
1072 // alternatively you can return an array [errorName, true|false]
1073 }
1074 * }
1075 * }
1076 * }
1077 * }
1078 * ```
Matteo Scandolobfb8ebd2016-10-28 17:53:05 +02001079 * @param {Object} ngModel The model object (it is mandatory to specify at least an empty object)
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001080 * @element ANY
1081 * @scope
1082 * @requires xos.uiComponents.directive:xosField
1083 * @requires xos.uiComponents.XosFormHelpers
1084 * @requires xos.helpers._
1085 * @example
Steven Burrows84818482016-09-29 15:33:46 -07001086 Autogenerated form
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001087 <example module="sampleForm">
1088 <file name="script.js">
1089 angular.module('sampleForm', ['xos.uiComponents'])
1090 .factory('_', function($window){
1091 return $window._;
1092 })
1093 .controller('SampleCtrl', function(){
1094 this.model = {
1095 first_name: 'Jhon',
1096 last_name: 'Doe',
1097 email: 'jhon.doe@sample.com',
1098 active: true,
1099 birthDate: '2015-02-17T22:06:38.059000Z'
1100 }
1101 this.config = {
1102 exclude: ['password', 'last_login'],
1103 formName: 'sampleForm',
1104 actions: [
1105 {
1106 label: 'Save',
1107 icon: 'ok', // refers to bootstraps glyphicon
1108 cb: (user) => { // receive the model
1109 console.log(user);
1110 },
1111 class: 'success'
1112 }
1113 ]
1114 };
1115 });
1116 </file>
1117 <file name="index.html">
1118 <div ng-controller="SampleCtrl as vm">
1119 <xos-form ng-model="vm.model" config="vm.config"></xos-form>
1120 </div>
1121 </file>
1122 </example>
1123 Configuration defined form
1124 <example module="sampleForm1">
1125 <file name="script.js">
1126 angular.module('sampleForm1', ['xos.uiComponents','ngResource', 'ngMockE2E'])
1127 .factory('_', function($window){
1128 return $window._;
1129 })
1130 .controller('SampleCtrl1', function(SampleResource){
Matteo Scandolobfb8ebd2016-10-28 17:53:05 +02001131 this.model = {};
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001132 this.config = {
1133 exclude: ['password', 'last_login'],
1134 formName: 'sampleForm1',
1135 feedback: {
1136 show: false,
Matteo Scandolobfb8ebd2016-10-28 17:53:05 +02001137 message: 'Form submitted successfully!',
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001138 type: 'success'
1139 },
1140 actions: [
1141 {
1142 label: 'Save',
Matteo Scandolobfb8ebd2016-10-28 17:53:05 +02001143 icon: 'ok',
1144 cb: (user) => {
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001145 console.log(user);
1146 this.config.feedback.show = true;
1147 this.config.feedback.type='success';
1148 },
1149 class: 'success'
1150 }
1151 ],
Matteo Scandolobfb8ebd2016-10-28 17:53:05 +02001152 order: ['site', 'last_name', 'first_name', 'age'],
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001153 fields: {
1154 first_name: {
1155 type: 'string',
1156 validators: {
1157 required: true
1158 }
1159 },
1160 last_name: {
1161 label: 'Surname',
1162 type: 'string',
1163 validators: {
1164 required: true,
1165 minlength: 10
1166 }
1167 },
1168 age: {
1169 type: 'number',
1170 validators: {
1171 required: true,
1172 min: 21
1173 }
1174 },
Matteo Scandolobfb8ebd2016-10-28 17:53:05 +02001175 site: {
1176 label: 'Site',
1177 type: 'select',
1178 validators: { required: true},
1179 hint: 'The Site this Slice belongs to',
1180 options: []
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001181 },
1182 }
1183 };
1184 SampleResource.query().$promise
Matteo Scandolobfb8ebd2016-10-28 17:53:05 +02001185 .then((users) => {
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001186 this.optionVal = users;
1187 this.config.fields['site'].options = this.optionVal;
Matteo Scandolobfb8ebd2016-10-28 17:53:05 +02001188 })
1189 .catch((e) => {
1190 throw new Error(e);
1191 });
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001192 });
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001193 </file>
1194 <file name="backend.js">
1195 angular.module('sampleForm1')
1196 .run(function($httpBackend, _){
1197 let datas = [{id: 1, label: 'site1'},{id: 4, label: 'site4'},{id: 3, label: 'site3'}];
1198 let paramsUrl = new RegExp(/\/test\/(.+)/);
1199 $httpBackend.whenGET('/test').respond(200, datas)
1200 })
1201 .service('SampleResource', function($resource){
1202 return $resource('/test/:id', {id: '@id'});
1203 });
Matteo Scandolobfb8ebd2016-10-28 17:53:05 +02001204 </file>
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001205 <file name="index.html">
1206 <div ng-controller="SampleCtrl1 as vm">
1207 <xos-form ng-model="vm.model" config="vm.config"></xos-form>
1208 </div>
1209 </file>
1210 </example>
1211 **/
1212
Arpit Agarwal34b63832016-08-08 11:59:45 -07001213 .component('xosForm', {
1214 restrict: 'E',
1215 bindings: {
1216 config: '=',
1217 ngModel: '='
1218 },
1219 template: '\n <form name="vm.{{vm.config.formName || \'form\'}}" novalidate>\n <div class="form-group" ng-repeat="(name, field) in vm.formField">\n <xos-field name="name" field="field" ng-model="vm.ngModel[name]"></xos-field>\n <xos-validation field="vm[vm.config.formName || \'form\'][name]" form = "vm[vm.config.formName || \'form\']"></xos-validation>\n <div class="alert alert-info" ng-show="(field.hint).length >0" role="alert">{{field.hint}}</div>\n </div>\n <div class="form-group" ng-if="vm.config.actions">\n <xos-alert config="vm.config.feedback" show="vm.config.feedback.show">{{vm.config.feedback.message}}</xos-alert>\n\n <button role="button" href=""\n ng-repeat="action in vm.config.actions"\n ng-click="action.cb(vm.ngModel, vm[vm.config.formName || \'form\'])"\n class="btn btn-{{action.class}}"\n title="{{action.label}}">\n <i class="glyphicon glyphicon-{{action.icon}}"></i>\n {{action.label}}\n </button>\n </div>\n </form>\n ',
1220 bindToController: true,
1221 controllerAs: 'vm',
1222 controller: ["$scope", "$log", "_", "XosFormHelpers", function controller($scope, $log, _, XosFormHelpers) {
1223 var _this = this;
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001224
Arpit Agarwal34b63832016-08-08 11:59:45 -07001225 if (!this.config) {
1226 throw new Error('[xosForm] Please provide a configuration via the "config" attribute');
1227 }
1228
1229 if (!this.config.actions) {
1230 throw new Error('[xosForm] Please provide an action list in the configuration');
1231 }
1232
1233 if (!this.config.feedback) {
1234 this.config.feedback = {
1235 show: false,
1236 message: 'Form submitted successfully !!!',
1237 type: 'success'
1238 };
1239 }
1240
1241 this.excludedField = ['id', 'validators', 'created', 'updated', 'deleted', 'backend_status'];
1242 if (this.config && this.config.exclude) {
1243 this.excludedField = this.excludedField.concat(this.config.exclude);
1244 }
1245
1246 this.formField = [];
1247
1248 $scope.$watch(function () {
1249 return _this.config;
1250 }, function () {
1251 if (!_this.ngModel) {
1252 return;
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001253 }
Arpit Agarwal34b63832016-08-08 11:59:45 -07001254 var diff = _.difference(Object.keys(_this.ngModel), _this.excludedField);
1255 var modelField = XosFormHelpers.parseModelField(diff);
Matteo Scandolobfb8ebd2016-10-28 17:53:05 +02001256 _this.formField = XosFormHelpers.buildFormStructure(modelField, _this.config.fields, _this.ngModel, _this.config.order);
Arpit Agarwal34b63832016-08-08 11:59:45 -07001257 }, true);
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001258
Arpit Agarwal34b63832016-08-08 11:59:45 -07001259 $scope.$watch(function () {
1260 return _this.ngModel;
1261 }, function (model) {
1262 // empty from old stuff
1263 _this.formField = {};
1264 if (!model) {
1265 return;
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001266 }
Arpit Agarwal34b63832016-08-08 11:59:45 -07001267 var diff = _.difference(Object.keys(model), _this.excludedField);
1268 var modelField = XosFormHelpers.parseModelField(diff);
Steven Burrows84818482016-09-29 15:33:46 -07001269 _this.formField = XosFormHelpers.buildFormStructure(modelField, _this.config.fields, model, _this.config.order);
Arpit Agarwal34b63832016-08-08 11:59:45 -07001270 });
1271 }]
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001272 });
1273})();
Steven Burrows84818482016-09-29 15:33:46 -07001274'use strict';
1275
1276/**
1277 * © OpenCORD
1278 *
1279 * Visit http://guide.xosproject.org/devguide/addview/ for more information
1280 *
1281 * Created by teone on 4/15/16.
1282 */
1283
1284(function () {
1285 'use strict';
1286
1287 angular.module('xos.uiComponents')
1288
1289 /**
1290 * @ngdoc directive
1291 * @name xos.uiComponents.directive:xosPagination
1292 * @restrict E
1293 * @description The xos-table directive
1294 * @param {Number} pageSize Number of elements per page
1295 * @param {Number} totalElements Number of total elements in the collection
1296 * @param {Function} change The callback to be triggered on page change.
1297 * * @element ANY
1298 * @scope
1299 * @example
1300 <example module="samplePagination">
1301 <file name="index.html">
1302 <div ng-controller="SampleCtrl1 as vm">
1303 <xos-pagination
1304 page-size="vm.pageSize"
1305 total-elements="vm.totalElements"
1306 change="vm.change">
1307 </xos-pagination>
1308 </div>
1309 </file>
1310 <file name="script.js">
1311 angular.module('samplePagination', ['xos.uiComponents'])
1312 .controller('SampleCtrl1', function(){
1313 this.pageSize = 10;
1314 this.totalElements = 35;
1315 this.change = (pageNumber) => {
1316 console.log(pageNumber);
1317 }
1318 });
1319 </file>
1320 </example>
1321 **/
1322
1323 .component('xosPagination', {
1324 restrict: 'E',
1325 bindings: {
1326 pageSize: '=',
1327 totalElements: '=',
1328 change: '='
1329 },
1330 template: '\n <div class="row" ng-if="vm.pageList.length > 1">\n <div class="col-xs-12 text-center">\n <ul class="pagination">\n <li\n ng-click="vm.goToPage(vm.currentPage - 1)"\n ng-class="{disabled: vm.currentPage == 0}">\n <a href="" aria-label="Previous">\n <span aria-hidden="true">&laquo;</span>\n </a>\n </li>\n <li ng-repeat="i in vm.pageList" ng-class="{active: i === vm.currentPage}">\n <a href="" ng-click="vm.goToPage(i)">{{i + 1}}</a>\n </li>\n <li\n ng-click="vm.goToPage(vm.currentPage + 1)"\n ng-class="{disabled: vm.currentPage == vm.pages - 1}">\n <a href="" aria-label="Next">\n <span aria-hidden="true">&raquo;</span>\n </a>\n </li>\n </ul>\n </div>\n </div>\n ',
1331 bindToController: true,
1332 controllerAs: 'vm',
1333 controller: ["$scope", function controller($scope) {
1334 var _this = this;
1335
1336 this.currentPage = 0;
1337
1338 this.goToPage = function (n) {
1339 if (n < 0 || n === _this.pages) {
1340 return;
1341 }
1342 _this.currentPage = n;
1343 _this.change(n);
1344 };
1345
1346 this.createPages = function (pages) {
1347 var arr = [];
1348 for (var i = 0; i < pages; i++) {
1349 arr.push(i);
1350 }
1351 return arr;
1352 };
1353
1354 // watch for data changes
1355 $scope.$watch(function () {
1356 return _this.totalElements;
1357 }, function () {
1358 if (_this.totalElements) {
1359 _this.pages = Math.ceil(_this.totalElements / _this.pageSize);
1360 _this.pageList = _this.createPages(_this.pages);
1361 }
1362 });
1363 }]
1364 }).filter('pagination', function () {
1365 return function (input, start) {
1366 if (!input || !angular.isArray(input)) {
1367 return input;
1368 }
1369 start = parseInt(start, 10);
1370 return input.slice(start);
1371 };
1372 });
1373})();
Arpit Agarwal43978742016-08-09 15:38:25 -07001374'use strict';
1375
Matteo Scandolo65116c42016-09-21 17:06:23 -07001376function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
1377
1378/**
1379 * © OpenCORD
1380 *
1381 * Visit http://guide.xosproject.org/devguide/addview/ for more information
1382 *
1383 * Created by teone on 5/25/16.
1384 */
1385
1386(function () {
1387 'use strict';
1388
1389 angular.module('xos.uiComponents')
1390 /**
1391 * @ngdoc directive
1392 * @name xos.uiComponents.directive:xosField
1393 * @restrict E
1394 * @description The xos-field directive.
1395 * This component decide, give a field wich kind of input it need to print.
1396 * @param {string} name The field name
1397 * @param {object} field The field configuration:
1398 * ```
1399 * {
1400 * label: 'Label',
1401 * type: 'number', //typeof field
1402 * validators: {} // see xosForm for more details
1403 * }
1404 * ```
1405 * @param {mixed} ngModel The field value
1406 *
1407 * @example
1408
1409 # Basic Example
1410
1411 <example module="sampleField1">
1412 <file name="script.js">
1413 angular.module('sampleField1', ['xos.uiComponents'])
1414 .factory('_', function($window){
1415 return $window._;
1416 })
1417 .controller('SampleCtrl', function(){
1418 this.name = 'input-name';
1419 this.field = {label: 'My String Value:', type: 'string'};
1420 this.model = 'my string';
1421 });
1422 </file>
1423 <file name="index.html">
1424 <div ng-controller="SampleCtrl as vm">
1425 <xos-field ng-model="vm.model" name="vm.name" field="vm.field"></xos-field>
1426 </div>
1427 </file>
1428 </example>
1429
1430 # Possible Values
1431 <example module="sampleField2">
1432 <file name="script.js">
1433 angular.module('sampleField2', ['xos.uiComponents'])
1434 .factory('_', function($window){
1435 return $window._;
1436 })
1437 .controller('SampleCtrl', function(){
1438 this.field1 = {
1439 name: 'number-field',
1440 field: {label: 'My Number Value:', type: 'number'},
1441 model: 2
1442 };
1443 this.field2 = {
1444 name: 'date-field',
1445 field: {label: 'My Date Value:', type: 'date'},
1446 model: new Date()
1447 };
1448 this.field3 = {
1449 name: 'boolean-field',
1450 field: {label: 'My Boolean Value:', type: 'boolean'},
1451 model: true
1452 };
1453 this.field4 = {
1454 name: 'email-field',
1455 field: {label: 'My Email Value:', type: 'email'},
1456 model: 'sample@domain.us'
1457 };
1458 this.field5 = {
1459 name: 'select',
Matteo Scandolobfb8ebd2016-10-28 17:53:05 +02001460 field: {
1461 label: 'Select field:',
1462 type: 'select',
1463 options: [
1464 {id: 1, label: 'One'},
1465 {id: 2, label: 'Two'},
1466 {id: 3, label: 'Three'},
1467 ]
1468 },
1469 model: 1
1470 };
1471 this.arrayField = {
1472 name: 'array',
1473 field: {
1474 label: 'Array field:',
1475 type: 'array',
1476 options: ['one', 'two', 'three', 'four']
1477 },
1478 model: ['one', 'two'],
Matteo Scandolo65116c42016-09-21 17:06:23 -07001479 };
1480 });
1481 </file>
1482 <file name="index.html">
1483 <div ng-controller="SampleCtrl as vm">
1484 <xos-field ng-model="vm.field1.model" name="vm.field1.name" field="vm.field1.field"></xos-field>
1485 <xos-field ng-model="vm.field2.model" name="vm.field2.name" field="vm.field2.field"></xos-field>
1486 <xos-field ng-model="vm.field3.model" name="vm.field3.name" field="vm.field3.field"></xos-field>
1487 <xos-field ng-model="vm.field4.model" name="vm.field4.name" field="vm.field4.field"></xos-field>
1488 <xos-field ng-model="vm.field5.model" name="vm.field5.name" field="vm.field5.field"></xos-field>
Matteo Scandolobfb8ebd2016-10-28 17:53:05 +02001489 <xos-field ng-model="vm.arrayField.model" name="vm.arrayField.name" field="vm.arrayField.field"></xos-field>
Matteo Scandolo65116c42016-09-21 17:06:23 -07001490 </div>
1491 </file>
1492 </example>
1493 # This element is recursive
1494 <example module="sampleField3">
1495 <file name="script.js">
1496 angular.module('sampleField3', ['xos.uiComponents'])
1497 .factory('_', function($window){
1498 return $window._;
1499 })
1500 .controller('SampleCtrl', function(){
1501 this.name1 = 'input-name';
1502 this.field1 = {label: 'My Object Field:', type: 'object'};
1503 this.model1 = {
1504 name: 'Jhon',
1505 age: '25',
1506 email: 'jhon@thewall.ru',
1507 active: true
1508 };
1509 this.name2 = 'another-name';
1510 this.field2 = {
1511 label: 'Empty Object Field',
1512 type: 'object',
1513 properties: {
1514 foo: {
1515 label: 'FooLabel:',
1516 type: 'string',
1517 validators: {
1518 required: true
1519 }
1520 },
1521 bar: {
1522 type: 'number'
1523 }
1524 }
1525 }
1526 });
1527 </file>
1528 <file name="index.html">
1529 <div ng-controller="SampleCtrl as vm">
1530 <h4>Autogenerated object field</h4>
1531 <xos-field ng-model="vm.model1" name="vm.name1" field="vm.field1"></xos-field>
1532 <h4>Configured object field</h4>
1533 <xos-field ng-model="vm.model2" name="vm.name2" field="vm.field2"></xos-field>
1534 </div>
1535 </file>
1536 </example>
1537 */
1538 .component('xosField', {
1539 restrict: 'E',
1540 bindings: {
1541 name: '=',
1542 field: '=',
1543 ngModel: '='
1544 },
1545 template: '\n <label ng-if="vm.field.type !== \'object\' && vm.field.type !== \'array\'">{{vm.field.label}}</label>\n <input\n xos-custom-validator custom-validator="vm.field.validators.custom || null"\n ng-if="vm.field.type !== \'boolean\' && vm.field.type !== \'object\' && vm.field.type !== \'select\' && vm.field.type !== \'array\'"\n type="{{vm.field.type}}"\n name="{{vm.name}}"\n class="form-control"\n ng-model="vm.ngModel"\n ng-minlength="vm.field.validators.minlength || 0"\n ng-maxlength="vm.field.validators.maxlength || 2000"\n ng-required="vm.field.validators.required || false" />\n <select class="form-control" ng-if ="vm.field.type === \'select\'"\n name = "{{vm.name}}"\n ng-options="item.id as item.label for item in vm.field.options"\n ng-model="vm.ngModel"\n ng-required="vm.field.validators.required || false">\n </select>\n <span class="boolean-field" ng-if="vm.field.type === \'boolean\'">\n <a href="#"\n class="btn btn-success"\n ng-show="vm.ngModel"\n ng-click="vm.ngModel = false">\n <i class="glyphicon glyphicon-ok"></i>\n </a>\n <a href="#"\n class="btn btn-danger"\n ng-show="!vm.ngModel"\n ng-click="vm.ngModel = true">\n <i class="glyphicon glyphicon-remove"></i>\n </a>\n </span>\n <div\n class="panel panel-default object-field"\n ng-if="vm.field.type == \'object\' && (!vm.isEmptyObject(vm.ngModel) || !vm.isEmptyObject(vm.field.properties))"\n >\n <div class="panel-heading">{{vm.field.label}}</div>\n <div class="panel-body">\n <div ng-if="!vm.field.properties" ng-repeat="(k, v) in vm.ngModel">\n <xos-field\n name="k"\n field="{label: vm.formatLabel(k), type: vm.getType(v)}"\n ng-model="v">\n </xos-field>\n </div>\n <div ng-if="vm.field.properties" ng-repeat="(k, v) in vm.field.properties">\n <xos-field\n name="k"\n field="{\n label: v.label || vm.formatLabel(k),\n type: v.type,\n validators: v.validators\n }"\n ng-model="vm.ngModel[k]">\n </xos-field>\n </div>\n </div>\n </div>\n <div\n class="panel panel-default array-field"\n ng-if="vm.field.type == \'array\'">\n <div class="panel-heading">{{vm.field.label}}</div>\n <div class="panel-body selected">\n <ul class="draggable" dnd-list="vm.ngModel">\n <li\n class="array-element"\n ng-repeat="item in vm.ngModel"\n dnd-draggable="item"\n dnd-moved="vm.ngModel.splice($index, 1)"\n dnd-effect-allowed="move"\n dnd-selected="models.selected = item"\n >\n <div class="well well-sm text-center">\n {{item}}\n </div>\n </li>\n <div class="clearfix"></div>\n </ul>\n </div>\n <div class="panel-body unselected">\n <ul class="draggable" dnd-list="vm.field.availableOptions">\n <li\n class="array-element"\n ng-repeat="item in vm.field.availableOptions"\n dnd-draggable="item"\n dnd-moved="vm.field.availableOptions.splice($index, 1)"\n dnd-effect-allowed="move"\n dnd-selected="models.selected = item"\n >\n <div class="well well-sm text-center">\n {{item}}\n </div>\n </li>\n <div class="clearfix"></div>\n </ul>\n </div>\n </div>\n ',
1546 bindToController: true,
1547 controllerAs: 'vm',
1548 controller: ["$attrs", "$scope", "XosFormHelpers", "LabelFormatter", "_", function controller($attrs, $scope, XosFormHelpers, LabelFormatter, _) {
1549 var _this = this;
1550
1551 if (!this.name) {
1552 throw new Error('[xosField] Please provide a field name');
1553 }
1554 if (!this.field) {
1555 throw new Error('[xosField] Please provide a field definition');
1556 }
1557 if (!this.field.type) {
1558 throw new Error('[xosField] Please provide a type in the field definition');
1559 }
1560 if (!$attrs.ngModel) {
1561 throw new Error('[xosField] Please provide an ng-model');
1562 }
1563 this.getType = XosFormHelpers._getFieldFormat;
1564 this.formatLabel = LabelFormatter.format;
1565
1566 this.isEmptyObject = function (o) {
1567 return o ? Object.keys(o).length === 0 : true;
1568 };
1569
1570 if (this.field.type === 'array') {
1571 $scope.$watch(function () {
1572 return _this.ngModel.length;
1573 }, function () {
1574 _this.field.availableOptions = _.difference(_this.field.options, _this.ngModel);
1575 });
1576 }
1577 }]
1578 })
1579
1580 /**
1581 * @ngdoc directive
1582 * @name xos.uiComponents.directive:xosCustomValidator
1583 * @restrict A
1584 * @description The xosCustomValidator directive.
1585 * This component apply a custom validation function
1586 * @param {function} customValidator The function that execute the validation.
1587 *
1588 * You should do your validation here and return true | false,
1589 * or alternatively you can return an array [errorName, true|false]
1590 */
1591 .directive('xosCustomValidator', function () {
1592 return {
1593 restrict: 'A',
1594 scope: {
1595 fn: '=customValidator'
1596 },
1597 require: 'ngModel',
1598 link: function link(scope, element, attr, ctrl) {
1599 if (!angular.isFunction(scope.fn)) {
1600 return;
1601 }
1602
1603 function customValidatorWrapper(ngModelValue) {
1604 var valid = scope.fn(ngModelValue);
1605 if (angular.isArray(valid)) {
1606 // ES6 spread rocks over fn.apply()
1607 ctrl.$setValidity.apply(ctrl, _toConsumableArray(valid));
1608 } else {
1609 ctrl.$setValidity('custom', valid);
1610 }
1611 return ngModelValue;
1612 }
1613
1614 ctrl.$parsers.push(customValidatorWrapper);
1615 }
1616 };
1617 });
1618})();
Matteo Scandolo65116c42016-09-21 17:06:23 -07001619'use strict';
1620
1621/**
1622 * © OpenCORD
1623 *
1624 * Visit http://guide.xosproject.org/devguide/addview/ for more information
1625 *
Matteo Scandolo1d689852016-09-29 09:42:12 -07001626 * Created by teone on 4/15/16.
Matteo Scandolo65116c42016-09-21 17:06:23 -07001627 */
1628
1629(function () {
1630 'use strict';
1631
1632 angular.module('xos.uiComponents')
1633
1634 /**
Matteo Scandolo1d689852016-09-29 09:42:12 -07001635 * @ngdoc directive
1636 * @name xos.uiComponents.directive:xosAlert
1637 * @restrict E
1638 * @description The xos-alert directive
1639 * @param {Object} config The configuration object
1640 * ```
1641 * {
1642 * type: 'danger', //info, success, warning
1643 * closeBtn: true, //default false
1644 * autoHide: 3000 //delay to automatically hide the alert
1645 * }
1646 * ```
1647 * @param {Boolean=} show Binding to show and hide the alert, default to true
1648 * @element ANY
1649 * @scope
1650 * @example
1651 <example module="sampleAlert1">
Matteo Scandolo65116c42016-09-21 17:06:23 -07001652 <file name="index.html">
Matteo Scandolo1d689852016-09-29 09:42:12 -07001653 <div ng-controller="SampleCtrl1 as vm">
1654 <xos-alert config="vm.config1">
1655 A sample alert message
1656 </xos-alert>
1657 <xos-alert config="vm.config2">
1658 A sample alert message (with close button)
1659 </xos-alert>
1660 <xos-alert config="vm.config3">
1661 A sample info message
1662 </xos-alert>
1663 <xos-alert config="vm.config4">
1664 A sample success message
1665 </xos-alert>
1666 <xos-alert config="vm.config5">
1667 A sample warning message
1668 </xos-alert>
Matteo Scandolo65116c42016-09-21 17:06:23 -07001669 </div>
1670 </file>
1671 <file name="script.js">
Matteo Scandolo1d689852016-09-29 09:42:12 -07001672 angular.module('sampleAlert1', ['xos.uiComponents'])
1673 .controller('SampleCtrl1', function(){
1674 this.config1 = {
1675 type: 'danger'
1676 };
1677 this.config2 = {
1678 type: 'danger',
1679 closeBtn: true
1680 };
1681 this.config3 = {
1682 type: 'info'
1683 };
1684 this.config4 = {
1685 type: 'success'
1686 };
1687 this.config5 = {
1688 type: 'warning'
Matteo Scandolo65116c42016-09-21 17:06:23 -07001689 };
1690 });
1691 </file>
1692 </example>
Matteo Scandolo1d689852016-09-29 09:42:12 -07001693 <example module="sampleAlert2" animations="true">
1694 <file name="index.html">
1695 <div ng-controller="SampleCtrl as vm" class="row">
1696 <div class="col-sm-4">
1697 <a class="btn btn-default btn-block" ng-show="!vm.show" ng-click="vm.show = true">Show Alert</a>
1698 <a class="btn btn-default btn-block" ng-show="vm.show" ng-click="vm.show = false">Hide Alert</a>
1699 </div>
1700 <div class="col-sm-8">
1701 <xos-alert config="vm.config1" show="vm.show">
1702 A sample alert message, not displayed by default.
1703 </xos-alert>
1704 </div>
1705 </div>
1706 </file>
1707 <file name="script.js">
1708 angular.module('sampleAlert2', ['xos.uiComponents', 'ngAnimate'])
1709 .controller('SampleCtrl', function(){
1710 this.config1 = {
1711 type: 'success'
1712 };
1713 this.show = false;
1714 });
1715 </file>
1716 </example>
1717 **/
Matteo Scandolo65116c42016-09-21 17:06:23 -07001718
Matteo Scandolo1d689852016-09-29 09:42:12 -07001719 .component('xosAlert', {
Matteo Scandolo65116c42016-09-21 17:06:23 -07001720 restrict: 'E',
1721 bindings: {
Matteo Scandolo1d689852016-09-29 09:42:12 -07001722 config: '=',
1723 show: '=?'
Matteo Scandolo65116c42016-09-21 17:06:23 -07001724 },
Matteo Scandolo1d689852016-09-29 09:42:12 -07001725 template: '\n <div ng-cloak class="alert alert-{{vm.config.type}}" ng-hide="!vm.show">\n <button type="button" class="close" ng-if="vm.config.closeBtn" ng-click="vm.dismiss()">\n <span aria-hidden="true">&times;</span>\n </button>\n <p ng-transclude></p>\n </div>\n ',
1726 transclude: true,
Matteo Scandolo65116c42016-09-21 17:06:23 -07001727 bindToController: true,
1728 controllerAs: 'vm',
Matteo Scandolo1d689852016-09-29 09:42:12 -07001729 controller: ["$timeout", function controller($timeout) {
Matteo Scandolo65116c42016-09-21 17:06:23 -07001730 var _this = this;
1731
Matteo Scandolo1d689852016-09-29 09:42:12 -07001732 if (!this.config) {
1733 throw new Error('[xosAlert] Please provide a configuration via the "config" attribute');
Matteo Scandolo65116c42016-09-21 17:06:23 -07001734 }
1735
Matteo Scandolo1d689852016-09-29 09:42:12 -07001736 // default the value to true
1737 this.show = this.show !== false;
1738
1739 this.dismiss = function () {
1740 _this.show = false;
Matteo Scandolo65116c42016-09-21 17:06:23 -07001741 };
1742
Matteo Scandolo1d689852016-09-29 09:42:12 -07001743 if (this.config.autoHide) {
Matteo Scandolo65116c42016-09-21 17:06:23 -07001744 (function () {
Matteo Scandolo1d689852016-09-29 09:42:12 -07001745 var to = $timeout(function () {
1746 _this.dismiss();
1747 $timeout.cancel(to);
1748 }, _this.config.autoHide);
Matteo Scandolo65116c42016-09-21 17:06:23 -07001749 })();
Matteo Scandolo65116c42016-09-21 17:06:23 -07001750 }
Matteo Scandolo65116c42016-09-21 17:06:23 -07001751 }]
1752 });
1753})();
Matteo Scandolo65116c42016-09-21 17:06:23 -07001754'use strict';
1755
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001756(function () {
1757 'use strict';
1758
1759 /**
1760 * @ngdoc service
1761 * @name xos.uiComponents.LabelFormatter
1762 * @description This factory define a set of helper function to format label started from an object property
1763 **/
1764
1765 angular.module('xos.uiComponents').factory('LabelFormatter', labelFormatter);
1766
1767 function labelFormatter() {
1768
1769 /**
1770 * @ngdoc method
1771 * @name xos.uiComponents.LabelFormatter#_formatByUnderscore
1772 * @methodOf xos.uiComponents.LabelFormatter
1773 * @description
1774 * Convert a `snake_case` string to readable string.<br/>
1775 * Eg: `this_string` will became `this string`
1776 * @param {string} string The string to be converted
1777 * @returns {string} The converten string
1778 **/
1779
1780 var _formatByUnderscore = function _formatByUnderscore(string) {
1781 return string.split('_').join(' ').trim();
1782 };
1783
1784 /**
1785 * @ngdoc method
1786 * @name xos.uiComponents.LabelFormatter#_formatByUppercase
1787 * @methodOf xos.uiComponents.LabelFormatter
1788 * @description
1789 * Convert a `camelCase` string to readable string.<br/>
1790 * Eg: `thisString` will became `this string`
1791 * @param {string} string The string to be converted
1792 * @returns {string} The converten string
1793 **/
1794
1795 var _formatByUppercase = function _formatByUppercase(string) {
1796 return string.split(/(?=[A-Z])/).map(function (w) {
1797 return w.toLowerCase();
1798 }).join(' ');
1799 };
1800
1801 /**
1802 * @ngdoc method
1803 * @name xos.uiComponents.LabelFormatter#_capitalize
1804 * @methodOf xos.uiComponents.LabelFormatter
1805 * @description
1806 * Capitalize the first letter of a string.<br/>
1807 * Eg: `this string` will became `This string`
1808 * @param {string} string The string to be converted
1809 * @returns {string} The converten string
1810 **/
1811
1812 var _capitalize = function _capitalize(string) {
1813 return string.slice(0, 1).toUpperCase() + string.slice(1);
1814 };
1815
1816 /**
1817 * @ngdoc method
1818 * @name xos.uiComponents.LabelFormatter#format
1819 * @methodOf xos.uiComponents.LabelFormatter
1820 * @description
1821 * Apply in order:
1822 * - _formatByUnderscore
1823 * - _formatByUppercase
1824 * - _capitalize
1825 * - replace multiple space with a single one
Steven Burrows84818482016-09-29 15:33:46 -07001826 * - append `:` at the end
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001827 * <br/>
1828 * Eg: `this_string` will became `This string:`<br/>
1829 * Eg: `thisString` will became `This string:`
1830 * @param {string} string The string to be converted
1831 * @returns {string} The converten string
1832 **/
1833
1834 var format = function format(string) {
1835 string = _formatByUnderscore(string);
1836 string = _formatByUppercase(string);
1837
1838 string = _capitalize(string).replace(/\s\s+/g, ' ') + ':';
1839 return string.replace('::', ':');
1840 };
1841
1842 return {
1843 // test export
1844 _formatByUnderscore: _formatByUnderscore,
1845 _formatByUppercase: _formatByUppercase,
1846 _capitalize: _capitalize,
1847 // export to use
1848 format: format
1849 };
1850 }
1851})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001852'use strict';
1853
1854var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
1855
1856(function () {
1857
1858 angular.module('xos.uiComponents')
1859
1860 /**
1861 * @ngdoc service
1862 * @name xos.uiComponents.XosFormHelpers
1863 * @requires xos.uiComponents.LabelFormatter
1864 * @requires xos.helpers._
1865 **/
1866
1867 .service('XosFormHelpers', ["_", "LabelFormatter", function (_, LabelFormatter) {
1868 var _this = this;
1869
1870 /**
1871 * @ngdoc method
1872 * @name xos.uiComponents.XosFormHelpers#_isEmail
1873 * @methodOf xos.uiComponents.XosFormHelpers
1874 * @description
1875 * Return true if the string is an email address
1876 * @param {string} text The string to be evaluated
1877 * @returns {boolean} If the string match an email format
1878 **/
1879
1880 this._isEmail = function (text) {
1881 var re = /(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/;
1882 return re.test(text);
1883 };
1884
1885 /**
1886 * @ngdoc method
1887 * @name xos.uiComponents.XosFormHelpers#_getFieldFormat
1888 * @methodOf xos.uiComponents.XosFormHelpers
1889 * @description
1890 * Return the type of the input
1891 * @param {mixed} value The data to be evaluated
1892 * @returns {string} The type of the input
1893 **/
1894
1895 this._getFieldFormat = function (value) {
1896
1897 if (angular.isArray(value)) {
1898 return 'array';
1899 }
1900
1901 // check if is date
Matteo Scandoloe57712f2016-09-21 15:27:36 -07001902 if (angular.isDate(value) || !Number.isNaN(Date.parse(value)) && // Date.parse is a number
1903 /^\d+-\d+-\d+\D\d+:\d+:\d+\.\d+\D/.test(value) // the format match ISO dates
1904 ) {
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001905 return 'date';
1906 }
1907
1908 // check if is boolean
1909 // isNaN(false) = false, false is a number (0), true is a number (1)
1910 if (typeof value === 'boolean') {
1911 return 'boolean';
1912 }
1913
1914 // check if a string is an email
1915 if (_this._isEmail(value)) {
1916 return 'email';
1917 }
1918
1919 // if null return string
1920 if (angular.isString(value) || value === null) {
1921 return 'text';
1922 }
1923
1924 return typeof value === 'undefined' ? 'undefined' : _typeof(value);
1925 };
1926
1927 /**
1928 * @ngdoc method
1929 * @name xos.uiComponents.XosFormHelpers#buildFormStructure
1930 * @methodOf xos.uiComponents.XosFormHelpers
1931 * @description
1932 * Return the type of the input
1933 * @param {object} modelField An object containing one property for each field of the model
1934 * @param {object} customField An object containing one property for each field custom field
1935 * @param {object} model The actual model on wich build the form structure (it is used to determine the type of the input)
1936 * @returns {object} An object describing the form structure in the form of:
1937 * ```
1938 * {
1939 * 'field-name': {
1940 * label: 'Label',
1941 * type: 'number', //typeof field
1942 * validators: {}, // see xosForm for more details
1943 * hint: 'A Custom hint for the field'
1944 * }
1945 * }
1946 * ```
1947 **/
1948
Steven Burrows84818482016-09-29 15:33:46 -07001949 this.buildFormStructure = function (modelField, customField, model, order) {
Steven Burrows84818482016-09-29 15:33:46 -07001950 var orderedForm = {};
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001951
1952 modelField = angular.extend(modelField, customField);
1953 customField = customField || {};
1954
Steven Burrows84818482016-09-29 15:33:46 -07001955 if (order) {
1956 _.each(order, function (key) {
1957 orderedForm[key] = {};
1958 });
1959 }
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001960
Steven Burrows84818482016-09-29 15:33:46 -07001961 _.each(Object.keys(modelField), function (f) {
1962
1963 orderedForm[f] = {
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001964 label: customField[f] && customField[f].label ? customField[f].label + ':' : LabelFormatter.format(f),
1965 type: customField[f] && customField[f].type ? customField[f].type : _this._getFieldFormat(model[f]),
1966 validators: customField[f] && customField[f].validators ? customField[f].validators : {},
1967 hint: customField[f] && customField[f].hint ? customField[f].hint : ''
1968 };
1969
1970 if (customField[f] && customField[f].options) {
Steven Burrows84818482016-09-29 15:33:46 -07001971 orderedForm[f].options = customField[f].options;
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001972 }
1973 if (customField[f] && customField[f].properties) {
Steven Burrows84818482016-09-29 15:33:46 -07001974 orderedForm[f].properties = customField[f].properties;
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001975 }
Steven Burrows84818482016-09-29 15:33:46 -07001976 if (orderedForm[f].type === 'date') {
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001977 model[f] = new Date(model[f]);
1978 }
1979
Steven Burrows84818482016-09-29 15:33:46 -07001980 if (orderedForm[f].type === 'number') {
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001981 model[f] = parseInt(model[f], 10);
1982 }
Steven Burrows84818482016-09-29 15:33:46 -07001983 });
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001984
Steven Burrows84818482016-09-29 15:33:46 -07001985 return orderedForm;
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07001986 };
1987
1988 /**
1989 * @ngdoc method
1990 * @name xos.uiComponents.XosFormHelpers#parseModelField
1991 * @methodOf xos.uiComponents.XosFormHelpers
1992 * @description
1993 * Helpers for buildFormStructure, convert a list of model properties in an object used to build the form structure, eg:
1994 * ```
1995 * // input:
1996 * ['id', 'name'm 'mail']
1997 *
1998 * // output
1999 * {
2000 * id: {},
2001 * name: {},
2002 * mail: {}
2003 * }
2004 * ```
2005 * @param {array} fields An array of fields representing the model properties
2006 * @returns {object} An object containing one property for each field of the model
2007 **/
2008
2009 this.parseModelField = function (fields) {
2010 return _.reduce(fields, function (form, f) {
2011 form[f] = {};
2012 return form;
2013 }, {});
2014 };
2015 }]);
2016})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002017'use strict';
2018
2019(function () {
2020 'use strict';
2021
2022 /**
2023 * @ngdoc service
2024 * @name xos.uiComponents.Comparator
2025 * @description
2026 * This factory define a function that replace the native angular.filter comparator.
2027 *
2028 * It is done to allow the comparation between (0|1) values with booleans.
2029 * >Note that this factory return a single function, not an object.
2030 *
2031 * The tipical usage of this factory is inside an `ng-repeat`
2032 * @example
2033 * <example module="comparator">
2034 * <file name="index.html">
2035 * <div ng-controller="sample as vm">
2036 * <div class="row">
2037 * <div class="col-xs-6">
2038 * <label>Filter by name:</label>
2039 * <input class="form-control" type="text" ng-model="vm.query.name"/>
2040 * </div>
2041 * <div class="col-xs-6">
2042 * <label>Filter by status:</label>
2043 * <select
2044 * ng-model="vm.query.status"
2045 * ng-options="i for i in [true, false]">
2046 * </select>
2047 * </div>
2048 * </div>
2049 * <div ng-repeat="item in vm.data | filter:vm.query:vm.comparator">
2050 * <div class="row">
2051 * <div class="col-xs-6">{{item.name}}</div>
2052 * <div class="col-xs-6">{{item.status}}</div>
2053 * </div>
2054 * </div>
2055 * </div>
2056 * </file>
2057 * <file name="script.js">
2058 * angular.module('comparator', ['xos.uiComponents'])
2059 * .controller('sample', function(Comparator){
2060 * this.comparator = Comparator;
2061 * this.data = [
2062 * {name: 'Jhon', status: 1},
2063 * {name: 'Jack', status: 0},
2064 * {name: 'Mike', status: 1},
2065 * {name: 'Scott', status: 0}
2066 * ];
2067 * });
2068 * </file>
2069 * </example>
2070 **/
2071
2072 comparator.$inject = ["_"];
2073 angular.module('xos.uiComponents').factory('Comparator', comparator);
2074
2075 function comparator(_) {
2076
2077 return function (actual, expected) {
2078
2079 if (angular.isUndefined(actual)) {
2080 // No substring matching against `undefined`
2081 return false;
2082 }
2083 if (actual === null || expected === null) {
2084 // No substring matching against `null`; only match against `null`
2085 return actual === expected;
2086 }
2087 if (angular.isObject(expected) || angular.isObject(actual)) {
2088 return angular.equals(expected, actual);
2089 }
2090
2091 if (_.isBoolean(actual) || _.isBoolean(expected)) {
2092 if (actual === 0 || actual === 1) {
2093 actual = !!actual;
2094 }
2095 return angular.equals(expected, actual);
2096 }
2097
2098 if (!angular.isString(actual) || !angular.isString(expected)) {
2099 if (angular.isDefined(actual.toString) && angular.isDefined(expected.toString)) {
2100 actual = actual.toString();
2101 expected = expected.toString();
2102 } else {
2103 return actual === expected;
2104 }
2105 }
2106
2107 actual = actual.toLowerCase() + '';
2108 expected = expected.toLowerCase() + '';
2109 return actual.indexOf(expected) !== -1;
2110 };
2111 }
2112})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002113'use strict';
2114
2115(function () {
2116 'use strict';
2117
2118 /**
2119 * @ngdoc overview
2120 * @name xos.helpers
2121 * @description
2122 * # xos.Helpers
2123 * A collection of helpers to work with XOS <br/>
2124 * Currently available components are:
2125 * - [NoHyperlinks](/#/module/xos.helpers.NoHyperlinks)
2126 * - [SetCSRFToken](/#/module/xos.helpers.SetCSRFToken)
2127 * - [xosNotification](/#/module/xos.helpers.xosNotification)
2128 * - [XosUserPrefs](/#/module/xos.helpers.XosUserPrefs)
2129 * <br/><br/>
2130 * A set of angular [$resource](https://docs.angularjs.org/api/ngResource/service/$resource) is provided to work with the API.<br>
2131 * You can find the documentation [here](#/rest-api)
2132 **/
2133
2134 config.$inject = ["$httpProvider", "$interpolateProvider", "$resourceProvider"];
2135 angular.module('xos.helpers', ['ngCookies', 'ngResource', 'ngAnimate', 'xos.uiComponents']).config(config)
2136
2137 /**
2138 * @ngdoc service
2139 * @name xos.helpers._
2140 * @description Wrap [lodash](https://lodash.com/docs) in an Angular Service
2141 **/
2142
2143 .factory('_', ["$window", function ($window) {
2144 return $window._;
2145 }]);
2146
2147 function config($httpProvider, $interpolateProvider, $resourceProvider) {
2148 $httpProvider.interceptors.push('SetCSRFToken');
2149
2150 // NOTE http://www.masnun.com/2013/09/18/django-rest-framework-angularjs-resource-trailing-slash-problem.html
2151 $resourceProvider.defaults.stripTrailingSlashes = false;
2152 }
2153})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002154'use strict';
2155
2156(function () {
2157 'use strict';
2158
2159 angular.module('xos.helpers')
2160 /**
2161 * @ngdoc service
2162 * @name xos.helpers.vSG-Collection
2163 * @description Angular resource to fetch /api/service/vsg/
2164 **/
2165 .service('vSG-Collection', ["$resource", function ($resource) {
2166 return $resource('/api/service/vsg/');
2167 }]);
2168})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002169'use strict';
2170
2171(function () {
2172 'use strict';
2173
2174 angular.module('xos.helpers')
2175 /**
2176 * @ngdoc service
2177 * @name xos.helpers.vOLT-Collection
2178 * @description Angular resource to fetch /api/tenant/cord/volt/:volt_id/
2179 **/
2180 .service('vOLT-Collection', ["$resource", function ($resource) {
2181 return $resource('/api/tenant/cord/volt/:volt_id/', { volt_id: '@id' }, {
2182 update: { method: 'PUT' }
2183 });
2184 }]);
2185})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002186'use strict';
2187
2188(function () {
2189 'use strict';
2190
2191 angular.module('xos.helpers')
2192 /**
2193 * @ngdoc service
2194 * @name xos.helpers.Login
2195 * @description Angular resource to fetch /api/utility/login/
2196 **/
2197 .service('Login', ["$resource", function ($resource) {
2198 return $resource('/api/utility/login/');
2199 }])
2200 /**
2201 * @ngdoc service
2202 * @name xos.helpers.Logout
2203 * @description Angular resource to fetch /api/utility/logout/
2204 **/
2205 .service('Logout', ["$resource", function ($resource) {
2206 return $resource('/api/utility/logout/');
2207 }]);
2208})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002209'use strict';
2210
2211(function () {
2212 'use strict';
2213
2214 angular.module('xos.helpers')
2215 /**
2216 * @ngdoc service
2217 * @name xos.helpers.Users
2218 * @description Angular resource to fetch /api/core/users/:id/
2219 **/
2220 .service('Users', ["$resource", function ($resource) {
2221 return $resource('/api/core/users/:id/', { id: '@id' }, {
2222 update: { method: 'PUT' }
2223 });
2224 }]);
2225})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002226'use strict';
2227
2228(function () {
2229 'use strict';
2230
2231 angular.module('xos.helpers')
2232 /**
2233 * @ngdoc service
2234 * @name xos.helpers.Truckroll
2235 * @description Angular resource to fetch /api/tenant/truckroll/:id/
2236 **/
2237 .service('Truckroll', ["$resource", function ($resource) {
2238 return $resource('/api/tenant/truckroll/:id/', { id: '@id' }, {
2239 update: { method: 'PUT' }
2240 });
2241 }]);
2242})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002243'use strict';
2244
2245(function () {
2246 'use strict';
2247
2248 angular.module('xos.helpers')
2249 /**
2250 * @ngdoc service
2251 * @name xos.helpers.Tenant
2252 * @description Angular resource to fetch /api/core/tenant/:id/
2253 **/
2254 .service('Tenants', ["$resource", function ($resource) {
2255 return $resource('/api/core/tenants/:id/', { id: '@id' }, {
2256 update: { method: 'PUT' }
2257 });
2258 }]);
2259})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002260'use strict';
2261
2262(function () {
2263 'use strict';
2264
2265 angular.module('xos.helpers')
2266 /**
2267 * @ngdoc service
2268 * @name xos.helpers.Subscribers
2269 * @description Angular resource to fetch Subscribers
2270 **/
2271 .service('Subscribers', ["$resource", function ($resource) {
2272 return $resource('/api/tenant/cord/subscriber/:id/', { id: '@id' }, {
2273 update: { method: 'PUT' },
2274 /**
2275 * @ngdoc method
2276 * @name xos.helpers.Subscribers#View-a-Subscriber-Features-Detail
2277 * @methodOf xos.helpers.Subscribers
2278 * @description
2279 * View-a-Subscriber-Features-Detail
2280 **/
2281 'View-a-Subscriber-Features-Detail': {
2282 method: 'GET',
2283 isArray: false,
2284 url: '/api/tenant/cord/subscriber/:id/features/'
2285 },
2286 /**
2287 * @ngdoc method
2288 * @name xos.helpers.Subscribers#Read-Subscriber-uplink_speed
2289 * @methodOf xos.helpers.Subscribers
2290 * @description
2291 * Read-Subscriber-uplink_speed
2292 **/
2293 'Read-Subscriber-uplink_speed': {
2294 method: 'GET',
2295 isArray: false,
2296 url: '/api/tenant/cord/subscriber/:id/features/uplink_speed/'
2297 },
2298 /**
2299 * @ngdoc method
2300 * @name xos.helpers.Subscribers#Update-Subscriber-uplink_speed
2301 * @methodOf xos.helpers.Subscribers
2302 * @description
2303 * Update-Subscriber-uplink_speed
2304 **/
2305 'Update-Subscriber-uplink_speed': {
2306 method: 'PUT',
2307 isArray: false,
2308 url: '/api/tenant/cord/subscriber/:id/features/uplink_speed/'
2309 },
2310 /**
2311 * @ngdoc method
2312 * @name xos.helpers.Subscribers#Read-Subscriber-downlink_speed
2313 * @methodOf xos.helpers.Subscribers
2314 * @description
2315 * Read-Subscriber-downlink_speed
2316 **/
2317 'Read-Subscriber-downlink_speed': {
2318 method: 'GET',
2319 isArray: false,
2320 url: '/api/tenant/cord/subscriber/:id/features/downlink_speed/'
2321 },
2322 /**
2323 * @ngdoc method
2324 * @name xos.helpers.Subscribers#Update-Subscriber-downlink_speed
2325 * @methodOf xos.helpers.Subscribers
2326 * @description
2327 * Update-Subscriber-downlink_speed
2328 **/
2329 'Update-Subscriber-downlink_speed': {
2330 method: 'PUT',
2331 isArray: false,
2332 url: '/api/tenant/cord/subscriber/:id/features/downlink_speed/'
2333 },
2334 /**
2335 * @ngdoc method
2336 * @name xos.helpers.Subscribers#Read-Subscriber-cdn
2337 * @methodOf xos.helpers.Subscribers
2338 * @description
2339 * Read-Subscriber-cdn
2340 **/
2341 'Read-Subscriber-cdn': {
2342 method: 'GET',
2343 isArray: false,
2344 url: '/api/tenant/cord/subscriber/:id/features/cdn/'
2345 },
2346 /**
2347 * @ngdoc method
2348 * @name xos.helpers.Subscribers#Update-Subscriber-cdn
2349 * @methodOf xos.helpers.Subscribers
2350 * @description
2351 * Update-Subscriber-cdn
2352 **/
2353 'Update-Subscriber-cdn': {
2354 method: 'PUT',
2355 isArray: false,
2356 url: '/api/tenant/cord/subscriber/:id/features/cdn/'
2357 },
2358 /**
2359 * @ngdoc method
2360 * @name xos.helpers.Subscribers#Read-Subscriber-uverse
2361 * @methodOf xos.helpers.Subscribers
2362 * @description
2363 * Read-Subscriber-uverse
2364 **/
2365 'Read-Subscriber-uverse': {
2366 method: 'GET',
2367 isArray: false,
2368 url: '/api/tenant/cord/subscriber/:id/features/uverse/'
2369 },
2370 /**
2371 * @ngdoc method
2372 * @name xos.helpers.Subscribers#Update-Subscriber-uverse
2373 * @methodOf xos.helpers.Subscribers
2374 * @description
2375 * Update-Subscriber-uverse
2376 **/
2377 'Update-Subscriber-uverse': {
2378 method: 'PUT',
2379 isArray: false,
2380 url: '/api/tenant/cord/subscriber/:id/features/uverse/'
2381 },
2382 /**
2383 * @ngdoc method
2384 * @name xos.helpers.Subscribers#Read-Subscriber-status
2385 * @methodOf xos.helpers.Subscribers
2386 * @description
2387 * Read-Subscriber-status
2388 **/
2389 'Read-Subscriber-status': {
2390 method: 'GET',
2391 isArray: false,
2392 url: '/api/tenant/cord/subscriber/:id/features/status/'
2393 },
2394 /**
2395 * @ngdoc method
2396 * @name xos.helpers.Subscribers#Update-Subscriber-status
2397 * @methodOf xos.helpers.Subscribers
2398 * @description
2399 * Update-Subscriber-status
2400 **/
2401 'Update-Subscriber-status': {
2402 method: 'PUT',
2403 isArray: false,
2404 url: '/api/tenant/cord/subscriber/:id/features/status/'
2405 }
2406 });
2407 }]);
2408})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002409'use strict';
2410
2411(function () {
2412 'use strict';
2413
2414 angular.module('xos.helpers')
2415 /**
2416 * @ngdoc service
2417 * @name xos.helpers.SlicesPlus
2418 * @description Angular resource to fetch /api/utility/slicesplus/
2419 * This is a read-only API and only the `query` method is currently supported.
2420 **/
2421 .service('SlicesPlus', ["$http", "$q", function ($http, $q) {
2422 this.query = function (params) {
2423 var deferred = $q.defer();
2424
2425 $http.get('/api/utility/slicesplus/', { params: params }).then(function (res) {
2426 deferred.resolve(res.data);
2427 }).catch(function (res) {
2428 deferred.reject(res.data);
2429 });
2430
2431 return { $promise: deferred.promise };
2432 };
2433
2434 this.get = function (id, params) {
2435 var deferred = $q.defer();
2436
2437 $http.get('/api/utility/slicesplus/' + id, { params: params }).then(function (res) {
2438 deferred.resolve(res.data);
2439 }).catch(function (res) {
2440 deferred.reject(res.data);
2441 });
2442 return { $promise: deferred.promise };
2443 };
2444 }]);
2445})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002446'use strict';
2447
2448(function () {
2449 'use strict';
2450
2451 angular.module('xos.helpers')
2452 /**
2453 * @ngdoc service
2454 * @name xos.helpers.Slices
2455 * @description Angular resource to fetch /api/core/slices/:id/
2456 **/
2457 .service('Slices', ["$resource", function ($resource) {
2458 return $resource('/api/core/slices/:id/', { id: '@id' }, {
2459 update: { method: 'PUT' }
2460 });
2461 }]);
2462})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002463'use strict';
2464
2465(function () {
2466 'use strict';
2467
2468 angular.module('xos.helpers')
2469 /**
2470 * @ngdoc service
2471 * @name xos.helpers.Sites
2472 * @description Angular resource to fetch /api/core/sites/:id/
2473 **/
2474 .service('Sites', ["$resource", function ($resource) {
2475 return $resource('/api/core/sites/:id/', { id: '@id' }, {
2476 update: { method: 'PUT' }
2477 });
2478 }]);
2479})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002480'use strict';
2481
2482(function () {
2483 'use strict';
2484
2485 angular.module('xos.helpers')
2486 /**
2487 * @ngdoc service
2488 * @name xos.helpers.Services
2489 * @description Angular resource to fetch /api/core/services/:id/
2490 **/
2491 .service('Services', ["$resource", function ($resource) {
2492 return $resource('/api/core/services/:id/', { id: '@id' }, {
2493 update: { method: 'PUT' }
2494 });
2495 }]);
2496})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002497'use strict';
2498
2499(function () {
2500 'use strict';
2501
2502 angular.module('xos.helpers')
2503 /**
2504 * @ngdoc service
2505 * @name xos.helpers.ONOS-Services-Collection
2506 * @description Angular resource to fetch /api/service/onos/
2507 **/
2508 .service('ONOS-Services-Collection', ["$resource", function ($resource) {
2509 return $resource('/api/service/onos/');
2510 }]);
2511})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002512'use strict';
2513
2514(function () {
2515 'use strict';
2516
2517 angular.module('xos.helpers')
2518 /**
2519 * @ngdoc service
2520 * @name xos.helpers.ONOS-App-Collection
2521 * @description Angular resource to fetch /api/tenant/onos/app/
2522 **/
2523 .service('ONOS-App-Collection', ["$resource", function ($resource) {
2524 return $resource('/api/tenant/onos/app/');
2525 }]);
2526})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002527'use strict';
2528
2529(function () {
2530 'use strict';
2531
2532 angular.module('xos.helpers')
2533 /**
2534 * @ngdoc service
2535 * @name xos.helpers.Nodes
2536 * @description Angular resource to fetch /api/core/nodes/:id/
2537 **/
2538 .service('Nodes', ["$resource", function ($resource) {
2539 return $resource('/api/core/nodes/:id/', { id: '@id' }, {
2540 update: { method: 'PUT' }
2541 });
2542 }]);
2543})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002544'use strict';
2545
2546(function () {
2547 'use strict';
2548
2549 angular.module('xos.helpers')
2550 /**
2551 * @ngdoc service
2552 * @name xos.helpers.Networkstemplates
2553 * @description Angular resource to fetch /api/core/networktemplates/:id/
2554 **/
2555 .service('Networkstemplates', ["$resource", function ($resource) {
2556 return $resource('/api/core/networktemplates/:id/', { id: '@id' }, {
2557 update: { method: 'PUT' }
2558 });
2559 }]);
2560})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002561'use strict';
2562
2563(function () {
2564 'use strict';
2565
2566 angular.module('xos.helpers')
2567 /**
2568 * @ngdoc service
2569 * @name xos.helpers.Networks
2570 * @description Angular resource to fetch /api/core/networks/:id/
2571 **/
2572 .service('Networks', ["$resource", function ($resource) {
2573 return $resource('/api/core/networks/:id/', { id: '@id' }, {
2574 update: { method: 'PUT' }
2575 });
2576 }]);
2577})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002578'use strict';
2579
2580(function () {
2581 'use strict';
2582
2583 angular.module('xos.helpers')
2584 /**
2585 * @ngdoc service
2586 * @name xos.helpers.Me
2587 * @description Http read-only api to fetch /api/utility/me/
2588 **/
2589 .service('Me', ["$q", "$http", function ($q, $http) {
2590
2591 this.get = function () {
2592 var deferred = $q.defer();
2593
2594 $http.get('/api/utility/me/').then(function (res) {
2595 deferred.resolve(res.data);
2596 }).catch(function (e) {
2597 deferred.reject(e);
2598 });
2599 return deferred.promise;
2600 };
2601 }]);
2602})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002603'use strict';
2604
2605(function () {
2606 'use strict';
2607
2608 angular.module('xos.helpers')
2609 /**
2610 * @ngdoc service
2611 * @name xos.helpers.Instances
2612 * @description Angular resource to fetch /api/core/instances/:id/
2613 **/
2614 .service('Instances', ["$resource", function ($resource) {
2615 return $resource('/api/core/instances/:id/', { id: '@id' }, {
2616 update: { method: 'PUT' }
2617 });
2618 }]);
2619})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002620'use strict';
2621
2622(function () {
2623 'use strict';
2624
2625 angular.module('xos.helpers')
2626 /**
2627 * @ngdoc service
2628 * @name xos.helpers.Images
2629 * @description Angular resource to fetch /api/core/images/
2630 **/
2631 .service('Images', ["$resource", function ($resource) {
2632 return $resource('/api/core/images/:id/', { id: '@id' }, {
2633 update: { method: 'PUT' }
2634 });
2635 }]);
2636})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002637'use strict';
2638
2639(function () {
2640 'use strict';
2641
2642 angular.module('xos.helpers')
2643 /**
2644 * @ngdoc service
2645 * @name xos.helpers.Flavors
2646 * @description Angular resource to fetch /api/core/flavors/:id/
2647 **/
2648 .service('Flavors', ["$resource", function ($resource) {
2649 return $resource('/api/core/flavors/:id/', { id: '@id' }, {
2650 update: { method: 'PUT' }
2651 });
2652 }]);
2653})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002654'use strict';
2655
2656(function () {
2657 'use strict';
2658
2659 angular.module('xos.helpers')
2660 /**
2661 * @ngdoc service
2662 * @name xos.helpers.Example-Services-Collection
2663 * @description Angular resource to fetch /api/service/exampleservice/
2664 **/
2665 .service('Example-Services-Collection', ["$resource", function ($resource) {
2666 return $resource('/api/service/exampleservice/');
2667 }]);
2668})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002669'use strict';
2670
2671(function () {
2672 'use strict';
2673
2674 angular.module('xos.helpers')
2675 /**
2676 * @ngdoc service
2677 * @name xos.helpers.Deployments
2678 * @description Angular resource to fetch /api/core/deployments/:id/
2679 **/
2680 .service('Deployments', ["$resource", function ($resource) {
2681 return $resource('/api/core/deployments/:id/', { id: '@id' }, {
2682 update: { method: 'PUT' }
2683 });
2684 }]);
2685})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002686'use strict';
2687
2688(function () {
2689 'use strict';
2690
2691 angular.module('xos.helpers')
2692 /**
2693 * @ngdoc service
2694 * @name xos.helpers.Dashboards
2695 * @description Angular resource to fetch /api/core/dashboardviews/:id/
2696 **/
2697 .service('Dashboards', ["$resource", "$q", "$http", function ($resource, $q, $http) {
2698 var r = $resource('/api/core/dashboardviews/:id/', { id: '@id' }, {
2699 update: { method: 'PUT' }
2700 });
2701
2702 r.prototype.$save = function () {
2703 var d = $q.defer();
2704
2705 $http.put('/api/core/dashboardviews/' + this.id + '/', this).then(function (res) {
2706 d.resolve(res.data);
2707 }).catch(function (e) {
2708 d.reject(e.data);
2709 });
2710
2711 return d.promise;
2712 };
2713
2714 return r;
2715 }]);
2716})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002717'use strict';
2718
2719(function () {
2720
2721 angular.module('xos.helpers')
2722
2723 /**
2724 * @ngdoc service
2725 * @name xos.helpers.XosUserPrefs
2726 * @description
2727 * This service is used to store the user preferences in cookies, so that they survive to page changes.
2728 * The structure of the user preference is:
2729 * ```
2730 * {
2731 * synchronizers: {
2732 * notification: {
2733 * 'volt': boolean,
2734 * 'openstack': boolean,
2735 * ...
2736 * }
2737 * }
2738 * userData: {
2739 * current_user_site_id: Number,
2740 * current_user_site_user_names: Array[1],
2741 * ...
2742 * }
2743 * }
2744 * ```
2745 **/
2746
2747 .service('XosUserPrefs', ["$cookies", "Me", "$q", function ($cookies, Me, $q) {
2748 var _this = this;
2749
2750 var userPrefs = $cookies.get('xosUserPrefs') ? angular.fromJson($cookies.get('xosUserPrefs')) : {};
2751
2752 /**
2753 * @ngdoc method
2754 * @name xos.helpers.XosUserPrefs#getAll
2755 * @methodOf xos.helpers.XosUserPrefs
2756 * @description
2757 * Return all the user preferences stored in cookies
2758 * @returns {object} The user preferences
2759 **/
2760 this.getAll = function () {
2761 userPrefs = $cookies.get('xosUserPrefs') ? angular.fromJson($cookies.get('xosUserPrefs')) : {};
2762 return userPrefs;
2763 };
2764
2765 /**
2766 * @ngdoc method
2767 * @name xos.helpers.XosUserPrefs#setAll
2768 * @methodOf xos.helpers.XosUserPrefs
2769 * @description
2770 * Override all user preferences
2771 * @param {object} prefs The user preferences
2772 **/
2773 this.setAll = function (prefs) {
2774 $cookies.put('xosUserPrefs', angular.toJson(prefs));
2775 };
2776
2777 /**
2778 * @ngdoc method
2779 * @name xos.helpers.XosUserPrefs#getSynchronizerNotificationStatus
2780 * @methodOf xos.helpers.XosUserPrefs
2781 * @description
2782 * Return the synchronizer notification status, if name is not provided return the status for all synchronizers
2783 * @param {string=} prefs The synchronizer name
2784 * @returns {object | string} The synchronizer status
2785 **/
2786 this.getSynchronizerNotificationStatus = function () {
2787 var name = arguments.length <= 0 || arguments[0] === undefined ? false : arguments[0];
2788
2789 if (name) {
2790 return _this.getAll().synchronizers.notification[name];
2791 }
2792 return _this.getAll().synchronizers.notification;
2793 };
2794
2795 /**
2796 * @ngdoc method
2797 * @name xos.helpers.XosUserPrefs#getUserDetailsCookie
2798 * @methodOf xos.helpers.XosUserPrefs
2799 * @description
2800 * Return all the user details stored in cookies or call the service
2801 * @returns {object} The user details
2802 **/
2803 this.getUserDetailsCookie = function () {
2804 var defer = $q.defer();
2805 var localPref = _this.getAll();
2806 if (!localPref.userData) {
2807 _this.setUserDetailsCookie().$promise.then(function (data) {
2808 defer.resolve(data);
2809 });
2810 } else {
2811 defer.resolve(localPref.userData);
2812 }
2813 return { $promise: defer.promise };
2814 };
2815
2816 /**
2817 * @ngdoc method
2818 * @name xos.helpers.XosUserPrefs#setUserDetailsCookie
2819 * @methodOf xos.helpers.XosUserPrefs
2820 * @description
2821 * Save the user details in the cookie
2822 * @param {object} details stored in cookie
2823 * @param {objects} returns the user details as a promise
2824 **/
2825 this.setUserDetailsCookie = function () {
2826 var userData = arguments.length <= 0 || arguments[0] === undefined ? null : arguments[0];
2827
2828
2829 var defer = $q.defer();
2830 var cookies = _this.getAll();
2831 if (!userData) {
2832 Me.get().then(function (user) {
2833 cookies.userData = user;
2834 _this.setAll(cookies);
2835 defer.resolve(user);
2836 }).catch(function (e) {
2837 defer.reject(e);
2838 });
2839 } else {
2840 cookies.userData = userData;
2841 _this.setAll(cookies);
2842 defer.resolve(userData);
2843 }
2844 return { $promise: defer.promise };
2845 };
2846
2847 /**
2848 * @ngdoc method
2849 * @name xos.helpers.XosUserPrefs#setSynchronizerNotificationStatus
2850 * @methodOf xos.helpers.XosUserPrefs
2851 * @description
2852 * Update the notification status for a single synchronizer
2853 * @param {string} name The synchronizer name
2854 * @param {boolean} value The notification status (true means that it has been sent)
2855 **/
2856
2857 this.setSynchronizerNotificationStatus = function () {
2858 var name = arguments.length <= 0 || arguments[0] === undefined ? false : arguments[0];
2859 var value = arguments[1];
2860
2861 if (!name) {
2862 throw new Error('[XosUserPrefs] When updating a synchronizer is mandatory to provide a name.');
2863 }
2864
2865 var cookies = _this.getAll();
2866
2867 if (!cookies.synchronizers) {
2868 cookies.synchronizers = {
2869 notification: {}
2870 };
2871 }
2872 cookies.synchronizers.notification[name] = value;
2873 _this.setAll(cookies);
2874 };
2875 }]);
2876})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002877'use strict';
2878
2879(function () {
2880 'use strict';
2881
2882 /**
2883 * @ngdoc service
2884 * @name xos.helpers.ServiceGraph
2885 * @description This factory define a set of helper function to query the service tenancy graph
2886 **/
2887
2888 angular.module('xos.helpers').service('GraphService', ["$q", "Tenants", "Services", function ($q, Tenants, Services) {
2889 var _this = this;
2890
2891 this.loadCoarseData = function () {
2892
2893 var services = void 0;
2894
2895 var deferred = $q.defer();
2896
2897 Services.query().$promise.then(function (res) {
2898 services = res;
2899 return Tenants.query({ kind: 'coarse' }).$promise;
2900 }).then(function (tenants) {
2901 deferred.resolve({
2902 tenants: tenants,
2903 services: services
2904 });
2905 });
2906
2907 return deferred.promise;
2908 };
2909
2910 this.getCoarseGraph = function () {
2911 _this.loadCoarseData().then(function (res) {
2912 console.log(res);
2913 });
2914 return 'ciao';
2915 };
2916 }]);
2917})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002918'use strict';
2919
2920/* eslint-disable angular/ng_window_service*/
2921(function () {
2922 'use strict';
2923
2924 angular.module('xos.helpers').factory('Notification', function () {
2925 return window.Notification;
2926 })
2927 /**
2928 * @ngdoc service
2929 * @name xos.helpers.xosNotification
2930 * @description This factory define a set of helper function to trigger desktop notification
2931 **/
2932 .service('xosNotification', ["$q", "$log", "Notification", function ($q, $log, Notification) {
2933 var _this = this;
2934
2935 this.checkPermission = function () {
2936 var deferred = $q.defer();
2937 Notification.requestPermission().then(function (permission) {
2938 if (permission === 'granted') {
2939 deferred.resolve(permission);
2940 } else {
2941 deferred.reject(permission);
2942 }
2943 });
2944 return deferred.promise;
2945 };
2946
2947 this.sendNotification = function (title, options) {
2948 var notification = new Notification(title, options);
2949 notification.onerror = function (err) {
2950 $log.error(err);
2951 };
2952 };
2953
2954 /**
2955 * @ngdoc method
2956 * @name xos.helpers.xosNotification#notify
2957 * @methodOf xos.helpers.xosNotification
2958 * @description
2959 * This method will check for user permission and if granted will send a browser notification.
2960 * @param {string} title The notification title
2961 * @param {object} options The notification options: `{icon: 'url', body: 'Notification body'}`
2962 **/
2963
2964 this.notify = function (title, options) {
2965 if (!('Notification' in window)) {
2966 $log.info('This browser does not support desktop notification');
2967 } else if (Notification.permission !== 'granted') {
2968 _this.checkPermission().then(function () {
2969 return _this.sendNotification(title, options);
2970 });
2971 } else if (Notification.permission === 'granted') {
2972 _this.sendNotification(title, options);
2973 }
2974 };
2975 }]);
2976})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07002977'use strict';
2978
2979(function () {
2980 'use strict';
2981
2982 /**
2983 * @ngdoc service
2984 * @name xos.helpers.NoHyperlinks
2985 * @description This factory is automatically loaded trough xos.helpers and will add an $http interceptor that will add ?no_hyperlinks=1 to your api request, that is required by django
2986 **/
2987
2988 angular.module('xos.helpers').factory('NoHyperlinks', noHyperlinks);
2989
2990 function noHyperlinks() {
2991 return {
2992 request: function request(_request) {
2993 if (_request.url.indexOf('.html') === -1) {
2994 _request.url += '?no_hyperlinks=1';
2995 }
2996 return _request;
2997 }
2998 };
2999 }
3000})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07003001'use strict';
3002
3003// TODO write tests for log
3004
3005/* eslint-disable angular/ng_window_service*/
3006
3007angular.module('xos.helpers').config(['$provide', function ($provide) {
3008 // Use the `decorator` solution to substitute or attach behaviors to
3009 // original service instance; @see angular-mocks for more examples....
3010
3011 $provide.decorator('$log', ['$delegate', function ($delegate) {
3012
3013 var isLogEnabled = function isLogEnabled() {
3014 return window.location.href.indexOf('debug=true') >= 0;
3015 };
3016 // Save the original $log.debug()
3017 var logFn = $delegate.log;
3018 var infoFn = $delegate.info;
3019 var warnFn = $delegate.warn;
3020 //let errorFn = $delegate.error;
3021 var debugFn = $delegate.debug;
3022
3023 // create the replacement function
3024 var replacement = function replacement(fn) {
3025 return function () {
3026 //console.log(`Is Log Enabled: ${isLogEnabled()}`)
3027 if (!isLogEnabled()) {
3028 // console.log('logging is disabled');
3029 return;
3030 }
3031
3032 var args = [].slice.call(arguments);
3033 var now = new Date();
3034
3035 // Prepend timestamp
3036 args[0] = '[' + now.getHours() + ':' + now.getMinutes() + ':' + now.getSeconds() + '] ' + args[0];
3037
3038 // HACK awfull fix for angular mock implementation whithin jasmine test failing issue
3039 if (angular.isFunction($delegate.reset) && !($delegate.debug.logs instanceof Array)) {
3040 // if we are within the mock and did not reset yet, we call it to avoid issue
3041 // console.log('mock log impl fix to avoid logs array not existing...');
3042 $delegate.reset();
3043 }
3044
3045 // Call the original with the output prepended with formatted timestamp
3046
3047 return fn.apply(null, args);
3048 };
3049 };
3050
3051 $delegate.info = replacement(infoFn);
3052 $delegate.log = replacement(logFn);
3053 $delegate.warn = replacement(warnFn);
3054 //$delegate.error = replacement(errorFn); // note this will prevent errors to be printed
3055 $delegate.debug = replacement(debugFn);
3056
3057 return $delegate;
3058 }]);
3059}]);
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07003060'use strict';
3061
3062(function () {
3063 'use strict';
3064
3065 /**
3066 * @ngdoc service
3067 * @name xos.helpers.SetCSRFToken
3068 * @description This factory is automatically loaded trough xos.helpers and will add an $http interceptor that will the CSRF-Token to your request headers
3069 **/
3070
3071 setCSRFToken.$inject = ["$cookies"];
3072 angular.module('xos.helpers').factory('SetCSRFToken', setCSRFToken);
3073
3074 function setCSRFToken($cookies) {
3075 return {
3076 request: function request(_request) {
3077 if (_request.method !== 'GET') {
3078 _request.headers['X-CSRFToken'] = $cookies.get('xoscsrftoken');
3079 }
3080 return _request;
3081 }
3082 };
3083 }
3084})();
Matteo Scandoloa71ccfd2016-07-22 10:19:15 -07003085/**
3086* @ngdoc overview
3087* @name ngXosLib
3088* @id index
3089* @description
3090* # Welcome to the ngXosLib documentation! <br/>
3091* This is the module that group all the helpers service and UI components for XOS.
3092* <br/><br/>
3093* You can find all the documentation related to the UI Component Library here: <a href="#/module/xos.uiComponents"> xos.uiComponents</a> <br/>
3094* and the documentation related to all the other helpers here: <a href="#/module/xos.helpers"> xos.helpers</a> <br/>
3095* ## Issues
3096* Please report issues at https://jira.opencord.org
3097**/
Matteo Scandolobfb8ebd2016-10-28 17:53:05 +02003098"use strict";