├── .gitignore ├── README.md ├── app ├── Backend │ ├── RestApis │ │ ├── SampleAPI.js │ │ └── _all.js │ └── server.js ├── Frontend │ ├── app.js │ ├── favicon.ico │ ├── images │ │ └── logo │ │ │ ├── logo_iot_bzh.svg │ │ │ ├── logo_iot_bzhx350.png │ │ │ ├── tampon-iot-bzhx450.png │ │ │ ├── triskel_iot_bzh.png │ │ │ ├── triskel_iot_bzh.svg │ │ │ └── triskel_iot_bzhx250.png │ ├── index.html │ ├── pages │ │ ├── ajax │ │ │ ├── ajax.html │ │ │ ├── ajax.js │ │ │ └── ajax.scss │ │ ├── home │ │ │ ├── home.html │ │ │ └── homeModule.js │ │ └── sample │ │ │ ├── sample.html │ │ │ └── sampleModule.js │ ├── styles │ │ ├── _settings.scss │ │ ├── app.scss │ │ └── globalapp.scss │ ├── tmp │ │ └── routes.js │ └── widgets │ │ ├── widgetA │ │ ├── widgetA.html │ │ ├── widgetA.js │ │ └── widgetA.scss │ │ └── widgetB │ │ ├── widgetB.html │ │ └── widgetB.js └── etc │ ├── AppDefaults.js │ ├── _Config.js │ └── _Debug.js ├── bower.json ├── gulpfile.js ├── nbproject ├── project.properties └── project.xml └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /bower_components 3 | /node_modules 4 | /dist.* 5 | *.DS_Store 6 | /nbproject/private/ 7 | npm-debug.log 8 | .sass-cache/ 9 | .noderc* 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Angular/Foundation6 best practices template: fork from http://paislee.io/a-healthy-gulp-setup-for-angularjs-projects 2 | 3 | ### Modifications from original version 4 | + support for Fondation-6 for App http://foundation.zurb.com/apps/docs/#!/ 5 | + support for NodeJS V4+V5 6 | + sample based on a components somehow similar to what Angular-2 should use 7 | + support development and production mode [javascript html partial templates are loaded in the right order where ever they are within dev tree] 8 | + support node debugger in development mode [tested with Netbeans 8.1, but should work with any] 9 | 10 | ### Installation 11 | 12 | 0. Install Node.js 13 | 1. Download/Install healthy-gulp-angular-foundation6 from https://github.com/iotbzh/healthy-gulp-angular-foundation6 14 | 2. npm install 15 | 3. npm run start 16 | Optional: Chrome/LiveReload (https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei) 17 | 18 | ### Using Gulp 19 | A. ./node_modules/.bin/gulp help 20 | B. ./node_modules/.bin/gulp watch-dev 21 | Note: if gulp is installed globally you may use directly "gulp help" 22 | 23 | 24 | ### customisation 25 | # Create a ".noderc.js" at project root to overload .app/etc/AppDefault.js 26 | 27 | var config= { 28 | APPNAME: "MyFirstApp" // replace @@APPNAME@@ in Index.html & app.js for dev/prod 29 | HOST : "localhost", // listen on a specific interface/IP [default==localhost] 30 | PORT : 8081, // httpd port [default 8080] 31 | DEBUG : 9081, // nodejs debug port in dev mode [comment to remove debug in devmod] 32 | URLBASE: '/' // URL base for rewriting should match with your http server application base [default/] 33 | }; 34 | module.exports = config; 35 | 36 | ### Bugs 37 | + Check Angular & Angular-Animate get the exact same version otherwise you may get an error looking like " [$injector:unpr] Unknown provider: $$asyncCallbackProvider" 38 | + Gulp watch modification only on existing files. Adding a new file will not be detected. User should restart Gulp watch command 39 | + In some case automatic update notification to browser fail and page has to be reloaded manually 40 | + When using IDEs it's easy to have multiple GULP process watching the same thing!!! In case of doubt when having strange result 'pkill -9 gulp; pkill -9 node" 41 | 42 | ## Project Structure 43 | The project ships with a directory structure like: 44 | 45 | /MyProject 46 | | 47 | |-- gulpfile.js // Check 'gulp help' for options 48 | |-- package.json 49 | |-- bower.json 50 | |-- .noderc.js [Warning: contains private keys DO-NOT upload in Github] 51 | | 52 | |--- /app 53 | | | 54 | | |---etc 55 | | | | 56 | | | | AppDefault.js // Default config for Application 57 | | | 58 | | |---Backend [HTTPd server production/mock] 59 | | | |--- server.js // server bootstrap and options 60 | | | |--- /RestApi 61 | | | | | _all.js // API module registration 62 | | | | | SampleApi.js // As many API modules as needed 63 | | | 64 | | |---Frontend [Angular/Foundation HTML5 app] 65 | | | |--- index.html // index template should not need any changes 66 | | | |--- app.js // main entry point should register here every pages module 67 | | | | 68 | | | |--- /styles // your global SASS files and Foundation6 config 69 | | | | |--- _settings.scss 70 | | | | |---- app.scss 71 | | | | 72 | | | |--- /Widgets // Add as many widgets Directories/Files as needed 73 | | | | |--- Widget-1 74 | | | | |... Widget-xxx 75 | | | | 76 | | | |----/Pages // Partial Directory/Files as needed 77 | | | | |--- Home Partial 78 | | | | |--- Any Other Partials 79 | | | | 80 | | | |----/xxxx // Partial/Widget/Style may sit in as many directories as needed 81 | | | 82 | | 83 | |--- (/dist.dev) // received copy of JS/HTML during debug session 84 | |--- (/dist.prod // received compressed JS/HTML for production mode 85 | 86 | NOTE: By convention Directory/Files name starting by an Uppercase can be customised. 87 | Changing those ones starting by lowercase might break GULP config. -------------------------------------------------------------------------------- /app/Backend/RestApis/SampleAPI.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Dummy API that return basic JSON objects 3 | */ 4 | 5 | var config = require('../../etc/_Config'); 6 | 7 | function RestAPI (app) { 8 | 'use strict'; 9 | 10 | app.get('/api/get-date', function (req, res) { 11 | var now = new Date(); 12 | if (req.session && !req.session.logged) res.send({type: 'error', app: config.APPNAME, data: 'No Session Cookie'}); 13 | else { 14 | var date= now.getDate() + '/' + now.getMonth() +'/'+ now.getFullYear() ; 15 | res.send({type: 'date', data: date}); 16 | } 17 | }); 18 | 19 | app.get('/api/get-time', function (req, res) { 20 | if (req.session && !req.session.logged) res.send({type: 'error', app: config.APPNAME, data: 'No Session Cookie'}); 21 | else { 22 | var time= new Date().toTimeString().replace(/.*(\d{2}:\d{2}:\d{2}).*/, "$1"); 23 | res.send({type: 'time', data: time}); 24 | } 25 | }); 26 | 27 | } 28 | 29 | module.exports = RestAPI; -------------------------------------------------------------------------------- /app/Backend/RestApis/_all.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 "IoT.bzh" 3 | * Author "Fulup Ar Foll" 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | SampleApi = require ('./SampleAPI'); 20 | 21 | // Include here every application APIs routes modules. 22 | function Initialise (app, passport) { 23 | 24 | this.sample= new SampleApi (app, passport); 25 | } 26 | 27 | module.exports = Initialise; 28 | 29 | -------------------------------------------------------------------------------- /app/Backend/server.js: -------------------------------------------------------------------------------- 1 | var config = require('../etc/_Config'); 2 | var RestAPI = require('./RestApis/_all'); 3 | var fs = require('fs'); 4 | 5 | var express = require('express'); 6 | var session = require('express-session'); 7 | var bodyParser = require('body-parser'); 8 | var methodOverride = require('method-override'); 9 | 10 | // instanciate express HTTP server 11 | var app = express(); 12 | 13 | // create a session cookie to protect API 14 | app.use(session({secret:config.SECRET, resave: false, saveUninitialized:false})); 15 | 16 | // instanciate REST API before set session flag to clean 17 | new RestAPI (app); 18 | 19 | // chose dev or prod rootdir 20 | var staticdir = 'dist.dev'; 21 | if (process.env.MODE) staticdir = process.env.MODE === 'prod' ? 'dist.prod' : 'dist.dev'; 22 | else staticdir = config.MODE === 'prod' ? 'dist.prod' : 'dist.dev'; 23 | 24 | // get all data/stuff of the body (POST) parameters 25 | app.use(bodyParser.json()); // parse application/json 26 | 27 | app.use(methodOverride('X-HTTP-Method-Override')); // override with the X-HTTP-Method-Override header in the request. simulate DELETE/PUT 28 | 29 | // Fake loggin when user request '/' page. 30 | function setSession (req, res, next) { 31 | if (req.originalUrl === "/") req.session.logged=true; 32 | next(); 33 | } 34 | 35 | var rootdir= __dirname + '/../../' + staticdir; 36 | if (!fs.existsSync (rootdir)) { 37 | console.log ("### HOOPS Rootdir not found rootdir=%s\n", rootdir); 38 | process.exit (); 39 | } 40 | 41 | // set the static files location /public/img will be /img for users 42 | app.use(setSession, express.static(rootdir)); 43 | 44 | // rewrite requested URL to include Angular hashPrompt and set session flag for RestAPI 45 | app.get('/*', function(req, res) { 46 | console.log ("Page redirected to Angular hashed path %s", '/#!' + req.originalUrl); 47 | res.redirect('/#!' + req.originalUrl); 48 | }); 49 | 50 | // start app =============================================== 51 | app.listen(config.PORT, config.HOST); 52 | console.log('Server Listening http://%s:%d (rootdir=%s)', config.HOST, config.PORT, rootdir); -------------------------------------------------------------------------------- /app/Frontend/app.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular.module('@@APPNAME@@', [ // Warning: Appname should fit with gulpfile.js & index.html 5 | 'ui.router', 6 | 'ngAnimate', 7 | 8 | //foundation 9 | 'foundation', 10 | 'foundation.dynamicRouting', 11 | 'foundation.dynamicRouting.animations', 12 | 13 | // Application Components 14 | 'MyHomeModule', 15 | 'MySampleModule', 16 | 'MyAjaxModule' 17 | ]) 18 | .config(config) 19 | .run(run) 20 | ; 21 | 22 | config.$inject = ['$urlRouterProvider', '$locationProvider']; 23 | 24 | function config($urlProvider, $locationProvider) { 25 | $urlProvider.otherwise('/home'); 26 | 27 | $locationProvider.html5Mode(true).hashPrefix('!'); 28 | } 29 | 30 | function run() { 31 | FastClick.attach(document.body); 32 | } 33 | 34 | console.log ("@@APPNAME@@ Loaded"); 35 | })(); 36 | -------------------------------------------------------------------------------- /app/Frontend/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotbzh/healthy-gulp-angular-foundation6/26378f7125598d5ab0949cd7d6d5debd83054b03/app/Frontend/favicon.ico -------------------------------------------------------------------------------- /app/Frontend/images/logo/logo_iot_bzh.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 24 | 29 | 35 | 39 | 44 | 50 | 51 | 52 | 74 | 76 | 77 | 79 | image/svg+xml 80 | 82 | 83 | 84 | 85 | 86 | 91 | 98 | IOT 110 | 115 | BZH 127 | 128 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /app/Frontend/images/logo/logo_iot_bzhx350.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotbzh/healthy-gulp-angular-foundation6/26378f7125598d5ab0949cd7d6d5debd83054b03/app/Frontend/images/logo/logo_iot_bzhx350.png -------------------------------------------------------------------------------- /app/Frontend/images/logo/tampon-iot-bzhx450.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotbzh/healthy-gulp-angular-foundation6/26378f7125598d5ab0949cd7d6d5debd83054b03/app/Frontend/images/logo/tampon-iot-bzhx450.png -------------------------------------------------------------------------------- /app/Frontend/images/logo/triskel_iot_bzh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotbzh/healthy-gulp-angular-foundation6/26378f7125598d5ab0949cd7d6d5debd83054b03/app/Frontend/images/logo/triskel_iot_bzh.png -------------------------------------------------------------------------------- /app/Frontend/images/logo/triskel_iot_bzh.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 24 | 29 | 35 | 39 | 44 | 50 | 51 | 52 | 74 | 76 | 77 | 79 | image/svg+xml 80 | 82 | 83 | 84 | 85 | 86 | 91 | 99 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /app/Frontend/images/logo/triskel_iot_bzhx250.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotbzh/healthy-gulp-angular-foundation6/26378f7125598d5ab0949cd7d6d5debd83054b03/app/Frontend/images/logo/triskel_iot_bzhx250.png -------------------------------------------------------------------------------- /app/Frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Simple Sample Application 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/Frontend/pages/ajax/ajax.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | --- 4 | name: ajaxsample 5 | url: /ajax 6 | animationIn: slideInUp 7 | --- 8 | 9 | IoT.bzh Logo 10 | 11 | 12 |

