Generating app and serving APIs
diff --git a/xos/core/xoslib/ngXosLib/generator-xos/app/index.js b/xos/core/xoslib/ngXosLib/generator-xos/app/index.js
index 7824d89..43a4bcc 100755
--- a/xos/core/xoslib/ngXosLib/generator-xos/app/index.js
+++ b/xos/core/xoslib/ngXosLib/generator-xos/app/index.js
@@ -1,6 +1,9 @@
 'use strict';
 
 var generators = require('yeoman-generator');
+var user = require('../node_modules/yeoman-generator/lib/actions/user');
+
+var config = {};
 
 module.exports = generators.Base.extend({
   prompting: function(){
@@ -11,7 +14,64 @@
       message : 'Your project name',
       default : this.config.get('name') // value set in .yo-rc.json
     }, function (answers) {
-      this.log(answers.name);
+      // TODO check if this view already exist
+      config.name = answers.name;
+      done();
+    }.bind(this));
+  },
+  writing: {
+    rcFiles: function(){
+      this.fs.copy(this.templatePath('.bowerrc'), this.destinationPath(`${this.config.get('folder')}/${config.name}/.bowerrc`));
+      this.fs.copy(this.templatePath('.gitignore'), this.destinationPath(`${this.config.get('folder')}/${config.name}/.gitignore`));
+    },
+    packageJson: function(){
+      this.fs.copyTpl(
+        this.templatePath('package.json'),
+        this.destinationPath(`${this.config.get('folder')}/${config.name}/package.json`),
+        { name: config.name, author: {name:user.git.name()} }
+      );
+    },
+    bowerJson: function(){
+      this.fs.copyTpl(
+        this.templatePath('bower.json'),
+        this.destinationPath(`${this.config.get('folder')}/${config.name}/bower.json`),
+        { name: config.name, author: {name:user.git.name(), email: user.git.email()} }
+      );
+    },
+    index: function(){
+      this.fs.copyTpl(
+        this.templatePath('src/index.html'),
+        this.destinationPath(`${this.config.get('folder')}/${config.name}/src/index.html`),
+        { name: config.name }
+      );
+    },
+    mainJs: function(){
+      this.fs.copyTpl(
+        this.templatePath('src/js/main.js'),
+        this.destinationPath(`${this.config.get('folder')}/${config.name}/src/js/main.js`),
+        { name: config.name }
+      );
+    },
+    template: function(){
+      this.fs.copy(this.templatePath('src/templates/users-list.tpl.html'), this.destinationPath(`${this.config.get('folder')}/${config.name}/src/templates/users-list.tpl.html`));
+    },
+    gulp: function(){
+      this.fs.copy(this.templatePath('gulp/*.js'), this.destinationPath(`${this.config.get('folder')}/${config.name}/gulp`));
+      this.fs.copy(this.templatePath('gulpfile.js'), this.destinationPath(`${this.config.get('folder')}/${config.name}/gulpfile.js`));
+    }
+  },
+  install: function(){
+    var done = this.async();
+    this.prompt({
+      type    : 'confirm',
+      name    : 'deps',
+      message : 'Install dependecies?',
+      default : false // value set in .yo-rc.json
+    }, function (answers) {
+      if(answers.deps){
+        process.chdir(`${this.config.get('folder')}/${config.name}`);
+        this.installDependencies();
+      }
       done();
     }.bind(this));
   }
