Developer view first draft
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartPie/smartPie.component.js b/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartPie/smartPie.component.js
index 6616b50..c1f08fa 100644
--- a/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartPie/smartPie.component.js
+++ b/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartPie/smartPie.component.js
@@ -187,7 +187,7 @@
`,
bindToController: true,
controllerAs: 'vm',
- controller: function($injector, $timeout, $interval, $scope, _){
+ controller: function($injector, $interval, $scope, $timeout, _){
if(!this.config.resource && !this.config.data){
throw new Error('[xosSmartPie] Please provide a resource or an array of data in the configuration');
@@ -198,11 +198,13 @@
const formatLabels = (data) => angular.isFunction(this.config.labelFormatter) ? this.config.labelFormatter(Object.keys(data)) : Object.keys(data);
const prepareData = (data) => {
- // group data
- let grouped = groupData(data);
- this.data = formatData(grouped);
- // create labels
- this.labels = formatLabels(grouped);
+ // $timeout(() => {
+ // group data
+ let grouped = groupData(data);
+ this.data = formatData(grouped);
+ // create labels
+ this.labels = formatLabels(grouped);
+ // }, 10);
}
if(this.config.resource){
@@ -234,6 +236,14 @@
}, true);
}
+ $scope.$on('create', function (event, chart) {
+ console.log(`create: ${chart.id}`);
+ });
+
+ $scope.$on('destroy', function (event, chart) {
+ console.log(`destroy: ${chart.id}`);
+ });
+
}
};
});
diff --git a/views/ngXosViews/developer/gulp/build.js b/views/ngXosViews/developer/gulp/build.js
index b90ff38..f86af0f 100644
--- a/views/ngXosViews/developer/gulp/build.js
+++ b/views/ngXosViews/developer/gulp/build.js
@@ -98,8 +98,8 @@
gulp.task('copyHtml', function(){
return gulp.src(options.src + 'index.html')
// remove dev dependencies from html
- .pipe(replace(/<!-- bower:css -->(\n.*)*\n<!-- endbower --><!-- endcss -->/, ''))
- .pipe(replace(/<!-- bower:js -->(\n.*)*\n<!-- endbower --><!-- endjs -->/, ''))
+ .pipe(replace(/<!-- bower:css -->(\n^<link.*)*\n<!-- endbower -->/gmi, ''))
+ .pipe(replace(/<!-- bower:js -->(\n^<script.*)*\n<!-- endbower -->/gmi, ''))
// injecting minified files
.pipe(
inject(
diff --git a/views/ngXosViews/developer/src/js/main.js b/views/ngXosViews/developer/src/js/main.js
index c4ddcd8..5cb919b 100644
--- a/views/ngXosViews/developer/src/js/main.js
+++ b/views/ngXosViews/developer/src/js/main.js
@@ -23,14 +23,17 @@
bindToController: true,
controllerAs: 'vm',
templateUrl: 'templates/developer-dashboard.tpl.html',
- controller: function($timeout, SlicesPlus, _){
+ controller: function($scope, $timeout, SlicesPlus, Instances, _){
this.instancePerSliceConfig = {
- resource: 'Instances',
+ data: [],
groupBy: 'slice',
legend: true,
+ classes: 'instance per slice',
labelFormatter: (labels) => {
- return labels.map(l => _.find(this.slices, {id: parseInt(l)}).name);
+ return labels.map(l => {
+ return _.find(this.slices, {id: parseInt(l)}).name
+ });
}
};
@@ -38,12 +41,14 @@
data: [],
groupBy: 'site',
legend: true,
+ classes: 'instance per site',
};
this.networkPerSliceConfig = {
data: [],
groupBy: 'name',
legend: true,
+ classes: 'network per slice',
};
this.tableConfig = {
@@ -82,13 +87,17 @@
// retrieving user list
SlicesPlus.query().$promise
- .then(slices => {
+ .then((slices) => {
+ this.slices = slices;
+ return Instances.query().$promise
+ })
+ .then(instances => {
// formatting data in this way sucks.
// Provide a way to just pass data to the chart if needed [smartPie].
// retrieving network per slices
- let networkPerSlice = _.reduce(slices, (list, s) => {
+ let networkPerSlice = _.reduce(this.slices, (list, s) => {
if( s.networks.length > 1){
// push s.neworks.length values in array
for(let i = 0; i < s.networks.length; i++){
@@ -102,7 +111,7 @@
}, []);
// retrieving instance distribution across sites
- let instancePerSite = _.reduce(slices, (list, s) => {
+ let instancePerSite = _.reduce(this.slices, (list, s) => {
_.forEach(Object.keys(s.instance_distribution), k => {
for(let i = 0; i < s.instance_distribution[k]; i++){
list.push({site: k, instance: i})
@@ -113,12 +122,10 @@
this.sites = Object.keys(_.groupBy(instancePerSite, 'site'));
- $timeout(() => {
- this.instancePerSiteConfig.data = instancePerSite;
- this.networkPerSliceConfig.data = networkPerSlice;
- }, 0);
+ this.instancePerSliceConfig.data = instances;
+ this.instancePerSiteConfig.data = instancePerSite;
+ this.networkPerSliceConfig.data = networkPerSlice;
- this.slices = slices;
})
.catch((e) => {
throw new Error(e);
diff --git a/views/ngXosViews/developer/src/templates/developer-dashboard.tpl.html b/views/ngXosViews/developer/src/templates/developer-dashboard.tpl.html
index f1688fb..fd82f77 100644
--- a/views/ngXosViews/developer/src/templates/developer-dashboard.tpl.html
+++ b/views/ngXosViews/developer/src/templates/developer-dashboard.tpl.html
@@ -1,13 +1,13 @@
<div class="row">
- <div ng-class="{'col-sm-4': vm.sites.length > 1, 'col-sm-6': vm.sites.length <= 1}" class="text-center">
+ <div ng-class="{'col-sm-4': vm.sites.length > 1 || !vm.sites, 'col-sm-6': vm.sites.length <= 1}" class="text-center">
<h3>Instances per Slice</h3>
- <xos-smart-pie ng-if="vm.slices" config="vm.instancePerSliceConfig"></xos-smart-pie>
+ <xos-smart-pie ng-if="vm.instancePerSliceConfig.data.length > 0" config="vm.instancePerSliceConfig"></xos-smart-pie>
</div>
<div ng-if="vm.sites.length > 1" class="col-sm-4 text-center">
<h3>Instances per Site</h3>
<xos-smart-pie ng-if="vm.instancePerSiteConfig.data.length > 0" config="vm.instancePerSiteConfig"></xos-smart-pie>
</div>
- <div ng-class="{'col-sm-4': vm.sites.length > 1, 'col-sm-6': vm.sites.length <= 1}" class="text-center">
+ <div ng-class="{'col-sm-4': vm.sites.length > 1 || !vm.sites, 'col-sm-6': vm.sites.length <= 1}" class="text-center">
<h3>Network per Slice</h3>
<xos-smart-pie ng-if="vm.networkPerSliceConfig.data.length > 0" config="vm.networkPerSliceConfig"></xos-smart-pie>
</div>
diff --git a/xos/core/xoslib/dashboards/xosDeveloper.html b/xos/core/xoslib/dashboards/xosDeveloper.html
index ee7a28b..f3abf18 100644
--- a/xos/core/xoslib/dashboards/xosDeveloper.html
+++ b/xos/core/xoslib/dashboards/xosDeveloper.html
@@ -1,6 +1,5 @@
<!-- browserSync -->
-<!-- bower:css -->
-<!-- endbower -->
+
<!-- endcss -->
<!-- inject:css -->
<link rel="stylesheet" href="/static/css/xosDeveloper.css">
@@ -10,8 +9,7 @@
<div ui-view></div>
</div>
-<!-- bower:js -->
-<!-- endbower -->
+
<!-- endjs -->
<!-- inject:js -->
<script src="/static/js/xosDeveloper.js"></script>
diff --git a/xos/core/xoslib/static/css/xosDeveloper.css b/xos/core/xoslib/static/css/xosDeveloper.css
index 459bc8a..dee3249 100644
--- a/xos/core/xoslib/static/css/xosDeveloper.css
+++ b/xos/core/xoslib/static/css/xosDeveloper.css
@@ -1,19 +1 @@
-#xosDeveloper .pie-legend li {
- display: inline-block;
- white-space: nowrap;
- position: relative;
- margin-bottom: 4px;
- border-radius: 5px;
- padding: 2px 8px 2px 28px;
- font-size: smaller;
- cursor: default;
-}
-
-#xosDeveloper .pie-legend-icon {
- display: block;
- position: absolute;
- left: 0;
- top: 0;
- width: 20px;
- height: 20px;
- border-radius: 5px; }
+#xosDeveloper .pie-legend li{display:inline-block;white-space:nowrap;position:relative;margin-bottom:4px;border-radius:5px;padding:2px 8px 2px 28px;font-size:smaller;cursor:default}#xosDeveloper .pie-legend-icon{display:block;position:absolute;left:0;top:0;width:20px;height:20px;border-radius:5px}
\ No newline at end of file
diff --git a/xos/core/xoslib/static/js/vendor/ngXosHelpers.js b/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
index 584e53a..35b33dc 100644
--- a/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
+++ b/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
@@ -36,6 +36,479 @@
*
* Visit http://guide.xosproject.org/devguide/addview/ for more information
*
+ * Created by teone on 3/24/16.
+ */
+
+(function () {
+ 'use strict';
+
+ angular.module('xos.uiComponents')
+
+ /**
+ * @ngdoc directive
+ * @name xos.uiComponents.directive:xosSmartTable
+ * @link xos.uiComponents.directive:xosTable xosTable
+ * @link xos.uiComponents.directive:xosForm xosForm
+ * @restrict E
+ * @description The xos-table directive
+ * @param {Object} config The configuration for the component,
+ * it is composed by the name of an angular [$resource](https://docs.angularjs.org/api/ngResource/service/$resource)
+ * and an array of fields that shouldn't be printed.
+ * ```
+ * {
+ resource: 'Users',
+ hiddenFields: []
+ }
+ * ```
+ * @scope
+ * @example
+ <example module="sampleSmartTable">
+ <file name="index.html">
+ <div ng-controller="SampleCtrl as vm">
+ <xos-smart-table config="vm.config"></xos-smart-table>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('sampleSmartTable', ['xos.uiComponents', 'ngResource', 'ngMockE2E'])
+ // This is only for documentation purpose
+ .run(function($httpBackend, _){
+ let datas = [{id: 1, name: 'Jhon', surname: 'Doe'}];
+ let count = 1;
+ let paramsUrl = new RegExp(/\/test\/(.+)/);
+ $httpBackend.whenDELETE(paramsUrl, undefined, ['id']).respond((method, url, data, headers, params) => {
+ data = angular.fromJson(data);
+ let id = url.match(paramsUrl)[1];
+ _.remove(datas, (d) => {
+ return d.id === parseInt(id);
+ })
+ return [204];
+ });
+ $httpBackend.whenGET('/test').respond(200, datas)
+ $httpBackend.whenPOST('/test').respond((method, url, data) => {
+ data = angular.fromJson(data);
+ data.id = ++count;
+ datas.push(data);
+ return [201, data, {}];
+ });
+ })
+ .factory('_', function($window){
+ return $window._;
+ })
+ .service('SampleResource', function($resource){
+ return $resource('/test/:id', {id: '@id'});
+ })
+ // End of documentation purpose, example start
+ .controller('SampleCtrl', function(){
+ this.config = {
+ resource: 'SampleResource'
+ };
+ });
+ </file>
+ </example>
+ */
+
+ .directive('xosSmartTable', function () {
+ return {
+ restrict: 'E',
+ scope: {
+ config: '='
+ },
+ 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 ',
+ bindToController: true,
+ controllerAs: 'vm',
+ controller: ["$injector", "LabelFormatter", "_", "XosFormHelpers", function controller($injector, LabelFormatter, _, XosFormHelpers) {
+ var _this = this;
+
+ // TODO
+ // - Validate the config (what if resource does not exist?)
+
+ // NOTE
+ // Corner case
+ // - if response is empty, how can we generate a form ?
+
+ this.responseMsg = false;
+ this.responseErr = false;
+
+ this.tableConfig = {
+ columns: [],
+ actions: [{
+ label: 'delete',
+ icon: 'remove',
+ cb: function cb(item) {
+ _this.Resource.delete({ id: item.id }).$promise.then(function () {
+ _.remove(_this.data, function (d) {
+ return d.id === item.id;
+ });
+ _this.responseMsg = _this.config.resource + ' with id ' + item.id + ' successfully deleted';
+ }).catch(function (err) {
+ _this.responseErr = err.data.detail || 'Error while deleting ' + _this.config.resource + ' with id ' + item.id;
+ });
+ },
+ color: 'red'
+ }, {
+ label: 'details',
+ icon: 'search',
+ cb: function cb(item) {
+ _this.detailedItem = item;
+ }
+ }],
+ classes: 'table table-striped table-bordered table-responsive',
+ filter: 'field',
+ order: true,
+ pagination: {
+ pageSize: 10
+ }
+ };
+
+ this.formConfig = {
+ exclude: this.config.hiddenFields,
+ fields: {},
+ formName: this.config.resource + 'Form',
+ actions: [{
+ label: 'Save',
+ icon: 'ok',
+ cb: function cb(item) {
+ var p = void 0;
+ var isNew = true;
+
+ if (item.id) {
+ p = item.$update();
+ isNew = false;
+ } else {
+ p = item.$save();
+ }
+
+ p.then(function (res) {
+ if (isNew) {
+ _this.data.push(angular.copy(res));
+ }
+ delete _this.detailedItem;
+ _this.responseMsg = _this.config.resource + ' with id ' + item.id + ' successfully saved';
+ }).catch(function (err) {
+ _this.responseErr = err.data.detail || 'Error while saving ' + _this.config.resource + ' with id ' + item.id;
+ });
+ },
+ class: 'success'
+ }]
+ };
+
+ this.cleanForm = function () {
+ delete _this.detailedItem;
+ };
+
+ this.createItem = function () {
+ _this.detailedItem = new _this.Resource();
+ };
+
+ this.Resource = $injector.get(this.config.resource);
+
+ var getData = function getData() {
+ _this.Resource.query().$promise.then(function (res) {
+
+ if (!res[0]) {
+ return;
+ }
+
+ var item = res[0];
+ var props = Object.keys(item);
+
+ _.remove(props, function (p) {
+ return p == 'id' || p == 'validators';
+ });
+
+ // TODO move out cb
+ if (angular.isArray(_this.config.hiddenFields)) {
+ props = _.difference(props, _this.config.hiddenFields);
+ }
+
+ var labels = props.map(function (p) {
+ return LabelFormatter.format(p);
+ });
+
+ props.forEach(function (p, i) {
+ _this.tableConfig.columns.push({
+ label: labels[i],
+ prop: p
+ });
+ });
+
+ // build form structure
+ props.forEach(function (p, i) {
+ _this.formConfig.fields[p] = {
+ label: LabelFormatter.format(labels[i]).replace(':', ''),
+ type: XosFormHelpers._getFieldFormat(item[p])
+ };
+ });
+
+ _this.data = res;
+ });
+ };
+
+ getData();
+ }]
+ };
+ });
+})();
+//# sourceMappingURL=../../../maps/ui_components/smartComponents/smartTable/smartTable.component.js.map
+
+'use strict';
+
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 3/24/16.
+ */
+
+(function () {
+ 'use strict';
+
+ angular.module('xos.uiComponents')
+ /**
+ * @ngdoc directive
+ * @name xos.uiComponents.directive:xosSmartPie
+ * @restrict E
+ * @description The xos-table directive
+ * @param {Object} config The configuration for the component,
+ * it is composed by the name of an angular [$resource](https://docs.angularjs.org/api/ngResource/service/$resource)
+ * and a field name that is used to group the data.
+ * ```
+ * {
+ resource: 'Users',
+ groupBy: 'fieldName',
+ classes: 'my-custom-class',
+ labelFormatter: (labels) => {
+ // here you can format your label,
+ // you should return an array with the same order
+ return labels;
+ }
+ }
+ * ```
+ * @scope
+ * @example
+
+ Displaying Local data
+ <example module="sampleSmartPieLocal">
+ <file name="index.html">
+ <div ng-controller="SampleCtrlLocal as vm">
+ <xos-smart-pie config="vm.configLocal"></xos-smart-pie>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('sampleSmartPieLocal', ['xos.uiComponents'])
+ .factory('_', function($window){
+ return $window._;
+ })
+ .controller('SampleCtrlLocal', function($timeout){
+
+ this.datas = [
+ {id: 1, first_name: 'Jon', last_name: 'aaa', category: 2},
+ {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 1},
+ {id: 3, first_name: 'Aria', last_name: 'Stark', category: 2}
+ ];
+ this.configLocal = {
+ data: [],
+ groupBy: 'category',
+ classes: 'local',
+ labelFormatter: (labels) => {
+ return labels.map(l => l === '1' ? 'North' : 'Dragon');
+ }
+ };
+
+ $timeout(() => {
+ // this need to be triggered in this way just because of ngDoc,
+ // otherwise you can assign data directly in the config
+ this.configLocal.data = this.datas;
+ }, 1)
+ });
+ </file>
+ </example>
+ Fetching data from API
+ <example module="sampleSmartPieResource">
+ <file name="index.html">
+ <div ng-controller="SampleCtrl as vm">
+ <xos-smart-pie config="vm.config"></xos-smart-pie>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('sampleSmartPieResource', ['xos.uiComponents', 'ngResource', 'ngMockE2E'])
+ .controller('SampleCtrl', function(){
+ this.config = {
+ resource: 'SampleResource',
+ groupBy: 'category',
+ classes: 'resource',
+ labelFormatter: (labels) => {
+ return labels.map(l => l === '1' ? 'North' : 'Dragon');
+ }
+ };
+ });
+ </file>
+ <file name="backendPoll.js">
+ angular.module('sampleSmartPieResource')
+ .run(function($httpBackend, _){
+ let datas = [
+ {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
+ {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
+ {id: 3, first_name: 'Aria', last_name: 'Stark', category: 1}
+ ];
+ $httpBackend.whenGET('/test').respond(200, datas)
+ })
+ .factory('_', function($window){
+ return $window._;
+ })
+ .service('SampleResource', function($resource){
+ return $resource('/test/:id', {id: '@id'});
+ })
+ </file>
+ </example>
+ Polling data from API
+ <example module="sampleSmartPiePoll">
+ <file name="index.html">
+ <div ng-controller="SampleCtrl as vm">
+ <xos-smart-pie config="vm.config"></xos-smart-pie>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('sampleSmartPiePoll', ['xos.uiComponents', 'ngResource', 'ngMockE2E'])
+ .controller('SampleCtrl', function(){
+ this.config = {
+ resource: 'SampleResource',
+ groupBy: 'category',
+ poll: 2,
+ labelFormatter: (labels) => {
+ return labels.map(l => l === '1' ? 'Active' : 'Banned');
+ }
+ };
+ });
+ </file>
+ <file name="backend.js">
+ angular.module('sampleSmartPiePoll')
+ .run(function($httpBackend, _){
+ let mock = [
+ [
+ {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
+ {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
+ {id: 3, first_name: 'Aria', last_name: 'Stark', category: 1},
+ {id: 3, first_name: 'Tyrion', last_name: 'Lannister', category: 1}
+ ],
+ [
+ {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
+ {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
+ {id: 3, first_name: 'Aria', last_name: 'Stark', category: 2},
+ {id: 3, first_name: 'Tyrion', last_name: 'Lannister', category: 2}
+ ],
+ [
+ {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
+ {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
+ {id: 3, first_name: 'Aria', last_name: 'Stark', category: 1},
+ {id: 3, first_name: 'Tyrion', last_name: 'Lannister', category: 2}
+ ]
+ ];
+ $httpBackend.whenGET('/test').respond(function(method, url, data, headers, params) {
+ return [200, mock[Math.round(Math.random() * 3)]];
+ });
+ })
+ .factory('_', function($window){
+ return $window._;
+ })
+ .service('SampleResource', function($resource){
+ return $resource('/test/:id', {id: '@id'});
+ })
+ </file>
+ </example>
+ */
+ .directive('xosSmartPie', function () {
+ return {
+ restrict: 'E',
+ scope: {
+ config: '='
+ },
+ 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 ',
+ bindToController: true,
+ controllerAs: 'vm',
+ controller: ["$injector", "$interval", "$scope", "$timeout", "_", function controller($injector, $interval, $scope, $timeout, _) {
+ var _this = this;
+
+ if (!this.config.resource && !this.config.data) {
+ throw new Error('[xosSmartPie] Please provide a resource or an array of data in the configuration');
+ }
+
+ var groupData = function groupData(data) {
+ return _.groupBy(data, _this.config.groupBy);
+ };
+ var formatData = function formatData(data) {
+ return _.reduce(Object.keys(data), function (list, group) {
+ return list.concat(data[group].length);
+ }, []);
+ };
+ var formatLabels = function formatLabels(data) {
+ return angular.isFunction(_this.config.labelFormatter) ? _this.config.labelFormatter(Object.keys(data)) : Object.keys(data);
+ };
+
+ var prepareData = function prepareData(data) {
+ // $timeout(() => {
+ // group data
+ var grouped = groupData(data);
+ _this.data = formatData(grouped);
+ // create labels
+ _this.labels = formatLabels(grouped);
+ // }, 10);
+ };
+
+ if (this.config.resource) {
+ (function () {
+
+ _this.Resource = $injector.get(_this.config.resource);
+ var getData = function getData() {
+ _this.Resource.query().$promise.then(function (res) {
+
+ if (!res[0]) {
+ return;
+ }
+
+ prepareData(res);
+ });
+ };
+
+ getData();
+
+ if (_this.config.poll) {
+ $interval(function () {
+ getData();
+ }, _this.config.poll * 1000);
+ }
+ })();
+ } else {
+ $scope.$watch(function () {
+ return _this.config.data;
+ }, function (data) {
+ if (data) {
+ prepareData(_this.config.data);
+ }
+ }, true);
+ }
+
+ $scope.$on('create', function (event, chart) {
+ console.log('create: ' + chart.id);
+ });
+
+ $scope.$on('destroy', function (event, chart) {
+ console.log('destroy: ' + chart.id);
+ });
+ }]
+ };
+ });
+})();
+//# sourceMappingURL=../../../maps/ui_components/smartComponents/smartPie/smartPie.component.js.map
+
+'use strict';
+
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
* Created by teone on 4/15/16.
*/
@@ -1027,469 +1500,6 @@
'use strict';
-/**
- * © OpenCORD
- *
- * Visit http://guide.xosproject.org/devguide/addview/ for more information
- *
- * Created by teone on 3/24/16.
- */
-
-(function () {
- 'use strict';
-
- angular.module('xos.uiComponents')
-
- /**
- * @ngdoc directive
- * @name xos.uiComponents.directive:xosSmartTable
- * @link xos.uiComponents.directive:xosTable xosTable
- * @link xos.uiComponents.directive:xosForm xosForm
- * @restrict E
- * @description The xos-table directive
- * @param {Object} config The configuration for the component,
- * it is composed by the name of an angular [$resource](https://docs.angularjs.org/api/ngResource/service/$resource)
- * and an array of fields that shouldn't be printed.
- * ```
- * {
- resource: 'Users',
- hiddenFields: []
- }
- * ```
- * @scope
- * @example
- <example module="sampleSmartTable">
- <file name="index.html">
- <div ng-controller="SampleCtrl as vm">
- <xos-smart-table config="vm.config"></xos-smart-table>
- </div>
- </file>
- <file name="script.js">
- angular.module('sampleSmartTable', ['xos.uiComponents', 'ngResource', 'ngMockE2E'])
- // This is only for documentation purpose
- .run(function($httpBackend, _){
- let datas = [{id: 1, name: 'Jhon', surname: 'Doe'}];
- let count = 1;
- let paramsUrl = new RegExp(/\/test\/(.+)/);
- $httpBackend.whenDELETE(paramsUrl, undefined, ['id']).respond((method, url, data, headers, params) => {
- data = angular.fromJson(data);
- let id = url.match(paramsUrl)[1];
- _.remove(datas, (d) => {
- return d.id === parseInt(id);
- })
- return [204];
- });
- $httpBackend.whenGET('/test').respond(200, datas)
- $httpBackend.whenPOST('/test').respond((method, url, data) => {
- data = angular.fromJson(data);
- data.id = ++count;
- datas.push(data);
- return [201, data, {}];
- });
- })
- .factory('_', function($window){
- return $window._;
- })
- .service('SampleResource', function($resource){
- return $resource('/test/:id', {id: '@id'});
- })
- // End of documentation purpose, example start
- .controller('SampleCtrl', function(){
- this.config = {
- resource: 'SampleResource'
- };
- });
- </file>
- </example>
- */
-
- .directive('xosSmartTable', function () {
- return {
- restrict: 'E',
- scope: {
- config: '='
- },
- 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 ',
- bindToController: true,
- controllerAs: 'vm',
- controller: ["$injector", "LabelFormatter", "_", "XosFormHelpers", function controller($injector, LabelFormatter, _, XosFormHelpers) {
- var _this = this;
-
- // TODO
- // - Validate the config (what if resource does not exist?)
-
- // NOTE
- // Corner case
- // - if response is empty, how can we generate a form ?
-
- this.responseMsg = false;
- this.responseErr = false;
-
- this.tableConfig = {
- columns: [],
- actions: [{
- label: 'delete',
- icon: 'remove',
- cb: function cb(item) {
- _this.Resource.delete({ id: item.id }).$promise.then(function () {
- _.remove(_this.data, function (d) {
- return d.id === item.id;
- });
- _this.responseMsg = _this.config.resource + ' with id ' + item.id + ' successfully deleted';
- }).catch(function (err) {
- _this.responseErr = err.data.detail || 'Error while deleting ' + _this.config.resource + ' with id ' + item.id;
- });
- },
- color: 'red'
- }, {
- label: 'details',
- icon: 'search',
- cb: function cb(item) {
- _this.detailedItem = item;
- }
- }],
- classes: 'table table-striped table-bordered table-responsive',
- filter: 'field',
- order: true,
- pagination: {
- pageSize: 10
- }
- };
-
- this.formConfig = {
- exclude: this.config.hiddenFields,
- fields: {},
- formName: this.config.resource + 'Form',
- actions: [{
- label: 'Save',
- icon: 'ok',
- cb: function cb(item) {
- var p = void 0;
- var isNew = true;
-
- if (item.id) {
- p = item.$update();
- isNew = false;
- } else {
- p = item.$save();
- }
-
- p.then(function (res) {
- if (isNew) {
- _this.data.push(angular.copy(res));
- }
- delete _this.detailedItem;
- _this.responseMsg = _this.config.resource + ' with id ' + item.id + ' successfully saved';
- }).catch(function (err) {
- _this.responseErr = err.data.detail || 'Error while saving ' + _this.config.resource + ' with id ' + item.id;
- });
- },
- class: 'success'
- }]
- };
-
- this.cleanForm = function () {
- delete _this.detailedItem;
- };
-
- this.createItem = function () {
- _this.detailedItem = new _this.Resource();
- };
-
- this.Resource = $injector.get(this.config.resource);
-
- var getData = function getData() {
- _this.Resource.query().$promise.then(function (res) {
-
- if (!res[0]) {
- return;
- }
-
- var item = res[0];
- var props = Object.keys(item);
-
- _.remove(props, function (p) {
- return p == 'id' || p == 'validators';
- });
-
- // TODO move out cb
- if (angular.isArray(_this.config.hiddenFields)) {
- props = _.difference(props, _this.config.hiddenFields);
- }
-
- var labels = props.map(function (p) {
- return LabelFormatter.format(p);
- });
-
- props.forEach(function (p, i) {
- _this.tableConfig.columns.push({
- label: labels[i],
- prop: p
- });
- });
-
- // build form structure
- props.forEach(function (p, i) {
- _this.formConfig.fields[p] = {
- label: LabelFormatter.format(labels[i]).replace(':', ''),
- type: XosFormHelpers._getFieldFormat(item[p])
- };
- });
-
- _this.data = res;
- });
- };
-
- getData();
- }]
- };
- });
-})();
-//# sourceMappingURL=../../../maps/ui_components/smartComponents/smartTable/smartTable.component.js.map
-
-'use strict';
-
-/**
- * © OpenCORD
- *
- * Visit http://guide.xosproject.org/devguide/addview/ for more information
- *
- * Created by teone on 3/24/16.
- */
-
-(function () {
- 'use strict';
-
- angular.module('xos.uiComponents')
- /**
- * @ngdoc directive
- * @name xos.uiComponents.directive:xosSmartPie
- * @restrict E
- * @description The xos-table directive
- * @param {Object} config The configuration for the component,
- * it is composed by the name of an angular [$resource](https://docs.angularjs.org/api/ngResource/service/$resource)
- * and a field name that is used to group the data.
- * ```
- * {
- resource: 'Users',
- groupBy: 'fieldName',
- classes: 'my-custom-class',
- labelFormatter: (labels) => {
- // here you can format your label,
- // you should return an array with the same order
- return labels;
- }
- }
- * ```
- * @scope
- * @example
-
- Displaying Local data
- <example module="sampleSmartPieLocal">
- <file name="index.html">
- <div ng-controller="SampleCtrlLocal as vm">
- <xos-smart-pie config="vm.configLocal"></xos-smart-pie>
- </div>
- </file>
- <file name="script.js">
- angular.module('sampleSmartPieLocal', ['xos.uiComponents'])
- .factory('_', function($window){
- return $window._;
- })
- .controller('SampleCtrlLocal', function($timeout){
-
- this.datas = [
- {id: 1, first_name: 'Jon', last_name: 'aaa', category: 2},
- {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 1},
- {id: 3, first_name: 'Aria', last_name: 'Stark', category: 2}
- ];
- this.configLocal = {
- data: [],
- groupBy: 'category',
- classes: 'local',
- labelFormatter: (labels) => {
- return labels.map(l => l === '1' ? 'North' : 'Dragon');
- }
- };
-
- $timeout(() => {
- // this need to be triggered in this way just because of ngDoc,
- // otherwise you can assign data directly in the config
- this.configLocal.data = this.datas;
- }, 1)
- });
- </file>
- </example>
- Fetching data from API
- <example module="sampleSmartPieResource">
- <file name="index.html">
- <div ng-controller="SampleCtrl as vm">
- <xos-smart-pie config="vm.config"></xos-smart-pie>
- </div>
- </file>
- <file name="script.js">
- angular.module('sampleSmartPieResource', ['xos.uiComponents', 'ngResource', 'ngMockE2E'])
- .controller('SampleCtrl', function(){
- this.config = {
- resource: 'SampleResource',
- groupBy: 'category',
- classes: 'resource',
- labelFormatter: (labels) => {
- return labels.map(l => l === '1' ? 'North' : 'Dragon');
- }
- };
- });
- </file>
- <file name="backendPoll.js">
- angular.module('sampleSmartPieResource')
- .run(function($httpBackend, _){
- let datas = [
- {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
- {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
- {id: 3, first_name: 'Aria', last_name: 'Stark', category: 1}
- ];
- $httpBackend.whenGET('/test').respond(200, datas)
- })
- .factory('_', function($window){
- return $window._;
- })
- .service('SampleResource', function($resource){
- return $resource('/test/:id', {id: '@id'});
- })
- </file>
- </example>
- Polling data from API
- <example module="sampleSmartPiePoll">
- <file name="index.html">
- <div ng-controller="SampleCtrl as vm">
- <xos-smart-pie config="vm.config"></xos-smart-pie>
- </div>
- </file>
- <file name="script.js">
- angular.module('sampleSmartPiePoll', ['xos.uiComponents', 'ngResource', 'ngMockE2E'])
- .controller('SampleCtrl', function(){
- this.config = {
- resource: 'SampleResource',
- groupBy: 'category',
- poll: 2,
- labelFormatter: (labels) => {
- return labels.map(l => l === '1' ? 'Active' : 'Banned');
- }
- };
- });
- </file>
- <file name="backend.js">
- angular.module('sampleSmartPiePoll')
- .run(function($httpBackend, _){
- let mock = [
- [
- {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
- {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
- {id: 3, first_name: 'Aria', last_name: 'Stark', category: 1},
- {id: 3, first_name: 'Tyrion', last_name: 'Lannister', category: 1}
- ],
- [
- {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
- {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
- {id: 3, first_name: 'Aria', last_name: 'Stark', category: 2},
- {id: 3, first_name: 'Tyrion', last_name: 'Lannister', category: 2}
- ],
- [
- {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
- {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
- {id: 3, first_name: 'Aria', last_name: 'Stark', category: 1},
- {id: 3, first_name: 'Tyrion', last_name: 'Lannister', category: 2}
- ]
- ];
- $httpBackend.whenGET('/test').respond(function(method, url, data, headers, params) {
- return [200, mock[Math.round(Math.random() * 3)]];
- });
- })
- .factory('_', function($window){
- return $window._;
- })
- .service('SampleResource', function($resource){
- return $resource('/test/:id', {id: '@id'});
- })
- </file>
- </example>
- */
- .directive('xosSmartPie', function () {
- return {
- restrict: 'E',
- scope: {
- config: '='
- },
- 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 ',
- bindToController: true,
- controllerAs: 'vm',
- controller: ["$injector", "$timeout", "$interval", "$scope", "_", function controller($injector, $timeout, $interval, $scope, _) {
- var _this = this;
-
- if (!this.config.resource && !this.config.data) {
- throw new Error('[xosSmartPie] Please provide a resource or an array of data in the configuration');
- }
-
- var groupData = function groupData(data) {
- return _.groupBy(data, _this.config.groupBy);
- };
- var formatData = function formatData(data) {
- return _.reduce(Object.keys(data), function (list, group) {
- return list.concat(data[group].length);
- }, []);
- };
- var formatLabels = function formatLabels(data) {
- return angular.isFunction(_this.config.labelFormatter) ? _this.config.labelFormatter(Object.keys(data)) : Object.keys(data);
- };
-
- var prepareData = function prepareData(data) {
- // group data
- var grouped = groupData(data);
- _this.data = formatData(grouped);
- // create labels
- _this.labels = formatLabels(grouped);
- };
-
- if (this.config.resource) {
- (function () {
-
- _this.Resource = $injector.get(_this.config.resource);
- var getData = function getData() {
- _this.Resource.query().$promise.then(function (res) {
-
- if (!res[0]) {
- return;
- }
-
- prepareData(res);
- });
- };
-
- getData();
-
- if (_this.config.poll) {
- $interval(function () {
- getData();
- }, _this.config.poll * 1000);
- }
- })();
- } else {
- $scope.$watch(function () {
- return _this.config.data;
- }, function (data) {
- if (data) {
- prepareData(_this.config.data);
- }
- }, true);
- }
- }]
- };
- });
-})();
-//# sourceMappingURL=../../../maps/ui_components/smartComponents/smartPie/smartPie.component.js.map
-
-'use strict';
-
(function () {
'use strict';
diff --git a/xos/core/xoslib/static/js/xosDeveloper.js b/xos/core/xoslib/static/js/xosDeveloper.js
index 784dd95..cd4f5b1 100644
--- a/xos/core/xoslib/static/js/xosDeveloper.js
+++ b/xos/core/xoslib/static/js/xosDeveloper.js
@@ -1 +1 @@
-"use strict";angular.module("xos.developer",["ngResource","ngCookies","ui.router","xos.helpers"]).config(["$stateProvider",function(e){e.state("developer",{url:"/",template:"<developer-dashboard></developer-dashboard>"})}]).config(["$httpProvider",function(e){e.interceptors.push("NoHyperlinks")}]).directive("developerDashboard",function(){return{restrict:"E",scope:{},bindToController:!0,controllerAs:"vm",templateUrl:"templates/developer-dashboard.tpl.html",controller:["$timeout","SlicesPlus","_",function(e,t,n){var r=this;this.instancePerSliceConfig={resource:"Instances",groupBy:"slice",legend:!0,labelFormatter:function(e){return e.map(function(e){return n.find(r.slices,{id:parseInt(e)}).name})}},this.instancePerSiteConfig={data:[],groupBy:"site",legend:!0},this.networkPerSliceConfig={data:[],groupBy:"name",legend:!0},this.tableConfig={columns:[{label:"Name",prop:"name"},{label:"Privileges",prop:"current_user_roles",type:"array"},{label:"Number of Instances (active / total)",type:"custom",formatter:function(e){return e.instance_total_ready+" / "+e.instance_total}},{label:"Total Instances per Sites",type:"object",prop:"instance_distribution"},{label:"Active Instances per Sites",type:"object",prop:"instance_distribution_ready"},{label:"Networks",type:"custom",formatter:function(e){return e.networks.length}}]},t.query().$promise.then(function(t){var s=n.reduce(t,function(e,t){if(t.networks.length>1)for(var n=0;n<t.networks.length;n++)e.push({id:t.id,name:t.name,network:t.networks[n]});else 1===t.networks.length&&e.push({id:t.id,name:t.name,network:t.networks[0]});return e},[]),i=n.reduce(t,function(e,t){return n.forEach(Object.keys(t.instance_distribution),function(n){for(var r=0;r<t.instance_distribution[n];r++)e.push({site:n,instance:r})}),e},[]);r.sites=Object.keys(n.groupBy(i,"site")),e(function(){r.instancePerSiteConfig.data=i,r.networkPerSliceConfig.data=s},0),r.slices=t})["catch"](function(e){throw new Error(e)})}]}}),angular.module("xos.developer").run(["$templateCache",function(e){e.put("templates/developer-dashboard.tpl.html",'<div class="row">\n <div ng-class="{\'col-sm-4\': vm.sites.length > 1, \'col-sm-6\': vm.sites.length <= 1}" class="text-center">\n <h3>Instances per Slice</h3>\n <xos-smart-pie ng-if="vm.slices" config="vm.instancePerSliceConfig"></xos-smart-pie>\n </div>\n <div ng-if="vm.sites.length > 1" class="col-sm-4 text-center">\n <h3>Instances per Site</h3>\n <xos-smart-pie ng-if="vm.instancePerSiteConfig.data.length > 0" config="vm.instancePerSiteConfig"></xos-smart-pie>\n </div>\n <div ng-class="{\'col-sm-4\': vm.sites.length > 1, \'col-sm-6\': vm.sites.length <= 1}" class="text-center">\n <h3>Network per Slice</h3>\n <xos-smart-pie ng-if="vm.networkPerSliceConfig.data.length > 0" config="vm.networkPerSliceConfig"></xos-smart-pie>\n </div>\n</div>\n\n<xos-table config="vm.tableConfig" data="vm.slices"></xos-table>')}]),angular.module("xos.developer").run(["$location",function(e){e.path("/")}]);
\ No newline at end of file
+"use strict";angular.module("xos.developer",["ngResource","ngCookies","ui.router","xos.helpers"]).config(["$stateProvider",function(e){e.state("developer",{url:"/",template:"<developer-dashboard></developer-dashboard>"})}]).config(["$httpProvider",function(e){e.interceptors.push("NoHyperlinks")}]).directive("developerDashboard",function(){return{restrict:"E",scope:{},bindToController:!0,controllerAs:"vm",templateUrl:"templates/developer-dashboard.tpl.html",controller:["$scope","$timeout","SlicesPlus","Instances","_",function(e,t,n,s,i){var r=this;this.instancePerSliceConfig={data:[],groupBy:"slice",legend:!0,classes:"instance per slice",labelFormatter:function(e){return e.map(function(e){return i.find(r.slices,{id:parseInt(e)}).name})}},this.instancePerSiteConfig={data:[],groupBy:"site",legend:!0,classes:"instance per site"},this.networkPerSliceConfig={data:[],groupBy:"name",legend:!0,classes:"network per slice"},this.tableConfig={columns:[{label:"Name",prop:"name"},{label:"Privileges",prop:"current_user_roles",type:"array"},{label:"Number of Instances (active / total)",type:"custom",formatter:function(e){return e.instance_total_ready+" / "+e.instance_total}},{label:"Total Instances per Sites",type:"object",prop:"instance_distribution"},{label:"Active Instances per Sites",type:"object",prop:"instance_distribution_ready"},{label:"Networks",type:"custom",formatter:function(e){return e.networks.length}}]},n.query().$promise.then(function(e){return r.slices=e,s.query().$promise}).then(function(e){var t=i.reduce(r.slices,function(e,t){if(t.networks.length>1)for(var n=0;n<t.networks.length;n++)e.push({id:t.id,name:t.name,network:t.networks[n]});else 1===t.networks.length&&e.push({id:t.id,name:t.name,network:t.networks[0]});return e},[]),n=i.reduce(r.slices,function(e,t){return i.forEach(Object.keys(t.instance_distribution),function(n){for(var s=0;s<t.instance_distribution[n];s++)e.push({site:n,instance:s})}),e},[]);r.sites=Object.keys(i.groupBy(n,"site")),r.instancePerSliceConfig.data=e,r.instancePerSiteConfig.data=n,r.networkPerSliceConfig.data=t})["catch"](function(e){throw new Error(e)})}]}}),angular.module("xos.developer").run(["$templateCache",function(e){e.put("templates/developer-dashboard.tpl.html",'<div class="row">\n <div ng-class="{\'col-sm-4\': vm.sites.length > 1 || !vm.sites, \'col-sm-6\': vm.sites.length <= 1}" class="text-center">\n <h3>Instances per Slice</h3>\n <xos-smart-pie ng-if="vm.instancePerSliceConfig.data.length > 0" config="vm.instancePerSliceConfig"></xos-smart-pie>\n </div>\n <div ng-if="vm.sites.length > 1" class="col-sm-4 text-center">\n <h3>Instances per Site</h3>\n <xos-smart-pie ng-if="vm.instancePerSiteConfig.data.length > 0" config="vm.instancePerSiteConfig"></xos-smart-pie>\n </div>\n <div ng-class="{\'col-sm-4\': vm.sites.length > 1 || !vm.sites, \'col-sm-6\': vm.sites.length <= 1}" class="text-center">\n <h3>Network per Slice</h3>\n <xos-smart-pie ng-if="vm.networkPerSliceConfig.data.length > 0" config="vm.networkPerSliceConfig"></xos-smart-pie>\n </div>\n</div>\n\n<xos-table config="vm.tableConfig" data="vm.slices"></xos-table>')}]),angular.module("xos.developer").run(["$location",function(e){e.path("/")}]);
\ No newline at end of file