Ajax Sample Page

13 | 14 |

15 | 16 | 17 |

18 | 19 |

Note: To Check error handling "Stop" your httpd server and click on any button

20 | 21 |

22 |
Home 23 |
Sample 24 |

25 | -------------------------------------------------------------------------------- /app/Frontend/pages/ajax/ajax.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This sample module implement two directives with a share templates. 3 | * 4 | * Note: 5 | * - while both directives are within the same module each owns a private scope. 6 | * - depending on where you place static date they are share or not 7 | */ 8 | 9 | (function() { 10 | 'use strict'; 11 | 12 | // simple template can be store directly inside a static variable 13 | var tmpl = ' {{info}}: [{{data}}] Elapse:{{elapsed}}s'; 14 | 15 | // list all rependencies within the page + controler if needed 16 | angular.module('MyAjaxModule', []) 17 | 18 | .directive('serverTime', function($http, $timeout) { 19 | 20 | 21 | function private_methods(scope, elem, attrs) { 22 | 23 | // initial scope at instanciation 24 | scope.data = "Click For Time"; 25 | scope.status = "FX"; 26 | scope.info = attrs.info; 27 | scope.counter = 0; 28 | scope.elapsed = 0; 29 | scope.rate = 250; // increase timer every 250ms 30 | 31 | // method call when user click on element 32 | scope.clicked = function () { 33 | 34 | // send AJAX request to server 35 | var handler = $http.get('/api/get-time'); 36 | 37 | handler.success(function(response, errcode, headers, config) { 38 | 39 | // check if response is valid 40 | if (response.type !== "time") { 41 | alert ("Hoops [server restarted] :" + response.data); 42 | return; 43 | } 44 | 45 | scope.data = response.data; 46 | scope.status = "OK"; 47 | scope.counter= 0; 48 | }); 49 | 50 | handler.error(function(status, errcode, headers) { 51 | console.log ("Hoops /api/get-time failed err=" + errcode); 52 | scope.data = "Server not Responding"; 53 | scope.status = "FX"; 54 | }); 55 | }; 56 | 57 | scope.count = function() { 58 | scope.counter ++; 59 | scope.elapsed = (scope.counter * scope.rate / 1000).toFixed(2); 60 | $timeout (scope.count, scope.rate); 61 | 62 | // when date too old change color 63 | if (scope.counter > 25) scope.status = "FX"; 64 | }; 65 | 66 | // init counter timeout 67 | $timeout (scope.count, scope.rate); 68 | 69 | } // end link 70 | 71 | return { 72 | restrict: 'E', 73 | template: tmpl, 74 | link: private_methods, 75 | scope: {} // 100% Private Scope 76 | }; 77 | }) 78 | 79 | .directive('serverDate', function($http, $timeout) { 80 | 81 | 82 | function private_methods(scope, elem, attrs) { 83 | 84 | // initial scope at instanciation 85 | scope.data = "Click For Time"; 86 | scope.status = "FX"; 87 | scope.info = attrs.info; 88 | scope.counter = 0; 89 | scope.elapsed = 0; 90 | scope.rate = 1000; // count every second 91 | 92 | // method call when user click on element 93 | scope.clicked = function () { 94 | 95 | // send AJAX request to server 96 | var handler = $http.get('/api/get-date'); 97 | 98 | handler.success(function(response, errcode, headers, config) { 99 | 100 | // check if response is valid 101 | if (response.type !== "date") { 102 | alert ("Hoops [server restarted] : " + response.data); 103 | return; 104 | } 105 | 106 | scope.data = response.data; 107 | scope.status = "OK"; 108 | scope.counter= 0; 109 | }); 110 | 111 | handler.error(function(status, errcode, headers) { 112 | console.log ("Hoops /api/get-date failed err=" + errcode); 113 | scope.data = "Server not Responding"; 114 | scope.status = "FX"; 115 | }); 116 | }; 117 | 118 | scope.count = function() { 119 | scope.counter ++; 120 | scope.elapsed = (scope.counter * scope.rate / 1000).toFixed(2); 121 | $timeout (scope.count, scope.rate); 122 | 123 | // when date too old change color 124 | if (scope.counter > 15) scope.status = "FX"; 125 | }; 126 | 127 | // init counter timeout 128 | $timeout (scope.count, scope.rate); 129 | 130 | } // end link 131 | 132 | return { 133 | restrict: 'E', 134 | template: tmpl, 135 | link: private_methods, 136 | scope: {} // 100% Private Scope 137 | }; 138 | }); 139 | 140 | console.log ("RestSampleModule Loaded"); 141 | })(); -------------------------------------------------------------------------------- /app/Frontend/pages/ajax/ajax.scss: -------------------------------------------------------------------------------- 1 | /* 2 | Sample of style overload for a specific widget 3 | 4 | Note: this SCSS is injected with main HTML page, it scope should be reduce 5 | to a specific widget or it value will be propagated at a global level. 6 | */ 7 | 8 | @mixin server-button { 9 | display: block; 10 | margin: 1rem; 11 | box-shadow: 5px 5px 2px #656565; 12 | } 13 | 14 | server-date, server-time { 15 | 16 | .OK { 17 | @include server-button; 18 | color: #191970; 19 | border: 2px solid blue !important; 20 | padding:15px 50px 15px 50px;margin:0 0 5px 5px; 21 | 22 | background-color: rgba(150, 200, 50,0.7); 23 | } 24 | .OK:hover{background-color:greenyellow;} 25 | 26 | .FX { 27 | @include server-button; 28 | color: #191970; 29 | border: 2px solid red !important; 30 | padding:15px 50px 15px 50px;margin:0 0 5px 5px; 31 | background-color: rgba(255, 165, 0,0.7); 32 | } 33 | .FX:hover{background-color:red;} 34 | } 35 | -------------------------------------------------------------------------------- /app/Frontend/pages/home/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | --- 4 | name: myhome 5 | url: /home 6 | animationIn: slideInLeft 7 | animationOut: slideOutRight 8 | controller: MyHomeController 9 | --- 10 | 11 | IoT.bzh Logo 12 | 13 |

Home Page

14 |

15 | 16 | 17 |

18 | 19 |

20 |
Sample Page 21 |
Ajax Sample 22 |

-------------------------------------------------------------------------------- /app/Frontend/pages/home/homeModule.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | // list all rependencies within the page + controler if needed 5 | angular.module('MyHomeModule', ['WidgetA', 'WidgetB']) 6 | 7 | // Injection are added automatically with ng-anotate 8 | .controller('MyHomeController', function ($scope, $stateParams, $state, $controller) { 9 | 10 | // add some usefull code here. Note than Angular2 does not have controler anymore 11 | // building your code directly within directive could be a good idea. 12 | 13 | }); 14 | 15 | console.log ("HomeModule Loaded"); 16 | })(); -------------------------------------------------------------------------------- /app/Frontend/pages/sample/sample.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | --- 4 | name: mysample 5 | url: /sample 6 | animationIn: slideInRight 7 | --- 8 | 9 | IoT.bzh Logo 10 | 11 | 12 |

Sample Page snoopy

13 | 14 |

15 | 16 | 17 |

18 | 19 |

20 |
Home Page 21 |
Ajax Sample 22 |

-------------------------------------------------------------------------------- /app/Frontend/pages/sample/sampleModule.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | // list all rependencies within the page + controler if needed 5 | angular.module('MySampleModule', ['WidgetA', 'WidgetB']) 6 | .controller('MySampleController', MySampleController); 7 | 8 | // Do not forget to force injection of Minified production version wont work 9 | MySampleController.$inject = ['$scope', '$stateParams', '$state', '$controller']; 10 | function MySampleController($scope, $stateParams, $state, $controller) { 11 | 12 | angular.extend(this, $controller('DefaultController', {$scope: $scope, $stateParams: $stateParams, $state: $state})); 13 | console.log ("Init MySampleController"); 14 | 15 | } 16 | 17 | console.log ("SampleModule Loaded"); 18 | })(); -------------------------------------------------------------------------------- /app/Frontend/styles/_settings.scss: -------------------------------------------------------------------------------- 1 | // FOUNDATION FOR APPS SETTINGS 2 | // ---------------------------- 3 | // 4 | // Table of Contents: 5 | // 6 | // 1. CSS Exports 7 | // 2. Global Styles 8 | // 3. Breakpoints 9 | // 4. Typography 10 | // 5. Grid 11 | // 6. Button 12 | // 7. Accordion 13 | // 8. Action Sheet 14 | // 9. Block List 15 | // 10. Button Group 16 | // 11. Card 17 | // 12. Extras 18 | // 13. Forms 19 | // 14. Iconic 20 | // 15. Label 21 | // 16. Menu Bar 22 | // 17. Modal 23 | // 18. Motion UI 24 | // 19. Notification 25 | // 20. Off-canvas 26 | // 21. Panel 27 | // 22. Popup 28 | // 23. Switch 29 | // 24. Tabs 30 | // 25. Title Bar 31 | 32 | @import "helpers/functions"; 33 | 34 | // 1. CSS Exports 35 | // - - - - - - - - - - - - - - - 36 | 37 | // Change any value in this map from "true" to "false" to disable that component's CSS class output. You'll still be able to use the component's mixins, but none of our pre-written classes will be in your CSS. 38 | 39 | // $include-css: ( 40 | // accordion: true, 41 | // action-sheet: true, 42 | // block-list: true, 43 | // button: true, 44 | // button-group: true, 45 | // card: true, 46 | // coloring: true, 47 | // extras: true, 48 | // forms: true, 49 | // grid: true, 50 | // iconic: true, 51 | // label: true, 52 | // badge: true, 53 | // list: true, 54 | // menu-bar: true, 55 | // modal: true, 56 | // motion: true, 57 | // notification: true, 58 | // off-canvas: true, 59 | // panel: true, 60 | // popup: true, 61 | // switch: true, 62 | // tabs: true, 63 | // title-bar: true, 64 | // typography: true, 65 | // utilities: true, 66 | // ); 67 | 68 | // 2. Global Styles 69 | // - - - - - - - - - - - - - - - 70 | 71 | // This sets 1rem to be 16px 72 | // $rem-base: 16px; 73 | 74 | // The default font-size is set to 100% of the browser style sheet (usually 16px) 75 | // for compatibility with browser-based text zoom or user-set defaults. 76 | 77 | // Since the typical default browser font-size is 16px, that makes the calculation for grid size. 78 | // If you want your base font-size to be different and not have it affect the grid breakpoints, 79 | // set $rem-base to $base-font-size and make sure $base-font-size is a px value. 80 | // $base-font-size: 100%; 81 | 82 | // $base-line-height is 24px while $base-font-size is 16px 83 | // $base-line-height: 1.5; 84 | 85 | // Text selector helpers 86 | // $headers: "h1,h2,h3,h4,h5,h6"; 87 | 88 | // We use these to define default font weights 89 | // $font-weight-normal: normal; 90 | // $font-weight-bold: bold; 91 | 92 | // We use these to control various global styles 93 | // $body-background: #fff; 94 | // $body-font-color: #222; 95 | // $body-font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; 96 | // $body-font-weight: $font-weight-normal; 97 | // $body-font-style: normal; 98 | // $body-antialiased: true; 99 | 100 | // Application Colors 101 | // $primary-color: #00558b; 102 | // $secondary-color: #f1f1f1; 103 | // $alert-color: #F04124; 104 | // $info-color: #A0D3E8; 105 | // $success-color: #43AC6A; 106 | // $warning-color: #F08A24; 107 | // $dark-color: #232323; 108 | // $gray: #dfdfdf; 109 | // $gray-dark: darken($gray, 8); 110 | // $gray-light: lighten($gray, 8); 111 | 112 | // We use these to make sure border radius matches unless we want it different. 113 | // $global-radius: 4px; 114 | // $global-rounded: 1000px; 115 | 116 | // We use this for default spacing 117 | // $global-padding: 1rem; 118 | // $global-spacing: rem-calc(15); 119 | 120 | // 3. Breakpoints 121 | // - - - - - - - - - - - - - - - 122 | 123 | // These are our named breakpoints. You can use them in our breakpoint function like this: @include breakpoint(medium) { // Medium and larger styles } 124 | // $breakpoints: ( 125 | // small: rem-calc(0), 126 | // medium: rem-calc(640), 127 | // large: rem-calc(1200), 128 | // xlarge: rem-calc(1440), 129 | // xxlarge: rem-calc(1920), 130 | // ); 131 | 132 | // All of the names in this list will be output as classes in your CSS, like small-12, medium-6, and so on. 133 | // $breakpoint-classes: (small medium large); 134 | 135 | // 4. Typography 136 | // - - - - - - - - - - - - - - - 137 | 138 | // We use these to control header font styles 139 | // $header-font-family: $body-font-family; 140 | // $header-font-weight: $font-weight-normal; 141 | // $header-font-style: $font-weight-normal; 142 | // $header-font-color: #222; 143 | // $header-line-height: 1.4; 144 | // $header-top-margin: .2rem; 145 | // $header-bottom-margin: .5rem; 146 | // $header-text-rendering: optimizeLegibility; 147 | 148 | // We use these to control header font sizes 149 | // $h1-font-size: rem-calc(44); 150 | // $h2-font-size: rem-calc(37); 151 | // $h3-font-size: rem-calc(27); 152 | // $h4-font-size: rem-calc(23); 153 | // $h5-font-size: rem-calc(18); 154 | // $h6-font-size: 1rem; 155 | 156 | // We use these to control header size reduction on small screens 157 | // $h1-font-reduction: rem-calc(10); 158 | // $h2-font-reduction: rem-calc(10); 159 | // $h3-font-reduction: rem-calc(5); 160 | // $h4-font-reduction: rem-calc(5); 161 | // $h5-font-reduction: 0; 162 | // $h6-font-reduction: 0; 163 | 164 | // These control how subheaders are styled. 165 | // $subheader-line-height: 1.4; 166 | // $subheader-font-color: scale-color($header-font-color, $lightness: 35%); 167 | // $subheader-font-weight: $font-weight-normal; 168 | // $subheader-top-margin: .2rem; 169 | // $subheader-bottom-margin: .5rem; 170 | 171 | // A general styling 172 | // $small-font-size: 60%; 173 | // $small-font-color: scale-color($header-font-color, $lightness: 35%); 174 | 175 | // We use these to style paragraphs 176 | // $paragraph-font-family: inherit; 177 | // $paragraph-font-weight: $font-weight-normal; 178 | // $paragraph-font-size: 1rem; 179 | // $paragraph-line-height: 1.6; 180 | // $paragraph-margin-bottom: rem-calc(20); 181 | // $paragraph-aside-font-size: rem-calc(14); 182 | // $paragraph-aside-line-height: 1.35; 183 | // $paragraph-aside-font-style: italic; 184 | // $paragraph-text-rendering: optimizeLegibility; 185 | 186 | // We use these to style tags 187 | // $code-color: grayscale($primary-color); 188 | // $code-font-family: Consolas, 'Liberation Mono', Courier, monospace; 189 | // $code-font-weight: $font-weight-normal; 190 | // $code-background-color: scale-color($secondary-color, $lightness: 70%); 191 | // $code-border-size: 1px; 192 | // $code-border-style: solid; 193 | // $code-border-color: scale-color($code-background-color, $lightness: -10%); 194 | // $code-padding: rem-calc(2) rem-calc(5) rem-calc(1); 195 | 196 | // We use these to style anchors 197 | // $anchor-text-decoration: none; 198 | // $anchor-text-decoration-hover: none; 199 | // $anchor-font-color: $primary-color; 200 | // $anchor-font-color-hover: scale-color($anchor-font-color, $lightness: -14%); 201 | 202 | // We use these to style the
element 203 | // $hr-border-width: 1px; 204 | // $hr-border-style: solid; 205 | // $hr-border-color: #ddd; 206 | // $hr-margin: rem-calc(20); 207 | 208 | // We use these to style lists 209 | // $list-font-family: $paragraph-font-family; 210 | // $list-font-size: $paragraph-font-size; 211 | // $list-line-height: $paragraph-line-height; 212 | // $list-margin-bottom: $paragraph-margin-bottom; 213 | // $list-style-position: outside; 214 | // $list-side-margin: 1.1rem; 215 | // $list-ordered-side-margin: 1.4rem; 216 | // $list-side-margin-no-bullet: 0; 217 | // $list-nested-margin: rem-calc(20); 218 | // $definition-list-header-weight: $font-weight-bold; 219 | // $definition-list-header-margin-bottom: .3rem; 220 | // $definition-list-margin-bottom: rem-calc(12); 221 | 222 | // We use these to style blockquotes 223 | // $blockquote-font-color: scale-color($header-font-color, $lightness: 35%); 224 | // $blockquote-padding: rem-calc(9 20 0 19); 225 | // $blockquote-border: 1px solid #ddd; 226 | // $blockquote-cite-font-size: rem-calc(13); 227 | // $blockquote-cite-font-color: scale-color($header-font-color, $lightness: 23%); 228 | // $blockquote-cite-link-color: $blockquote-cite-font-color; 229 | 230 | // Acronym styles 231 | // $acronym-underline: 1px dotted #ddd; 232 | 233 | // 5. Grid 234 | // - - - - - - - - - - - - - - - 235 | 236 | // $container-width: rem-calc(900); 237 | // $block-padding: $global-padding; 238 | // $total-columns: 12; 239 | // $block-grid-max-size: 6; 240 | 241 | // 6. Button 242 | // - - - - - - - - - - - - - - - 243 | 244 | // $button-padding: 0.85em 1em; 245 | // $button-margin: 0 $global-padding $global-padding 0; 246 | // $button-style: solid; 247 | // $button-background: $primary-color; 248 | // $button-color: auto; 249 | // $button-radius: 0; 250 | // $button-sizes: ( 251 | // tiny: 0.7, 252 | // small: 0.8, 253 | // medium: 1, 254 | // large: 1.3, 255 | // ); 256 | // $button-font-size: 0.9rem; 257 | // $button-opacity-disabled: 0.5; 258 | // $button-tag-selector: false; 259 | 260 | // 7. Accordion 261 | // - - - - - - - - - - - - - - - 262 | 263 | // $accordion-border: 1px solid $gray-dark; 264 | 265 | // $accordion-title-background: $gray-light; 266 | // $accordion-title-background-hover: smartscale($accordion-title-background, 5%); 267 | // $accordion-title-background-active: smartscale($accordion-title-background, 3%); 268 | // $accordion-title-color: isitlight($accordion-title-background); 269 | // $accordion-title-color-active: isitlight($accordion-title-background); 270 | 271 | // $accordion-title-padding: $global-padding; 272 | // $accordion-content-padding: $global-padding; 273 | 274 | // 8. Action Sheet 275 | // - - - - - - - - - - - - - - - 276 | 277 | // $actionsheet-background: white; 278 | // $actionsheet-border-color: #ccc; 279 | // $actionsheet-animate: transform opacity; 280 | // $actionsheet-animation-speed: 0.25s; 281 | // $actionsheet-width: 300px; 282 | // $actionsheet-radius: 4px; 283 | // $actionsheet-shadow: 0 -3px 10px rgba(black, 0.25); 284 | // $actionsheet-padding: $global-padding; 285 | // $actionsheet-tail-size: 10px; 286 | 287 | // $actionsheet-popup-shadow: 0 0 10px rgba(black, 0.25); 288 | 289 | // $actionsheet-link-color: #000; 290 | // $actionsheet-link-background-hover: smartscale($actionsheet-background); 291 | 292 | // 9. Block List 293 | // - - - - - - - - - - - - - - - 294 | 295 | // $blocklist-background: #fff; 296 | // $blocklist-fullbleed: true; 297 | // $blocklist-fontsize: 1rem; 298 | 299 | // $blocklist-item-padding: 0.8rem 1rem; 300 | // $blocklist-item-color: isitlight($blocklist-background, #000, #fff); 301 | // $blocklist-item-background-hover: smartscale($blocklist-background, 4.5%); 302 | // $blocklist-item-color-disabled: #999; 303 | // $blocklist-item-border: 1px solid smartscale($blocklist-background, 18.5%); 304 | 305 | // $blocklist-item-label-color: scale-color($blocklist-item-color, $lightness: 60%); 306 | // $blocklist-item-icon-size: 0.8; 307 | 308 | // $blocklist-header-fontsize: 0.8em; 309 | // $blocklist-header-color: smartscale($blocklist-item-color, 40%); 310 | // $blocklist-header-uppercase: true; 311 | 312 | // $blocklist-check-icons: true; 313 | 314 | // 10. Button Group 315 | // - - - - - - - - - - - - - - - 316 | 317 | // $btngroup-background: $primary-color; 318 | // $btngroup-color: #fff; 319 | // $btngroup-radius: $button-radius; 320 | 321 | // 11. Card 322 | // - - - - - - - - - - - - - - - 323 | 324 | // $card-background: #fff; 325 | // $card-color: isitlight($card-background); 326 | // $card-border: 1px solid smartscale($card-background, 7%); 327 | // $card-radius: $global-radius; 328 | // $card-shadow: 0 1px 2px rgba(#000, 0.2); 329 | // $card-padding: $global-padding; 330 | // $card-margin: 0.5rem; 331 | 332 | // $card-divider-background: smartscale($card-background, 7%); 333 | 334 | // 12. Extras 335 | // - - - - - - - - - - - - - - - 336 | 337 | // $closebutton-position: (top right); 338 | // $closebutton-size: 2em; 339 | // $closebutton-lineheight: 0.5; 340 | // $closebutton-color: #999; 341 | // $closebutton-color-hover: #333; 342 | 343 | // $thumbnail-padding: 0.5rem; 344 | // $thumbnail-shadow: 0 3px 15px rgba(black, 0.25); 345 | 346 | // 13. Forms 347 | // - - - - - - - - - - - - - - - 348 | 349 | // Basic form variables 350 | // $form-fontsize: 1rem; 351 | // $form-padding: 0.5rem; 352 | 353 | // Text fields 354 | // $input-color: #000; 355 | // $input-color-hover: $input-color; 356 | // $input-color-focus: $input-color; 357 | // $input-background: #fff; 358 | // $input-background-hover: $input-background; 359 | // $input-background-focus: $input-background; 360 | // $input-border: 1px solid #ccc; 361 | // $input-border-hover: 1px solid #bbb; 362 | // $input-border-focus: 1px solid #999; 363 | 364 | // Select menus 365 | // $select-color: #000; 366 | // $select-background: #fafafa; 367 | // $select-background-hover: smartscale($select-background, 4%); 368 | // $select-arrow: true; 369 | // $select-arrow-color: $select-color; 370 | 371 | // Labels 372 | // $form-label-fontsize: 0.9rem; 373 | // $form-label-margin: 0.5rem; 374 | // $form-label-color: #333; 375 | 376 | // Inline labels 377 | // $inlinelabel-color: #333; 378 | // $inlinelabel-background: #eee; 379 | // $inlinelabel-border: $input-border; 380 | 381 | // Range slider 382 | // $slider-background: #ddd; 383 | // $slider-height: 1rem; 384 | // $slider-radius: 0px; 385 | // $slider-thumb-height: 1.5rem; 386 | // $slider-thumb-color: $primary-color; 387 | // $slider-thumb-radius: 0px; 388 | 389 | // Progress and meter 390 | // $meter-height: 1.5rem; 391 | // $meter-background: #ccc; 392 | // $meter-fill: $primary-color; 393 | // $meter-fill-high: $success-color; 394 | // $meter-fill-medium: #e7cf00; 395 | // $meter-fill-low: $alert-color; 396 | // $meter-radius: 0; 397 | 398 | // 14. Iconic 399 | // - - - - - - - - - - - - - - - 400 | 401 | // $iconic-primary-fill: $primary-color; 402 | // $iconic-primary-stroke: $primary-color; 403 | // $iconic-accent-fill: $iconic-primary-fill; 404 | // $iconic-accent-stroke: $iconic-accent-fill; 405 | 406 | // 15. Label 407 | // - - - - - - - - - - - - - - - 408 | 409 | // $label-fontsize: 0.8rem; 410 | // $label-padding: ($global-padding / 3) ($global-padding / 2); 411 | // $label-radius: 0; 412 | // $label-background: $primary-color; 413 | // $label-color: isitlight($primary-color); 414 | 415 | // $badge-fontsize: 0.8em; 416 | // $badge-diameter: 1.5rem; 417 | // $badge-background: $primary-color; 418 | // $badge-color: #fff; 419 | 420 | // DEPRECATED: these variables will be removed in v1.1. 421 | // $badge-padding: .1em .61em; 422 | // $badge-radius: $global-rounded; 423 | // $badge-font-color: #fff; 424 | 425 | // 16. Menu Bar 426 | // - - - - - - - - - - - - - - - 427 | 428 | // $menubar-fontsize: 1rem; 429 | // $menubar-background: #fff; 430 | // $menubar-background-hover: smartscale($menubar-background, 7%); 431 | // $menubar-background-active: $menubar-background-hover; 432 | // $menubar-color: isitlight($menubar-background); 433 | // $menubar-color-hover: $menubar-color; 434 | // $menubar-color-active: $menubar-color-hover; 435 | 436 | // $menubar-item-padding: $global-padding; 437 | // $menubar-icon-size: 25px; 438 | // $menubar-icon-spacing: $menubar-item-padding; 439 | 440 | // 17. Modal 441 | // - - - - - - - - - - - - - - - 442 | 443 | // $modal-background: #fff; 444 | // $modal-border: 0; 445 | // $modal-radius: 0px; 446 | // $modal-shadow: none; 447 | // $modal-zindex: 1000; 448 | // $modal-sizes: ( 449 | // tiny: 300px, 450 | // small: 500px, 451 | // medium: 600px, 452 | // large: 800px, 453 | // ); 454 | 455 | // $modal-overlay-class: 'modal-overlay'; 456 | // $modal-overlay-background: rgba(#333, 0.7); 457 | 458 | // 18. Motion UI 459 | // - - - - - - - - - - - - - - - 460 | 461 | // Classes to use when triggering in/out animations 462 | // $motion-class: ( 463 | // in: "ng-enter", 464 | // out: "ng-leave", 465 | // ); 466 | // $motion-class-active: ( 467 | // in: "ng-enter-active", 468 | // out: "ng-leave-active", 469 | // ); 470 | // $motion-class-stagger: ( 471 | // in: "ng-enter-stagger", 472 | // out: "ng-leave-stagger", 473 | // ); 474 | 475 | // Set if movement-based transitions should also fade the element in and out 476 | // $motion-slide-and-fade: false; 477 | // $motion-hinge-and-fade: true; 478 | // $motion-scale-and-fade: true; 479 | // $motion-spin-and-fade: true; 480 | 481 | // Default speed for transitions and animations 482 | // $motion-duration-default: 500ms; 483 | // Slow and fast modifiders 484 | // $motion-duration-slow: 750ms; 485 | // $motion-duration-fast: 250ms; 486 | // $motion-stagger-duration-default: 150ms; 487 | // $motion-stagger-duration-short: 50ms; 488 | // $motion-stagger-duration-long: 300ms; 489 | 490 | // Default timing function for transitions and animations 491 | // $motion-timing-default: ease; 492 | // Built-in and custom easing functions 493 | // Every item in this map becomes a CSS class 494 | // $motion-timings: ( 495 | // linear: linear, 496 | // ease: ease, 497 | // easeIn: ease-in, 498 | // easeOut: ease-out, 499 | // easeInOut: ease-in-out, 500 | // bounceIn: cubic-bezier(0.485, 0.155, 0.240, 1.245), 501 | // bounceOut: cubic-bezier(0.485, 0.155, 0.515, 0.845), 502 | // bounceInOut: cubic-bezier(0.760, -0.245, 0.240, 1.245), 503 | // ); 504 | 505 | // Default delay for all transitions and animations 506 | // $motion-delay-default: 0; 507 | // Short and long delay modifiers 508 | // $motion-delay-short: 300ms; 509 | // $motion-delay-long: 700ms; 510 | 511 | // 19. Notification 512 | // - - - - - - - - - - - - - - - 513 | 514 | // $notification-default-position: right top; 515 | // $notification-width: rem-calc(400); 516 | // $notification-offset: $global-padding; 517 | 518 | // $notification-background: $primary-color; 519 | // $notification-color: white; 520 | // $notification-padding: $global-padding; 521 | // $notification-radius: 4px; 522 | 523 | // $notification-icon-size: 60px; 524 | // $notification-icon-margin: $global-padding; 525 | // $notification-icon-align: top; 526 | 527 | 528 | // 20. Off-canvas 529 | // - - - - - - - - - - - - - - - 530 | 531 | // $offcanvas-size-horizontal: 250px; 532 | // $offcanvas-size-vertical: 250px; 533 | 534 | // $offcanvas-background: #fff; 535 | // $offcanvas-color: isitlight($offcanvas-background); 536 | // $offcanvas-padding: 0; 537 | // $offcanvas-shadow: 3px 0 10px rgba(black, 0.25); 538 | // $offcanvas-animation-speed: 0.25s; 539 | 540 | // $offcanvas-frame-selector: '.grid-frame'; 541 | 542 | // 21. Panel 543 | // - - - - - - - - - - - - - - - 544 | 545 | // $panel-size-horizontal: 300px; 546 | // $panel-size-vertical: 300px; 547 | // $panel-padding: 0; 548 | 549 | // $panel-background: #fff; 550 | // $panel-shadow: 3px 0 10px rgba(black, 0.25); 551 | // $panel-animation-speed: 0.25s; 552 | 553 | // 22. Popup 554 | // - - - - - - - - - - - - - - - 555 | 556 | // $popup-width: rem-calc(300); 557 | // $popup-background: #fff; 558 | // $popup-border: 0; 559 | // $popup-radius: 0; 560 | // $popup-shadow: 0 0 10px rgba(#000, 0.25); 561 | 562 | // 23. Switch 563 | // - - - - - - - - - - - - - - - 564 | 565 | // $switch-width: rem-calc(50); 566 | // $switch-height: rem-calc(32); 567 | // $switch-background: #ccc; 568 | // $switch-background-active: $primary-color; 569 | // $switch-border: 0; 570 | // $switch-radius: 9999px; 571 | // $switch-animation-speed: 0.15s; 572 | 573 | // $switch-paddle-color: white; 574 | // $switch-paddle-offset: 4px; 575 | 576 | // 24. Tabs 577 | // - - - - - - - - - - - - - - - 578 | 579 | // $tabstrip-background: transparent; 580 | 581 | // $tab-title-background: $gray-light; 582 | // $tab-title-background-hover: smartscale($tab-title-background, 5%); 583 | // $tab-title-background-active: smartscale($tab-title-background, 3%); 584 | // $tab-title-color: isitlight($tab-title-background); 585 | // $tab-title-color-active: $tab-title-color; 586 | 587 | // $tab-title-padding: $global-padding; 588 | // $tab-content-padding: $global-padding; 589 | 590 | // 25. Title Bar 591 | // - - - - - - - - - - - - - - - 592 | 593 | // $titlebar-center-width: 50%; 594 | // $titlebar-side-width: (100% - $titlebar-center-width) / 2; 595 | // $titlebar-background: #eee; 596 | // $titlebar-color: #000; 597 | // $titlebar-border: 1px solid #ccc; 598 | // $titlebar-padding: $global-padding; 599 | // $titlebar-item-classes: ( 600 | // center: 'center', 601 | // left: 'left', 602 | // right: 'right', 603 | // title: 'title', 604 | // ); 605 | -------------------------------------------------------------------------------- /app/Frontend/styles/app.scss: -------------------------------------------------------------------------------- 1 | @import "settings"; 2 | @import "foundation"; 3 | -------------------------------------------------------------------------------- /app/Frontend/styles/globalapp.scss: -------------------------------------------------------------------------------- 1 | /* 2 | Every SCSS files will be injected into main HTML page 3 | */ 4 | 5 | .status-ok { 6 | color: #191970; 7 | border: 2px solid greenyellow !important; 8 | padding:15px 50px 15px 50px;margin:0 0 5px 5px; 9 | box-shadow: 5px 5px 2px #656565; 10 | background-color: rgba(20, 205, 50,0.7); 11 | } 12 | .status-ok:hover{background-color:greenyellow;} 13 | 14 | .status-fx { 15 | color: #191970; 16 | border: 2px solid violet !important; 17 | padding:15px 50px 15px 50px;margin:0 0 5px 5px; 18 | box-shadow: 5px 5px 2px #656565; 19 | background-color: rgba(180, 50, 50,0.7); 20 | } 21 | .status-fx:hover{background-color:#696969;} 22 | 23 | -------------------------------------------------------------------------------- /app/Frontend/tmp/routes.js: -------------------------------------------------------------------------------- 1 | var foundationRoutes = [{"name":"mysample","url":"/sample","animationIn":"slideInRight","path":"pages/sample/sample.html"},{"name":"myhome","url":"/home","animationIn":"slideInLeft","animationOut":"slideOutRight","controller":"MyHomeController","path":"pages/home/home.html"},{"name":"ajaxsample","url":"/ajax","animationIn":"slideInUp","path":"pages/ajax/ajax.html"}]; 2 | -------------------------------------------------------------------------------- /app/Frontend/widgets/widgetA/widgetA.html: -------------------------------------------------------------------------------- 1 | Widget-AA [{{value}}] -------------------------------------------------------------------------------- /app/Frontend/widgets/widgetA/widgetA.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * This model force class change simply by updating a variable within the 4 | * private scope of the directive. Might not be the prefered model to change 5 | * a class, but it a simple way to demonstrate how a template can interact with 6 | * javascript. 7 | * 8 | * Note: widgetA uses a private widgetA.scss style. 9 | */ 10 | 11 | (function() { 12 | 'use strict'; 13 | 14 | angular.module('WidgetA',[]) 15 | 16 | .directive('widgetA', function() { 17 | function mymethods(scope, elem, attrs) { 18 | 19 | scope.value="OFF"; 20 | 21 | scope.clicked = function () { 22 | if (scope.value === "ON") { 23 | scope.value = "OFF"; 24 | } else { 25 | scope.value = "ON"; 26 | } 27 | console.log ("Clicked WidgetA value=" + scope.value); 28 | }; 29 | 30 | } 31 | 32 | return { 33 | restrict: 'E', 34 | templateUrl: 'widgets/widgetA/widgetA.html', 35 | link: mymethods, 36 | scope: {} 37 | }; 38 | }); 39 | 40 | console.log ("widgetA Loaded"); 41 | })(); 42 | -------------------------------------------------------------------------------- /app/Frontend/widgets/widgetA/widgetA.scss: -------------------------------------------------------------------------------- 1 | /* 2 | Sample of style overload for a specific widget 3 | 4 | Note: this SCSS is injected with main HTML page, it scope should be reduce 5 | to a specific widget or it value will be propagated at a global level. 6 | */ 7 | 8 | widget-a { 9 | .status-ON { 10 | color: #191970; 11 | border: 2px solid blue !important; 12 | padding:15px 50px 15px 50px;margin:0 0 5px 5px; 13 | box-shadow: 5px 5px 2px #656565; 14 | background-color: rgba(150, 200, 50,0.7); 15 | } 16 | .status-ON:hover{background-color:greenyellow;} 17 | 18 | .status-OFF { 19 | color: #191970; 20 | border: 2px solid red !important; 21 | padding:15px 50px 15px 50px;margin:0 0 5px 5px; 22 | box-shadow: 5px 5px 2px #656565; 23 | background-color: rgba(200, 10, 10,0.7); 24 | } 25 | .status-OFF:hover{background-color:red;} 26 | } 27 | -------------------------------------------------------------------------------- /app/Frontend/widgets/widgetB/widgetB.html: -------------------------------------------------------------------------------- 1 | Widget-B [ON] -------------------------------------------------------------------------------- /app/Frontend/widgets/widgetB/widgetB.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Change class through Angular Add/Remove class methods. 4 | * Note that Element point onto HTML tag element and that searching 5 | * in the widget for the right element is necessary. This search can 6 | * use tag,id,class,... 7 | * 8 | * We may search for the element only once at initialisation time and keep 9 | * the reference within the private scope of the directive. 10 | * 11 | * Note: widgetB uses globalapp.scss style. 12 | */ 13 | 14 | (function() { 15 | 'use strict'; 16 | 17 | angular.module('WidgetB',[]) 18 | 19 | .directive('widgetB', function() { 20 | function mymethods(scope, elem, attrs) { 21 | 22 | scope.button = elem.children('span'); 23 | console.log (scope.button); 24 | 25 | scope.clicked = function () { 26 | if (scope.button.hasClass ("status-ok")) { 27 | console.log ("Clicked WidgetB value=FX" ); 28 | scope.button.removeClass("status-ok"); 29 | scope.button.addClass("status-fx"); 30 | scope.button.text("Widget-B [OFF]"); 31 | } else { 32 | console.log ("Clicked WidgetB value=OK" ); 33 | scope.button.removeClass("status-fx"); 34 | scope.button.addClass("status-ok"); 35 | scope.button.text("Widget-B [ON]"); 36 | } 37 | }; 38 | } 39 | 40 | return { 41 | restrict: 'E', 42 | templateUrl: 'widgets/widgetB/widgetB.html', 43 | link: mymethods, 44 | scope: { 45 | initvalues : '=' 46 | } 47 | }; 48 | }); 49 | 50 | console.log ("widgetB Loaded"); 51 | })(); -------------------------------------------------------------------------------- /app/etc/AppDefaults.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 "IoT.bzh" 3 | * Author "Fulup Ar Foll" 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | // Default config will be superseaded by ProjectRoot/.config-l4a.js $HOME/.config-l4a.js /etc/default/config-l4a.js 20 | config = { 21 | APPNAME : 'MySampleApp', // AppName is use as main Angular Module name 22 | HOST : 'localhost', // HTTP will only listen on related Internet interface 23 | PORT : 8080, // HTTP port 24 | URLBASE : '/', // HTML basedir when running in production 25 | LOGDIR : __dirname + '/log', // httpd log file 26 | FRONTEND: "Frontend", // HTML5 frontend [WARNING: no leading './'] 27 | BACKEND : "Backend", // NodeJS Rest API [WARNING: no leading './'] 28 | SECRET : Math.random().toString(36).slice(2) // [default cookie session] 29 | }; 30 | 31 | module.exports = config; 32 | 33 | -------------------------------------------------------------------------------- /app/etc/_Config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Fulup Ar Foll 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | var fs = require('fs'); 18 | 19 | function Config () { 20 | 'use strict'; 21 | var values=[]; 22 | var extention='-myapp.js'; 23 | var conf; 24 | 25 | // Configs file path last one supersead first one. 26 | var files= [__dirname + "/AppDefaults.js", "/etc/default/noderc"+ extention, process.env.NODERC, process.env.HOME + "/.noderc"+ extention , __dirname +"/../../.noderc.js" ]; 27 | 28 | // Parse any existing files within config list & merge them 29 | for (var idx in files) { 30 | if (files[idx]) { 31 | if (fs.existsSync (files[idx])) conf=require (files[idx]); 32 | for (var i in conf) values[i] = conf[i]; 33 | } 34 | } 35 | // console.log ("values=", values); 36 | return values; 37 | } 38 | 39 | module.exports = Config(); 40 | -------------------------------------------------------------------------------- /app/etc/_Debug.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Fulup Ar Foll 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | var traceback = require('traceback'); // https://www.npmjs.org/package/traceback 18 | var util = require("util"); 19 | 20 | // ------- Public Methods -------------- 21 | var Debug = function(level, format) { //+ arguments 22 | 23 | if (this.debug >= level ) { 24 | 25 | var args = [].slice.call(arguments, 1); // copy argument in a real array leaving out level 26 | var message = util.format.apply(null, args); 27 | 28 | try { 29 | var trace = traceback()[1]; // get trace up to previous calling function 30 | if (this.debug > 5) console.log("-%d- %s/%s:%d [%s]", level, trace.file, trace.name, trace.line, message); 31 | else console.log("-- %s [%s] -- %j", level, trace.name, message); 32 | } catch (e) { 33 | console.log("-- %s [%s] -- %j", level, 'no trace', message); 34 | } 35 | } 36 | }; 37 | 38 | module.exports = Debug; 39 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "healthy-gulp-angular", 3 | "version": "0.0.0", 4 | "authors": "", 5 | "private": true, 6 | "dependencies": { 7 | "foundation-apps": "~1.1.0" 8 | }, 9 | 10 | "overrides": { 11 | "foundation": { 12 | "main": [ 13 | 14 | ] 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | var gulp = require('gulp'); 4 | var plugins = require('gulp-load-plugins')(); 5 | var del = require('del'); 6 | var es = require('event-stream'); 7 | var bowerFiles = require('main-bower-files'); 8 | var print = require('gulp-print'); 9 | var Q = require('q'); 10 | var imagemin = require('gulp-imagemin'), pngquant = require('imagemin-pngquant'); 11 | var taskListing = require('gulp-task-listing'); 12 | 13 | // addon for Foundation6 14 | var router = require('front-router'); 15 | 16 | // == PATH STRINGS ======== 17 | var appdir = "./app/"; // Warning to not forget trailling '/' 18 | config=require (appdir + "etc/_Config"); // upload user local preferences if any 19 | 20 | // Run node in debug mode in developpement mode ? 21 | var nodeopts = config.DEBUG !== undefined ? '--debug='+config.DEBUG : ''; 22 | var frontend= appdir + config.FRONTEND; 23 | var backend = appdir + config.BACKEND; 24 | 25 | var paths = { 26 | application: frontend, 27 | scripts : frontend+'/**/*.js', 28 | styles : [frontend+'/**/*.css', frontend+'/**/*.scss'], 29 | images : [frontend+'/**/*.ico',frontend+'/**/*.png',frontend+'/**/*.jpg',frontend+'/**/*.jpeg',frontend+'/**/*.svg',frontend+'/**/*.ttf'], 30 | index : frontend+'/index.html', 31 | partials : [frontend + '/**/*.html', '!' + frontend +'/index.html'], 32 | distDev : './dist.dev', 33 | distProd : './dist.prod', 34 | distScriptsProd: './dist.prod/scripts', 35 | scriptsDevServer: backend + '/**/*.js', 36 | sass: ['bower_components/foundation-apps/scss'] 37 | }; 38 | 39 | // Run node in debug mode in developpement mode ? 40 | var nodeopts = config.DEBUG !== undefined ? '--debug='+config.DEBUG : ''; 41 | 42 | // == PIPE SEGMENTS ======== 43 | var pipes = {}; 44 | 45 | pipes.orderedVendorScripts = function() { 46 | return plugins.order(['jquery.js', 'angular.js']); 47 | }; 48 | 49 | pipes.orderedAppScripts = function() { 50 | return plugins.angularFilesort(); 51 | }; 52 | 53 | pipes.minifiedFileName = function() { 54 | return plugins.rename(function (path) { 55 | path.extname = '.min' + path.extname; 56 | }); 57 | }; 58 | 59 | pipes.validatedAppScripts = function() { 60 | return gulp.src(paths.scripts) 61 | .pipe(plugins.replace('@@APPNAME@@', config.APPNAME)) 62 | .pipe(plugins.jshint()) 63 | .pipe(plugins.jshint.reporter('jshint-stylish')); 64 | }; 65 | 66 | pipes.builtAppScriptsDev = function() { 67 | return pipes.validatedAppScripts() 68 | .pipe(gulp.dest(paths.distDev)); 69 | }; 70 | 71 | pipes.builtAppScriptsProd = function() { 72 | var scriptedPartials = pipes.scriptedPartials(); 73 | var validatedAppScripts = pipes.validatedAppScripts(); 74 | 75 | return es.merge(scriptedPartials, validatedAppScripts) 76 | .pipe(plugins.ngAnnotate()) 77 | .pipe(pipes.orderedAppScripts()) 78 | .pipe(plugins.sourcemaps.init()) 79 | .pipe(plugins.concat('app.min.js')) 80 | .pipe(plugins.uglify({compress: {drop_console: true}})) 81 | .pipe(plugins.sourcemaps.write()) 82 | .pipe(gulp.dest(paths.distScriptsProd)); 83 | }; 84 | 85 | pipes.builtVendorScriptsDev = function() { 86 | return gulp.src(bowerFiles()) 87 | .pipe(gulp.dest('dist.dev/bower_components')); 88 | }; 89 | 90 | pipes.builtVendorScriptsProd = function() { 91 | return gulp.src(bowerFiles('**/*.js')) 92 | .pipe(pipes.orderedVendorScripts()) 93 | .pipe(plugins.concat('vendor.min.js')) 94 | .pipe(plugins.uglify()) 95 | .pipe(gulp.dest(paths.distScriptsProd)); 96 | }; 97 | 98 | pipes.validatedDevServerScripts = function() { 99 | return gulp.src(paths.scriptsDevServer) 100 | .pipe(plugins.jshint()) 101 | .pipe(plugins.jshint.reporter('jshint-stylish')); 102 | }; 103 | 104 | pipes.validatedPartials = function() { 105 | return gulp.src(paths.partials) 106 | .pipe(plugins.htmlhint({'doctype-first': false})) 107 | .pipe(router({path: paths.application+'/tmp/routes.js', root: paths.application})) 108 | .pipe(plugins.htmlhint.reporter()); 109 | }; 110 | 111 | pipes.builtPartialsDev = function() { 112 | return pipes.validatedPartials() 113 | .pipe(gulp.dest(paths.distDev)); 114 | }; 115 | 116 | pipes.scriptedPartials = function() { 117 | return pipes.validatedPartials() 118 | .pipe(plugins.htmlhint.failReporter()) 119 | .pipe(plugins.htmlmin({collapseWhitespace: true, removeComments: true})) 120 | .pipe(plugins.ngHtml2js({ 121 | moduleName: config.APPNAME, 122 | template: "(function() {" 123 | + "angular.module('<%= moduleName %>').run(['$templateCache', function($templateCache) {" 124 | + "$templateCache.put('<%= template.url %>',\n '<%= template.escapedContent %>');" 125 | + "}]);\n" 126 | + "})();\n" 127 | })); 128 | }; 129 | 130 | pipes.builtStylesDev = function() { 131 | return gulp.src(paths.styles) 132 | .pipe(plugins.sass({includePaths: paths.sass})) 133 | .pipe(gulp.dest(paths.distDev)); 134 | }; 135 | 136 | pipes.builtStylesProd = function() { 137 | return gulp.src(paths.styles) 138 | .pipe(plugins.sourcemaps.init()) 139 | .pipe(plugins.sass({includePaths: paths.sass})) 140 | .pipe(plugins.minifyCss()) 141 | .pipe(plugins.sourcemaps.write()) 142 | .pipe(pipes.minifiedFileName()) 143 | .pipe(gulp.dest(paths.distProd)); 144 | }; 145 | 146 | pipes.processedImagesDev = function() { 147 | return gulp.src(paths.images) 148 | .pipe(gulp.dest(paths.distDev)); 149 | }; 150 | 151 | pipes.processedImagesProd = function() { 152 | return gulp.src(paths.images) 153 | .pipe(imagemin({ 154 | progressive: true, 155 | svgoPlugins: [{removeViewBox: false}], 156 | use: [pngquant()] 157 | })) 158 | .pipe(gulp.dest(paths.distProd)); 159 | }; 160 | 161 | pipes.validatedIndex = function() { 162 | return gulp.src(paths.index) 163 | .pipe(plugins.replace('@@APPNAME@@', config.APPNAME)) 164 | .pipe(plugins.replace('@@URLBASE@@', config.URLBASE)) 165 | .pipe(plugins.htmlhint()) 166 | .pipe(plugins.htmlhint.reporter()); 167 | }; 168 | 169 | pipes.builtIndexDev = function() { 170 | 171 | var orderedVendorScripts = pipes.builtVendorScriptsDev() 172 | .pipe(pipes.orderedVendorScripts()); 173 | 174 | var orderedAppScripts = pipes.builtAppScriptsDev() 175 | .pipe(pipes.orderedAppScripts()); 176 | 177 | var appStyles = pipes.builtStylesDev(); 178 | 179 | return pipes.validatedIndex() 180 | .pipe(gulp.dest(paths.distDev)) // write first to get relative path for inject 181 | .pipe(plugins.inject(orderedVendorScripts, {relative: true, name: 'bower'})) 182 | .pipe(plugins.inject(orderedAppScripts, {relative: true})) 183 | .pipe(plugins.inject(appStyles, {relative: true})) 184 | .pipe(gulp.dest(paths.distDev)); 185 | }; 186 | 187 | pipes.builtIndexProd = function() { 188 | 189 | var vendorScripts = pipes.builtVendorScriptsProd(); 190 | var appScripts = pipes.builtAppScriptsProd(); 191 | var appStyles = pipes.builtStylesProd(); 192 | 193 | return pipes.validatedIndex() 194 | .pipe(gulp.dest(paths.distProd)) // write first to get relative path for inject 195 | .pipe(plugins.inject(vendorScripts, {relative: true, name: 'bower'})) 196 | .pipe(plugins.inject(appScripts, {relative: true})) 197 | .pipe(plugins.inject(appStyles, {relative: true})) 198 | .pipe(plugins.htmlmin({collapseWhitespace: true, removeComments: true})) 199 | .pipe(gulp.dest(paths.distProd)); 200 | }; 201 | 202 | pipes.builtAppDev = function() { 203 | return es.merge(pipes.builtIndexDev(), pipes.builtPartialsDev(), pipes.processedImagesDev()); 204 | }; 205 | 206 | pipes.builtAppProd = function() { 207 | return es.merge(pipes.builtIndexProd(), pipes.processedImagesProd()); 208 | }; 209 | 210 | 211 | // == TASKS ======== 212 | 213 | // Add a task to render the output 214 | gulp.task('help', taskListing.withFilters(/-/)); 215 | 216 | // clean, build of production environement 217 | gulp.task('build', ['clean-build-app-prod', 'validate-devserver-scripts']); 218 | 219 | gulp.task('run', function() { 220 | // start nodemon to auto-reload the dev server 221 | plugins.nodemon({ script: 'server.js', ext: 'js', watch: ['devServer/']}) 222 | .on('change', ['validate-devserver-scripts']) 223 | .on('restart', function () { 224 | console.log('[nodemon] restarted dev server'); 225 | }); 226 | }); 227 | 228 | // removes all compiled dev files 229 | gulp.task('clean-dev', function() { 230 | var deferred = Q.defer(); 231 | del(paths.distDev, function() { 232 | deferred.resolve(); 233 | }); 234 | return deferred.promise; 235 | }); 236 | 237 | // removes all compiled production files 238 | gulp.task('clean-prod', function() { 239 | var deferred = Q.defer(); 240 | del(paths.distProd, function() { 241 | deferred.resolve(); 242 | }); 243 | return deferred.promise; 244 | }); 245 | 246 | // checks html source files for syntax errors 247 | gulp.task('validate-partials', pipes.validatedPartials); 248 | 249 | // checks index.html for syntax errors 250 | gulp.task('validate-index', pipes.validatedIndex); 251 | 252 | // moves html source files into the dev environment 253 | gulp.task('build-partials-dev', pipes.builtPartialsDev); 254 | 255 | // converts partials to javascript using html2js 256 | gulp.task('convert-partials-to-js', pipes.scriptedPartials); 257 | 258 | // runs jshint on the dev server scripts 259 | gulp.task('validate-devserver-scripts', pipes.validatedDevServerScripts); 260 | 261 | // runs jshint on the app scripts 262 | gulp.task('validate-app-scripts', pipes.validatedAppScripts); 263 | 264 | // moves app scripts into the dev environment 265 | gulp.task('build-app-scripts-dev', pipes.builtAppScriptsDev); 266 | 267 | // concatenates, uglifies, and moves app scripts and partials into the prod environment 268 | gulp.task('build-app-scripts-prod', pipes.builtAppScriptsProd); 269 | 270 | // compiles app sass and moves to the dev environment 271 | gulp.task('build-styles-dev', pipes.builtStylesDev); 272 | 273 | // compiles and minifies app sass to css and moves to the prod environment 274 | gulp.task('build-styles-prod', pipes.builtStylesProd); 275 | 276 | // moves vendor scripts into the dev environment 277 | gulp.task('build-vendor-scripts-dev', pipes.builtVendorScriptsDev); 278 | 279 | // concatenates, uglifies, and moves vendor scripts into the prod environment 280 | gulp.task('build-vendor-scripts-prod', pipes.builtVendorScriptsProd); 281 | 282 | // validates and injects sources into index.html and moves it to the dev environment 283 | gulp.task('build-index-dev', pipes.builtIndexDev); 284 | 285 | // validates and injects sources into index.html, minifies and moves it to the dev environment 286 | gulp.task('build-index-prod', pipes.builtIndexProd); 287 | 288 | // builds a complete dev environment 289 | gulp.task('build-app-dev', pipes.builtAppDev); 290 | 291 | // builds a complete prod environment 292 | gulp.task('build-app-prod', pipes.builtAppProd); 293 | 294 | // cleans and builds a complete dev environment 295 | gulp.task('clean-build-app-dev', ['clean-dev'], pipes.builtAppDev); 296 | 297 | // cleans and builds a complete prod environment 298 | gulp.task('clean-build-app-prod', ['clean-prod'], pipes.builtAppProd); 299 | 300 | // clean, build, and watch live changes to the dev environment 301 | gulp.task('watch-dev', ['clean-build-app-dev', 'validate-devserver-scripts'], function() { 302 | 303 | // start nodemon to auto-reload the dev server 304 | plugins.nodemon({ exec: 'node ' + nodeopts, script: backend+'/server.js', ext: 'js', watch: [backend], env: {NODE_ENV : 'dev'} }) 305 | .on('change', ['validate-devserver-scripts']) 306 | .on('restart', function () { 307 | console.log('[nodemon] restarted dev server'); 308 | }); 309 | 310 | // start live-reload server 311 | plugins.livereload.listen({ start: true }); 312 | 313 | // watch index 314 | gulp.watch(paths.index, function() { 315 | return pipes.builtIndexDev() 316 | .pipe(plugins.livereload()); 317 | }); 318 | 319 | // watch app scripts 320 | gulp.watch(paths.scripts, function() { 321 | return pipes.builtAppScriptsDev() 322 | .pipe(plugins.livereload()); 323 | }); 324 | 325 | // watch html partials 326 | gulp.watch(paths.partials, function() { 327 | return pipes.builtPartialsDev() 328 | .pipe(plugins.livereload()); 329 | }); 330 | 331 | // watch Images 332 | gulp.watch(paths.images, function() { 333 | return pipes.processedImagesDev() 334 | .pipe(plugins.livereload()); 335 | }); 336 | 337 | // watch styles 338 | gulp.watch(paths.styles, function() { 339 | return pipes.builtStylesDev() 340 | .pipe(plugins.livereload()); 341 | }); 342 | 343 | }); 344 | 345 | // clean, build, and watch live changes to the prod environment 346 | gulp.task('watch-prod', ['clean-build-app-prod', 'validate-devserver-scripts'], function() { 347 | 348 | // start nodemon to auto-reload the dev server 349 | plugins.nodemon({ script: backend +'/server.js', ext: 'js', watch: [backend], env: {MODE : 'prod'} }) 350 | .on('change', ['validate-devserver-scripts']) 351 | .on('restart', function () { 352 | console.log('[nodemon] restarted dev server'); 353 | }); 354 | 355 | // start live-reload server 356 | plugins.livereload.listen({start: true}); 357 | 358 | // watch index 359 | gulp.watch(paths.index, function() { 360 | return pipes.builtIndexProd() 361 | .pipe(plugins.livereload()); 362 | }); 363 | 364 | // watch app scripts 365 | gulp.watch(paths.scripts, function() { 366 | return pipes.builtAppScriptsProd() 367 | .pipe(plugins.livereload()); 368 | }); 369 | 370 | // watch hhtml partials 371 | gulp.watch(paths.partials, function() { 372 | return pipes.builtAppScriptsProd() 373 | .pipe(plugins.livereload()); 374 | }); 375 | 376 | // watch Images 377 | gulp.watch(paths.images, function() { 378 | return pipes.processedImagesProd() 379 | .pipe(plugins.livereload()); 380 | }); 381 | 382 | // watch styles 383 | gulp.watch(paths.styles, function() { 384 | return pipes.builtStylesProd() 385 | .pipe(plugins.livereload()); 386 | }); 387 | 388 | }); 389 | 390 | // default task builds for prod 391 | gulp.task('default', ['clean-build-app-prod']); 392 | -------------------------------------------------------------------------------- /nbproject/project.properties: -------------------------------------------------------------------------------- 1 | auxiliary.org-netbeans-modules-css-prep.sass_2e_configured=true 2 | file.reference.healthy-gulp-angular-foundation6-app=app 3 | file.reference.healthy-gulp-angular-foundation6-Frontend=Frontend 4 | files.encoding=UTF-8 5 | site.root.folder=${file.reference.healthy-gulp-angular-foundation6-Frontend} 6 | source.folder= 7 | -------------------------------------------------------------------------------- /nbproject/project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | org.netbeans.modules.web.clientproject 4 | 5 | 6 | healthy-gulp-angular-foundation6 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "healthy-gulp-angular", 3 | "private": true, 4 | "version": "0.0.0", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/iotbzh/healthy-gulp-angular-foundation6" 8 | }, 9 | "scripts": { 10 | "postinstall": "bower install", 11 | "build": "./node_modules/.bin/gulp clean-build-app-dev", 12 | "start": "./node_modules/.bin/gulp watch-dev" 13 | }, 14 | "devDependencies": { 15 | "body-parser": "^1.5.2", 16 | "bower": "^1.3.1", 17 | "cookie-parser": "^1.4.0", 18 | "del": "^1.1.1", 19 | "event-stream": "^3.2.2", 20 | "express": "^4.7.2", 21 | "express-session": "^1.12.1", 22 | "front-router": "^1.0.0", 23 | "gulp": "^3.9.0", 24 | "gulp-angular-filesort": "^1.0.4", 25 | "gulp-concat": "^2.4.3", 26 | "gulp-htmlhint": "0.0.9", 27 | "gulp-htmlmin": "^1.0.0", 28 | "gulp-imagemin": "*", 29 | "gulp-inject": "^1.1.1", 30 | "gulp-jshint": "^1.9.2", 31 | "gulp-livereload": "^3.7.0", 32 | "gulp-load-plugins": "^0.8.0", 33 | "gulp-minify-css": "^0.4.5", 34 | "gulp-ng-annotate": "^1.1.0", 35 | "gulp-ng-html2js": "^0.2.0", 36 | "gulp-nodemon": "^2.0.0", 37 | "gulp-order": "^1.1.1", 38 | "gulp-print": "^1.1.0", 39 | "gulp-rename": "^1.2.0", 40 | "gulp-replace": "^0.5.4", 41 | "gulp-sass": "^2.0.3", 42 | "gulp-sourcemaps": "^1.3.0", 43 | "gulp-task-listing": "^1.0.1", 44 | "gulp-uglify": "^1.2.0", 45 | "imagemin-pngquant": "*", 46 | "jshint-stylish": "^1.0.0", 47 | "karma": "^0.10", 48 | "karma-junit-reporter": "^0.2.2", 49 | "main-bower-files": "^2.5.0", 50 | "method-override": "^2.1.2", 51 | "protractor": "^1.1.1", 52 | "q": "^1.1.2", 53 | "shelljs": "^0.2.6" 54 | } 55 | } 56 | --------------------------------------------------------------------------------