diff --git a/xos/core/xoslib/ngXosLib/generator-xos/app/templates/.bowerrc b/xos/core/xoslib/ngXosLib/generator-xos/app/templates/.bowerrc
new file mode 100644
index 0000000..e491038
--- /dev/null
+++ b/xos/core/xoslib/ngXosLib/generator-xos/app/templates/.bowerrc
@@ -0,0 +1,3 @@
+{
+  "directory": "src/vendor/"
+}
\ No newline at end of file
diff --git a/xos/core/xoslib/ngXosLib/generator-xos/app/templates/.gitignore b/xos/core/xoslib/ngXosLib/generator-xos/app/templates/.gitignore
new file mode 100644
index 0000000..bccda71
--- /dev/null
+++ b/xos/core/xoslib/ngXosLib/generator-xos/app/templates/.gitignore
@@ -0,0 +1,5 @@
+dist/
+src/vendor
+.tmp
+node_modules
+npm-debug.log
\ No newline at end of file
diff --git a/xos/core/xoslib/ngXosLib/generator-xos/app/templates/bower.json b/xos/core/xoslib/ngXosLib/generator-xos/app/templates/bower.json
new file mode 100644
index 0000000..bc2289d
--- /dev/null
+++ b/xos/core/xoslib/ngXosLib/generator-xos/app/templates/bower.json
@@ -0,0 +1,27 @@
+{
+  "name": "xos-<%= name %>",
+  "version": "0.0.0",
+  "authors": [
+    "<%= author.name %> <<%= author.email %>>"
+  ],
+  "description": "The <%= name %> view",
+  "license": "MIT",
+  "ignore": [
+    "**/.*",
+    "node_modules",
+    "bower_components",
+    "static/js/vendor/",
+    "test",
+    "tests"
+  ],
+  "dependencies": {
+    "angular": "~1.4.7",
+    "angular-route": "~1.4.7",
+    "angular-cookies": "~1.4.7",
+    "angular-resource": "~1.4.7",
+    "ng-lodash": "~0.3.0"
+  },
+  "devDependencies": {
+    "bootstrap-css": "2.3.2"
+  }
+}
diff --git a/xos/core/xoslib/ngXosLib/generator-xos/app/templates/gulp/build.js b/xos/core/xoslib/ngXosLib/generator-xos/app/templates/gulp/build.js
new file mode 100644
index 0000000..40136c8
--- /dev/null
+++ b/xos/core/xoslib/ngXosLib/generator-xos/app/templates/gulp/build.js
@@ -0,0 +1,93 @@
+'use strict';
+
+// BUILD
+// 
+// The only purpose of this gulpfile is to build a XOS view and copy the correct files into
+// .html => dashboards
+// .js (minified and concat) => static/js
+// 
+// The template are parsed and added to js with angular $templateCache
+
+var gulp = require('gulp');
+var ngmin = require('gulp-ngmin');
+var uglify = require('gulp-uglify');
+var templateCache = require('gulp-angular-templatecache');
+var runSequence = require('run-sequence');
+var minifyHtml = require("gulp-minify-html");
+var concat = require("gulp-concat");
+var del = require('del');
+var wiredep = require('wiredep');
+var babel = require('gulp-babel');
+var angularFilesort = require('gulp-angular-filesort');
+
+var TEMPLATE_HEADER = '/*This code is autogenerated from the templates files */ angular.module("<%= module %>"<%= standalone %>).run(["$templateCache", function($templateCache) {';
+
+module.exports = function(options){
+  
+  // empty the dist folder
+  gulp.task('clean', function(){
+    return del([options.dist + '**/*']);
+  });
+
+  // compile and minify scripts
+  gulp.task('scripts', function() {
+    return gulp.src([
+        options.scripts + '**/*.js'
+      ])
+      .pipe(babel())
+      .pipe(ngmin())
+      .pipe(angularFilesort())
+      .pipe(concat('xosContentProvider.js'))
+      .pipe(uglify())
+      .pipe(gulp.dest(options.dist));
+  });
+
+  // set templates in cache
+  gulp.task('templates', function(){
+    return gulp.src("./src/templates/*.html")
+      .pipe(templateCache({
+        module: 'xos.contentProviderApp',
+        root: '../../static/templates/contentProvider/',
+        templateHeader: TEMPLATE_HEADER
+      }))
+      .pipe(gulp.dest(options.scripts));
+  });
+
+  // copy js output to Django Folder
+  gulp.task('copyJs', function(){
+    return gulp.src('dist/xosContentProvider.js')
+      .pipe(gulp.dest('../static/js/'))
+  });
+
+  // copy vendor js output to Django Folder
+  gulp.task('copyVendor', function(){
+    return gulp.src('dist/xosNgVendor.js')
+      .pipe(gulp.dest('../static/js/vendor/'));
+  });
+
+  // minify vendor js files
+  gulp.task('wiredep', function(){
+    var bowerDeps = wiredep().js;
+    return gulp.src(bowerDeps)
+      .pipe(concat('xosNgVendor.js'))
+      .pipe(uglify())
+      .pipe(gulp.dest(options.dist));
+  });
+
+  // TODO vendor
+  // - define a list of common components (eg: angular, angular-route, ...)
+  // - find the difference between local components e common components
+  // - minify only the local
+  // - unify wiredep, filter and copyVendor task
+
+  gulp.task('build', function() {
+    runSequence(
+      'clean',
+      'templates',
+      'scripts',
+      'copyJs',
+      'wiredep',
+      'copyVendor'
+    );
+  });
+}
\ No newline at end of file
diff --git a/xos/core/xoslib/ngXosLib/generator-xos/app/templates/gulp/server.js b/xos/core/xoslib/ngXosLib/generator-xos/app/templates/gulp/server.js
new file mode 100644
index 0000000..50f2371
--- /dev/null
+++ b/xos/core/xoslib/ngXosLib/generator-xos/app/templates/gulp/server.js
@@ -0,0 +1,91 @@
+'use strict';
+
+var gulp = require('gulp');
+var browserSync = require('browser-sync').create();
+var inject = require('gulp-inject');
+var runSequence = require('run-sequence');
+var angularFilesort = require('gulp-angular-filesort');
+var babel = require('gulp-babel');
+var wiredep = require('wiredep').stream;
+var httpProxy = require('http-proxy');
+
+var proxy = httpProxy.createProxyServer({
+  target: 'http://0.0.0.0:9999'
+});
+
+
+proxy.on('error', function(error, req, res) {
+  res.writeHead(500, {
+    'Content-Type': 'text/plain'
+  });
+
+  console.error('[Proxy]', error);
+});
+
+module.exports = function(options){
+
+  // open in browser with sync and proxy to 0.0.0.0
+  gulp.task('browser', function() {
+    browserSync.init({
+      reloadDelay: 500,
+      server: {
+        baseDir: options.src,
+        routes: {
+          '/api': options.api
+        },
+        middleware: function(req, res, next){
+          if(req.url.indexOf('no_hyperlinks') !== -1){
+            proxy.web(req, res);
+          }
+          else{
+            next();
+          }
+        }
+      }
+    });
+
+     gulp.watch(options.src + '**/*.js', ['js-watch']);
+  });
+
+  // transpile js with sourceMaps
+  gulp.task('babel', function(){
+    return gulp.src(options.scripts + '**/*.js')
+      .pipe(babel({sourceMaps: true}))
+      .pipe(gulp.dest(options.tmp));
+  });
+
+  // inject scripts
+  gulp.task('inject', ['babel'],function(){
+    return gulp.src(options.src + 'index.html')
+      .pipe(
+        inject(
+          gulp.src([
+            options.tmp + '**/*.js',
+            options.api + '*.js'
+          ])
+          .pipe(angularFilesort()),
+          {
+            ignorePath: [options.src, '/../../ngXosLib']
+          }
+        )
+      )
+      .pipe(gulp.dest(options.src));
+  });
+
+  // inject bower dependencies with wiredep
+  gulp.task('bower', function () {
+    gulp.src(options.src + 'index.html')
+    .pipe(wiredep({devDependencies: true}))
+    .pipe(gulp.dest(options.src));
+  });
+
+  gulp.task('js-watch', ['babel'], browserSync.reload);
+
+  gulp.task('serve', function() {
+    runSequence(
+      'bower',
+      'inject',
+      ['browser']
+    );
+  });
+}
\ No newline at end of file
diff --git a/xos/core/xoslib/ngXosLib/generator-xos/app/templates/gulpfile.js b/xos/core/xoslib/ngXosLib/generator-xos/app/templates/gulpfile.js
new file mode 100644
index 0000000..fd2db79
--- /dev/null
+++ b/xos/core/xoslib/ngXosLib/generator-xos/app/templates/gulpfile.js
@@ -0,0 +1,21 @@
+'use strict';
+
+var gulp = require('gulp');
+var wrench = require('wrench');
+
+var options = {
+  src: 'src/',
+  scripts: 'src/js/',
+  tmp: 'src/.tmp',
+  dist: 'dist/',
+  api: '../../ngXosLib/api/'
+};
+
+wrench.readdirSyncRecursive('./gulp')
+.map(function(file) {
+  require('./gulp/' + file)(options);
+});
+
+gulp.task('default', ['clean'], function () {
+  gulp.start('build');
+});
diff --git a/xos/core/xoslib/ngXosLib/generator-xos/app/templates/package.json b/xos/core/xoslib/ngXosLib/generator-xos/app/templates/package.json
new file mode 100644
index 0000000..7dc19d0
--- /dev/null
+++ b/xos/core/xoslib/ngXosLib/generator-xos/app/templates/package.json
@@ -0,0 +1,34 @@
+{
+  "name": "xos-<%= name %>",
+  "version": "1.0.0",
+  "description": "Angular Application for XOS, created with generator-xos",
+  "scripts": {
+    "start": "gulp serve"
+  },
+  "keywords": [
+    "XOS",
+    "Angular",
+    "XOSlib"
+  ],
+  "author": "<%= author.name %>",
+  "license": "MIT",
+  "dependencies": {},
+  "devDependencies": {
+    "browser-sync": "^2.9.11",
+    "del": "^2.0.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-inject": "^3.0.0",
+    "gulp-minify-html": "^1.0.4",
+    "gulp-ngmin": "^0.3.0",
+    "gulp-uglify": "^1.4.2",
+    "http-proxy": "^1.12.0",
+    "proxy-middleware": "^0.15.0",
+    "run-sequence": "^1.1.4",
+    "wiredep": "^3.0.0-beta",
+    "wrench": "^1.5.8"
+  }
+}
diff --git a/xos/core/xoslib/ngXosLib/generator-xos/app/templates/src/index.html b/xos/core/xoslib/ngXosLib/generator-xos/app/templates/src/index.html
new file mode 100644
index 0000000..317ac0e
--- /dev/null
+++ b/xos/core/xoslib/ngXosLib/generator-xos/app/templates/src/index.html
@@ -0,0 +1,21 @@
+<!-- bower:css -->
+<!-- endbower -->
+
+<style>
+  .container{
+    position: absolute;
+    top: 100px;
+    left: 200px;
+  }
+</style>
+
+<div class="container">
+  <div ng-app="xos.<%= name %>">
+    <ng-view></ng-view>
+  </div>
+</div>
+
+<!-- bower:js -->
+<!-- endbower -->
+<!-- inject:js -->
+<!-- endinject -->
diff --git a/xos/core/xoslib/ngXosLib/generator-xos/app/templates/src/js/main.js b/xos/core/xoslib/ngXosLib/generator-xos/app/templates/src/js/main.js
new file mode 100644
index 0000000..d816188
--- /dev/null
+++ b/xos/core/xoslib/ngXosLib/generator-xos/app/templates/src/js/main.js
@@ -0,0 +1,67 @@
+/* global angular */
+/* eslint-disable dot-location*/
+
+// TODO
+// - Add Cache
+// - Refactor routing with ui.router and child views (share the navigation and header)
+
+angular.module('xos.<%= name %>', [
+  'ngResource',
+  'ngRoute',
+  'ngCookies',
+  'ngLodash'
+])
+.config(($interpolateProvider, $routeProvider, $resourceProvider) => {
+  $interpolateProvider.startSymbol('{$');
+  $interpolateProvider.endSymbol('$}');
+
+  // NOTE http://www.masnun.com/2013/09/18/django-rest-framework-angularjs-resource-trailing-slash-problem.html
+  $resourceProvider.defaults.stripTrailingSlashes = false;
+
+  $routeProvider
+  .when('/', {
+    template: '<users-list></users-list>',
+  })
+
+  .otherwise('/');
+})
+// TODO move this in xos.service module
+.config(function($httpProvider){
+  // add X-CSRFToken header for update, create, delete (!GET)
+  $httpProvider.interceptors.push('SetCSRFToken');
+})
+.factory('SetCSRFToken', function($cookies){
+  return {
+    request: function(request){
+
+      // if request is not HTML
+      if(request.url.indexOf('.html') === -1){
+        request.url += '?no_hyperlinks=1';
+      }
+
+      if(request.method !== 'GET'){
+        // request.headers['X-CSRFToken'] = $cookies.get('csrftoken');
+        request.headers['X-CSRFToken'] = $cookies.get('xoscsrftoken');
+      }
+      return request;
+    }
+  };
+})
+// ENDTODO
+.directive('usersList', function(){
+  return {
+    restrict: 'E',
+    scope: {},
+    bindToController: true,
+    controllerAs: 'vm',
+    templateUrl: 'templates/users-list.tpl.html',
+    controller: function(){
+      this.deleteCp = function(id){
+        ContentProvider.delete({id: id}).$promise
+        .then(function(){
+          $location.url('/');
+        });
+      };
+    }
+  };
+});
\ No newline at end of file
diff --git a/xos/core/xoslib/ngXosLib/generator-xos/app/templates/src/templates/users-list.tpl.html b/xos/core/xoslib/ngXosLib/generator-xos/app/templates/src/templates/users-list.tpl.html
new file mode 100644
index 0000000..2873029
--- /dev/null
+++ b/xos/core/xoslib/ngXosLib/generator-xos/app/templates/src/templates/users-list.tpl.html
@@ -0,0 +1,5 @@
+<div class="row-fluid">
+  <div class="span4">{{user.email}}</div>
+  <div class="span4">{{user.firstname}}</div>
+  <div class="span4">{{user.lastname}}</div>
+</div>  
\ No newline at end of file