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