Initial Version. Support both AfbDaemon & Backend Mock server.
authorFulup Ar Foll <fulup@iot.bzh>
Wed, 16 Dec 2015 15:54:56 +0000 (16:54 +0100)
committerFulup Ar Foll <fulup@iot.bzh>
Wed, 16 Dec 2015 15:54:56 +0000 (16:54 +0100)
afb-client/.gitignore [new file with mode: 0644]
afb-client/LICENSE [new file with mode: 0644]
afb-client/README.md
afb-client/bower.json [new file with mode: 0644]
afb-client/gulpfile.js [new file with mode: 0644]
afb-client/index.html [new file with mode: 0644]
afb-client/package.json [new file with mode: 0644]

diff --git a/afb-client/.gitignore b/afb-client/.gitignore
new file mode 100644 (file)
index 0000000..bb6f2ab
--- /dev/null
@@ -0,0 +1,7 @@
+bower_components/
+node_modules/
+dist.dev/
+dist.prod/
+*.DS_Store
+nbproject/private/
+.noderc*
diff --git a/afb-client/LICENSE b/afb-client/LICENSE
new file mode 100644 (file)
index 0000000..89f9ced
--- /dev/null
@@ -0,0 +1,17 @@
+/* 
+ * Copyright (C) 2015 "IoT.bzh"
+ * Author "Fulup Ar Foll"
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
index 11a8f45..e31390e 100644 (file)
@@ -1,2 +1,95 @@
-# afb-client-sample
-Simple HTML5 Application Framework Client base on Angular &amp; Zurb Foundation + Gulp
+
+## Installation
+
+Install HTML5 development toolchain on your host
+
+1. Check out this repository
+   git clone https://github.com/iotbzh/afb-client-sample.git
+
+2) Install NodeJs [not used on target] 
+    zypper install nodejs
+    yum install nodejs
+
+3) Install building tools [bower, gulp, ....]
+   npm install # this install all development tool chain dependencies
+   sudo npm install --global gulp  # this is not mandatory but it will make your live simpler
+
+4. For livereload functionality [automatic refresh of HTML/CSS]
+   install [livereload Chrome extension](https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei)
+
+
+### Overload ./etc/Defaults.js with '.noderc.js'
+    var config= {
+        APPNAME : 'AFBclient',   // AppName is use as main Angular Module name
+        FRONTEND: "Frontend",    // HTML5 frontend  [no leading ./]
+        BACKEND : "Backend",     // NodeJS Rest API [no leading ./]
+        URLBASE : '/opa/',       // HTML basedir when running in production [should end with a /]
+        APIBASE : '/api/',       // Api url base dir [should end with a /]
+        DEBUG   : 4001,          // Node Debug Port [for mock API debug only]
+        DBG_LVL : 5,             // Debug Trace Level 0=no trace.
+    };
+    module.exports = config;
+
+    WARNING: in current version Frontend/services/ConfigApp.js is not updated automatically
+    you should make sure than your backend config fit with your frontend config.
+    Note: FCS version should have ConfigApp.js configurated automatically from GULP, but this is for "tomorrow"
+
+### Build project
+    gulp help
+    gulp build-app-dev
+    gulp watch-dev 
+    http://localhost:3001/opa  /* debug mock api base on Backend/RestApi */
+
+### Test with Application server binder  [you may safely run gulp 'watch-dev' + 'afb-daemon' simultaneously]
+    export MYWORKSPACE=$HOME/Workspace
+    $MYWORKSPACE/afb-daemon/build/afb-daemon --port=1234 --verbose --token=123456789 --rootdir=$MYWORKSPACE/afb-client/dist.dev
+    http://localhost:1234/opa
+
+    Note: 
+      - do not forget "/opa" that should match with your config.URLBASE
+      - if you change --token=xxxx do not forget to update ./Frontend/pages/HomeModules.js
+      - Force HTML/OPA reload with F5 after each HTML5/OPA update or new pages may not be loaded. 
+      - When reloading HTML/OPA with F5 do not forget that your initial token wont be accepted anymore. You should either restart to clean existing session or cleanup AJB_session cookie.
+
+### Move to Target
+    cd $MYWORKSPACE/afb-client
+    gulp build-app-prod
+    scp -r ./dist.pro/* user@mytarget:/rootdir/apfDaemon
+
+    /AppClient
+    |
+    |---- package.json
+    |---- bower.json
+    |---- gulpfile.js
+    |---- .noderc.js  [Warning: contains private keys should not uploaded in Github]
+    |
+    |---- /Frontend
+    |     |
+    |     |---- index.html
+    |     |---- app.js
+    |     |
+    |     |---- /styles
+    |     |     |
+    |     |     |---- _settings.scss
+    |     |     |---- app.scss
+    |     |
+    |     |---- /Widgets
+    |     |     |
+    |     |     |--- Widget-1
+    |     |     |...
+    |     |
+    |     |-----/Pages
+    |           |--- Home-Page
+    |           |... 
+    |
+    |
+    |---- /Backend
+    |     |-- server.js     // launcher
+    |     |----/ models     // mogoose database schemas
+    |     |----/ providers  // authentication services
+    |     |----/ restapis   // application APIs
+    |
+    |---- (/dist.dev)
+    |---- (/dist.prod)
+
+    
\ No newline at end of file
diff --git a/afb-client/bower.json b/afb-client/bower.json
new file mode 100644 (file)
index 0000000..84dbe1e
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "name": "healthy-gulp-angular",
+  "version": "0.0.0",
+  "authors": "",
+  "private": true,
+  "dependencies": {
+    "angular": "~1.3.4",
+    "angular-cookies": "~1.3.4",
+    "foundation-apps": "~1.1.0",
+    "angular-ui-notification": "~0.0.14",
+    "foundation-icon-fonts": "*"
+  },
+  "overrides": {
+    "foundation": {
+       "main": ["dist/js/foundation-apps-templates.js", "dist/js/foundation-apps.js"]
+    }
+  }
+}
diff --git a/afb-client/gulpfile.js b/afb-client/gulpfile.js
new file mode 100644 (file)
index 0000000..f483431
--- /dev/null
@@ -0,0 +1,456 @@
+// BUG Symlink not working
+
+var gulp = require('gulp');
+var debug = require('gulp-debug');
+var plugins = require('gulp-load-plugins')();
+var del = require('del');
+var es = require('event-stream');
+var bowerFiles = require('main-bower-files');
+var print = require('gulp-print');
+var Q = require('q');
+var imagemin = require('gulp-imagemin'), pngquant = require('imagemin-pngquant');
+var taskListing = require('gulp-task-listing');
+var symlink = require('gulp-sym');
+var rename = require("gulp-rename");
+
+// addon for Foundation6
+var router   = require('front-router');
+
+// == PATH STRINGS ========
+var appdir  = "./app/";   // Warning to not forget trailling '/'
+config=require (appdir + "etc/_Config"); // upload user local preferences if any
+
+// Run node in debug mode in developpement mode ?
+var nodeopts = config.DEBUG !== undefined ? '--debug='+config.DEBUG : ''; 
+var frontend= appdir + config.FRONTEND;
+var backend = appdir + config.BACKEND;
+
+var paths = {
+    application : frontend,
+    scripts     : frontend+'/**/*.js',
+    appStyles   : [frontend+'/**/*.scss', '!'+frontend+'/styles/*/*-conf.scss'],
+    globalStyles: [frontend+'/styles/**/*.scss'],
+    images      : [frontend+'/**/*.png',frontend+'/**/*.jpg',frontend+'/**/*.jpeg',frontend+'/**/*.svg',frontend+'/**/*.ttf'],
+    index       : frontend+'/index.html',
+    partials    : [frontend + '/**/*.html', '!' + frontend +'/index.html'],
+    distDev     : './dist.dev',
+    distProd    : './dist.prod',
+    scriptsDevServer: backend + '/**/*.js',
+    sass:  [frontend+'/styles', 'bower_components/foundation-apps/scss','bower_components/foundation-icon-fonts'],
+    fonts: ['bower_components/**/*.woff'],
+    favicon: frontend+'/favicon.ico'
+};
+
+paths['distAppDev']  = paths.distDev + config.URLBASE;
+paths['distAppProd'] = paths.distProd + config.URLBASE;
+
+// Run node in debug mode in developpement mode ?
+var nodeopts = config.DEBUG !== undefined ? '--debug='+config.DEBUG : ''; 
+
+// == PIPE SEGMENTS ========
+var pipes = {};
+
+pipes.orderedVendorScripts = function() {
+    return plugins.order(['jquery.js', 'angular.js']);
+};
+
+pipes.orderedAppScripts = function() {
+    return plugins.angularFilesort();
+};
+
+pipes.minifiedFileName = function() {
+    return plugins.rename(function (path) {
+        path.extname = '.min' + path.extname;
+    });
+};
+
+pipes.validatedAppScripts = function() {
+    return gulp.src(paths.scripts)
+        .pipe(plugins.replace('@@APPNAME@@', config.APPNAME))
+        .pipe(plugins.jshint())
+        .pipe(plugins.jshint.reporter('jshint-stylish'));
+};
+
+pipes.builtAppScriptsDev = function() {
+    return pipes.validatedAppScripts()
+        .pipe(gulp.dest(paths.distAppDev));
+};
+
+pipes.builtAppScriptsProd = function() {
+    var scriptedPartials = pipes.scriptedPartials();
+    var validatedAppScripts = pipes.validatedAppScripts();
+
+    return es.merge(scriptedPartials, validatedAppScripts)
+        .pipe(plugins.ngAnnotate())
+        .pipe(pipes.orderedAppScripts())
+        .pipe(plugins.sourcemaps.init())
+        .pipe(plugins.concat(config.APPNAME+'.min.js'))
+        .pipe(plugins.uglify({compress: {drop_console: true}}))
+        .pipe(plugins.sourcemaps.write())
+        .pipe(gulp.dest(paths.distAppProd));
+};
+
+pipes.builtVendorScriptsDev = function() {
+    return gulp.src(bowerFiles())
+        .pipe(gulp.dest( paths.distDev +'/bower_components'));
+};
+
+pipes.builtVendorScriptsProd = function() {
+    return gulp.src(bowerFiles('**/*.js'))
+        .pipe(pipes.orderedVendorScripts())
+        .pipe(plugins.concat('vendor.min.js'))
+        .pipe(plugins.uglify())
+        .pipe(gulp.dest(paths.distProd+ '/bower_components'));
+};
+
+pipes.validatedDevServerScripts = function() {
+    return gulp.src(paths.scriptsDevServer)
+        .pipe(plugins.jshint())
+        .pipe(plugins.jshint.reporter('jshint-stylish'));
+};
+
+pipes.validatedPartials = function() {
+    return gulp.src(paths.partials)
+        .pipe(plugins.htmlhint({'doctype-first': false}))
+        .pipe(router({path: paths.application+'/tmp/routes.js', root: paths.application}))
+        .pipe(plugins.htmlhint.reporter());
+};
+
+pipes.builtPartialsDev = function() {
+    return pipes.validatedPartials()
+        .pipe(gulp.dest(paths.distAppDev));
+};
+
+pipes.scriptedPartials = function() {
+    return pipes.validatedPartials()
+        .pipe(plugins.htmlhint.failReporter())
+        .pipe(plugins.htmlmin({collapseWhitespace: true, removeComments: true}))
+        .pipe(plugins.ngHtml2js({
+            moduleName: config.APPNAME,
+            template: "(function() {"
+               + "angular.module('<%= moduleName %>').run(['$templateCache', function($templateCache) {"
+               + "$templateCache.put('<%= template.url %>',\n    '<%= template.escapedContent %>');"
+               + "}]);\n"
+               + "})();\n"
+        }));    
+};
+
+pipes.builtAppStylesDev = function() {
+    return gulp.src(paths.appStyles)
+        .pipe(plugins.sass({includePaths: paths.sass}))
+        .pipe(gulp.dest(paths.distAppDev + '/styles'));
+};
+
+pipes.builtglobalStylesDev = function() {
+    return gulp.src(paths.globalStyles)
+        .pipe(plugins.sass({includePaths: paths.sass}))
+        .pipe(gulp.dest(paths.distDev  + '/global_styles'));
+};
+
+pipes.builtAppStylesProd = function() {
+    return gulp.src(paths.appStyles)
+        .pipe(plugins.sourcemaps.init())
+        .pipe(plugins.sass({includePaths: frontend + '/styles'}))
+        // .pipe(debug({title: '***** appStyle:'}))
+        .pipe(plugins.minifyCss())
+        .pipe(plugins.concat(config.APPNAME+'.css'))
+        .pipe(plugins.sourcemaps.write())
+        .pipe(pipes.minifiedFileName())
+        .pipe(gulp.dest(paths.distAppProd));
+};
+
+pipes.builtglobalStylesProd = function() {
+    return gulp.src(paths.globalStyles)
+        .pipe(plugins.sourcemaps.init())
+        .pipe(plugins.sass({includePaths: paths.sass}))
+        .pipe(plugins.minifyCss())
+        .pipe(plugins.sourcemaps.write())
+        .pipe(pipes.minifiedFileName())
+        .pipe(rename(function (path) {path.dirname="";return path;}))
+        .pipe(gulp.dest(paths.distProd + '/global_styles'));
+};
+
+pipes.processedFontsDev = function() {
+    return gulp.src(paths.fonts)
+        .pipe(rename(function (path) {path.dirname="";return path;}))
+        .pipe(gulp.dest(paths.distDev+'/bower_components'));
+};
+
+pipes.processedFontsProd = function() {
+    return gulp.src(paths.fonts)
+        .pipe(rename(function (path) {path.dirname="";return path;}))
+        .pipe(gulp.dest(paths.distProd+'/bower_components'));
+};
+
+
+pipes.processedImagesDev = function() {
+    return gulp.src(paths.images)
+        .pipe(gulp.dest(paths.distAppDev));
+};
+
+pipes.processedFaviconDev = function() {
+    return gulp.src(paths.favicon)
+        .pipe(gulp.dest(paths.distDev));
+};
+
+pipes.processedImagesProd = function() {
+    return gulp.src(paths.images)
+       .pipe(imagemin({
+            progressive: true,
+            svgoPlugins: [{removeViewBox: false}],
+            use: [pngquant()]
+        }))
+        .pipe(gulp.dest(paths.distAppProd));
+};
+
+pipes.processedFaviconProd = function() {
+    return gulp.src(paths.favicon)
+        .pipe(gulp.dest(paths.distProd));
+};
+
+// Create an Symlink when config.URLBASE exist
+pipes.createDevSymLink = function() {
+    return gulp.src(paths.distDev).pipe(symlink(paths.distDev+config.URLBASE, {force: true}));
+};
+
+pipes.createProdSymLink = function() {
+    return gulp.src(paths.distProd).pipe(symlink(paths.distDev+config.URLBASE,{force: true}));
+};
+
+pipes.validatedIndex = function() {
+    return gulp.src(paths.index)       
+        .pipe(plugins.replace('@@APPNAME@@', config.APPNAME))
+        .pipe(plugins.replace('@@URLBASE@@', config.URLBASE))
+        .pipe(plugins.htmlhint())
+        .pipe(plugins.htmlhint.reporter());
+};
+
+pipes.builtIndexDev = function() {
+
+    var orderedVendorScripts = pipes.builtVendorScriptsDev()
+        .pipe(pipes.orderedVendorScripts());
+
+    var orderedAppScripts = pipes.builtAppScriptsDev()
+        .pipe(pipes.orderedAppScripts());
+
+    var appStyles    = pipes.builtAppStylesDev();
+    var globalStyles = pipes.builtglobalStylesDev();
+
+    return pipes.validatedIndex()
+         // Vendor and Global should have absolute path to rootdir application one are relative to BaseURL
+        .pipe(plugins.inject(orderedVendorScripts, {relative: false, ignorePath: "/dist.dev", name: 'bower'}))
+        .pipe(plugins.inject(globalStyles, {relative: false, ignorePath: "/dist.dev", name:'vendor'}))
+        .pipe(gulp.dest(paths.distAppDev)) // write first to get relative path for inject
+        .pipe(plugins.inject(orderedAppScripts, {relative: true}))
+        .pipe(plugins.inject(appStyles, {relative: true, name: 'appli'}))
+        .pipe(gulp.dest(paths.distAppDev));
+};
+
+pipes.builtIndexProd = function() {
+
+    var vendorScripts= pipes.builtVendorScriptsProd();
+    var appScripts   = pipes.builtAppScriptsProd();
+    var appStyles    = pipes.builtAppStylesProd();
+    var globalStyles = pipes.builtglobalStylesProd();
+
+    return pipes.validatedIndex()
+         // Vendor and Global should have absolute path to rootdir application one are relative to BaseURL
+        .pipe(plugins.inject(vendorScripts, {relative: false, ignorePath: "/dist.prod", name: 'bower'}))
+        .pipe(plugins.inject(globalStyles, {relative: false, ignorePath: "/dist.prod", name:'vendor'}))
+        .pipe(gulp.dest(paths.distAppProd)) // write first to get relative path for inject
+        .pipe(plugins.inject(appScripts, {relative: true}))
+        .pipe(plugins.inject(appStyles, {relative: true, name:'appli'}))
+        .pipe(plugins.htmlmin({collapseWhitespace: true, removeComments: true}))
+        .pipe(gulp.dest(paths.distAppProd));
+};
+
+pipes.builtAppDev = function() {
+    return es.merge(pipes.builtIndexDev(), pipes.builtPartialsDev(), pipes.processedFaviconDev(), pipes.processedImagesDev(), pipes.processedFontsDev() );
+};
+
+pipes.builtAppProd = function() {
+    return es.merge(pipes.builtIndexProd(), pipes.processedFaviconProd(), pipes.processedImagesProd(), pipes.processedFontsProd());
+};
+
+
+// == TASKS ========
+
+// Add a task to render the output 
+gulp.task('help', taskListing.withFilters(/-/));
+   
+// clean, build of production environement
+gulp.task('build', ['clean-build-app-prod', 'validate-devserver-scripts']);
+
+gulp.task('run', function() {
+    // start nodemon to auto-reload the dev server
+    plugins.nodemon({ script: 'server.js', ext: 'js', watch: ['devServer/']})
+        .on('change', ['validate-devserver-scripts'])
+        .on('restart', function () {
+            console.log('[nodemon] restarted dev server');
+        });
+});       
+
+// removes all compiled dev files
+gulp.task('clean-dev', function() {
+    var deferred = Q.defer();
+    del(paths.distDev, function() {
+        deferred.resolve();
+    });
+    return deferred.promise;
+});
+
+// removes all compiled production files
+gulp.task('clean-prod', function() {
+    var deferred = Q.defer();
+    del(paths.distProd, function() {
+        deferred.resolve();
+    });
+    return deferred.promise;
+});
+
+// checks html source files for syntax errors
+gulp.task('validate-partials', pipes.validatedPartials);
+
+// checks index.html for syntax errors
+gulp.task('validate-index', pipes.validatedIndex);
+
+// moves html source files into the dev environment
+gulp.task('build-partials-dev', pipes.builtPartialsDev);
+
+// converts partials to javascript using html2js
+gulp.task('convert-partials-to-js', pipes.scriptedPartials);
+
+// runs jshint on the dev server scripts
+gulp.task('validate-devserver-scripts', pipes.validatedDevServerScripts);
+
+// runs jshint on the app scripts
+gulp.task('validate-app-scripts', pipes.validatedAppScripts);
+
+// moves app scripts into the dev environment
+gulp.task('build-app-scripts-dev', pipes.builtAppScriptsDev);
+
+// concatenates, uglifies, and moves app scripts and partials into the prod environment
+gulp.task('build-app-scripts-prod', pipes.builtAppScriptsProd);
+
+// compiles app sass and moves to the dev environment
+gulp.task('build-app-styles-dev', pipes.builtAppStylesDev);
+
+// compiles and minifies app sass to css and moves to the prod environment
+gulp.task('build-app-styles-prod', pipes.builtAppStylesProd);
+
+// moves vendor scripts into the dev environment
+gulp.task('build-vendor-scripts-dev', pipes.builtVendorScriptsDev);
+
+// concatenates, uglifies, and moves vendor scripts into the prod environment
+gulp.task('build-vendor-scripts-prod', pipes.builtVendorScriptsProd);
+
+// validates and injects sources into index.html and moves it to the dev environment
+gulp.task('build-index-dev', pipes.builtIndexDev);
+
+// validates and injects sources into index.html, minifies and moves it to the dev environment
+gulp.task('build-index-prod', pipes.builtIndexProd);
+
+// builds a complete dev environment
+gulp.task('build-app-dev', pipes.builtAppDev);
+
+// builds a complete prod environment
+gulp.task('build-app-prod', pipes.builtAppProd);
+
+// cleans and builds a complete dev environment
+gulp.task('clean-build-app-dev', ['clean-dev'], pipes.builtAppDev);
+
+// cleans and builds a complete prod environment
+gulp.task('clean-build-app-prod', ['clean-prod'], pipes.builtAppProd);
+
+// clean, build, and watch live changes to the dev environment
+gulp.task('watch-dev', ['clean-build-app-dev', 'validate-devserver-scripts'], function() {
+
+    // start nodemon to auto-reload the dev server
+    plugins.nodemon({  exec: 'node ' + nodeopts, script: backend+'/server.js', ext: 'js', watch: [backend], env: {NODE_ENV : 'dev'} })
+        .on('change', ['validate-devserver-scripts'])
+        .on('restart', function () {
+            console.log('[nodemon] restarted dev server');
+        });
+
+    // start live-reload server
+    plugins.livereload.listen({ start: true });
+
+    // watch index
+    gulp.watch(paths.index, function() {
+        return pipes.builtIndexDev()
+            .pipe(plugins.livereload());
+    });
+
+    // watch app scripts
+    gulp.watch(paths.scripts, function() {
+        return pipes.builtAppScriptsDev()
+            .pipe(plugins.livereload());
+    });
+
+    // watch html partials
+    gulp.watch(paths.partials, function() {
+        return pipes.builtPartialsDev()
+            .pipe(plugins.livereload());
+    });
+    
+    // watch Images
+    gulp.watch(paths.images, function() {
+        return pipes.processedImagesDev()
+            .pipe(plugins.livereload());
+    });
+
+    // watch styles
+    gulp.watch(paths.appStyles, function() {
+        return pipes.builtAppStylesDev()
+            .pipe(plugins.livereload());
+    });
+
+});
+
+// clean, build, and watch live changes to the prod environment
+gulp.task('watch-prod', ['clean-build-app-prod', 'validate-devserver-scripts'], function() {
+
+    // start nodemon to auto-reload the dev server
+    plugins.nodemon({ script: backend +'/server.js', ext: 'js', watch: [backend], env: {MODE : 'prod'} })
+        .on('change', ['validate-devserver-scripts'])
+        .on('restart', function () {
+            console.log('[nodemon] restarted dev server');
+        });
+
+    // start live-reload server
+    plugins.livereload.listen({start: true});
+
+    // watch index
+    gulp.watch(paths.index, function() {
+        return pipes.builtIndexProd()
+            .pipe(plugins.livereload());
+    });
+
+    // watch app scripts
+    gulp.watch(paths.scripts, function() {
+        return pipes.builtAppScriptsProd()
+            .pipe(plugins.livereload());
+    });
+
+    // watch hhtml partials
+    gulp.watch(paths.partials, function() {
+        return pipes.builtAppScriptsProd()
+            .pipe(plugins.livereload());
+    });
+    
+    // watch Images
+    gulp.watch(paths.images, function() {
+        return pipes.processedImagesProd()
+            .pipe(plugins.livereload());
+    });
+
+    // watch styles
+    gulp.watch(paths.appStyles, function() {
+        return pipes.builtAppStylesProd()
+            .pipe(plugins.livereload());
+    });
+    
+});
+
+// default task builds for prod
+gulp.task('default', ['clean-build-app-prod']);
diff --git a/afb-client/index.html b/afb-client/index.html
new file mode 100644 (file)
index 0000000..32e0efe
--- /dev/null
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!--[if lt IE 7]>      <html lang="en" ng-app="AudioClient" class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
+<!--[if IE 7]>         <html lang="en" ng-app="AudioClient" class="no-js lt-ie9 lt-ie8"> <![endif]-->
+<!--[if IE 8]>         <html lang="en" ng-app="AudioClient" class="no-js lt-ie9"> <![endif]-->
+<!--[if gt IE 8]><!--> <html lang="en" ng-app="AudioClient" class="no-js"> <!--<![endif]-->
+<head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <title>Simple Sample Application</title>
+    <meta name="description" content="">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <!-- bower:css -->
+    <!-- endinject -->
+     <!--vendor:css -->
+    <!-- endinject -->
+    <!-- appli:css -->
+    <!-- endinject -->
+    <!-- inject:css -->
+    <!-- endinject -->
+    <base href="/opa/"> <!-- https://docs.angularjs.org/error/$location/nobase -->
+
+</head>
+<body>
+<!--[if lt IE 7]>
+<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
+<![endif]-->
+<div ui-view></div>
+<!-- bower:js -->
+<!-- endinject -->
+<!-- inject:js -->
+<!-- endinject -->
+
+<!-- Generic Foundation Modal Template -->
+<script id="components/modal/modal.html" type="text/ng-template">
+   <div  class="modal-overlay" ng-click="hideOverlay()">
+    <aside class="modal" ng-click="$event.stopPropagation();" ng-transclude></aside>
+  </div>
+</script>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/afb-client/package.json b/afb-client/package.json
new file mode 100644 (file)
index 0000000..3b11ee1
--- /dev/null
@@ -0,0 +1,61 @@
+{
+  "name": "AudioClient",
+  "private": true,
+  "version": "0.0.0",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/iotbzh/healthy-gulp-angular-foundation6"
+  },
+  "scripts": {
+    "postinstall": "bower install",
+    "build": "./node_modules/.bin/gulp clean-build-app-dev",
+    "start": "node node_modules/.bin/gulp watch-dev"
+  },
+  "devDependencies": {
+    "body-parser": "^1.5.2",
+    "bower": "^1.3.1",
+    "cookie-parser": "^1.4.0",
+    "del": "^1.1.1",
+    "event-stream": "^3.2.2",
+    "express": "^4.7.2",
+    "express-session": "^1.12.1",
+    "front-router": "^1.0.0",
+    "gulp": "^3.9.0",
+    "gulp-angular-filesort": "^1.0.4",
+    "gulp-debug": "^2.1.2",
+    "gulp-concat": "^2.4.3",
+    "gulp-htmlhint": "0.0.9",
+    "gulp-htmlmin": "^1.0.0",
+    "gulp-imagemin": "*",
+    "gulp-inject": "^1.1.1",
+    "gulp-jshint": "^1.9.2",
+    "gulp-livereload": "^3.7.0",
+    "gulp-load-plugins": "^0.8.0",
+    "gulp-minify-css": "^0.4.5",
+    "gulp-ng-annotate": "^1.1.0",
+    "gulp-ng-html2js": "^0.2.0",
+    "gulp-nodemon": "^2.0.0",
+    "gulp-order": "^1.1.1",
+    "gulp-print": "^1.1.0",
+    "gulp-rename": "^1.2.0",
+    "gulp-replace": "^0.5.4",
+    "gulp-sass": "^2.0.3",
+    "gulp-sourcemaps": "^1.3.0",
+    "gulp-task-listing": "^1.0.1",
+    "gulp-uglify": "^1.2.0",
+    "imagemin-pngquant": "*",
+    "jshint-stylish": "^1.0.0",
+    "karma": "^0.10",
+    "karma-junit-reporter": "^0.2.2",
+    "main-bower-files": "^2.5.0",
+    "method-override": "^2.1.2",
+    "protractor": "^1.1.1",
+    "q": "^1.1.2",
+    "shelljs": "^0.2.6",
+    "traceback": "^0.3.1",
+    "gulp-sym": "0.0.14"
+  },
+  "dependencies": {
+    "multer": "^1.1.0"
+  }
+}