Merge branch 'feature/common-components'
diff --git a/views/ngXosLib/.eslintrc b/views/ngXosLib/.eslintrc
index f9a952f..cf02168 100644
--- a/views/ngXosLib/.eslintrc
+++ b/views/ngXosLib/.eslintrc
@@ -24,7 +24,6 @@
"indent": [2, 2],
"no-irregular-whitespace": 1,
"eol-last": 0,
- "max-nested-callbacks": [2, 4],
"comma-spacing": [1, {"before": false, "after": true}],
"no-trailing-spaces": [1, { skipBlankLines: true }],
"no-unused-vars": [1, {"vars": "all", "args": "after-used"}],
diff --git a/views/ngXosLib/.gitignore b/views/ngXosLib/.gitignore
index 9b2df09..5df6f2d 100644
--- a/views/ngXosLib/.gitignore
+++ b/views/ngXosLib/.gitignore
@@ -1,3 +1,5 @@
node_modules
bower_components
-docs
\ No newline at end of file
+docs
+xosHelpers/.tmp
+xos
\ No newline at end of file
diff --git a/views/ngXosLib/README.md b/views/ngXosLib/README.md
index 3da0271..2eb73cb 100644
--- a/views/ngXosLib/README.md
+++ b/views/ngXosLib/README.md
@@ -49,6 +49,8 @@
>_NOTE: for the API related service, check documentation in [Apigen](#apigen) section._
+To develop components inside this folder there is a particular command: `npm run dev`, this will watch the helpers file and rebuild them with sourcemaps. For this reason remember to build them when done developing.
+
When some changes are applied to this common library it should be rebuilt with: `npm run build`
### Yo Xos
diff --git a/views/ngXosLib/generator-xos/app/templates/src/templates/users-list.tpl.html b/views/ngXosLib/generator-xos/app/templates/src/templates/users-list.tpl.html
index 03be487..fd8d208 100644
--- a/views/ngXosLib/generator-xos/app/templates/src/templates/users-list.tpl.html
+++ b/views/ngXosLib/generator-xos/app/templates/src/templates/users-list.tpl.html
@@ -1,6 +1,8 @@
<div class="row">
- <h1>Users List</h1>
- <p>This is only an example view.</p>
+ <div class="col-xs-12">
+ <h1>Users List</h1>
+ <p>This is only an example view.</p>
+ </div>
</div>
<div class="row">
<div class="col-xs-4">Email</div>
diff --git a/views/ngXosLib/gulp/ngXosHelpers.js b/views/ngXosLib/gulp/ngXosHelpers.js
index f833fb8..f046681 100644
--- a/views/ngXosLib/gulp/ngXosHelpers.js
+++ b/views/ngXosLib/gulp/ngXosHelpers.js
@@ -5,10 +5,34 @@
var angularFilesort = require('gulp-angular-filesort');
var gulpDocs = require('gulp-ngdocs');
var del = require('del');
+var babel = require('gulp-babel');
+const sourcemaps = require('gulp-sourcemaps');
+var browserSync = require('browser-sync').create();
module.exports = function(options){
- gulp.task('helpers', function(){
- return gulp.src([options.xosHelperSource + '**/*.js'])
+
+ // transpile js with sourceMaps
+ gulp.task('babel', function(){
+ return gulp.src(options.xosHelperSource + '**/*.js')
+ .pipe(babel({
+ presets: ['es2015']
+ }))
+ .pipe(gulp.dest(options.xosHelperTmp));
+ });
+
+ gulp.task('babelDev', function(){
+ return gulp.src(options.xosHelperSource + '**/*.js')
+ .pipe(sourcemaps.init())
+ .pipe(babel({
+ presets: ['es2015']
+ }))
+ .pipe(sourcemaps.write('./maps'))
+ .pipe(gulp.dest(options.xosHelperTmp));
+ });
+
+ // build
+ gulp.task('helpers', ['babel'], function(){
+ return gulp.src([options.xosHelperTmp + '**/*.js'])
.pipe(angularFilesort())
.pipe(concat('ngXosHelpers.js'))
.pipe(ngAnnotate())
@@ -16,18 +40,30 @@
.pipe(gulp.dest(options.ngXosVendor));
});
+ // build Dev (no minify, sourcemaps)
+ gulp.task('helpersDev', ['babelDev'], function(){
+ return gulp.src([options.xosHelperTmp + '**/*.js'])
+ .pipe(angularFilesort())
+ .pipe(concat('ngXosHelpers.js'))
+ .pipe(ngAnnotate())
+ .pipe(gulp.dest(options.ngXosVendor));
+ });
+
gulp.task('cleanDocs', function(){
- console.log(options);
return del([options.docs + '**/*']);
});
- gulp.task('docs', ['cleanDocs'], function(){
+ gulp.task('makeDocs', ['cleanDocs'], function(){
var ngOptions = {
scripts: [
'http://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js',
- 'http://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular-animate.min.js'
+ 'http://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular-animate.min.js',
+ `${options.ngXosVendor}ngXosHelpers.js`
],
- html5Mode: true,
+ styles: [
+ 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css',
+ ],
+ html5Mode: false,
title: 'XOS Helpers documentation',
startPage: '/module',
}
@@ -36,7 +72,8 @@
module: {
glob: [
options.xosHelperSource + '*.js',
- options.xosHelperSource + 'services/*.js'
+ options.xosHelperSource + 'services/*.js',
+ options.xosHelperSource + 'ui_components/**/*.js'
],
title: 'Module Documentation',
},
@@ -49,4 +86,34 @@
}
}).pipe(gulpDocs.process(ngOptions)).pipe(gulp.dest('./docs'));
});
+
+ gulp.task('serveDocs', function(){
+ browserSync.init({
+ server: {
+ baseDir: './docs',
+ routes: {
+ '/xos/core/xoslib/static/js/vendor': options.ngXosVendor
+ }
+ }
+ });
+ });
+
+ gulp.task('docs', ['makeDocs', 'serveDocs'], function(){
+
+ var files = [
+ options.xosHelperSource + '*.js',
+ options.xosHelperSource + 'services/*.js',
+ options.xosHelperSource + 'ui_components/**/*.js'
+ ];
+
+ gulp.watch(files, ['makeDocs']);
+
+ gulp.watch(files, function(){
+ browserSync.reload();
+ });
+ })
+
+ gulp.task('dev', function(){
+ gulp.watch(options.xosHelperSource + '**/*.js', ['helpersDev']);
+ });
};
\ No newline at end of file
diff --git a/views/ngXosLib/gulpfile.js b/views/ngXosLib/gulpfile.js
index bb6bc5e..77a5c07 100644
--- a/views/ngXosLib/gulpfile.js
+++ b/views/ngXosLib/gulpfile.js
@@ -6,6 +6,7 @@
var options = {
ngXosVendor: '../../xos/core/xoslib/static/js/vendor/', //save here the minfied vendor file, this is automatically loaded in the django page
xosHelperSource: './xosHelpers/src/',
+ xosHelperTmp: './xosHelpers/.tmp/',
docs: './docs'
};
diff --git a/views/ngXosLib/karma.conf.js b/views/ngXosLib/karma.conf.js
index 060e7dd..b602d66 100644
--- a/views/ngXosLib/karma.conf.js
+++ b/views/ngXosLib/karma.conf.js
@@ -13,7 +13,7 @@
var files = bowerComponents.concat([
'api/**/*.js',
- 'xosHelpers/src/*.module.js',
+ 'xosHelpers/src/**/*.module.js',
'xosHelpers/src/**/*.js',
'xosHelpers/spec/**/*.test.js'
]);
@@ -43,7 +43,7 @@
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
- '**/*.test.js': ['babel']
+ 'xosHelpers/**/*.js': ['babel'],
},
babelPreprocessor: {
@@ -86,7 +86,7 @@
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
- browsers: ['PhantomJS', 'Chrome'],
+ browsers: ['PhantomJS'],
// Continuous Integration mode
diff --git a/views/ngXosLib/package.json b/views/ngXosLib/package.json
index 486db22..9e8906c 100644
--- a/views/ngXosLib/package.json
+++ b/views/ngXosLib/package.json
@@ -7,8 +7,9 @@
"test": "karma start",
"apigen": "node apigen/blueprintToNgResource.js",
"swagger": "node xos-swagger-def.js",
- "doc": "gulp docs; cd ./docs; http-server -o -c-1",
- "build": "gulp vendor && gulp helpers"
+ "doc": "gulp docs; cd ./docs",
+ "build": "gulp vendor && gulp helpers",
+ "dev": "gulp dev"
},
"author": "Matteo Scandolo",
"license": "ISC",
@@ -24,15 +25,17 @@
},
"devDependencies": {
"babel-preset-es2015": "^6.6.0",
+ "browser-sync": "^2.12.3",
"concat": "^2.0.0",
"del": "^2.2.0",
"gulp": "^3.9.0",
"gulp-angular-filesort": "^1.1.1",
+ "gulp-babel": "^6.1.2",
"gulp-concat": "^2.6.0",
"gulp-ng-annotate": "^1.1.0",
"gulp-ngdocs": "^0.2.13",
+ "gulp-sourcemaps": "^1.6.0",
"gulp-uglify": "^1.4.2",
- "http-server": "^0.9.0",
"jasmine-core": "^2.4.1",
"karma": "^0.13.19",
"karma-babel-preprocessor": "^6.0.1",
diff --git a/views/ngXosLib/xosHelpers/spec/csrftoken.test.js b/views/ngXosLib/xosHelpers/spec/csrftoken.test.js
index 200014d..8901bde 100644
--- a/views/ngXosLib/xosHelpers/spec/csrftoken.test.js
+++ b/views/ngXosLib/xosHelpers/spec/csrftoken.test.js
@@ -34,6 +34,7 @@
httpBackend.when('POST', 'http://example.com', null, function(headers) {
expect(headers['X-CSRFToken']).toBe(fakeToken);
done();
+ return headers;
}).respond(200, {name: 'example' });
http.post('http://example.com');
diff --git a/views/ngXosLib/xosHelpers/spec/noHyperlinks.test.js b/views/ngXosLib/xosHelpers/spec/noHyperlinks.test.js
index 560f4dc..7b6e9d0 100644
--- a/views/ngXosLib/xosHelpers/spec/noHyperlinks.test.js
+++ b/views/ngXosLib/xosHelpers/spec/noHyperlinks.test.js
@@ -9,43 +9,43 @@
(function () {
'use strict';
- describe('The NoHyperlinks factory', () => {
+ describe('The xos.helper module', function(){
+ describe('The NoHyperlinks factory', () => {
- let httpProviderObj, httpBackend, http, noHyperlinks;
+ let httpProviderObj, noHyperlinks;
- beforeEach(() => {
- module(
- 'xos.helpers',
- ($httpProvider) => {
- //save our interceptor
- httpProviderObj = $httpProvider;
- }
- );
+ beforeEach(() => {
+ module(
+ 'xos.helpers',
+ ($httpProvider) => {
+ //save our interceptor
+ httpProviderObj = $httpProvider;
+ }
+ );
- inject(function (_$httpBackend_, _$http_, _NoHyperlinks_) {
- httpBackend = _$httpBackend_;
- http = _$http_;
- noHyperlinks = _NoHyperlinks_
+ inject(function (_NoHyperlinks_) {
+ noHyperlinks = _NoHyperlinks_
+ });
+
+ httpProviderObj.interceptors.push('NoHyperlinks');
+
});
- httpProviderObj.interceptors.push('NoHyperlinks');
+ it('should set NoHyperlinks interceptor', () => {
+ expect(httpProviderObj.interceptors).toContain('NoHyperlinks');
+ });
+
+ it('should attach ?no_hyperlinks=1 to the request url', () => {
+ let result = noHyperlinks.request({url: 'sample.url'});
+ expect(result.url).toEqual('sample.url?no_hyperlinks=1');
+ });
+
+ it('should NOT attach ?no_hyperlinks=1 to the request url if is HTML', () => {
+ let result = noHyperlinks.request({url: 'sample.html'});
+ expect(result.url).toEqual('sample.html');
+ });
});
-
- it('should set NoHyperlinks interceptor', () => {
- expect(httpProviderObj.interceptors).toContain('NoHyperlinks');
- });
-
- it('should attach ?no_hyperlinks=1 to the request url', () => {
- let result = noHyperlinks.request({url: 'sample.url'});
- expect(result.url).toEqual('sample.url?no_hyperlinks=1');
- });
-
- it('should NOT attach ?no_hyperlinks=1 to the request url if is HTML', () => {
- let result = noHyperlinks.request({url: 'sample.html'});
- expect(result.url).toEqual('sample.html');
- });
-
});
})();
diff --git a/views/ngXosLib/xosHelpers/spec/ui/alert.test.js b/views/ngXosLib/xosHelpers/spec/ui/alert.test.js
new file mode 100644
index 0000000..c67d03a
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/spec/ui/alert.test.js
@@ -0,0 +1,131 @@
+/**
+ * © OpenCORD
+ *
+ * Created by teone on 4/15/16.
+ */
+
+(function () {
+ 'use strict';
+
+ describe('The xos.helper module', function(){
+ describe('The xos-alert component', () => {
+
+ let element, scope, isolatedScope;
+
+ let message = 'Test Error Message';
+
+ beforeEach(module('xos.helpers'));
+
+ it('should throw an error if no config is specified', inject(($compile, $rootScope) => {
+ function errorFunctionWrapper(){
+ $compile(angular.element('<xos-alert></xos-alert>'))($rootScope);
+ $rootScope.$digest();
+ }
+ expect(errorFunctionWrapper).toThrow(new Error('[xosAlert] Please provide a configuration via the "config" attribute'));
+ }));
+
+ describe('when correctly configured', () => {
+ beforeEach(inject(($compile, $rootScope) => {
+
+ scope = $rootScope.$new();
+
+ scope.config = {
+ type: 'danger',
+ closeBtn: true
+ };
+
+ element = angular.element(`<xos-alert config="config">${message}</xos-alert>`);
+ $compile(element)(scope);
+ scope.$digest();
+ isolatedScope = element.isolateScope().vm;
+ }));
+
+ it('should transclude the message', () => {
+ let textContainer = element[0].getElementsByTagName('p')[0];
+ let text = angular.element(textContainer).text();
+ expect(text).toEqual(message)
+ });
+
+ it('should have a close button', () => {
+ let btn = element[0].getElementsByTagName('button');
+ expect(btn.length).toEqual(1);
+ });
+
+ describe('when the close button is clicked', () => {
+ it('should hide the alert', () => {
+ let btn = element[0].getElementsByTagName('button')[0];
+ btn.click();
+ let alert = angular.element(element[0].querySelectorAll('.alert')[0]);
+ expect(alert.hasClass('ng-hide')).toBeTruthy();
+ });
+ });
+
+ describe('when autoHide is set', () => {
+
+ let to;
+
+ beforeEach(inject(($compile, $rootScope, $timeout) => {
+ scope = $rootScope.$new();
+
+ scope.config = {
+ type: 'danger',
+ closeBtn: true,
+ autoHide: 500
+ };
+
+ to = $timeout;
+
+ element = angular.element(`<xos-alert config="config">${message}</xos-alert>`);
+ $compile(element)(scope);
+ scope.$digest();
+ isolatedScope = element.isolateScope().vm;
+ }));
+
+ it('should hide the alert', () => {
+ to.flush();
+ expect(isolatedScope.show).toBeFalsy();
+ let alert = angular.element(element[0].querySelectorAll('.alert')[0]);
+ expect(alert.hasClass('ng-hide')).toBeTruthy();
+ });
+ });
+
+ describe('when show is set to false', () => {
+
+ beforeEach(inject(($compile, $rootScope) => {
+ scope = $rootScope.$new();
+
+ scope.config = {
+ type: 'danger',
+ closeBtn: true
+ };
+
+ scope.show = false;
+
+ element = angular.element(`<xos-alert config="config" show="show">${message}</xos-alert>`);
+ $compile(element)(scope);
+ scope.$digest();
+ isolatedScope = element.isolateScope().vm;
+ }));
+
+ it('should hide the alert', () => {
+ let alert = angular.element(element[0].querySelectorAll('.alert')[0]);
+ expect(alert.hasClass('ng-hide')).toBeTruthy();
+ });
+
+ describe('when show is changed to true', () => {
+ beforeEach(() => {
+ scope.show = true;
+ scope.$digest();
+ });
+
+ it('should show the alert', () => {
+ let alert = angular.element(element[0].querySelectorAll('.alert')[0]);
+ expect(alert.hasClass('ng-hide')).toBeFalsy();
+ });
+ });
+ });
+
+ });
+ });
+ });
+})();
\ No newline at end of file
diff --git a/views/ngXosLib/xosHelpers/spec/ui/pagination.test.js b/views/ngXosLib/xosHelpers/spec/ui/pagination.test.js
new file mode 100644
index 0000000..a8a7482
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/spec/ui/pagination.test.js
@@ -0,0 +1,53 @@
+(function () {
+ 'use strict';
+
+ describe('The xos.helper module', function(){
+ describe('The xos-pagination component', () => {
+
+ let scope, element, isolatedScope;
+ let cb = jasmine.createSpy('callback')
+
+ beforeEach(module('xos.helpers'));
+
+ beforeEach(inject(function ($compile, $rootScope) {
+ scope = $rootScope.$new();
+
+ scope.pageSize = 2;
+
+ scope.totalElements = 5;
+
+ scope.change = cb;
+
+ element = angular.element('<xos-pagination page-size="pageSize" total-elements="totalElements" change="change"></xos-table>');
+ $compile(element)(scope);
+ scope.$digest();
+ isolatedScope = element.isolateScope().vm;
+ }));
+
+ it('should contain 3 pages', function() {
+ var li = element[0].getElementsByTagName('li');
+ expect(li.length).toEqual(5);
+ });
+
+ it('should call the change function', () => {
+ var li = element[0].getElementsByTagName('li')[3];
+ let link = li.getElementsByTagName('a')[0];
+ link.click();
+ expect(cb).toHaveBeenCalledWith(2);
+ });
+
+ describe('when elements number is less than page size', () => {
+ beforeEach(() => {
+ isolatedScope.pageSize = 10;
+ isolatedScope.totalElements = 9;
+ scope.$digest();
+ });
+
+ it('should not be rendered', () => {
+ var pagination = element[0].getElementsByClassName('pagination');
+ expect(pagination.length).toEqual(0);
+ });
+ });
+ });
+ });
+})();
\ No newline at end of file
diff --git a/views/ngXosLib/xosHelpers/spec/ui/table.test.js b/views/ngXosLib/xosHelpers/spec/ui/table.test.js
new file mode 100644
index 0000000..50a5d72
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/spec/ui/table.test.js
@@ -0,0 +1,200 @@
+/**
+ * © OpenCORD
+ *
+ * Created by teone on 3/24/16.
+ */
+
+(function () {
+ 'use strict';
+
+ describe('The xos.helper module', function(){
+ describe('The xos-table component', () => {
+
+ beforeEach(module('xos.helpers'));
+
+ it('should throw an error if no config is specified', inject(($compile, $rootScope) => {
+ function errorFunctionWrapper(){
+ $compile(angular.element('<xos-table></xos-table>'))($rootScope);
+ $rootScope.$digest();
+ }
+ expect(errorFunctionWrapper).toThrow(new Error('[xosTable] Please provide a configuration via the "config" attribute'));
+ }));
+
+ it('should throw an error if no config columns are specified', inject(($compile, $rootScope) => {
+ function errorFunctionWrapper(){
+ // setup the parent scope
+ let scope = $rootScope.$new();
+ scope.config = 'green';
+ $compile(angular.element('<xos-table config="config"></xos-table>'))(scope);
+ $rootScope.$digest();
+ }
+ expect(errorFunctionWrapper).toThrow(new Error('[xosTable] Please provide a columns list in the configuration'));
+ }));
+
+ describe('when basicly configured', function() {
+ var scope, element, isolatedScope;
+
+ beforeEach(inject(function ($compile, $rootScope) {
+ scope = $rootScope.$new();
+
+ scope.config = {
+ columns: [
+ {
+ label: 'Label 1',
+ prop: 'label-1'
+ },
+ {
+ label: 'Label 2',
+ prop: 'label-2'
+ }
+ ]
+ };
+
+ scope.data = [
+ {
+ 'label-1': 'Sample 1.1',
+ 'label-2': 'Sample 1.2'
+ },
+ {
+ 'label-1': 'Sample 2.1',
+ 'label-2': 'Sample 2.2'
+ }
+ ]
+
+ element = angular.element('<xos-table config="config" data="data"></xos-table>');
+ $compile(element)(scope);
+ scope.$digest();
+ isolatedScope = element.isolateScope().vm;
+ }));
+
+ it('should contain 2 columns', function() {
+ var th = element[0].getElementsByTagName('th');
+ expect(th.length).toEqual(2);
+ expect(isolatedScope.columns.length).toEqual(2);
+ });
+
+ it('should contain 3 rows', function() {
+ var tr = element[0].getElementsByTagName('tr');
+ expect(tr.length).toEqual(3);
+ });
+
+ describe('when no data are provided', () => {
+ beforeEach(() => {
+ isolatedScope.data = [];
+ scope.$digest();
+ });
+ it('should render an alert', () => {
+ let alert = element[0].getElementsByClassName('alert');
+ let table = element[0].getElementsByTagName('table');
+ expect(alert.length).toEqual(1);
+ expect(table.length).toEqual(1);
+ });
+ });
+
+ describe('when actions are passed', () => {
+
+ let cb = jasmine.createSpy('callback')
+
+ beforeEach(() => {
+ isolatedScope.config.actions = [
+ {
+ label: 'delete',
+ icon: 'remove',
+ cb: cb,
+ color: 'red'
+ }
+ ];
+ scope.$digest();
+ });
+
+ it('should have 3 columns', () => {
+ var th = element[0].getElementsByTagName('th');
+ expect(th.length).toEqual(3);
+ expect(isolatedScope.columns.length).toEqual(2);
+ });
+
+ it('when clicking on action should invoke callback', () => {
+ var link = element[0].getElementsByTagName('a')[0];
+ link.click();
+ expect(cb).toHaveBeenCalledWith(scope.data[0]);
+ });
+ });
+
+ describe('when filter is fulltext', () => {
+ beforeEach(() => {
+ isolatedScope.config.filter = 'fulltext';
+ scope.$digest();
+ });
+
+ it('should render a text field', () => {
+ var textField = element[0].getElementsByTagName('input');
+ expect(textField.length).toEqual(1);
+ });
+
+ describe('and a value is enterd', () => {
+ beforeEach(() => {
+ isolatedScope.query = '2.2';
+ scope.$digest();
+ });
+
+ it('should contain 2 rows', function() {
+ var tr = element[0].getElementsByTagName('tr');
+ expect(tr.length).toEqual(2);
+ });
+ });
+ });
+
+ describe('when filter is field', () => {
+ beforeEach(() => {
+ isolatedScope.config.filter = 'field';
+ scope.$digest();
+ });
+
+ it('should render a text field for each column', () => {
+ var textField = element[0].getElementsByTagName('input');
+ expect(textField.length).toEqual(2);
+ });
+
+ describe('and a value is enterd', () => {
+ beforeEach(() => {
+ isolatedScope.query = {'label-1': '2.1'};
+ scope.$digest();
+ });
+
+ it('should contain 3 rows', function() {
+ var tr = element[0].getElementsByTagName('tr');
+ expect(tr.length).toEqual(3);
+ });
+ });
+ });
+
+ describe('when order is true', () => {
+ beforeEach(() => {
+ isolatedScope.config.order = true;
+ scope.$digest();
+ });
+
+ it('should render a arrows beside', () => {
+ var arrows = element[0].getElementsByTagName('i');
+ expect(arrows.length).toEqual(4);
+ });
+
+ describe('and an order is set', () => {
+ beforeEach(() => {
+ isolatedScope.orderBy = 'label-1';
+ isolatedScope.reverse = true;
+ scope.$digest();
+ });
+
+ it('should orderBy', function() {
+ var tr = element[0].getElementsByTagName('tr');
+ expect(angular.element(tr[1]).text()).toContain('Sample 2.2');
+ expect(angular.element(tr[2]).text()).toContain('Sample 1.1');
+ });
+ });
+ });
+ });
+ });
+ });
+})();
+
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/table/alert.component.js b/views/ngXosLib/xosHelpers/src/ui_components/table/alert.component.js
new file mode 100644
index 0000000..7d7a026
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/src/ui_components/table/alert.component.js
@@ -0,0 +1,145 @@
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 4/15/16.
+ */
+
+(function () {
+ 'use strict';
+
+ angular.module('xos.uiComponents')
+
+ /**
+ * @ngdoc directive
+ * @name xos.uiComponents.directive:xosAlert
+ * @restrict E
+ * @description The xos-alert directive
+ * @param {Object} config The configuration object
+ * ```
+ * {
+ * type: 'danger', //info, success, warning
+ * closeBtn: true, //default false
+ * autoHide: 3000 //delay to automatically hide the alert
+ * }
+ * ```
+ * @param {Boolean=} show Binding to show and hide the alert, default to true
+ * @element ANY
+ * @scope
+ * @example
+ <example module="sampleAlert1">
+ <file name="index.html">
+ <div ng-controller="SampleCtrl1 as vm">
+ <xos-alert config="vm.config1">
+ A sample alert message
+ </xos-alert>
+ <xos-alert config="vm.config2">
+ A sample alert message (with close button)
+ </xos-alert>
+ <xos-alert config="vm.config3">
+ A sample info message
+ </xos-alert>
+ <xos-alert config="vm.config4">
+ A sample success message
+ </xos-alert>
+ <xos-alert config="vm.config5">
+ A sample warning message
+ </xos-alert>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('sampleAlert1', ['xos.uiComponents'])
+ .controller('SampleCtrl1', function(){
+ this.config1 = {
+ type: 'danger'
+ };
+
+ this.config2 = {
+ type: 'danger',
+ closeBtn: true
+ };
+
+ this.config3 = {
+ type: 'info'
+ };
+
+ this.config4 = {
+ type: 'success'
+ };
+
+ this.config5 = {
+ type: 'warning'
+ };
+ });
+ </file>
+ </example>
+
+ <example module="sampleAlert2">
+ <file name="index.html">
+ <div ng-controller="SampleCtrl as vm" class="row">
+ <div class="col-sm-4">
+ <a class="btn btn-default btn-block" ng-show="!vm.show" ng-click="vm.show = true">Show Alert</a>
+ <a class="btn btn-default btn-block" ng-show="vm.show" ng-click="vm.show = false">Hide Alert</a>
+ </div>
+ <div class="col-sm-8">
+ <xos-alert config="vm.config1" show="vm.show">
+ A sample alert message, not displayed by default.
+ </xos-alert>
+ </div>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('sampleAlert2', ['xos.uiComponents'])
+ .controller('SampleCtrl', function(){
+ this.config1 = {
+ type: 'success'
+ };
+
+ this.show = false;
+ });
+ </file>
+ </example>
+ **/
+
+ .directive('xosAlert', function(){
+ return {
+ restrict: 'E',
+ scope: {
+ config: '=',
+ show: '=?'
+ },
+ template: `
+ <div class="alert alert-{{vm.config.type}}" ng-show="vm.show">
+ <button type="button" class="close" ng-if="vm.config.closeBtn" ng-click="vm.dismiss()">
+ <span aria-hidden="true">×</span>
+ </button>
+ <p ng-transclude></p>
+ </div>
+ `,
+ transclude: true,
+ bindToController: true,
+ controllerAs: 'vm',
+ controller: function($timeout){
+
+ if(!this.config){
+ throw new Error('[xosAlert] Please provide a configuration via the "config" attribute');
+ }
+
+ // default the value to true
+ this.show = this.show !== false;
+
+ this.dismiss = () => {
+ this.show = false;
+ }
+
+ if(this.config.autoHide){
+ let to = $timeout(() => {
+ this.dismiss();
+ $timeout.cancel(to);
+ }, this.config.autoHide);
+ }
+ }
+ }
+ })
+})();
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/table/pagination.component.js b/views/ngXosLib/xosHelpers/src/ui_components/table/pagination.component.js
new file mode 100644
index 0000000..b7b1701
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/src/ui_components/table/pagination.component.js
@@ -0,0 +1,122 @@
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 4/15/16.
+ */
+
+(function () {
+ 'use strict';
+
+ angular.module('xos.uiComponents')
+
+ /**
+ * @ngdoc directive
+ * @name xos.uiComponents.directive:xosPagination
+ * @restrict E
+ * @description The xos-table directive
+ * @param {Number} pageSize Number of elements per page
+ * @param {Number} totalElements Number of total elements in the collection
+ * @param {Function} change The callback to be triggered on page change.
+ * * @element ANY
+ * @scope
+ * @example
+ <example module="samplePagination">
+ <file name="index.html">
+ <div ng-controller="SampleCtrl1 as vm">
+ <xos-pagination
+ page-size="vm.pageSize"
+ total-elements="vm.totalElements"
+ change="vm.change">
+ </xos-pagination>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('samplePagination', ['xos.uiComponents'])
+ .controller('SampleCtrl1', function(){
+ this.pageSize = 10;
+ this.totalElements = 35;
+ this.change = (pageNumber) => {
+ console.log(pageNumber);
+ }
+ });
+ </file>
+ </example>
+ **/
+
+ .directive('xosPagination', function(){
+ return {
+ restrict: 'E',
+ scope: {
+ pageSize: '=',
+ totalElements: '=',
+ change: '='
+ },
+ template: `
+ <div class="row" ng-if="vm.pageList.length > 1">
+ <div class="col-xs-12 text-center">
+ <ul class="pagination">
+ <li
+ ng-click="vm.goToPage(vm.currentPage - 1)"
+ ng-class="{disabled: vm.currentPage == 0}">
+ <a href="" aria-label="Previous">
+ <span aria-hidden="true">«</span>
+ </a>
+ </li>
+ <li ng-repeat="i in vm.pageList" ng-class="{active: i === vm.currentPage}">
+ <a href="" ng-click="vm.goToPage(i)">{{i + 1}}</a>
+ </li>
+ <li
+ ng-click="vm.goToPage(vm.currentPage + 1)"
+ ng-class="{disabled: vm.currentPage == vm.pages - 1}">
+ <a href="" aria-label="Next">
+ <span aria-hidden="true">»</span>
+ </a>
+ </li>
+ </ul>
+ </div>
+ </div>
+ `,
+ bindToController: true,
+ controllerAs: 'vm',
+ controller: function($scope){
+
+ this.currentPage = 0;
+
+ this.goToPage = (n) => {
+ if(n < 0 || n === this.pages){
+ return;
+ }
+ this.currentPage = n;
+ this.change(n);
+ }
+
+ this.createPages = (pages) => {
+ let arr = [];
+ for(var i = 0; i < pages; i++){
+ arr.push(i);
+ }
+ return arr;
+ }
+
+ // watch for data changes
+ $scope.$watch(() => this.totalElements, () => {
+ if(this.totalElements){
+ this.pages = Math.ceil(this.totalElements / this.pageSize);
+ this.pageList = this.createPages(this.pages);
+ }
+ });
+ }
+ }
+ })
+ .filter('pagination', function(){
+ return function(input, start) {
+ if(!input || !angular.isArray(input)){
+ return input;
+ }
+ start = parseInt(start, 10);
+ return input.slice(start);
+ };
+ });
+})();
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/table/table.component.js b/views/ngXosLib/xosHelpers/src/ui_components/table/table.component.js
index faeaa26..daca484 100644
--- a/views/ngXosLib/xosHelpers/src/ui_components/table/table.component.js
+++ b/views/ngXosLib/xosHelpers/src/ui_components/table/table.component.js
@@ -9,33 +9,276 @@
(function () {
'use strict';
- angular.module('xos.uiComponents.table', [])
+ angular.module('xos.uiComponents')
+
+ /**
+ * @ngdoc directive
+ * @name xos.uiComponents.directive:xosTable
+ * @restrict E
+ * @description The xos-table directive
+ * @param {Object} config The configuration for the component.
+ * ```
+ * {
+ * columns: [
+ * {
+ * label: 'Human readable name',
+ * prop: 'Property to read in the model object'
+ * }
+ * ],
+ * classes: 'table table-striped table-bordered',
+ * actions: [ // if defined add an action column
+ {
+ label: 'delete',
+ icon: 'remove', // refers to bootstraps glyphicon
+ cb: (user) => { // receive the model
+ console.log(user);
+ },
+ color: 'red'
+ }
+ ],
+ filter: 'field', // can be by `field` or `fulltext`
+ order: true // whether to show ordering arrows
+ * }
+ * ```
+ * @param {Array} data The data that should be rendered
+ * @element ANY
+ * @scope
+ * @example
+
+ <example module="sampleTable1">
+ <file name="index.html">
+ <div ng-controller="SampleCtrl1 as vm">
+ <xos-table data="vm.data" config="vm.config"></xos-table>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('sampleTable1', ['xos.uiComponents'])
+ .controller('SampleCtrl1', function(){
+ this.config = {
+ columns: [
+ {
+ label: 'First Name', // column title
+ prop: 'name' // property to read in the data array
+ },
+ {
+ label: 'Last Name',
+ prop: 'lastname'
+ }
+ ]
+ };
+
+ this.data = [
+ {
+ name: 'John',
+ lastname: 'Doe'
+ },
+ {
+ name: 'Gili',
+ lastname: 'Fereydoun'
+ }
+ ]
+ });
+ </file>
+ </example>
+
+ <example module="sampleTable2">
+ <file name="index.html">
+ <div ng-controller="SampleCtrl2 as vm">
+ <xos-table data="vm.data" config="vm.config"></xos-table>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('sampleTable2', ['xos.uiComponents'])
+ .controller('SampleCtrl2', function(){
+ this.config = {
+ columns: [
+ {
+ label: 'First Name', // column title
+ prop: 'name' // property to read in the data array
+ },
+ {
+ label: 'Last Name',
+ prop: 'lastname'
+ }
+ ],
+ classes: 'table table-striped table-condensed', // table classes, default to `table table-striped table-bordered`
+ actions: [ // if defined add an action column
+ {
+ label: 'delete', // label
+ icon: 'remove', // icons, refers to bootstraps glyphicon
+ cb: (user) => { // callback, get feeded with the full object
+ console.log(user);
+ },
+ color: 'red' // icon color
+ }
+ ],
+ filter: 'field', // can be by `field` or `fulltext`
+ order: true
+ };
+
+ this.data = [
+ {
+ name: 'John',
+ lastname: 'Doe'
+ },
+ {
+ name: 'Gili',
+ lastname: 'Fereydoun'
+ }
+ ]
+ });
+ </file>
+ </example>
+
+ <example module="sampleTable3">
+ <file name="index.html">
+ <div ng-controller="SampleCtrl3 as vm">
+ <xos-table data="vm.data" config="vm.config"></xos-table>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('sampleTable3', ['xos.uiComponents'])
+ .controller('SampleCtrl3', function(){
+ this.config = {
+ columns: [
+ {
+ label: 'First Name', // column title
+ prop: 'name' // property to read in the data array
+ },
+ {
+ label: 'Last Name',
+ prop: 'lastname'
+ }
+ ],
+ pagination: {
+ pageSize: 2
+ }
+ };
+
+ this.data = [
+ {
+ name: 'John',
+ lastname: 'Doe'
+ },
+ {
+ name: 'Gili',
+ lastname: 'Fereydoun'
+ },
+ {
+ name: 'Lucky',
+ lastname: 'Clarkson'
+ },
+ {
+ name: 'Tate',
+ lastname: 'Spalding'
+ }
+ ]
+ });
+ </file>
+ </example>
+ **/
+
.directive('xosTable', function(){
return {
restrict: 'E',
scope: {
data: '=',
- columns: '='
+ config: '='
},
- template: [
- '<!--<pre>{{vm.data | json}}</pre>-->',
- '<table class="table table-striped" ng-show="vm.data.length > 0">',
- '<thead>',
- '<tr>',
- '<th ng-repeat="col in vm.columns">{{col}}</th>',
- '</tr>',
- '</thead>',
- '<tbody>',
- '<tr ng-repeat="item in vm.data">',
- '<td ng-repeat="col in vm.columns">{{item[col]}}</td>',
- '</tr>',
- '</tbody>',
- '</table>'
- ].join(),
+ template: `
+ <div ng-show="vm.data.length > 0">
+ <div class="row" ng-if="vm.config.filter == 'fulltext'">
+ <div class="col-xs-12">
+ <input
+ class="form-control"
+ placeholder="Type to search.."
+ type="text"
+ ng-model="vm.query"/>
+ </div>
+ </div>
+ <table ng-class="vm.classes" ng-show="vm.data.length > 0">
+ <thead>
+ <tr>
+ <th ng-repeat="col in vm.columns">
+ {{col.label}}
+ <span ng-if="vm.config.order">
+ <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = false">
+ <i class="glyphicon glyphicon-chevron-up"></i>
+ </a>
+ <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = true">
+ <i class="glyphicon glyphicon-chevron-down"></i>
+ </a>
+ </span>
+ </th>
+ <th ng-if="vm.config.actions">Actions</th>
+ </tr>
+ </thead>
+ <tbody ng-if="vm.config.filter == 'field'">
+ <tr>
+ <td ng-repeat="col in vm.columns">
+ <input
+ class="form-control"
+ placeholder="Type to search by {{col.label}}"
+ type="text"
+ ng-model="vm.query[col.prop]"/>
+ </td>
+ <td ng-if="vm.config.actions"></td>
+ </tr>
+ </tbody>
+ <tbody>
+ <tr ng-repeat="item in vm.data | filter:vm.query | orderBy:vm.orderBy:vm.reverse | pagination:vm.currentPage * vm.config.pagination.pageSize | limitTo: (vm.config.pagination.pageSize || vm.data.length) track by $index">
+ <td ng-repeat="col in vm.columns">{{item[col.prop]}}</td>
+ <td ng-if="vm.config.actions">
+ <a href=""
+ ng-repeat="action in vm.config.actions"
+ ng-click="action.cb(item)"
+ title="{{action.label}}">
+ <i
+ class="glyphicon glyphicon-{{action.icon}}"
+ style="color: {{action.color}};"></i>
+ </a>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <xos-pagination
+ ng-if="vm.config.pagination"
+ page-size="vm.config.pagination.pageSize"
+ total-elements="vm.data.length"
+ change="vm.goToPage">
+ </xos-pagination>
+ </div>
+ <div ng-show="vm.data.length == 0 || !vm.data">
+ <div class="alert alert-info">
+ No data to show.
+ </div>
+ </div>
+ `,
bindToController: true,
controllerAs: 'vm',
controller: function(){
- console.log(this.data, this.columns);
+
+ if(!this.config){
+ throw new Error('[xosTable] Please provide a configuration via the "config" attribute');
+ }
+
+ if(!this.config.columns){
+ throw new Error('[xosTable] Please provide a columns list in the configuration');
+ }
+
+ this.columns = this.config.columns;
+ this.classes = this.config.classes || 'table table-striped table-bordered';
+
+ if(this.config.actions){
+ // TODO validate action format
+ }
+ if(this.config.pagination){
+ this.currentPage = 0;
+ this.goToPage = (n) => {
+ this.currentPage = n;
+ };
+ }
+
}
}
})
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/ui-components.module.js b/views/ngXosLib/xosHelpers/src/ui_components/ui-components.module.js
index 0cbe70e..bd07908 100644
--- a/views/ngXosLib/xosHelpers/src/ui_components/ui-components.module.js
+++ b/views/ngXosLib/xosHelpers/src/ui_components/ui-components.module.js
@@ -9,7 +9,12 @@
(function () {
'use strict';
+ /**
+ * @ngdoc overview
+ * @name xos.uiComponents
+ * @description A collection of UI components useful for Dashboard development
+ **/
+
angular.module('xos.uiComponents', [
- 'xos.uiComponents.table'
])
})();
diff --git a/views/ngXosViews/sampleView/gulp/server.js b/views/ngXosViews/sampleView/gulp/server.js
index 13659c3..3c6a8e3 100644
--- a/views/ngXosViews/sampleView/gulp/server.js
+++ b/views/ngXosViews/sampleView/gulp/server.js
@@ -3,6 +3,7 @@
var gulp = require('gulp');
var browserSync = require('browser-sync').create();
var inject = require('gulp-inject');
+var es = require('event-stream');
var runSequence = require('run-sequence');
var angularFilesort = require('gulp-angular-filesort');
var babel = require('gulp-babel');
@@ -10,6 +11,7 @@
var httpProxy = require('http-proxy');
var del = require('del');
var sass = require('gulp-sass');
+var debug = require('gulp-debug');
const environment = process.env.NODE_ENV;
@@ -34,9 +36,9 @@
});
module.exports = function(options){
-
// open in browser with sync and proxy to 0.0.0.0
gulp.task('browser', function() {
+ console.log(options.helpers);
browserSync.init({
// reloadDelay: 500,
// logLevel: 'debug',
@@ -50,13 +52,14 @@
server: {
baseDir: options.src,
routes: {
- '/xosHelpers/src': options.helpers
+ // '/xosHelpers/src': options.helpers,
+ '/xos/core/xoslib/static/js/vendor': options.helpers
},
middleware: function(req, res, next){
if(
- req.url.indexOf('/xos/') !== -1 ||
- req.url.indexOf('/xoslib/') !== -1 ||
- req.url.indexOf('/hpcapi/') !== -1 ||
+ // req.url.indexOf('/xos/') !== -1 ||
+ // req.url.indexOf('/xoslib/') !== -1 ||
+ // req.url.indexOf('/hpcapi/') !== -1 ||
req.url.indexOf('/api/') !== -1
){
if(conf.xoscsrftoken && conf.xossessionid){
@@ -82,6 +85,11 @@
gulp.watch(options.css + '**/*.css', function(){
browserSync.reload();
});
+
+ gulp.watch(options.helpers + 'ngXosHelpers.js', function(){
+ browserSync.reload();
+ });
+
gulp.watch(`${options.sass}/**/*.scss`, ['sass'], function(){
browserSync.reload();
});
@@ -101,16 +109,40 @@
.pipe(gulp.dest(options.tmp));
});
+ // // inject sourceMap
+ // gulp.task('injectMaps', function(){
+ // return gulp.src(options.src + 'index.html')
+ // .pipe(
+ // inject(
+ // gulp.src([
+ // options.helpersSourceMaps + '**/*.js.map'
+ // ], {read: false}).pipe(debug()),
+ // {
+ // starttag: '<!-- inject:maps -->',
+ // // ignorePath: [options.src, '/../../ngXosLib']
+ // }
+ // )
+ // )
+ // .pipe(gulp.dest(options.src));
+ // });
+
// inject scripts
gulp.task('injectScript', ['cleanTmp', 'babel'], function(){
+
+ var appScripts = gulp.src([
+ options.tmp + '**/*.js',
+ options.helpers + 'ngXosHelpers.js'
+ ])
+ .pipe(angularFilesort()).pipe(debug());
+
+ var helpersSourceMaps = gulp.src([
+ options.helpersSourceMaps + '**/*.js.map'
+ ]).pipe(debug());
+
return gulp.src(options.src + 'index.html')
.pipe(
inject(
- gulp.src([
- options.tmp + '**/*.js',
- options.helpers + '**/*.js' // todo add Babel here
- ])
- .pipe(angularFilesort()),
+ es.merge(appScripts, helpersSourceMaps),
{
ignorePath: [options.src, '/../../ngXosLib']
}
diff --git a/views/ngXosViews/sampleView/gulpfile.js b/views/ngXosViews/sampleView/gulpfile.js
index 8d30660..8b50345 100644
--- a/views/ngXosViews/sampleView/gulpfile.js
+++ b/views/ngXosViews/sampleView/gulpfile.js
@@ -11,7 +11,8 @@
tmp: 'src/.tmp',
dist: 'dist/',
api: '../../ngXosLib/api/',
- helpers: '../../ngXosLib/xosHelpers/src/',
+ helpers: '../../../xos/core/xoslib/static/js/vendor/',
+ helpersSourceMaps: '../../ngXosLib/xosHelpers/.tmp/maps/',
static: '../../../xos/core/xoslib/static/', // this is the django static folder
dashboards: '../../../xos/core/xoslib/dashboards/' // this is the django html folder
};
diff --git a/views/ngXosViews/sampleView/package.json b/views/ngXosViews/sampleView/package.json
index 0ffe32c..e92f937 100644
--- a/views/ngXosViews/sampleView/package.json
+++ b/views/ngXosViews/sampleView/package.json
@@ -28,12 +28,14 @@
"easy-mocker": "^1.2.0",
"eslint": "^1.8.0",
"eslint-plugin-angular": "linkmesrl/eslint-plugin-angular",
+ "event-stream": "^3.3.2",
"gulp": "^3.9.0",
"gulp-angular-filesort": "^1.1.1",
"gulp-angular-templatecache": "^1.8.0",
"gulp-babel": "^5.3.0",
"gulp-concat": "^2.6.0",
"gulp-concat-util": "^0.5.5",
+ "gulp-debug": "^2.1.2",
"gulp-eslint": "^1.0.0",
"gulp-inject": "^3.0.0",
"gulp-minify-html": "^1.0.4",
diff --git a/views/ngXosViews/sampleView/spec/sample.test.js b/views/ngXosViews/sampleView/spec/sample.test.js
index f0db699..6005af7 100644
--- a/views/ngXosViews/sampleView/spec/sample.test.js
+++ b/views/ngXosViews/sampleView/spec/sample.test.js
@@ -15,7 +15,7 @@
{
email: 'teo@onlab.us',
firstname: 'Matteo',
- lastname: 'Scandolo'
+ lastname: 'Scandolo'
}
]);
diff --git a/views/ngXosViews/sampleView/src/css/main.css b/views/ngXosViews/sampleView/src/css/main.css
index afdeba7..e69de29 100644
--- a/views/ngXosViews/sampleView/src/css/main.css
+++ b/views/ngXosViews/sampleView/src/css/main.css
@@ -1,2 +0,0 @@
-#xosSampleView .row {
- color: #d9534f; }
diff --git a/views/ngXosViews/sampleView/src/index.html b/views/ngXosViews/sampleView/src/index.html
index a925a7e..d04fc3b 100644
--- a/views/ngXosViews/sampleView/src/index.html
+++ b/views/ngXosViews/sampleView/src/index.html
@@ -21,17 +21,9 @@
<script src="vendor/bootstrap-css/js/bootstrap.min.js"></script>
<!-- endbower --><!-- endjs -->
<!-- inject:js -->
-<script src="/xosHelpers/src/xosHelpers.module.js"></script>
-<script src="/xosHelpers/src/ui_components/table/table.component.js"></script>
-<script src="/xosHelpers/src/services/rest/vSG.js"></script>
-<script src="/xosHelpers/src/services/rest/vOLT.js"></script>
-<script src="/xosHelpers/src/services/rest/Users.js"></script>
-<script src="/xosHelpers/src/services/rest/Truckroll.js"></script>
-<script src="/xosHelpers/src/services/rest/Subscribers.js"></script>
-<script src="/xosHelpers/src/services/rest/ONOS-Services.js"></script>
-<script src="/xosHelpers/src/services/rest/ONOS-Apps.js"></script>
-<script src="/xosHelpers/src/ui_components/ui-components.module.js"></script>
-<script src="/xosHelpers/src/services/noHyperlinks.interceptor.js"></script>
-<script src="/xosHelpers/src/services/csrfToken.interceptor.js"></script>
+<script src="/../../../xos/core/xoslib/static/js/vendor/ngXosHelpers.js"></script>
<script src="/.tmp/main.js"></script>
<!-- endinject -->
+
+<!-- inject:map -->
+<!-- endinject -->
\ No newline at end of file
diff --git a/views/ngXosViews/sampleView/src/js/main.js b/views/ngXosViews/sampleView/src/js/main.js
index 896ab77..b00aa0b 100644
--- a/views/ngXosViews/sampleView/src/js/main.js
+++ b/views/ngXosViews/sampleView/src/js/main.js
@@ -25,6 +25,46 @@
controllerAs: 'vm',
templateUrl: 'templates/users-list.tpl.html',
controller: function(Users){
+
+ this.tableConfig = {
+ columns: [
+ {
+ label: 'E-Mail',
+ prop: 'email'
+ },
+ {
+ label: 'First Name',
+ prop: 'firstname'
+ },
+ {
+ label: 'Last Name',
+ prop: 'lastname'
+ }
+ ],
+ classes: 'table table-striped table-condensed',
+ actions: [
+ {
+ label: 'delete',
+ icon: 'remove',
+ cb: (user) => {
+ console.log(user);
+ },
+ color: 'red'
+ }
+ ],
+ filter: 'field',
+ order: true,
+ // pagination: {
+ // pageSize: 6
+ // }
+ };
+
+ this.alertConfig = {
+ type: 'danger',
+ closeBtn: true
+ }
+
+
// retrieving user list
Users.query().$promise
.then((users) => {
diff --git a/views/ngXosViews/sampleView/src/sass/main.scss b/views/ngXosViews/sampleView/src/sass/main.scss
index 76d5ce8..efe6cdc 100644
--- a/views/ngXosViews/sampleView/src/sass/main.scss
+++ b/views/ngXosViews/sampleView/src/sass/main.scss
@@ -1,7 +1,5 @@
@import '../../../../style/sass/lib/_variables.scss';
#xosSampleView {
- .row {
- color: $brand-danger;
- }
+
}
\ No newline at end of file
diff --git a/views/ngXosViews/sampleView/src/templates/users-list.tpl.html b/views/ngXosViews/sampleView/src/templates/users-list.tpl.html
index 03be487..c0c58cb 100644
--- a/views/ngXosViews/sampleView/src/templates/users-list.tpl.html
+++ b/views/ngXosViews/sampleView/src/templates/users-list.tpl.html
@@ -1,14 +1,14 @@
<div class="row">
- <h1>Users List</h1>
- <p>This is only an example view.</p>
+ <div class="col-xs-12">
+ <h1>Users List</h1>
+ <p>This is only an example view.</p>
+ </div>
</div>
+
+ <xos-alert config="vm.alertConfig">Alert message Here</xos-alert>
+
<div class="row">
- <div class="col-xs-4">Email</div>
- <div class="col-xs-4">First Name</div>
- <div class="col-xs-4">Last Name</div>
-</div>
-<div class="row" ng-repeat="user in vm.users">
- <div class="col-xs-4">{{user.email}}</div>
- <div class="col-xs-4">{{user.firstname}}</div>
- <div class="col-xs-4">{{user.lastname}}</div>
-</div>
\ No newline at end of file
+ <div class="col-xs-12">
+ <xos-table data="vm.users" config="vm.tableConfig"></xos-table>
+ </div>
+</div>
\ No newline at end of file
diff --git a/xos/core/xoslib/static/css/xosSampleView.css b/xos/core/xoslib/static/css/xosSampleView.css
index 1a67321..e69de29 100644
--- a/xos/core/xoslib/static/css/xosSampleView.css
+++ b/xos/core/xoslib/static/css/xosSampleView.css
@@ -1 +0,0 @@
-#xosSampleView .row{color:#d9534f}
\ 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 23316a7..f981551 100644
--- a/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
+++ b/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
@@ -1 +1 @@
-!function(){"use strict";angular.module("xos.uiComponents.table",[]).directive("xosTable",function(){return{restrict:"E",scope:{data:"=",columns:"="},template:["<!--<pre>{{vm.data | json}}</pre>-->",'<table class="table table-striped" ng-show="vm.data.length > 0">',"<thead>","<tr>",'<th ng-repeat="col in vm.columns">{{col}}</th>',"</tr>","</thead>","<tbody>",'<tr ng-repeat="item in vm.data">','<td ng-repeat="col in vm.columns">{{item[col]}}</td>',"</tr>","</tbody>","</table>"].join(),bindToController:!0,controllerAs:"vm",controller:function(){console.log(this.data,this.columns)}}})}(),function(){"use strict";function e(e,r,s){e.interceptors.push("SetCSRFToken"),r.startSymbol("{$"),r.endSymbol("$}"),s.defaults.stripTrailingSlashes=!1}e.$inject=["$httpProvider","$interpolateProvider","$resourceProvider"],console.log("XOS Helpers Module"),angular.module("bugSnag",[]).factory("$exceptionHandler",function(){return function(e,r){window.Bugsnag?Bugsnag.notifyException(e,{diagnostics:{cause:r}}):console.error(e,r,e.stack)}}),angular.module("xos.helpers",["ngCookies","ngResource","bugSnag","xos.uiComponents"]).config(e)}(),function(){"use strict";angular.module("xos.helpers").service("vSG-Collection",["$resource",function(e){return e("/api/service/vsg/")}])}(),function(){"use strict";angular.module("xos.helpers").service("vOLT-Collection",["$resource",function(e){return e("/api/tenant/cord/volt/:volt_id/",{volt_id:"@id"})}])}(),function(){"use strict";angular.module("xos.helpers").service("Users",["$resource",function(e){return e("/api/core/users/")}])}(),function(){"use strict";angular.module("xos.helpers").service("Truckroll-Collection",["$resource",function(e){return e("/api/tenant/truckroll/:truckroll_id/",{truckroll_id:"@id"})}])}(),function(){"use strict";angular.module("xos.helpers").service("Subscribers",["$resource",function(e){return e("/api/tenant/cord/subscriber/:subscriber_id/",{subscriber_id:"@id"})}]).service("Subscriber-features",["$resource",function(e){return e("/api/tenant/cord/subscriber/:subscriber_id/features/",{subscriber_id:"@id"})}]).service("Subscriber-features-uplink_speed",["$resource",function(e){return e("/api/tenant/cord/subscriber/:subscriber_id/features/uplink_speed/",{subscriber_id:"@id"})}]).service("Subscriber-features-downlink_speed",["$resource",function(e){return e("/api/tenant/cord/subscriber/:subscriber_id/features/downlink_speed/",{subscriber_id:"@id"})}]).service("Subscriber-features-cdn",["$resource",function(e){return e("/api/tenant/cord/subscriber/:subscriber_id/features/cdn/",{subscriber_id:"@id"})}]).service("Subscriber-features-uverse",["$resource",function(e){return e("/api/tenant/cord/subscriber/:subscriber_id/features/uverse/",{subscriber_id:"@id"})}]).service("Subscriber-features-status",["$resource",function(e){return e("/api/tenant/cord/subscriber/:subscriber_id/features/status/",{subscriber_id:"@id"})}])}(),function(){"use strict";angular.module("xos.helpers").service("ONOS-Services-Collection",["$resource",function(e){return e("/api/service/onos/")}])}(),function(){"use strict";angular.module("xos.helpers").service("ONOS-App-Collection",["$resource",function(e){return e("/api/tenant/onos/app/")}])}(),function(){"use strict";angular.module("xos.uiComponents",["xos.uiComponents.table"])}(),function(){"use strict";function e(){return{request:function(e){return-1===e.url.indexOf(".html")&&(e.url+="?no_hyperlinks=1"),e}}}angular.module("xos.helpers").factory("NoHyperlinks",e)}(),function(){"use strict";function e(e){return{request:function(r){return"GET"!==r.method&&(r.headers["X-CSRFToken"]=e.get("xoscsrftoken")),r}}}e.$inject=["$cookies"],angular.module("xos.helpers").factory("SetCSRFToken",e)}();
\ No newline at end of file
+"use strict";!function(){angular.module("xos.uiComponents",[])}(),function(){angular.module("xos.uiComponents").directive("xosTable",function(){return{restrict:"E",scope:{data:"=",config:"="},template:'\n <div ng-show="vm.data.length > 0">\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-show="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 class="form-control"\n placeholder="Type to search by {{col.label}}"\n type="text"\n ng-model="vm.query[col.prop]"/>\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 | 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">{{item[col.prop]}}</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">\n <div class="alert alert-info">\n No data to show.\n </div>\n </div>\n ',bindToController:!0,controllerAs:"vm",controller:function(){var n=this;if(!this.config)throw new Error('[xosTable] Please provide a configuration via the "config" attribute');if(!this.config.columns)throw new Error("[xosTable] Please provide a columns list in the configuration");this.columns=this.config.columns,this.classes=this.config.classes||"table table-striped table-bordered",this.config.actions,this.config.pagination&&(this.currentPage=0,this.goToPage=function(e){n.currentPage=e})}}})}(),function(){angular.module("xos.uiComponents").directive("xosPagination",function(){return{restrict:"E",scope:{pageSize:"=",totalElements:"=",change:"="},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">«</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">»</span>\n </a>\n </li>\n </ul>\n </div>\n </div>\n ',bindToController:!0,controllerAs:"vm",controller:["$scope",function(n){var e=this;this.currentPage=0,this.goToPage=function(n){0>n||n===e.pages||(e.currentPage=n,e.change(n))},this.createPages=function(n){for(var e=[],r=0;n>r;r++)e.push(r);return e},n.$watch(function(){return e.totalElements},function(){e.totalElements&&(e.pages=Math.ceil(e.totalElements/e.pageSize),e.pageList=e.createPages(e.pages))})}]}}).filter("pagination",function(){return function(n,e){return n&&angular.isArray(n)?(e=parseInt(e,10),n.slice(e)):n}})}(),function(){angular.module("xos.uiComponents").directive("xosAlert",function(){return{restrict:"E",scope:{config:"=",show:"=?"},template:'\n <div class="alert alert-{{vm.config.type}}" ng-show="vm.show">\n <button type="button" class="close" ng-if="vm.config.closeBtn" ng-click="vm.dismiss()">\n <span aria-hidden="true">×</span>\n </button>\n <p ng-transclude></p>\n </div>\n ',transclude:!0,bindToController:!0,controllerAs:"vm",controller:["$timeout",function(n){var e=this;if(!this.config)throw new Error('[xosAlert] Please provide a configuration via the "config" attribute');this.show=this.show!==!1,this.dismiss=function(){e.show=!1},this.config.autoHide&&!function(){var r=n(function(){e.dismiss(),n.cancel(r)},e.config.autoHide)}()}]}})}(),function(){function n(n,e,r){n.interceptors.push("SetCSRFToken"),e.startSymbol("{$"),e.endSymbol("$}"),r.defaults.stripTrailingSlashes=!1}n.$inject=["$httpProvider","$interpolateProvider","$resourceProvider"],angular.module("bugSnag",[]).factory("$exceptionHandler",function(){return function(n,e){window.Bugsnag?Bugsnag.notifyException(n,{diagnostics:{cause:e}}):console.error(n,e,n.stack)}}),angular.module("xos.helpers",["ngCookies","ngResource","bugSnag","xos.uiComponents"]).config(n)}(),function(){angular.module("xos.helpers").service("vSG-Collection",["$resource",function(n){return n("/api/service/vsg/")}])}(),function(){angular.module("xos.helpers").service("vOLT-Collection",["$resource",function(n){return n("/api/tenant/cord/volt/:volt_id/",{volt_id:"@id"})}])}(),function(){angular.module("xos.helpers").service("Users",["$resource",function(n){return n("/api/core/users/")}])}(),function(){angular.module("xos.helpers").service("Truckroll-Collection",["$resource",function(n){return n("/api/tenant/truckroll/:truckroll_id/",{truckroll_id:"@id"})}])}(),function(){angular.module("xos.helpers").service("Subscribers",["$resource",function(n){return n("/api/tenant/cord/subscriber/:subscriber_id/",{subscriber_id:"@id"})}]).service("Subscriber-features",["$resource",function(n){return n("/api/tenant/cord/subscriber/:subscriber_id/features/",{subscriber_id:"@id"})}]).service("Subscriber-features-uplink_speed",["$resource",function(n){return n("/api/tenant/cord/subscriber/:subscriber_id/features/uplink_speed/",{subscriber_id:"@id"})}]).service("Subscriber-features-downlink_speed",["$resource",function(n){return n("/api/tenant/cord/subscriber/:subscriber_id/features/downlink_speed/",{subscriber_id:"@id"})}]).service("Subscriber-features-cdn",["$resource",function(n){return n("/api/tenant/cord/subscriber/:subscriber_id/features/cdn/",{subscriber_id:"@id"})}]).service("Subscriber-features-uverse",["$resource",function(n){return n("/api/tenant/cord/subscriber/:subscriber_id/features/uverse/",{subscriber_id:"@id"})}]).service("Subscriber-features-status",["$resource",function(n){return n("/api/tenant/cord/subscriber/:subscriber_id/features/status/",{subscriber_id:"@id"})}])}(),function(){angular.module("xos.helpers").service("ONOS-Services-Collection",["$resource",function(n){return n("/api/service/onos/")}])}(),function(){angular.module("xos.helpers").service("ONOS-App-Collection",["$resource",function(n){return n("/api/tenant/onos/app/")}])}(),function(){function n(){return{request:function(n){return-1===n.url.indexOf(".html")&&(n.url+="?no_hyperlinks=1"),n}}}angular.module("xos.helpers").factory("NoHyperlinks",n)}(),function(){function n(n){return{request:function(e){return"GET"!==e.method&&(e.headers["X-CSRFToken"]=n.get("xoscsrftoken")),e}}}n.$inject=["$cookies"],angular.module("xos.helpers").factory("SetCSRFToken",n)}();
\ No newline at end of file