├── .gitignore ├── Cakefile ├── LICENSE ├── README.md ├── app.coffee ├── app ├── angular │ ├── README.md │ ├── app.coffee │ ├── controllers.coffee │ ├── directives.coffee │ ├── filters.coffee │ └── services.coffee ├── config │ ├── README.md │ └── index.coffee ├── index.coffee ├── resources │ └── README.md ├── routes │ ├── README.md │ └── index.coffee ├── services │ ├── README.md │ └── users.coffee └── socket │ ├── README.md │ └── index.coffee ├── package.json ├── public └── images │ └── favicon.ico ├── setup.bat ├── setup.sh ├── styles ├── README.md └── espresso.less └── views ├── index.jade ├── layout.jade └── partials ├── home.jade ├── socket.jade └── user.jade /.gitignore: -------------------------------------------------------------------------------- 1 | .espresso 2 | .idea 3 | *.iml 4 | node_modules 5 | public/angular 6 | public/js 7 | public/styles 8 | *.js -------------------------------------------------------------------------------- /Cakefile: -------------------------------------------------------------------------------- 1 | fs = require "fs" 2 | uglifyjs = require "uglify-js" 3 | 4 | {print} = require "sys" 5 | {exec} = require "child_process" 6 | 7 | ### 8 | Directory where the Espresso module will be generated 9 | ### 10 | ESPRESSO_DIR = ".espresso" 11 | 12 | ### 13 | Module's index filename. DO NOT MODIFY! 14 | ### 15 | ESPRESSO_INDEX = "index.coffee" 16 | 17 | ### 18 | Types of source files. DO NOT MODIFY! 19 | ### 20 | SOURCES = { COFFEE: "coffee", LESS: "less" } 21 | 22 | ### 23 | Directory where the source code is 24 | ### 25 | APP_DIR = "app" 26 | 27 | ### 28 | Module directories 29 | ### 30 | APP_SRC = [ 31 | "config", 32 | "routes", 33 | "services", 34 | "socket" 35 | ] 36 | 37 | ### 38 | Server filename. File that is run by Node 39 | ### 40 | SERVER_FILENAME = "app.coffee" 41 | 42 | ### 43 | Angular app source folder under APP_DIR 44 | ### 45 | ANGULAR_APP_SRC = "#{__dirname}/#{APP_DIR}/angular" 46 | 47 | ### 48 | Client files (static resources) output directory. DO NOT MODIFY! 49 | ### 50 | PUBLIC_DIR = "#{__dirname}/public" 51 | 52 | ### 53 | Angular app output folder under PUBLIC_DIR 54 | ### 55 | ANGULAR_APP_OUT = "#{PUBLIC_DIR}/angular" 56 | 57 | ### 58 | Client scripts source folder other than angular files 59 | ### 60 | CLIENT_RESOURCES_SRC = "#{APP_DIR}/resources" 61 | 62 | ### 63 | Client scripts output folder other than angular files 64 | ### 65 | CLIENT_RESOURCES_OUT = "#{PUBLIC_DIR}/js" 66 | 67 | ### 68 | Styles source folder 69 | ### 70 | STYLES_SRC = "#{__dirname}/styles" 71 | 72 | ### 73 | Styles output filename 74 | ### 75 | STYLES_NAME = "espresso.css" 76 | 77 | ### 78 | Styles output folder 79 | ### 80 | STYLES_OUT = "#{PUBLIC_DIR}/styles" 81 | 82 | ### 83 | Compiles all APP_SRC directories and into ESPRESSO_DIR 84 | ### 85 | buildModule = -> 86 | options = "-c -b -o" 87 | compile SOURCES.COFFEE, "#{options} #{ESPRESSO_DIR}/#{input} #{APP_DIR}/#{input}" for input in APP_SRC 88 | compile SOURCES.COFFEE, "#{options} #{ESPRESSO_DIR} #{APP_DIR}/#{ESPRESSO_INDEX}" 89 | 90 | 91 | ### 92 | Compiles ESPRESSO_INDEX in the project root 93 | ### 94 | buildServer = -> 95 | options = "-c -b" 96 | compile SOURCES.COFFEE, "#{options} #{SERVER_FILENAME}" 97 | 98 | ### 99 | Compiles and uglifies client dirs 100 | ### 101 | buildClient = -> 102 | 103 | clientDirs = [ 104 | { 105 | type: SOURCES.COFFEE, 106 | output: "#{ANGULAR_APP_OUT}", 107 | input: "#{ANGULAR_APP_SRC}" 108 | }, 109 | { 110 | type: SOURCES.COFFEE, 111 | output: "#{CLIENT_RESOURCES_OUT}", 112 | input: "#{CLIENT_RESOURCES_SRC}" 113 | }, 114 | { 115 | type: SOURCES.LESS, 116 | output: "#{STYLES_OUT}", 117 | input: "#{STYLES_SRC}" 118 | } 119 | ] 120 | 121 | for dir in clientDirs 122 | do (dir) -> 123 | switch dir.type 124 | when SOURCES.COFFEE 125 | compile dir.type, "-c -b -o #{dir.output} #{dir.input}", -> 126 | uglifyDirectory dir.output 127 | when SOURCES.LESS 128 | compile dir.type, "-x #{dir.input}/*.less > #{dir.output}/#{STYLES_NAME}" 129 | 130 | ### 131 | Uglifies a directory 132 | @dir - Directory to be uglified 133 | ### 134 | uglifyDirectory = (dir) -> 135 | 136 | console.log "Uglifying #{dir}" 137 | 138 | fs.readdir dir, (err, files) -> 139 | return if err? 140 | for file in files 141 | do (file) -> 142 | fs.stat "#{dir}/#{file}", 143 | (err, stats) -> 144 | if err then throw err 145 | if stats? and stats.isDirectory() 146 | uglifyDirectory "#{dir}/#{file}" 147 | else 148 | uglifyFile "#{dir}/#{file}" 149 | 150 | ### 151 | Uglifies a file 152 | @file - File to be uglified 153 | ### 154 | uglifyFile = (file) -> 155 | 156 | result = uglifyjs.minify "#{file}" 157 | data = result.code 158 | 159 | fs.writeFile file, data, (err) -> 160 | if err 161 | throw err 162 | console.log "#{file} uglified" 163 | 164 | ### 165 | Deletes ESPRESSO_DIR 166 | ### 167 | cleanEspresso = (callback) -> 168 | 169 | dir = "#{__dirname}/#{ESPRESSO_DIR}" 170 | 171 | deleteDirectory dir, -> 172 | fs.rmdir dir, (err) -> 173 | if err 174 | throw err 175 | 176 | if callback then callback() 177 | 178 | ### 179 | Deletes ANGULAR_APP_OUT, CLIENT_RESOURCES_OUT, and STYLES_OUT 180 | ### 181 | cleanClient = (callback) -> 182 | 183 | clientDirs = [ 184 | "#{ANGULAR_APP_OUT}", 185 | "#{CLIENT_RESOURCES_OUT}", 186 | "#{STYLES_OUT}" 187 | ] 188 | 189 | for dir in clientDirs 190 | do (dir) -> 191 | deleteDirectory dir, -> 192 | fs.rmdir dir, (err) -> 193 | if err then throw err 194 | 195 | if callback then callback() 196 | 197 | ### 198 | Deletes a directory 199 | @dir - Directory to be deleted 200 | ### 201 | deleteDirectory = (dir) -> 202 | 203 | fs.readdir dir, (err, files) -> 204 | return if err? 205 | for file in files 206 | do (file) -> 207 | fs.stat "#{dir}/#{file}", 208 | (err, stats) -> 209 | if err then throw err 210 | if stats? and stats.isDirectory() 211 | deleteDirectory "#{dir}/#{file}" 212 | else 213 | deleteFile "#{dir}/#{file}" 214 | 215 | ### 216 | Deletes a file 217 | @file - File to be deleted 218 | ### 219 | deleteFile = (file) -> 220 | fs.unlink file, (err) -> 221 | if err 222 | throw err 223 | 224 | ### 225 | Executes a compilation command 226 | @type - Type of source (SOURCES.COFFEE or SOURCES.LESS) 227 | @options - Command options 228 | ### 229 | compile = (type, options, callback) -> 230 | switch type 231 | when SOURCES.COFFEE 232 | exec "coffee #{options}", {}, (error, stdout, stderr) -> 233 | if error 234 | console.log stderr.toString() 235 | throw error 236 | if callback then callback() 237 | when SOURCES.LESS 238 | exec "lessc #{options}", {}, (error, stdout, stderr) -> 239 | if error 240 | console.log stderr.toString() 241 | throw error 242 | if callback then callback() 243 | 244 | ### 245 | Tasks 246 | ### 247 | task "build", "Builds app", (callback) -> 248 | invoke "clean" 249 | console.log "Building module..." 250 | buildModule() 251 | console.log "Building client..." 252 | buildClient() 253 | console.log "Building server..." 254 | buildServer() 255 | 256 | task "build:module", "Builds the Espresso module", -> 257 | invoke "clean:module" 258 | console.log "Building module..." 259 | buildModule() 260 | console.log "Building server..." 261 | buildServer() 262 | 263 | task "build:client", "Builds client scripts", -> 264 | invoke "clean:client" 265 | console.log "Building client..." 266 | buildClient() 267 | 268 | task "clean", "Clean module and client", -> 269 | invoke "clean:module" 270 | invoke "clean:client" 271 | 272 | task "clean:module", "Cleans the Espresso module", -> 273 | cleanEspresso -> 274 | console.log "Module cleaned" 275 | 276 | task "clean:client", "Cleans the client", -> 277 | cleanClient -> 278 | console.log "Client cleaned" 279 | 280 | task "run", "Runs the app", -> 281 | console.log "App running, press ^C to quit" 282 | exec "node app", (err, stdout, stderr) -> 283 | if err 284 | console.log "Error starting the app. Run 'cake build' to make sure everything's good" 285 | throw err -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 William Mora 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 6 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 7 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 8 | and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all copies or substantial portions 11 | of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 14 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 16 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular Espresso 2 | 3 | Start an app with AngularJS on the client, Express + Node + Socket.IO as your back-end, all written in CoffeeScript. 4 | 5 | ## Current version 6 | 7 | Current version: 0.3.0 8 | 9 | This version includes the following components: 10 | 11 | * AngularJS 1.2.20 12 | * Twitter Bootstrap 3.2.0 13 | * Express 4.6.1 14 | * LESS 1.7.3 15 | * Socket.IO 1.0.6 16 | * Jade 1.4.2 17 | * UglifyJS 2.4.15 18 | * Body Parser 1.4.3 19 | * Serve Favicon 2.0.1 20 | 21 | ## Installation 22 | 23 | You need to have installed [node](http://nodejs.org/), [CoffeeScript](http://coffeescript.org/), make sure 24 | you install CoffeeScript globally. You also need [LESS](http://lesscss.org/). 25 | 26 | Once you have them installed, extract the downloaded file, go to the directory it was extracted to and execute 27 | setup.sh or setup.bat (depending on your OS): 28 | 29 | ## Cakefile Usage 30 | 31 | Once you install the dependencies, use the Cakefile for performing different actions: 32 | ``` 33 | cake build # Builds app 34 | cake build:module # Builds the Espresso module 35 | cake build:client # Builds client scripts 36 | cake clean # Clean module and client 37 | cake clean:module # Cleans the Espresso module 38 | cake clean:client # Cleans the client 39 | cake run # Runs the app (you should build first) 40 | ``` 41 | The typical usage would be: 42 | ``` 43 | cake build 44 | node app # or cake run 45 | ``` 46 | ## Configuration 47 | 48 | There's no configuration for using Angular Espresso, all you need to do is download the project, install its 49 | dependencies with npm and run your node app. 50 | 51 | Your .coffee files should be under the "app" folder. The project structure is the following: 52 | 53 | NOTE: Each directory has a README file with more detail 54 | 55 | * Angular: Your AngularJS app should go in this directory 56 | * Services: Backend logic goes here 57 | * Config: Configuration that may be used to set up different values for a specific environment or a common config 58 | * Routes: This directory should contain the routing functions for your views. Define an entry point for a major 59 | component of your site and then use partials for all its sub-components 60 | * Resources: Any client scripts not related to AngularJS 61 | 62 | At the root folder, there are two more folders to consider: 63 | 64 | * Styles: Your LESS styles should go in this directory. Keep in mind that the project has Twitter Bootstrap already 65 | included 66 | * Views: Your views/partial views should go here 67 | 68 | In the future, I will be adding support for testing. I won't implement file watching until it is stable in node. 69 | 70 | ## Contribute 71 | If you want to help, fork/clone/share the project, suggest new features, and/or submit pull requests. 72 | Contact me directly at [william.r.mora@gmail.com](mailto:william.r.mora@gmail.com) or [@_williammora](https://twitter.com/_williammora). 73 | 74 | ## Author 75 | William Mora - [@_williammora](https://twitter.com/_williammora) - http://www.williammora.com 76 | 77 | ## References 78 | 79 | For more on AngularJS: http://angularjs.org 80 | 81 | For more on CoffeeScript: http://coffeescript.org 82 | 83 | For more on Express: http://expressjs.com 84 | 85 | For more on Jade: http://jade-lang.com 86 | 87 | For more on Socket.IO: http://socket.io/ 88 | 89 | For more on LESS: http://lesscss.org/ 90 | -------------------------------------------------------------------------------- /app.coffee: -------------------------------------------------------------------------------- 1 | app = require "./.espresso" -------------------------------------------------------------------------------- /app/angular/README.md: -------------------------------------------------------------------------------- 1 | Angular 2 | ======= 3 | 4 | Your AngularJS app should go in this directory. 5 | 6 | All .coffee files in this directory will be compiled into minified .js files and sent to 7 | "public/angular" after a build. 8 | 9 | You can have whatever directory structure you want here, just keep in mind that these are client files. 10 | 11 | When writing your views, refer to these files as "/angular/filename.js" 12 | 13 | For more info, check out [AngularJS](http://angularjs.org/) 14 | 15 | You might want to read the section "A Note on Minification" in their tutorial at 16 | http://docs.angularjs.org/tutorial/step_05 -------------------------------------------------------------------------------- /app/angular/app.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | ### 4 | Declare app level module which depends on filters, services, and directives 5 | ### 6 | 7 | angular.module("myApp", ["ngRoute", "myApp.filters", "myApp.services", "myApp.directives"]) 8 | .config ["$routeProvider", 9 | ($routeProvider) -> 10 | $routeProvider.when "/home", {templateUrl: "partials/home", controller: UsersCtrl} 11 | $routeProvider.when "/user/:userId", {templateUrl: "partials/user", controller: UserDetailCtrl} 12 | $routeProvider.when "/socket", {templateUrl: "partials/socket", controller: SocketCtrl} 13 | $routeProvider.otherwise {redirectTo: "/home"} 14 | ] 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/angular/controllers.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | ### 4 | Controllers 5 | ### 6 | 7 | AppCtrl = ($scope) -> 8 | $scope.name = "Espresso" 9 | 10 | AppCtrl.$inject = ["$scope"] 11 | 12 | UsersCtrl = ($scope, User) -> 13 | $scope.loadUsers = -> 14 | $scope.users = {} 15 | User.list {} 16 | , (data) -> 17 | $scope.users = data.message 18 | 19 | UsersCtrl.$inject = ["$scope", "User"] 20 | 21 | UserDetailCtrl = ($scope, $routeParams, User) -> 22 | $scope.user = 23 | User.get {userId: $routeParams.userId} 24 | , (data) -> 25 | $scope.user = data.user 26 | 27 | UserDetailCtrl.$inject = ["$scope", "$routeParams", "User"] 28 | 29 | SocketCtrl = ($scope, Socket) -> 30 | 31 | Socket.on "pong", (data) -> 32 | $scope.response = data.data 33 | 34 | $scope.ping = -> 35 | Socket.emit("ping", {}) 36 | 37 | SocketCtrl.$inject = ["$scope", "Socket"] -------------------------------------------------------------------------------- /app/angular/directives.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | ### 4 | Directives 5 | ### 6 | 7 | angular.module("myApp.directives", ["ngResource"]) 8 | .directive "appVersion", ["version", (version) -> 9 | (scope, elm, attrs) -> 10 | elm.text version 11 | ] 12 | -------------------------------------------------------------------------------- /app/angular/filters.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | ### 4 | Filters 5 | ### 6 | 7 | angular.module("myApp.filters", []) 8 | .filter "title", 9 | -> 10 | (user) -> 11 | "#{user.id} - #{user.name}" -------------------------------------------------------------------------------- /app/angular/services.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | ### 4 | Services 5 | ### 6 | 7 | socketServer = document.domain 8 | 9 | angular.module("myApp.services", []) 10 | .value("version", "0.3.0") 11 | .factory("Socket", 12 | ["$rootScope", 13 | ($rootScope) -> 14 | 15 | socketService = {} 16 | 17 | socket = io.connect(socketServer) 18 | 19 | socketService.emit = (event, data) -> 20 | socket.emit event, data 21 | 22 | socketService.on = (event, callback) -> 23 | socket.on event, (data) -> 24 | $rootScope.$apply -> 25 | callback data 26 | 27 | socketService 28 | ] 29 | ) 30 | .factory "User", 31 | ["$resource", 32 | ($resource) -> 33 | 34 | url = "/users/:userId" 35 | 36 | $resource url, {}, { 37 | 38 | list: {method: "GET", params: {userId: ""}}, 39 | get: {method: "GET", params: {}} 40 | 41 | } 42 | ] -------------------------------------------------------------------------------- /app/config/README.md: -------------------------------------------------------------------------------- 1 | Config 2 | ====== 3 | 4 | A simple configuration file (index.coffee) that may be used to set up different values for a specific environment 5 | or a common config -------------------------------------------------------------------------------- /app/config/index.coffee: -------------------------------------------------------------------------------- 1 | exports.setEnv = (environment) -> 2 | 3 | ### 4 | Common config 5 | ### 6 | exports.HOSTNAME = "localhost" 7 | exports.PORT = 8080 8 | exports.PUBLIC_PATH = "public" 9 | exports.VIEWS_ENGINE = "jade" 10 | exports.VIEWS_PATH = "views" 11 | exports.IMAGES_PATH = "images" 12 | 13 | ### 14 | Environment specific config 15 | ### 16 | switch environment 17 | when "development" 18 | null 19 | 20 | when "testing" 21 | null 22 | 23 | when "production" 24 | null 25 | 26 | else 27 | console.log "Unknown environment #{environment}!" 28 | -------------------------------------------------------------------------------- /app/index.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | Module dependencies. 3 | ### 4 | 5 | config = require "./config" 6 | express = require "express" 7 | path = require "path" 8 | routes = require "./routes" 9 | bodyParser = require "body-parser" 10 | favicon = require "serve-favicon" 11 | 12 | app = express() 13 | 14 | ### 15 | Configuration 16 | ### 17 | 18 | env = process.env.NODE_ENV || "development" 19 | config.setEnv app.settings.env 20 | 21 | app.set "ipaddr", config.HOSTNAME 22 | app.set "port", config.PORT 23 | app.set "views", path.join process.cwd(), config.VIEWS_PATH 24 | app.set "view engine", config.VIEWS_ENGINE 25 | app.use bodyParser.json() 26 | app.use bodyParser.urlencoded({extended: true}) 27 | app.use favicon("#{process.cwd()}/#{config.PUBLIC_PATH}/#{config.IMAGES_PATH}/favicon.ico") 28 | app.use express["static"] path.join process.cwd(), config.PUBLIC_PATH 29 | 30 | ### 31 | Routes config 32 | ### 33 | 34 | # Views 35 | app.get "/", routes.index 36 | app.get "/partials/:name", routes.partials 37 | 38 | # Services 39 | users = require "./services/users" 40 | app.get "/users", users.list 41 | app.get "/users/:id", users.get 42 | 43 | ### 44 | Server startup 45 | ### 46 | 47 | serverStarted = -> 48 | console.log "Server listening on http://#{app.get "ipaddr"}:#{app.get "port"}" 49 | 50 | server = app.listen app.get('port'), app.get('ipaddr'), serverStarted 51 | 52 | ### 53 | Socket.IO registration and configuration 54 | ### 55 | 56 | io = require("socket.io").listen server 57 | require("./socket").configure io 58 | 59 | ### 60 | Export server 61 | ### 62 | 63 | module.exports = server -------------------------------------------------------------------------------- /app/resources/README.md: -------------------------------------------------------------------------------- 1 | Resources 2 | ========= 3 | 4 | This directory should be used for adding any client scripts not related to AngularJS such as front-end scripts using 5 | jQuery or other libraries. 6 | 7 | All scripts in this directory will be compiled into minified .js files and sent to "public/js" after a build 8 | 9 | Note that this directory has been added to this project template for convenience, but all your client logic should be 10 | done with AngularJS. If you are still feeling tempted to write the DOM manipulation you are used to, refer to 11 | the "Common Pitfalls" section in the [FAQs](http://docs.angularjs.org/misc/faq) section of AngularJS. -------------------------------------------------------------------------------- /app/routes/README.md: -------------------------------------------------------------------------------- 1 | Routes 2 | ====== 3 | 4 | This directory should contain the routing functions for your views. It already has a route for an index view and for 5 | all partial views. You should leave those two alone. 6 | 7 | The idea is that you define an entry point for a major component of your site and then use partials for all its 8 | sub-components. -------------------------------------------------------------------------------- /app/routes/index.coffee: -------------------------------------------------------------------------------- 1 | 2 | ### 3 | GET home page 4 | ### 5 | 6 | exports.index = (request, response) -> 7 | response.render "index" 8 | 9 | ### 10 | GET partial templates 11 | ### 12 | 13 | exports.partials = (request, response) -> 14 | response.render "partials/" + request.params.name -------------------------------------------------------------------------------- /app/services/README.md: -------------------------------------------------------------------------------- 1 | Services 2 | ======== 3 | 4 | Your backend logic goes here. Whether it is a proxy for existing web services or your own web services to be 5 | consumed by AngularJS, you should handle them here. 6 | 7 | There is a file called "users.coffee" that you may use as a guide. -------------------------------------------------------------------------------- /app/services/users.coffee: -------------------------------------------------------------------------------- 1 | user1 = { id: "1", name: "John Doe", email: "jodoe@email.com" } 2 | user2 = { id: "2", name: "Jane Doe", email: "jadoe@email.com" } 3 | users = [user1, user2] 4 | 5 | user = module.exports = { 6 | 7 | list: (request, response) -> 8 | ### 9 | List all users 10 | ### 11 | response.json 200, { message: users } 12 | , 13 | get: (request, response) -> 14 | ### 15 | Return a single user 16 | ### 17 | id = request.params.id 18 | if not id 19 | return response.json 400, {error: "Missing user id"} 20 | 21 | switch id 22 | when "1" 23 | return response.json 200, {user: user1} 24 | when "2" 25 | return response.json 200, {user: user2} 26 | else 27 | return response.json 404, {error: "User not found"} 28 | } -------------------------------------------------------------------------------- /app/socket/README.md: -------------------------------------------------------------------------------- 1 | Socket 2 | ====== 3 | 4 | This directory configures the socket.io server. You should add all events that the server is listening to. 5 | 6 | The socket.io server is already registered in ../index.coffee, no need to do anything else. 7 | 8 | An event, "pong", is already configured as an example. -------------------------------------------------------------------------------- /app/socket/index.coffee: -------------------------------------------------------------------------------- 1 | exports.configure = (io) -> 2 | 3 | ### 4 | Socket.IO config 5 | ### 6 | 7 | io.on "connection", (socket) -> 8 | console.log "New socket connected!" 9 | 10 | socket.on "ping", -> 11 | time = new Date() 12 | io.sockets.emit "pong", {data: "pong! Time is #{time.toString()}"} 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-espresso", 3 | "description": "A project template for an AngularJS app with an Express, Socket.IO backend written in CoffeeScript", 4 | "version": "0.3.0", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/wmora/angular-espresso.git" 8 | }, 9 | "author": "William Mora ", 10 | "contributors": [ 11 | { 12 | "name": "William Mora", 13 | "email": "william.r.mora@gmail.com" 14 | } 15 | ], 16 | "keywords": [ 17 | "node", 18 | "express", 19 | "coffeescript", 20 | "socket.io" 21 | ], 22 | "dependencies": { 23 | "express": "4.6.1", 24 | "jade": "1.4.2", 25 | "socket.io": "1.0.6", 26 | "uglify-js": "2.4.15", 27 | "body-parser": "1.4.3", 28 | "serve-favicon": "2.0.1" 29 | }, 30 | "engines": { 31 | "node": ">=0.8" 32 | }, 33 | "scripts": { 34 | "start": "node app" 35 | } 36 | } -------------------------------------------------------------------------------- /public/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wmora/angular-espresso/ccff075f7a99a72d3c690a8e9dbba6af7530b5cf/public/images/favicon.ico -------------------------------------------------------------------------------- /setup.bat: -------------------------------------------------------------------------------- 1 | echo "Installing node modules..." 2 | npm install 3 | 4 | echo "Setting up required folders..." 5 | mkdir public\styles 6 | 7 | echo "Removing unnecessary stuff..." 8 | del .gitignore 9 | del README.md 10 | 11 | echo "Building project..." 12 | cake build 13 | 14 | echo "Done! now run your project with 'node app' or 'cake run' and build something awesome!" -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo "Installing node modules..." 3 | npm install 4 | 5 | echo "Setting up required folders..." 6 | mkdir public/styles 7 | 8 | echo "Removing unnecessary stuff..." 9 | rm .gitignore 10 | rm README.md 11 | 12 | echo "Building project..." 13 | cake build 14 | 15 | echo "Done! now run your project with 'node app' or 'cake run' and build something awesome!" -------------------------------------------------------------------------------- /styles/README.md: -------------------------------------------------------------------------------- 1 | Your LESS styles should go here. 2 | 3 | Remember that this project already includes Twitter Bootstrap. 4 | 5 | All files in this directory will be minified and sent to /public/styles/espresso.css. 6 | 7 | If you wish to change the .css filename, you can do so by modifying the project's Cakefile. -------------------------------------------------------------------------------- /styles/espresso.less: -------------------------------------------------------------------------------- 1 | @nice-blue: #5B83AD; 2 | 3 | #header { color: @nice-blue; } -------------------------------------------------------------------------------- /views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | div.jumbotron 5 | 6 | h1 Welcome to Angular Espresso 7 | 8 | div.lead(ng-controller='AppCtrl') Hello, {{name}} 9 | span.lead Click on one of the options below to test the project 10 | br 11 | ul 12 | li 13 | a(href='#/home') User listing, details 14 | li 15 | a(href='#/socket') Socket server 16 | hr 17 | div(ng-view) 18 | 19 | div 20 | | Angular Espresso, version   21 | span(app-version) 22 | 23 | script(src='//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js') 24 | script(src='//cdn.socket.io/socket.io-1.0.6.js') 25 | script(src='//ajax.googleapis.com/ajax/libs/angularjs/1.2.20/angular.js') 26 | script(src='//ajax.googleapis.com/ajax/libs/angularjs/1.2.20/angular-resource.min.js') 27 | script(src='//ajax.googleapis.com/ajax/libs/angularjs/1.2.20/angular-route.min.js') 28 | script(src='/angular/app.js') 29 | script(src='/angular/services.js') 30 | script(src='/angular/controllers.js') 31 | script(src='/angular/filters.js') 32 | script(src='/angular/directives.js') -------------------------------------------------------------------------------- /views/layout.jade: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | meta(charset="utf-8") 5 | meta(name="vierport", content="width=device-width, initial-scale=1") 6 | title Angular Espresso 7 | link(rel="stylesheet", href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css") 8 | body(ng-app="myApp") 9 | block content -------------------------------------------------------------------------------- /views/partials/home.jade: -------------------------------------------------------------------------------- 1 | h2 User Listing, Details 2 | 3 | p Click to load all users 4 | input.btn.btn-primary(type="button", ng-click="loadUsers()", value="Load!") 5 | br 6 | br 7 | p(ng-show="users && users.length > 1") Filter results:  8 | input(ng-model="narrow") 9 | 10 | ul 11 | li(ng-repeat="user in users | filter: narrow") 12 | p 13 | a(href="#/user/{{user.id}}") {{ user | title }} 14 | -------------------------------------------------------------------------------- /views/partials/socket.jade: -------------------------------------------------------------------------------- 1 | h2 Socket.IO 2 | 3 | p Click on the button to emit an event 4 | input.btn.btn-primary(type="button", ng-click="ping()", value="Ping!") 5 | br 6 | br 7 | p.lead {{ response }} 8 | -------------------------------------------------------------------------------- /views/partials/user.jade: -------------------------------------------------------------------------------- 1 | h2 {{user.name}} 2 | p.lead ID: {{user.id}} 3 | p 4 | | Email: {{user.email}}   5 | a(href="mailto:{{user.email}}") (Email me!) 6 | 7 | --------------------------------------------------------------------------------