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