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