├── .bowerrc
├── .buildignore
├── .editorconfig
├── .gitattributes
├── .gitignore
├── .travis.yml
├── .yo-rc.json
├── Gruntfile.js
├── README.md
├── bower.json
├── client
├── .htaccess
├── .jshintrc
├── app
│ ├── account
│ │ ├── account.js
│ │ ├── changePassword
│ │ │ ├── changePassword.controller.js
│ │ │ └── changePassword.html
│ │ ├── forgotPassword
│ │ │ ├── forgotPassword.controller.js
│ │ │ └── forgotPassword.html
│ │ ├── login
│ │ │ ├── login.controller.js
│ │ │ └── login.html
│ │ └── signUp
│ │ │ ├── signUp.controller.js
│ │ │ └── signUp.html
│ ├── app.js
│ ├── app.scss
│ ├── home
│ │ ├── home.controller.js
│ │ ├── home.html
│ │ └── home.js
│ ├── interceptor.js
│ └── landing
│ │ ├── landing.controller.js
│ │ ├── landing.html
│ │ └── landing.js
├── assets
│ └── images
│ │ └── yeoman.png
├── components
│ ├── api-services
│ │ └── user
│ │ │ └── user.service.js
│ ├── auth
│ │ └── auth.service.js
│ ├── config
│ │ └── config.js
│ ├── constants
│ │ └── constants.js
│ ├── footer
│ │ ├── footer.directive.js
│ │ └── footer.html
│ ├── header
│ │ ├── header.controller.js
│ │ ├── header.directive.js
│ │ └── header.html
│ ├── loader
│ │ └── loader.service.js
│ ├── messages
│ │ └── messages.js
│ ├── modal
│ │ ├── modal.controller.js
│ │ ├── modal.css
│ │ ├── modal.service.js
│ │ ├── popUp.html
│ │ └── views
│ │ │ ├── error.html
│ │ │ └── success.html
│ └── util
│ │ └── helper.js
├── favicon.ico
├── index.html
├── robots.txt
└── test
│ ├── account
│ ├── forgotPassword
│ │ └── forgotPassword.controller.spec.js
│ ├── login
│ │ └── login.controller.spec.js
│ ├── setPassword
│ │ └── setPassword.controller.spec.js
│ └── signup
│ │ └── signup.controller.spec.js
│ ├── home
│ └── home.controller.spec.js
│ ├── landing
│ └── landing.controller.spec.js
│ └── mocked.data.js
├── e2e
└── main
│ ├── main.po.js
│ └── main.spec.js
├── karma.conf.js
├── package.json
├── protractor.conf.js
└── server
└── app.js
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "client/bower_components"
3 | }
4 |
--------------------------------------------------------------------------------
/.buildignore:
--------------------------------------------------------------------------------
1 | *.coffee
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 |
8 | [*]
9 |
10 | # Change these settings to your own preference
11 | indent_style = space
12 | indent_size = 2
13 |
14 | # We recommend you to keep these unchanged
15 | end_of_line = lf
16 | charset = utf-8
17 | trim_trailing_whitespace = true
18 | insert_final_newline = true
19 |
20 | [*.md]
21 | trim_trailing_whitespace = false
22 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/princesoni1989/angular-js-seed/2e8338075f6c03f6204dab1a73f357a48d16da5e/.gitattributes
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | public
3 | .tmp
4 | .sass-cache
5 | .idea
6 | client/bower_components
7 | dist
8 | npm-debug.log
9 | coverage
10 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - '0.10'
4 | - '0.11'
5 | before_script:
6 | - npm install -g bower grunt-cli
7 | - gem install sass
8 | - bower install
9 |
--------------------------------------------------------------------------------
/.yo-rc.json:
--------------------------------------------------------------------------------
1 | {
2 | "generator-angular-fullstack": {
3 | "insertRoutes": true,
4 | "registerRoutesFile": "server/routes.js",
5 | "routesNeedle": "// Insert routes below",
6 | "routesBase": "/api/",
7 | "pluralizeRoutes": true,
8 | "insertSockets": true,
9 | "registerSocketsFile": "server/config/socketio.js",
10 | "socketsNeedle": "// Insert sockets below",
11 | "filters": {
12 | "babel": false,
13 | "js": true,
14 | "html": true,
15 | "sass": true,
16 | "uirouter": true,
17 | "bootstrap": true,
18 | "uibootstrap": true,
19 | "mongoose": true,
20 | "auth": true
21 | }
22 | },
23 | "generator-ng-component": {
24 | "routeDirectory": "client/app/",
25 | "directiveDirectory": "client/app/",
26 | "filterDirectory": "client/app/",
27 | "serviceDirectory": "client/app/",
28 | "basePath": "client",
29 | "moduleName": "",
30 | "filters": [
31 | "uirouter"
32 | ],
33 | "extensions": [
34 | "js",
35 | "html",
36 | "scss"
37 | ],
38 | "directiveSimpleTemplates": "",
39 | "directiveComplexTemplates": "",
40 | "filterTemplates": "",
41 | "serviceTemplates": "",
42 | "factoryTemplates": "",
43 | "controllerTemplates": "",
44 | "decoratorTemplates": "",
45 | "providerTemplates": "",
46 | "routeTemplates": ""
47 | }
48 | }
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | // Generated on 2016-05-28 using generator-angular-fullstack 2.1.1
2 | 'use strict';
3 |
4 | module.exports = function (grunt) {
5 | var localConfig;
6 | try {
7 | localConfig = require('./server/config/local.env');
8 | } catch(e) {
9 | localConfig = {};
10 | }
11 |
12 | // Load grunt tasks automatically, when needed
13 | require('jit-grunt')(grunt, {
14 | express: 'grunt-express-server',
15 | useminPrepare: 'grunt-usemin',
16 | ngtemplates: 'grunt-angular-templates',
17 | cdnify: 'grunt-google-cdn',
18 | protractor: 'grunt-protractor-runner',
19 | buildcontrol: 'grunt-build-control'
20 | });
21 |
22 | // Time how long tasks take. Can help when optimizing build times
23 | require('time-grunt')(grunt);
24 |
25 | // Define the configuration for all the tasks
26 | grunt.initConfig({
27 |
28 | // Project settings
29 | pkg: grunt.file.readJSON('package.json'),
30 | yeoman: {
31 | // configurable paths
32 | client: require('./bower.json').appPath || 'client',
33 | dist: 'dist'
34 | },
35 | express: {
36 | options: {
37 | port: process.env.PORT || 9000
38 | },
39 | dev: {
40 | options: {
41 | script: 'server/app.js',
42 | debug: true
43 | }
44 | },
45 | prod: {
46 | options: {
47 | script: 'dist/server/app.js'
48 | }
49 | }
50 | },
51 | open: {
52 | server: {
53 | url: 'http://localhost:<%= express.options.port %>'
54 | }
55 | },
56 | watch: {
57 | injectJS: {
58 | files: [
59 | '<%= yeoman.client %>/{app,components}/**/*.js',
60 | '!<%= yeoman.client %>/{app,components}/**/*.spec.js',
61 | '!<%= yeoman.client %>/{app,components}/**/*.mock.js',
62 | '!<%= yeoman.client %>/app/app.js'],
63 | tasks: ['injector:scripts']
64 | },
65 | injectCss: {
66 | files: [
67 | '<%= yeoman.client %>/{app,components}/**/*.css'
68 | ],
69 | tasks: ['injector:css']
70 | },
71 | jsTest: {
72 | files: [
73 | '<%= yeoman.client %>/{app,components}/**/*.spec.js',
74 | '<%= yeoman.client %>/{app,components}/**/*.mock.js'
75 | ],
76 | tasks: ['newer:jshint:all', 'karma']
77 | },
78 | injectSass: {
79 | files: [
80 | '<%= yeoman.client %>/{app,components}/**/*.{scss,sass}'],
81 | tasks: ['injector:sass']
82 | },
83 | sass: {
84 | files: [
85 | '<%= yeoman.client %>/{app,components}/**/*.{scss,sass}'],
86 | tasks: ['sass', 'autoprefixer']
87 | },
88 | gruntfile: {
89 | files: ['Gruntfile.js']
90 | },
91 | livereload: {
92 | files: [
93 | '{.tmp,<%= yeoman.client %>}/{app,components}/**/*.css',
94 | '{.tmp,<%= yeoman.client %>}/{app,components}/**/*.html',
95 |
96 | '{.tmp,<%= yeoman.client %>}/{app,components}/**/*.js',
97 |
98 | '!{.tmp,<%= yeoman.client %>}{app,components}/**/*.spec.js',
99 | '!{.tmp,<%= yeoman.client %>}/{app,components}/**/*.mock.js',
100 | '<%= yeoman.client %>/assets/images/{,*//*}*.{png,jpg,jpeg,gif,webp,svg}'
101 | ],
102 | options: {
103 | livereload: true
104 | }
105 | },
106 | express: {
107 | files: [
108 | 'server/**/*.{js,json}'
109 | ],
110 | tasks: ['express:dev', 'wait'],
111 | options: {
112 | livereload: true,
113 | nospawn: true //Without this option specified express won't be reloaded
114 | }
115 | }
116 | },
117 |
118 | // Make sure code styles are up to par and there are no obvious mistakes
119 | jshint: {
120 | options: {
121 | jshintrc: '<%= yeoman.client %>/.jshintrc',
122 | reporter: require('jshint-stylish')
123 | },
124 | server: {
125 | options: {
126 | jshintrc: 'server/.jshintrc'
127 | },
128 | src: [
129 | 'server/**/*.js',
130 | '!server/**/*.spec.js'
131 | ]
132 | },
133 | serverTest: {
134 | options: {
135 | jshintrc: 'server/.jshintrc-spec'
136 | },
137 | src: ['server/**/*.spec.js']
138 | },
139 | all: [
140 | '<%= yeoman.client %>/{app,components}/**/*.js',
141 | '!<%= yeoman.client %>/{app,components}/**/*.spec.js',
142 | '!<%= yeoman.client %>/{app,components}/**/*.mock.js'
143 | ],
144 | test: {
145 | src: [
146 | '<%= yeoman.client %>/{app,components}/**/*.spec.js',
147 | '<%= yeoman.client %>/{app,components}/**/*.mock.js'
148 | ]
149 | }
150 | },
151 |
152 | // Empties folders to start fresh
153 | clean: {
154 | dist: {
155 | files: [{
156 | dot: true,
157 | src: [
158 | '.tmp',
159 | '<%= yeoman.dist %>/*',
160 | '!<%= yeoman.dist %>/.git*',
161 | '!<%= yeoman.dist %>/.openshift',
162 | '!<%= yeoman.dist %>/Procfile'
163 | ]
164 | }]
165 | },
166 | server: '.tmp'
167 | },
168 |
169 | // Add vendor prefixed styles
170 | autoprefixer: {
171 | options: {
172 | browsers: ['last 1 version']
173 | },
174 | dist: {
175 | files: [{
176 | expand: true,
177 | cwd: '.tmp/',
178 | src: '{,*/}*.css',
179 | dest: '.tmp/'
180 | }]
181 | }
182 | },
183 |
184 | // Debugging with node inspector
185 | 'node-inspector': {
186 | custom: {
187 | options: {
188 | 'web-host': 'localhost'
189 | }
190 | }
191 | },
192 |
193 | // Use nodemon to run server in debug mode with an initial breakpoint
194 | nodemon: {
195 | debug: {
196 | script: 'server/app.js',
197 | options: {
198 | nodeArgs: ['--debug-brk'],
199 | env: {
200 | PORT: process.env.PORT || 9000
201 | },
202 | callback: function (nodemon) {
203 | nodemon.on('log', function (event) {
204 | console.log(event.colour);
205 | });
206 |
207 | // opens browser on initial server start
208 | nodemon.on('config:update', function () {
209 | setTimeout(function () {
210 | require('open')('http://localhost:8080/debug?port=5858');
211 | }, 500);
212 | });
213 | }
214 | }
215 | }
216 | },
217 |
218 | // Automatically inject Bower components into the app
219 | wiredep: {
220 | target: {
221 | src: '<%= yeoman.client %>/index.html',
222 | ignorePath: '<%= yeoman.client %>/',
223 | exclude: [/bootstrap-sass-official/, /bootstrap.js/, '/json3/', '/es5-shim/', /bootstrap.css/, /font-awesome.css/ ]
224 | }
225 | },
226 |
227 | // Renames files for browser caching purposes
228 | rev: {
229 | dist: {
230 | files: {
231 | src: [
232 | '<%= yeoman.dist %>/client/{,*/}*.js',
233 | '<%= yeoman.dist %>/client/{,*/}*.css',
234 | '<%= yeoman.dist %>/client/assets/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
235 | '<%= yeoman.dist %>/client/assets/fonts/*'
236 | ]
237 | }
238 | }
239 | },
240 |
241 | // Reads HTML for usemin blocks to enable smart builds that automatically
242 | // concat, minify and revision files. Creates configurations in memory so
243 | // additional tasks can operate on them
244 | useminPrepare: {
245 | html: ['<%= yeoman.client %>/index.html'],
246 | options: {
247 | dest: '<%= yeoman.dist %>/client'
248 | }
249 | },
250 |
251 | // Performs rewrites based on rev and the useminPrepare configuration
252 | usemin: {
253 | html: ['<%= yeoman.dist %>/client/{,*/}*.html'],
254 | css: ['<%= yeoman.dist %>/client/{,*/}*.css'],
255 | js: ['<%= yeoman.dist %>/client/{,*/}*.js'],
256 | options: {
257 | assetsDirs: [
258 | '<%= yeoman.dist %>/client',
259 | '<%= yeoman.dist %>/client/assets/images'
260 | ],
261 | // This is so we update image references in our ng-templates
262 | patterns: {
263 | js: [
264 | [/(assets\/images\/.*?\.(?:gif|jpeg|jpg|png|webp|svg))/gm, 'Update the JS to reference our revved images']
265 | ]
266 | }
267 | }
268 | },
269 |
270 | // The following *-min tasks produce minified files in the dist folder
271 | imagemin: {
272 | dist: {
273 | files: [{
274 | expand: true,
275 | cwd: '<%= yeoman.client %>/assets/images',
276 | src: '{,*/}*.{png,jpg,jpeg,gif}',
277 | dest: '<%= yeoman.dist %>/client/assets/images'
278 | }]
279 | }
280 | },
281 |
282 | svgmin: {
283 | dist: {
284 | files: [{
285 | expand: true,
286 | cwd: '<%= yeoman.client %>/assets/images',
287 | src: '{,*/}*.svg',
288 | dest: '<%= yeoman.dist %>/client/assets/images'
289 | }]
290 | }
291 | },
292 |
293 | // Allow the use of non-minsafe AngularJS files. Automatically makes it
294 | // minsafe compatible so Uglify does not destroy the ng references
295 | ngAnnotate: {
296 | dist: {
297 | files: [{
298 | expand: true,
299 | cwd: '.tmp/concat',
300 | src: '**/*.js',
301 | dest: '.tmp/concat'
302 | }]
303 | }
304 | },
305 |
306 | // Package all the html partials into a single javascript payload
307 | ngtemplates: {
308 | options: {
309 | // This should be the name of your apps angular module
310 | module: 'angularJsSeedApp',
311 | htmlmin: {
312 | collapseBooleanAttributes: true,
313 | collapseWhitespace: true,
314 | removeAttributeQuotes: true,
315 | removeEmptyAttributes: true,
316 | removeRedundantAttributes: true,
317 | removeScriptTypeAttributes: true,
318 | removeStyleLinkTypeAttributes: true
319 | },
320 | usemin: 'app/app.js'
321 | },
322 | main: {
323 | cwd: '<%= yeoman.client %>',
324 | src: ['{app,components}/**/*.html'],
325 | dest: '.tmp/templates.js'
326 | },
327 | tmp: {
328 | cwd: '.tmp',
329 | src: ['{app,components}/**/*.html'],
330 | dest: '.tmp/tmp-templates.js'
331 | }
332 | },
333 |
334 | // Replace Google CDN references
335 | cdnify: {
336 | dist: {
337 | html: ['<%= yeoman.dist %>/client/*.html']
338 | }
339 | },
340 |
341 | // Copies remaining files to places other tasks can use
342 | copy: {
343 | dist: {
344 | files: [{
345 | expand: true,
346 | dot: true,
347 | cwd: '<%= yeoman.client %>',
348 | dest: '<%= yeoman.dist %>/client',
349 | src: [
350 | '*.{ico,png,txt}',
351 | '.htaccess',
352 | 'bower_components/**/*',
353 | 'assets/images/{,*/}*.{webp}',
354 | 'assets/fonts/**/*',
355 | 'index.html'
356 | ]
357 | }, {
358 | expand: true,
359 | cwd: '.tmp/images',
360 | dest: '<%= yeoman.dist %>/client/assets/images',
361 | src: ['generated/*']
362 | }, {
363 | expand: true,
364 | dest: '<%= yeoman.dist %>',
365 | src: [
366 | 'package.json',
367 | 'server/**/*'
368 | ]
369 | }]
370 | },
371 | styles: {
372 | expand: true,
373 | cwd: '<%= yeoman.client %>',
374 | dest: '.tmp/',
375 | src: ['{app,components}/**/*.css']
376 | }
377 | },
378 |
379 | buildcontrol: {
380 | options: {
381 | dir: 'dist',
382 | commit: true,
383 | push: true,
384 | connectCommits: false,
385 | message: 'Built %sourceName% from commit %sourceCommit% on branch %sourceBranch%'
386 | },
387 | heroku: {
388 | options: {
389 | remote: 'heroku',
390 | branch: 'master'
391 | }
392 | },
393 | openshift: {
394 | options: {
395 | remote: 'openshift',
396 | branch: 'master'
397 | }
398 | }
399 | },
400 |
401 | // Run some tasks in parallel to speed up the build process
402 | concurrent: {
403 | server: [
404 | 'sass',
405 | ],
406 | test: [
407 | 'sass',
408 | ],
409 | debug: {
410 | tasks: [
411 | 'nodemon',
412 | 'node-inspector'
413 | ],
414 | options: {
415 | logConcurrentOutput: true
416 | }
417 | },
418 | dist: [
419 | 'sass',
420 | 'imagemin',
421 | 'svgmin'
422 | ]
423 | },
424 |
425 | // Test settings
426 | karma: {
427 | unit: {
428 | configFile: 'karma.conf.js',
429 | singleRun: true
430 | }
431 | },
432 | protractor: {
433 | options: {
434 | configFile: 'protractor.conf.js'
435 | },
436 | chrome: {
437 | options: {
438 | args: {
439 | browser: 'chrome'
440 | }
441 | }
442 | }
443 | },
444 |
445 | env: {
446 | test: {
447 | NODE_ENV: 'test'
448 | },
449 | prod: {
450 | NODE_ENV: 'production'
451 | },
452 | all: localConfig
453 | },
454 |
455 | // Compiles Sass to CSS
456 | sass: {
457 | server: {
458 | options: {
459 | loadPath: [
460 | '<%= yeoman.client %>/bower_components',
461 | '<%= yeoman.client %>/app',
462 | '<%= yeoman.client %>/components'
463 | ],
464 | compass: false
465 | },
466 | files: {
467 | '.tmp/app/app.css' : '<%= yeoman.client %>/app/app.scss'
468 | }
469 | }
470 | },
471 |
472 | injector: {
473 | options: {
474 |
475 | },
476 | // Inject application script files into index.html (doesn't include bower)
477 | scripts: {
478 | options: {
479 | transform: function(filePath) {
480 | filePath = filePath.replace('/client/', '');
481 | filePath = filePath.replace('/.tmp/', '');
482 | return '';
483 | },
484 | starttag: '',
485 | endtag: ''
486 | },
487 | files: {
488 | '<%= yeoman.client %>/index.html': [
489 | [
490 |
491 | '{.tmp,<%= yeoman.client %>}/{app,components}/**/*.js',
492 |
493 | '!{.tmp,<%= yeoman.client %>}/app/app.js',
494 | '!{.tmp,<%= yeoman.client %>}/{app,components}/**/*.spec.js',
495 | '!{.tmp,<%= yeoman.client %>}/{app,components}/**/*.mock.js'
496 | ]
497 | ]
498 | }
499 | },
500 |
501 | // Inject component scss into app.scss
502 | sass: {
503 | options: {
504 | transform: function(filePath) {
505 | filePath = filePath.replace('/client/app/', '');
506 | filePath = filePath.replace('/client/components/', '');
507 | return '@import \'' + filePath + '\';';
508 | },
509 | starttag: '// injector',
510 | endtag: '// endinjector'
511 | },
512 | files: {
513 | '<%= yeoman.client %>/app/app.scss': [
514 | '<%= yeoman.client %>/{app,components}/**/*.{scss,sass}',
515 | '!<%= yeoman.client %>/app/app.{scss,sass}'
516 | ]
517 | }
518 | },
519 |
520 | // Inject component css into index.html
521 | css: {
522 | options: {
523 | transform: function(filePath) {
524 | filePath = filePath.replace('/client/', '');
525 | filePath = filePath.replace('/.tmp/', '');
526 | return '';
527 | },
528 | starttag: '',
529 | endtag: ''
530 | },
531 | files: {
532 | '<%= yeoman.client %>/index.html': [
533 | '<%= yeoman.client %>/{app,components}/**/*.css'
534 | ]
535 | }
536 | }
537 | },
538 | });
539 |
540 | // Used for delaying livereload until after server has restarted
541 | grunt.registerTask('wait', function () {
542 | grunt.log.ok('Waiting for server reload...');
543 |
544 | var done = this.async();
545 |
546 | setTimeout(function () {
547 | grunt.log.writeln('Done waiting!');
548 | done();
549 | }, 1500);
550 | });
551 |
552 | grunt.registerTask('express-keepalive', 'Keep grunt running', function() {
553 | this.async();
554 | });
555 |
556 | grunt.registerTask('serve', function (target) {
557 | if (target === 'dist') {
558 | return grunt.task.run(['build', 'env:all', 'env:prod', 'express:prod', 'wait', 'open', 'express-keepalive']);
559 | }
560 |
561 | if (target === 'debug') {
562 | return grunt.task.run([
563 | 'clean:server',
564 | 'env:all',
565 | 'injector:sass',
566 | 'concurrent:server',
567 | 'injector',
568 | 'wiredep',
569 | 'autoprefixer',
570 | 'concurrent:debug'
571 | ]);
572 | }
573 |
574 | grunt.task.run([
575 | 'clean:server',
576 | 'env:all',
577 | 'injector:sass',
578 | 'concurrent:server',
579 | 'injector',
580 | 'wiredep',
581 | 'autoprefixer',
582 | 'express:dev',
583 | 'wait',
584 | 'open',
585 | 'watch'
586 | ]);
587 | });
588 |
589 | grunt.registerTask('server', function () {
590 | grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
591 | grunt.task.run(['serve']);
592 | });
593 |
594 | grunt.registerTask('test', function(target) {
595 | if (target === 'server') {
596 | return grunt.task.run([
597 | 'env:all',
598 | 'env:test'
599 | ]);
600 | }
601 |
602 | else if (target === 'client') {
603 | return grunt.task.run([
604 | 'clean:server',
605 | 'env:all',
606 | 'injector:sass',
607 | 'concurrent:test',
608 | 'injector',
609 | 'autoprefixer',
610 | 'karma'
611 | ]);
612 | }
613 |
614 | else if (target === 'e2e') {
615 | return grunt.task.run([
616 | 'clean:server',
617 | 'env:all',
618 | 'env:test',
619 | 'injector:sass',
620 | 'concurrent:test',
621 | 'injector',
622 | 'wiredep',
623 | 'autoprefixer',
624 | 'express:dev',
625 | 'protractor'
626 | ]);
627 | }
628 |
629 | else grunt.task.run([
630 | 'test:server',
631 | 'test:client'
632 | ]);
633 | });
634 |
635 | grunt.registerTask('build', [
636 | 'clean:dist',
637 | 'injector:sass',
638 | 'concurrent:dist',
639 | 'injector',
640 | 'wiredep',
641 | 'useminPrepare',
642 | 'autoprefixer',
643 | 'ngtemplates',
644 | 'concat',
645 | 'ngAnnotate',
646 | 'copy:dist',
647 | 'cdnify',
648 | 'cssmin',
649 | 'uglify',
650 | 'rev',
651 | 'usemin'
652 | ]);
653 |
654 | grunt.registerTask('default', [
655 | 'newer:jshint',
656 | 'test',
657 | 'build'
658 | ]);
659 | };
660 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # angular-js-seed — ready to start application for Angularjs
2 |
3 | This project is based on angular 1.x concept and wrap around usefull utility for angular application development.
4 |
5 | The seed contains a sample AngularJS application and is pre-configured to install the Angular
6 | framework and a bunch of development and testing tools for instant web development.
7 |
8 |
9 |
10 | ## Getting Started
11 |
12 | You can clone repository [angular-js-seed](https://github.com/princesoni1989/angular-js-seed) and install dependency.
13 |
14 | ### Prerequisites
15 | We have number of server and build tools preconfigured in application, to use them you need to pre-install below dependency
16 | * [Node](https://nodejs.org/en/download/)
17 | * [Sass](http://sass-lang.com/install)
18 | * [Grunt](http://gruntjs.com/installing-grunt)
19 | * [Bower](http://bower.io/)
20 |
21 | ### Clone angular-js-seed
22 |
23 | Clone the angular-seed repository using [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git):
24 |
25 | ```
26 | git https://github.com/princesoni1989/angular-js-seed
27 | cd angular-js-seed
28 | ```
29 |
30 |
31 | ### Install Dependencies
32 |
33 | We have two kinds of dependencies in this project: tools and angular framework code. The tools help
34 | us manage and test the application.
35 |
36 | ```
37 | bower install
38 |
39 | npm install
40 | ```
41 |
42 | You should find that you have two new
43 | folders in your project.
44 |
45 | * `node_modules` - contains the npm packages for the tools we need
46 | * `client/bower_components` - contains the angular framework files
47 |
48 |
49 | ### Run the Application
50 |
51 | We have preconfigured the project with a simple development web server. The simplest way to start
52 | this server is:
53 |
54 | ```
55 | grunt serve
56 | ```
57 |
58 | Now browse to the app at `http://localhost:9000`.This will start server in development mode and enable you do fast development. you can make changes and it will deploy automatically.
59 |
60 | You can also use:
61 | ```
62 | npm start
63 | ```
64 |
65 |
66 |
67 | ## Pre configured application
68 |
69 | This app comes with preconfigured configuration. You can find below listed functionality already imaplemented -
70 | * login
71 | * logout
72 | * signup
73 | * forgot password
74 | * change password
75 | * home screen
76 | * pop up management(Modal)
77 | * loader service
78 | * constants
79 | * configuration
80 | * server
81 | * build management
82 | * Initial test cases
83 | * test coverage and configuration
84 |
85 |
86 |
87 | ## Directory Layout
88 | 
89 |
90 | 
91 |
92 |
93 | ## Testing
94 |
95 | There are two kinds of tests in the angular-seed application: Unit tests and End to End tests.
96 |
97 | ### Running Unit Tests
98 |
99 | The angular-seed app comes preconfigured with unit tests. These are written in
100 | Jasmine, which we run with the Karma Test Runner. We provide a Karma
101 | configuration file to run them.
102 |
103 | * Configuration is found at `karma.conf.js`
104 | * Test an be dound under client/test
105 |
106 |
107 | The easiest way to run the unit tests is to use the supplied grunt configuration:
108 |
109 | ```
110 | grunt test or grunt test:client
111 | ```
112 |
113 | This script will start the Karma test runner to execute the unit tests. Moreover, Karma will sit and
114 | watch the source and test files for changes and then re-run the tests whenever any of them change.
115 | This is the recommended strategy; if your unit tests are being run every time you save a file then
116 | you receive instant feedback on any changes that break the expected code functionality.
117 |
118 | We have used karma code coverage tool preconfigured which will give percentage of code coverage.It will generate new folder having all coverage information
119 |
120 | ```
121 | /coverage
122 | ```
123 |
124 |
125 |
126 | ### End to end testing
127 |
128 | The angular-js-seed app comes with end-to-end tests, again written in Jasmine. These tests
129 | are run with the Protractor End-to-End test runner. It uses native events and has
130 | special features for Angular applications.
131 |
132 | * the configuration is found at `protractor-conf.js`
133 | * the end-to-end tests are found in `/e2e`
134 |
135 | Protractor simulates interaction with our web app and verifies that the application responds
136 | correctly. Therefore, our web server needs to be serving up the application, so that Protractor
137 | can interact with it.
138 |
139 | ## Updating Angular
140 |
141 | Angular framework library code and tools are acquired through package managers (npm and
142 | bower) you can use these tools instead to update the dependencies.
143 |
144 | You can update the tool dependencies by running:
145 |
146 | ```
147 | npm update
148 | ```
149 |
150 | This will find the latest versions that match the version ranges specified in the `package.json` file.
151 |
152 | You can update the Angular dependencies by running:
153 |
154 | ```
155 | bower update
156 | ```
157 |
158 | This will find the latest versions that match the version ranges specified in the `bower.json` file.
159 |
160 |
161 | ## Serving the Application Files
162 |
163 | ```
164 | grunt serve
165 | ```
166 |
167 | if you want to create build and move to production -
168 |
169 | ```
170 | grunt clean
171 | grunt build
172 | cd dist
173 | npm start
174 | ```
175 | This will minify all the file and will create production ready build.
176 |
177 |
178 |
179 | ## Continuous Integration
180 |
181 | ### Travis CI
182 |
183 | Travis CI is a continuous integration service, which can monitor GitHub for new commits
184 | to your repository and execute scripts such as building the app or running tests. The angular-seed
185 | project contains a Travis configuration file, `.travis.yml`, which will cause Travis to run your
186 | tests when you push to GitHub.
187 |
188 | You will need to enable the integration between Travis and GitHub. See the Travis website for more
189 | instruction on how to do this.
190 |
191 | ### Initial structure of this project is based on angular-fullstack generator.
192 |
193 | ## Contact
194 |
195 | For more information on AngularJS please check out http://angularjs.org/
196 |
197 | [git](http://git-scm.com/)
198 | [bower](http://bower.io)
199 | [npm](https://www.npmjs.org/)
200 | [node](http://nodejs.org)
201 | [protractor](https://github.com/angular/protractor)
202 | [jasmine](http://jasmine.github.io)
203 | [karma](http://karma-runner.github.io)
204 | [travis](https://travis-ci.org/)
205 |
206 |
207 | ## LICENSE
208 |
209 | angular-js-seed is released under the ISC License Copyright (c) 2016 Prince Soni
210 |
211 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
212 |
213 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
214 |
215 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
216 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-js-seed",
3 | "version": "0.0.0",
4 | "dependencies": {
5 | "angular": ">=1.3.*",
6 | "json3": "~3.3.1",
7 | "es5-shim": "~3.0.1",
8 | "bootstrap-sass-official": "~3.1.1",
9 | "bootstrap": "~3.1.1",
10 | "angular-resource": ">=1.2.*",
11 | "angular-cookies": ">=1.2.*",
12 | "angular-sanitize": ">=1.2.*",
13 | "angular-bootstrap": "~0.11.0",
14 | "font-awesome": ">=4.1.0",
15 | "lodash": "~2.4.1",
16 | "angular-ui-router": "~0.2.15",
17 | "angular-route": "^1.5.6"
18 | },
19 | "devDependencies": {
20 | "angular-mocks": ">=1.2.*",
21 | "angular-scenario": ">=1.2.*"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/client/.htaccess:
--------------------------------------------------------------------------------
1 | # Apache Configuration File
2 |
3 | # (!) Using `.htaccess` files slows down Apache, therefore, if you have access
4 | # to the main server config file (usually called `httpd.conf`), you should add
5 | # this logic there: http://httpd.apache.org/docs/current/howto/htaccess.html.
6 |
7 | # ##############################################################################
8 | # # CROSS-ORIGIN RESOURCE SHARING (CORS) #
9 | # ##############################################################################
10 |
11 | # ------------------------------------------------------------------------------
12 | # | Cross-domain AJAX requests |
13 | # ------------------------------------------------------------------------------
14 |
15 | # Enable cross-origin AJAX requests.
16 | # http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
17 | # http://enable-cors.org/
18 |
19 | #
20 | # Header set Access-Control-Allow-Origin "*"
21 | #
22 |
23 | # ------------------------------------------------------------------------------
24 | # | CORS-enabled images |
25 | # ------------------------------------------------------------------------------
26 |
27 | # Send the CORS header for images when browsers request it.
28 | # https://developer.mozilla.org/en/CORS_Enabled_Image
29 | # http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html
30 | # http://hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/
31 |
32 |
33 |
34 |
35 | SetEnvIf Origin ":" IS_CORS
36 | Header set Access-Control-Allow-Origin "*" env=IS_CORS
37 |
38 |
39 |
40 |
41 | # ------------------------------------------------------------------------------
42 | # | Web fonts access |
43 | # ------------------------------------------------------------------------------
44 |
45 | # Allow access from all domains for web fonts
46 |
47 |
48 |
49 | Header set Access-Control-Allow-Origin "*"
50 |
51 |
52 |
53 |
54 | # ##############################################################################
55 | # # ERRORS #
56 | # ##############################################################################
57 |
58 | # ------------------------------------------------------------------------------
59 | # | 404 error prevention for non-existing redirected folders |
60 | # ------------------------------------------------------------------------------
61 |
62 | # Prevent Apache from returning a 404 error for a rewrite if a directory
63 | # with the same name does not exist.
64 | # http://httpd.apache.org/docs/current/content-negotiation.html#multiviews
65 | # http://www.webmasterworld.com/apache/3808792.htm
66 |
67 | Options -MultiViews
68 |
69 | # ------------------------------------------------------------------------------
70 | # | Custom error messages / pages |
71 | # ------------------------------------------------------------------------------
72 |
73 | # You can customize what Apache returns to the client in case of an error (see
74 | # http://httpd.apache.org/docs/current/mod/core.html#errordocument), e.g.:
75 |
76 | ErrorDocument 404 /404.html
77 |
78 |
79 | # ##############################################################################
80 | # # INTERNET EXPLORER #
81 | # ##############################################################################
82 |
83 | # ------------------------------------------------------------------------------
84 | # | Better website experience |
85 | # ------------------------------------------------------------------------------
86 |
87 | # Force IE to render pages in the highest available mode in the various
88 | # cases when it may not: http://hsivonen.iki.fi/doctype/ie-mode.pdf.
89 |
90 |
91 | Header set X-UA-Compatible "IE=edge"
92 | # `mod_headers` can't match based on the content-type, however, we only
93 | # want to send this header for HTML pages and not for the other resources
94 |
95 | Header unset X-UA-Compatible
96 |
97 |
98 |
99 | # ------------------------------------------------------------------------------
100 | # | Cookie setting from iframes |
101 | # ------------------------------------------------------------------------------
102 |
103 | # Allow cookies to be set from iframes in IE.
104 |
105 | #
106 | # Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\""
107 | #
108 |
109 | # ------------------------------------------------------------------------------
110 | # | Screen flicker |
111 | # ------------------------------------------------------------------------------
112 |
113 | # Stop screen flicker in IE on CSS rollovers (this only works in
114 | # combination with the `ExpiresByType` directives for images from below).
115 |
116 | # BrowserMatch "MSIE" brokenvary=1
117 | # BrowserMatch "Mozilla/4.[0-9]{2}" brokenvary=1
118 | # BrowserMatch "Opera" !brokenvary
119 | # SetEnvIf brokenvary 1 force-no-vary
120 |
121 |
122 | # ##############################################################################
123 | # # MIME TYPES AND ENCODING #
124 | # ##############################################################################
125 |
126 | # ------------------------------------------------------------------------------
127 | # | Proper MIME types for all files |
128 | # ------------------------------------------------------------------------------
129 |
130 |
131 |
132 | # Audio
133 | AddType audio/mp4 m4a f4a f4b
134 | AddType audio/ogg oga ogg
135 |
136 | # JavaScript
137 | # Normalize to standard type (it's sniffed in IE anyways):
138 | # http://tools.ietf.org/html/rfc4329#section-7.2
139 | AddType application/javascript js jsonp
140 | AddType application/json json
141 |
142 | # Video
143 | AddType video/mp4 mp4 m4v f4v f4p
144 | AddType video/ogg ogv
145 | AddType video/webm webm
146 | AddType video/x-flv flv
147 |
148 | # Web fonts
149 | AddType application/font-woff woff
150 | AddType application/vnd.ms-fontobject eot
151 |
152 | # Browsers usually ignore the font MIME types and sniff the content,
153 | # however, Chrome shows a warning if other MIME types are used for the
154 | # following fonts.
155 | AddType application/x-font-ttf ttc ttf
156 | AddType font/opentype otf
157 |
158 | # Make SVGZ fonts work on iPad:
159 | # https://twitter.com/FontSquirrel/status/14855840545
160 | AddType image/svg+xml svg svgz
161 | AddEncoding gzip svgz
162 |
163 | # Other
164 | AddType application/octet-stream safariextz
165 | AddType application/x-chrome-extension crx
166 | AddType application/x-opera-extension oex
167 | AddType application/x-shockwave-flash swf
168 | AddType application/x-web-app-manifest+json webapp
169 | AddType application/x-xpinstall xpi
170 | AddType application/xml atom rdf rss xml
171 | AddType image/webp webp
172 | AddType image/x-icon ico
173 | AddType text/cache-manifest appcache manifest
174 | AddType text/vtt vtt
175 | AddType text/x-component htc
176 | AddType text/x-vcard vcf
177 |
178 |
179 |
180 | # ------------------------------------------------------------------------------
181 | # | UTF-8 encoding |
182 | # ------------------------------------------------------------------------------
183 |
184 | # Use UTF-8 encoding for anything served as `text/html` or `text/plain`.
185 | AddDefaultCharset utf-8
186 |
187 | # Force UTF-8 for certain file formats.
188 |
189 | AddCharset utf-8 .atom .css .js .json .rss .vtt .webapp .xml
190 |
191 |
192 |
193 | # ##############################################################################
194 | # # URL REWRITES #
195 | # ##############################################################################
196 |
197 | # ------------------------------------------------------------------------------
198 | # | Rewrite engine |
199 | # ------------------------------------------------------------------------------
200 |
201 | # Turning on the rewrite engine and enabling the `FollowSymLinks` option is
202 | # necessary for the following directives to work.
203 |
204 | # If your web host doesn't allow the `FollowSymlinks` option, you may need to
205 | # comment it out and use `Options +SymLinksIfOwnerMatch` but, be aware of the
206 | # performance impact: http://httpd.apache.org/docs/current/misc/perf-tuning.html#symlinks
207 |
208 | # Also, some cloud hosting services require `RewriteBase` to be set:
209 | # http://www.rackspace.com/knowledge_center/frequently-asked-question/why-is-mod-rewrite-not-working-on-my-site
210 |
211 |
212 | Options +FollowSymlinks
213 | # Options +SymLinksIfOwnerMatch
214 | RewriteEngine On
215 | # RewriteBase /
216 |
217 |
218 | # ------------------------------------------------------------------------------
219 | # | Suppressing / Forcing the "www." at the beginning of URLs |
220 | # ------------------------------------------------------------------------------
221 |
222 | # The same content should never be available under two different URLs especially
223 | # not with and without "www." at the beginning. This can cause SEO problems
224 | # (duplicate content), therefore, you should choose one of the alternatives and
225 | # redirect the other one.
226 |
227 | # By default option 1 (no "www.") is activated:
228 | # http://no-www.org/faq.php?q=class_b
229 |
230 | # If you'd prefer to use option 2, just comment out all the lines from option 1
231 | # and uncomment the ones from option 2.
232 |
233 | # IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME!
234 |
235 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
236 |
237 | # Option 1: rewrite www.example.com → example.com
238 |
239 |
240 | RewriteCond %{HTTPS} !=on
241 | RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
242 | RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
243 |
244 |
245 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
246 |
247 | # Option 2: rewrite example.com → www.example.com
248 |
249 | # Be aware that the following might not be a good idea if you use "real"
250 | # subdomains for certain parts of your website.
251 |
252 | #
253 | # RewriteCond %{HTTPS} !=on
254 | # RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
255 | # RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
256 | #
257 |
258 |
259 | # ##############################################################################
260 | # # SECURITY #
261 | # ##############################################################################
262 |
263 | # ------------------------------------------------------------------------------
264 | # | Content Security Policy (CSP) |
265 | # ------------------------------------------------------------------------------
266 |
267 | # You can mitigate the risk of cross-site scripting and other content-injection
268 | # attacks by setting a Content Security Policy which whitelists trusted sources
269 | # of content for your site.
270 |
271 | # The example header below allows ONLY scripts that are loaded from the current
272 | # site's origin (no inline scripts, no CDN, etc). This almost certainly won't
273 | # work as-is for your site!
274 |
275 | # To get all the details you'll need to craft a reasonable policy for your site,
276 | # read: http://html5rocks.com/en/tutorials/security/content-security-policy (or
277 | # see the specification: http://w3.org/TR/CSP).
278 |
279 | #
280 | # Header set Content-Security-Policy "script-src 'self'; object-src 'self'"
281 | #
282 | # Header unset Content-Security-Policy
283 | #
284 | #
285 |
286 | # ------------------------------------------------------------------------------
287 | # | File access |
288 | # ------------------------------------------------------------------------------
289 |
290 | # Block access to directories without a default document.
291 | # Usually you should leave this uncommented because you shouldn't allow anyone
292 | # to surf through every directory on your server (which may includes rather
293 | # private places like the CMS's directories).
294 |
295 |
296 | Options -Indexes
297 |
298 |
299 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
300 |
301 | # Block access to hidden files and directories.
302 | # This includes directories used by version control systems such as Git and SVN.
303 |
304 |
305 | RewriteCond %{SCRIPT_FILENAME} -d [OR]
306 | RewriteCond %{SCRIPT_FILENAME} -f
307 | RewriteRule "(^|/)\." - [F]
308 |
309 |
310 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
311 |
312 | # Block access to backup and source files.
313 | # These files may be left by some text editors and can pose a great security
314 | # danger when anyone has access to them.
315 |
316 |
317 | Order allow,deny
318 | Deny from all
319 | Satisfy All
320 |
321 |
322 | # ------------------------------------------------------------------------------
323 | # | Secure Sockets Layer (SSL) |
324 | # ------------------------------------------------------------------------------
325 |
326 | # Rewrite secure requests properly to prevent SSL certificate warnings, e.g.:
327 | # prevent `https://www.example.com` when your certificate only allows
328 | # `https://secure.example.com`.
329 |
330 | #
331 | # RewriteCond %{SERVER_PORT} !^443
332 | # RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L]
333 | #
334 |
335 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
336 |
337 | # Force client-side SSL redirection.
338 |
339 | # If a user types "example.com" in his browser, the above rule will redirect him
340 | # to the secure version of the site. That still leaves a window of opportunity
341 | # (the initial HTTP connection) for an attacker to downgrade or redirect the
342 | # request. The following header ensures that browser will ONLY connect to your
343 | # server via HTTPS, regardless of what the users type in the address bar.
344 | # http://www.html5rocks.com/en/tutorials/security/transport-layer-security/
345 |
346 | #
347 | # Header set Strict-Transport-Security max-age=16070400;
348 | #
349 |
350 | # ------------------------------------------------------------------------------
351 | # | Server software information |
352 | # ------------------------------------------------------------------------------
353 |
354 | # Avoid displaying the exact Apache version number, the description of the
355 | # generic OS-type and the information about Apache's compiled-in modules.
356 |
357 | # ADD THIS DIRECTIVE IN THE `httpd.conf` AS IT WILL NOT WORK IN THE `.htaccess`!
358 |
359 | # ServerTokens Prod
360 |
361 |
362 | # ##############################################################################
363 | # # WEB PERFORMANCE #
364 | # ##############################################################################
365 |
366 | # ------------------------------------------------------------------------------
367 | # | Compression |
368 | # ------------------------------------------------------------------------------
369 |
370 |
371 |
372 | # Force compression for mangled headers.
373 | # http://developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping
374 |
375 |
376 | SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
377 | RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
378 |
379 |
380 |
381 | # Compress all output labeled with one of the following MIME-types
382 | # (for Apache versions below 2.3.7, you don't need to enable `mod_filter`
383 | # and can remove the `` and `` lines
384 | # as `AddOutputFilterByType` is still in the core directives).
385 |
386 | AddOutputFilterByType DEFLATE application/atom+xml \
387 | application/javascript \
388 | application/json \
389 | application/rss+xml \
390 | application/vnd.ms-fontobject \
391 | application/x-font-ttf \
392 | application/x-web-app-manifest+json \
393 | application/xhtml+xml \
394 | application/xml \
395 | font/opentype \
396 | image/svg+xml \
397 | image/x-icon \
398 | text/css \
399 | text/html \
400 | text/plain \
401 | text/x-component \
402 | text/xml
403 |
404 |
405 |
406 |
407 | # ------------------------------------------------------------------------------
408 | # | Content transformations |
409 | # ------------------------------------------------------------------------------
410 |
411 | # Prevent some of the mobile network providers from modifying the content of
412 | # your site: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.5.
413 |
414 | #
415 | # Header set Cache-Control "no-transform"
416 | #
417 |
418 | # ------------------------------------------------------------------------------
419 | # | ETag removal |
420 | # ------------------------------------------------------------------------------
421 |
422 | # Since we're sending far-future expires headers (see below), ETags can
423 | # be removed: http://developer.yahoo.com/performance/rules.html#etags.
424 |
425 | # `FileETag None` is not enough for every server.
426 |
427 | Header unset ETag
428 |
429 |
430 | FileETag None
431 |
432 | # ------------------------------------------------------------------------------
433 | # | Expires headers (for better cache control) |
434 | # ------------------------------------------------------------------------------
435 |
436 | # The following expires headers are set pretty far in the future. If you don't
437 | # control versioning with filename-based cache busting, consider lowering the
438 | # cache time for resources like CSS and JS to something like 1 week.
439 |
440 |
441 |
442 | ExpiresActive on
443 | ExpiresDefault "access plus 1 month"
444 |
445 | # CSS
446 | ExpiresByType text/css "access plus 1 year"
447 |
448 | # Data interchange
449 | ExpiresByType application/json "access plus 0 seconds"
450 | ExpiresByType application/xml "access plus 0 seconds"
451 | ExpiresByType text/xml "access plus 0 seconds"
452 |
453 | # Favicon (cannot be renamed!)
454 | ExpiresByType image/x-icon "access plus 1 week"
455 |
456 | # HTML components (HTCs)
457 | ExpiresByType text/x-component "access plus 1 month"
458 |
459 | # HTML
460 | ExpiresByType text/html "access plus 0 seconds"
461 |
462 | # JavaScript
463 | ExpiresByType application/javascript "access plus 1 year"
464 |
465 | # Manifest files
466 | ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds"
467 | ExpiresByType text/cache-manifest "access plus 0 seconds"
468 |
469 | # Media
470 | ExpiresByType audio/ogg "access plus 1 month"
471 | ExpiresByType image/gif "access plus 1 month"
472 | ExpiresByType image/jpeg "access plus 1 month"
473 | ExpiresByType image/png "access plus 1 month"
474 | ExpiresByType video/mp4 "access plus 1 month"
475 | ExpiresByType video/ogg "access plus 1 month"
476 | ExpiresByType video/webm "access plus 1 month"
477 |
478 | # Web feeds
479 | ExpiresByType application/atom+xml "access plus 1 hour"
480 | ExpiresByType application/rss+xml "access plus 1 hour"
481 |
482 | # Web fonts
483 | ExpiresByType application/font-woff "access plus 1 month"
484 | ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
485 | ExpiresByType application/x-font-ttf "access plus 1 month"
486 | ExpiresByType font/opentype "access plus 1 month"
487 | ExpiresByType image/svg+xml "access plus 1 month"
488 |
489 |
490 |
491 | # ------------------------------------------------------------------------------
492 | # | Filename-based cache busting |
493 | # ------------------------------------------------------------------------------
494 |
495 | # If you're not using a build process to manage your filename version revving,
496 | # you might want to consider enabling the following directives to route all
497 | # requests such as `/css/style.12345.css` to `/css/style.css`.
498 |
499 | # To understand why this is important and a better idea than `*.css?v231`, read:
500 | # http://stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring
501 |
502 | #
503 | # RewriteCond %{REQUEST_FILENAME} !-f
504 | # RewriteCond %{REQUEST_FILENAME} !-d
505 | # RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpg|gif)$ $1.$3 [L]
506 | #
507 |
508 | # ------------------------------------------------------------------------------
509 | # | File concatenation |
510 | # ------------------------------------------------------------------------------
511 |
512 | # Allow concatenation from within specific CSS and JS files, e.g.:
513 | # Inside of `script.combined.js` you could have
514 | #
515 | #
516 | # and they would be included into this single file.
517 |
518 | #
519 | #
520 | # Options +Includes
521 | # AddOutputFilterByType INCLUDES application/javascript application/json
522 | # SetOutputFilter INCLUDES
523 | #
524 | #
525 | # Options +Includes
526 | # AddOutputFilterByType INCLUDES text/css
527 | # SetOutputFilter INCLUDES
528 | #
529 | #
530 |
531 | # ------------------------------------------------------------------------------
532 | # | Persistent connections |
533 | # ------------------------------------------------------------------------------
534 |
535 | # Allow multiple requests to be sent over the same TCP connection:
536 | # http://httpd.apache.org/docs/current/en/mod/core.html#keepalive.
537 |
538 | # Enable if you serve a lot of static content but, be aware of the
539 | # possible disadvantages!
540 |
541 | #
542 | # Header set Connection Keep-Alive
543 | #
544 |
--------------------------------------------------------------------------------
/client/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "browser": true,
4 | "esnext": true,
5 | "bitwise": true,
6 | "camelcase": true,
7 | "curly": true,
8 | "eqeqeq": true,
9 | "immed": true,
10 | "latedef": true,
11 | "newcap": true,
12 | "noarg": true,
13 | "quotmark": "single",
14 | "undef": true,
15 | "unused": true,
16 | "strict": true,
17 | "trailing": true,
18 | "smarttabs": true,
19 | "globals": {
20 | "jQuery": true,
21 | "angular": true,
22 | "console": true,
23 | "$": true,
24 | "_": true,
25 | "moment": true,
26 | "describe": true,
27 | "beforeEach": true,
28 | "module": true,
29 | "inject": true,
30 | "it": true,
31 | "expect": true,
32 | "browser": true,
33 | "element": true,
34 | "by": true
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/client/app/account/account.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function (angular) {
4 | angular.module('angularJsSeedApp')
5 | .config(function configuration($stateProvider) {
6 | $stateProvider
7 | .state('login', {
8 | url: '/login',
9 | templateUrl: 'app/account/login/login.html',
10 | controller: 'LoginCtrl',
11 | controllerAs: 'Login'
12 | })
13 | .state('logout', {
14 | url: '/logout?referrer',
15 | referrer: 'login',
16 | template: '',
17 | controller: function($state, Auth) {
18 | var referrer = $state.params.referrer || 'login';
19 | Auth.logout();
20 | $state.go(referrer);
21 | }
22 | })
23 | .state('signUp', {
24 | url: '/signup',
25 | templateUrl: 'app/account/signUp/signUp.html',
26 | controller: 'SignUpCtrl',
27 | controllerAs: 'SignUp'
28 | })
29 | .state('forgotPassword', {
30 | url: '/forgotpassword',
31 | templateUrl: 'app/account/forgotPassword/forgotPassword.html',
32 | controller: 'ForgotPasswordCtrl',
33 | controllerAs: 'ForgotPassword'
34 | })
35 | .state('changePassword', {
36 | url: '/changepassword',
37 | templateUrl: 'app/account/changePassword/changePassword.html',
38 | controller: 'ChangePasswordCtrl',
39 | controllerAs: 'ChangePassword',
40 | authenticate: true
41 | });
42 | })
43 | .run(function($rootScope) {
44 | $rootScope.$on('$stateChangeStart', function(event, next, nextParams, current) {
45 | if (next.name === 'logout' && current && current.name && !current.authenticate) {
46 | next.referrer = current.name;
47 | }
48 | });
49 | });
50 |
51 | })(angular)
52 |
--------------------------------------------------------------------------------
/client/app/account/changePassword/changePassword.controller.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function (angular) {
4 |
5 | function changePassword(Auth) {
6 |
7 | var ChangePassword = this;
8 | ChangePassword.errors = {};
9 |
10 | ChangePassword.reset = function (form) {
11 | ChangePassword.submitted = true;
12 | if (form.$valid) {
13 | Auth.changePassword(ChangePassword.user.oldPassword, ChangePassword.user.newPassword)
14 | .then(function () {
15 | ChangePassword.message = 'Password successfully changed.';
16 | })
17 | .catch(function () {
18 | ChangePassword.errors.other = 'Incorrect password';
19 | ChangePassword.message = 'Unable to change password, Please check current password';
20 | });
21 | }
22 | };
23 | };
24 |
25 | angular.module('angularJsSeedApp')
26 | .controller('ChangePasswordCtrl', changePassword)
27 | })(angular);
28 |
--------------------------------------------------------------------------------
/client/app/account/changePassword/changePassword.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
37 |
--------------------------------------------------------------------------------
/client/app/account/forgotPassword/forgotPassword.controller.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function (angular) {
4 |
5 | function forgotPassword(User, $state) {
6 |
7 | /**
8 | * Controller variables
9 | */
10 | var ForgotPassword = this;
11 | ForgotPassword.sent = false;
12 | ForgotPassword.posting = false;
13 | ForgotPassword.error = '';
14 | ForgotPassword.form = {
15 | email: ''
16 | };
17 | ForgotPassword.requestFailed = false;
18 | ForgotPassword.submitted = false;
19 |
20 | /**
21 | * Serves to submit a request for set password for provided user emailId.
22 | * @param form - formObject
23 | */
24 | ForgotPassword.forgotPassword = function (form) {
25 | ForgotPassword.submitted = true;
26 | if (form.$valid) {
27 | ForgotPassword.posting = true;
28 | ForgotPassword.requestFailed = false;
29 | User.forgotPassword({email: ForgotPassword.form.email}, function (data) {
30 | ForgotPassword.sent = true;
31 | ForgotPassword.goToLogin();
32 | }, function (err) {
33 | ForgotPassword.posting = false;
34 | ForgotPassword.error = err.code;
35 | ForgotPassword.requestFailed = true;
36 | })
37 | }
38 | };
39 |
40 | /**
41 | * navigate to login page
42 | */
43 | ForgotPassword.goToLogin = function () {
44 | $state.go('login');
45 | };
46 | };
47 |
48 | angular.module('angularJsSeedApp')
49 | .controller('ForgotPasswordCtrl', forgotPassword);
50 |
51 | })(angular);
52 |
--------------------------------------------------------------------------------
/client/app/account/forgotPassword/forgotPassword.html:
--------------------------------------------------------------------------------
1 |
2 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/client/app/account/login/login.controller.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function (angular) {
4 |
5 | function loginCtrl($scope, Auth, $state, $window) {
6 |
7 | /**
8 | * controller variables
9 | */
10 | var Login = this;
11 | Login.user = {};
12 | Login.errors = {};
13 |
14 | /**
15 | *Login user
16 | * @param form
17 | */
18 | Login.login = function(form) {
19 | Login.submitted = true;
20 |
21 | if (form.$valid) {
22 | Auth.login({
23 | email: Login.user.email,
24 | password: Login.user.password
25 | })
26 | .then(function() {
27 | // Logged in, redirect to home
28 | $state.go('home');
29 | })
30 | .catch(function(error) {
31 | Login.errors.other = error.message;
32 | });
33 | }
34 | };
35 |
36 | }
37 |
38 | angular.module('angularJsSeedApp')
39 | .controller('LoginCtrl',loginCtrl);
40 | })(angular);
41 |
--------------------------------------------------------------------------------
/client/app/account/login/login.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
47 |
--------------------------------------------------------------------------------
/client/app/account/signUp/signUp.controller.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function (angular) {
4 |
5 | function signUpCtrl($scope, Auth, $state, $window) {
6 |
7 | /**
8 | * controller varibles
9 | */
10 | var SignUp = this;
11 | SignUp.user = {};
12 | SignUp.errors = {};
13 |
14 | /**
15 | * Signup user
16 | * @param form
17 | */
18 | SignUp.register = function (form) {
19 | SignUp.submitted = true;
20 |
21 | if (form.$valid) {
22 | Auth.createUser(SignUp.user)
23 | .then(function () {
24 | // Account created, redirect to home
25 | $state.go('home');
26 | })
27 | .catch(function (err) {
28 | err = err.data;
29 | $scope.errors = {};
30 |
31 | });
32 | }
33 | };
34 |
35 | }
36 |
37 | angular.module('angularJsSeedApp')
38 | .controller('SignUpCtrl', signUpCtrl);;
39 |
40 | })(angular)
41 |
--------------------------------------------------------------------------------
/client/app/account/signUp/signUp.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
69 |
--------------------------------------------------------------------------------
/client/app/app.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function (angular) {
4 |
5 | angular.module('angularJsSeedApp', [
6 | 'ngCookies',
7 | 'ngResource',
8 | 'ngSanitize',
9 | 'ui.router',
10 | 'ui.bootstrap'
11 | ])
12 | .config(function ($stateProvider, $urlRouterProvider, $locationProvider, $httpProvider) {
13 | $urlRouterProvider
14 | .otherwise('/');
15 |
16 | $locationProvider.html5Mode(true);
17 | $httpProvider.interceptors.push('authInterceptor');
18 | })
19 | .run(['$rootScope', '$state', 'Auth', function ($rootScope, $state, Auth) {
20 | // Redirect to login if route requires auth and the user is not logged in
21 | $rootScope.$on('$stateChangeStart', function(event, next) {
22 | Auth.isLoggedInAsync(function(loggedIn) {
23 | //check for user authentication
24 | if (!loggedIn && next.authenticate) {
25 | event.preventDefault();
26 | $state.go('login');
27 | }
28 |
29 | //navigate to home if user is already authenticated
30 | if(loggedIn && (next.name === 'login' || next.name === 'landing')){
31 | event.preventDefault();
32 | $state.go('home');
33 | }
34 |
35 | if (next.authenticate && !loggedIn) {
36 | event.preventDefault();
37 | $state.go('login');
38 | }
39 | });
40 | });
41 | }]);
42 |
43 | })(angular);
44 |
--------------------------------------------------------------------------------
/client/app/app.scss:
--------------------------------------------------------------------------------
1 | $icon-font-path: "/bower_components/bootstrap-sass-official/vendor/assets/fonts/bootstrap/";
2 | $fa-font-path: "/bower_components/font-awesome/fonts";
3 |
4 | @import 'bootstrap-sass-official/vendor/assets/stylesheets/bootstrap';
5 | @import 'font-awesome/scss/font-awesome';
6 |
7 | /**
8 | * App-wide Styles
9 | */
10 |
11 | /* navbar */
12 | #nav-main
13 | {
14 | background-color: #2c3e50;
15 | margin-bottom: 0;
16 | border:none;
17 | }
18 | #nav-main a.navbar-brand
19 | {
20 | font-size: 20px;
21 | font-weight: 500;
22 | color: #fff;
23 | }
24 | #nav-main li a
25 | {
26 | text-transform: uppercase;
27 | font-size: 16px;
28 | color: #fff;
29 | font-weight: bold;
30 | &:focus
31 | {
32 | background: transparent;
33 | color:#18bc9c;
34 | }
35 | &:hover
36 | {
37 | background: transparent;
38 | color:#18bc9c;
39 | }
40 | }
41 | #nav-main li.active a
42 | {
43 | background: #18bc9c;
44 | color: #fff;
45 | }
46 | .navbar-nav .admin-welcome
47 | {
48 | color: #18bc9c;
49 | }
50 | /* navbar */
51 |
52 | /* body */
53 | .jumbotron.jumbo-main
54 | {
55 | text-align: center;
56 | h1
57 | {
58 | text-align: center;
59 | color: #2c3e50;
60 | text-transform: uppercase;
61 | }
62 | }
63 | /* body */
64 |
65 | /* Login Form */
66 |
67 | .login-form
68 | {
69 | border: 1px solid #ddd;
70 | padding: 20px 20px 40px 20px;
71 | margin-top: 50px;
72 | background: #f5f5f5;
73 | h2
74 | {
75 | text-align: center;
76 | font-size: 20px;
77 | }
78 | .btn-login,.btn-register,.btn-danger,.btn-success
79 | {
80 | display: block;
81 | width: 100%;
82 | background-color: #47a447;
83 | border-color: #398439;
84 | color: #fff;
85 | border-radius: 0;
86 | height: 35px;
87 | line-height: 35px;
88 | padding: 0;
89 | margin-top: 15px;
90 | font-size: 14px;
91 | }
92 | .btn-register
93 | {
94 | background-color: #428bca;
95 | border-color: #357ebd;
96 | }
97 | .forgot-password {
98 | margin-top: 8px;
99 | display: block;
100 | }
101 | .btn-danger
102 | {
103 | background-color: #d9534f;
104 | border-color: #d43f3a;
105 | }
106 | }
107 | /* Login Form */
108 | /* footer */
109 | footer
110 | {
111 | position: absolute;
112 | bottom: 0;
113 | width: 100%;
114 | height: 60px;
115 | background-color: #233140;
116 | h3
117 | {
118 | margin: 0;
119 | text-align: center;
120 | color: #fff;
121 | font-size: 16px;
122 | line-height: 60px;
123 | }
124 | }
125 | /* footer */
126 | .browsehappy {
127 | margin: 0.2em 0;
128 | background: #ccc;
129 | color: #000;
130 | padding: 0.2em 0;
131 | }
132 |
133 | // Component styles are injected through grunt
134 | // injector
135 | // endinjector
136 |
--------------------------------------------------------------------------------
/client/app/home/home.controller.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function (angular) {
4 |
5 | function homeCtrl(ModalService) {
6 | /**
7 | * Controller variables
8 | */
9 | var Home = this;
10 |
11 | /**
12 | *Show popup
13 | */
14 | Home.openPopUp = function (){
15 | ModalService.successPopup();
16 | }
17 | };
18 |
19 | angular.module('angularJsSeedApp')
20 | .controller('HomeCtrl', homeCtrl)
21 |
22 | })(angular)
23 |
--------------------------------------------------------------------------------
/client/app/home/home.html:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
--------------------------------------------------------------------------------
/client/app/home/home.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function (angular) {
4 |
5 | angular.module('angularJsSeedApp')
6 | .config(function($stateProvider) {
7 | $stateProvider
8 | .state('home', {
9 | url: '/home',
10 | templateUrl: 'app/home/home.html',
11 | controller: 'HomeCtrl',
12 | controllerAs: 'Home',
13 | authenticate: true
14 | })
15 | });
16 |
17 | })(angular)
18 |
--------------------------------------------------------------------------------
/client/app/interceptor.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function(angular) {
4 |
5 | angular.module('angularJsSeedApp')
6 | .factory('authInterceptor', function ($rootScope, $q, $cookies, $injector) {
7 | var state;
8 | return {
9 | // Add authorization token to headers
10 | request: function(config) {
11 | config.headers = config.headers || {};
12 | if ($cookies && $cookies.get('token')) {
13 | config.headers.Authorization = 'Bearer ' + JSON.parse($cookies.get('token'));
14 | }
15 | return config;
16 | },
17 |
18 | // Intercept 401s and redirect you sto login
19 | responseError: function(response) {
20 | if (response.status === 401) {
21 | (state || (state = $injector.get('$state'))).go('login');
22 | // remove any stale tokens
23 | $cookies.remove('token');
24 | return $q.reject(response);
25 | }
26 | else {
27 | return $q.reject(response);
28 | }
29 | }
30 | };
31 |
32 | })
33 |
34 | })(angular);
35 |
--------------------------------------------------------------------------------
/client/app/landing/landing.controller.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function (angular) {
4 |
5 | function landingCtrl(ModalService) {
6 |
7 | /**
8 | * Controller variables
9 | */
10 | var Landing = this;
11 |
12 | }
13 |
14 | angular.module('angularJsSeedApp')
15 | .controller('LandingCtrl', landingCtrl);
16 |
17 | })(angular)
18 |
--------------------------------------------------------------------------------
/client/app/landing/landing.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Hello, world!
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/client/app/landing/landing.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function (angular) {
4 |
5 | angular.module('angularJsSeedApp')
6 | .config(function($stateProvider) {
7 | $stateProvider
8 | .state('landing', {
9 | url: '/',
10 | templateUrl: 'app/landing/landing.html',
11 | controller: 'LandingCtrl',
12 | controllerAs: 'landing'
13 | });
14 | });
15 |
16 | })(angular)
17 |
--------------------------------------------------------------------------------
/client/assets/images/yeoman.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/princesoni1989/angular-js-seed/2e8338075f6c03f6204dab1a73f357a48d16da5e/client/assets/images/yeoman.png
--------------------------------------------------------------------------------
/client/components/api-services/user/user.service.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function (angular) {
4 |
5 | angular.module('angularJsSeedApp')
6 | .factory('User', ['$resource', 'Config', function ($resource, Config) {
7 | return $resource(Config.getHost() + '/api/users/:id/:controller', {
8 | id: '@_id'
9 | },
10 | {
11 | get: {
12 | method: 'GET',
13 | params: {
14 | id:'me'
15 | }
16 | },
17 | forgotPassword: {
18 | method: 'POST',
19 | params: {
20 | id:'forgotPassword'
21 | }
22 | },
23 | changePassword: {
24 | method: 'PUT',
25 | params: {
26 | controller:'password'
27 | }
28 | }
29 | });
30 | }]);
31 |
32 | })(angular);
33 |
--------------------------------------------------------------------------------
/client/components/auth/auth.service.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | (function (angular) {
3 |
4 |
5 | function Auth($http, User, $cookieStore, $q, Config) {
6 | var currentUser = {};
7 | var token = $cookieStore && $cookieStore.get('token');
8 | if (token) {
9 | currentUser = User.get();
10 | }
11 |
12 | return {
13 |
14 | /**
15 | * Authenticate user and save token
16 | *
17 | * @param {Object} user - login info
18 | * @param {Function} callback - optional
19 | * @return {Promise}
20 | */
21 | login: function (user, callback) {
22 | var cb = callback || angular.noop;
23 | var deferred = $q.defer();
24 |
25 | $http.post(Config.getHost() + '/auth/local', {
26 | email: user.email,
27 | password: user.password
28 | }).
29 | success(function (data) {
30 | $cookieStore.put('token', data.token);
31 | currentUser = User.get();
32 | deferred.resolve(data);
33 | return cb();
34 | }).
35 | error(function (err) {
36 | this.logout();
37 | deferred.reject(err);
38 | return cb(err);
39 | }.bind(this));
40 |
41 | return deferred.promise;
42 | },
43 |
44 | /**
45 | * Delete access token and user info
46 | *
47 | * @param {Function}
48 | */
49 | logout: function () {
50 | $cookieStore.remove('token');
51 | currentUser = {};
52 | },
53 |
54 | /**
55 | * Create a new user
56 | *
57 | * @param {Object} user - user info
58 | * @param {Function} callback - optional
59 | * @return {Promise}
60 | */
61 | createUser: function (user, callback) {
62 | var cb = callback || angular.noop;
63 |
64 | return User.save(user,
65 | function (data) {
66 | $cookieStore.put('token', data.token);
67 | currentUser = User.get();
68 | return cb(user);
69 | },
70 | function (err) {
71 | this.logout();
72 | return cb(err);
73 | }.bind(this)).$promise;
74 | },
75 |
76 | /**
77 | * Change password
78 | *
79 | * @param {String} oldPassword
80 | * @param {String} newPassword
81 | * @param {Function} callback - optional
82 | * @return {Promise}
83 | */
84 | changePassword: function (oldPassword, newPassword, callback) {
85 | var cb = callback || angular.noop;
86 |
87 | return User.changePassword({id: currentUser._id}, {
88 | oldPassword: oldPassword,
89 | newPassword: newPassword
90 | }, function (user) {
91 | return cb(user);
92 | }, function (err) {
93 | return cb(err);
94 | }).$promise;
95 | },
96 |
97 | /**
98 | * Gets all available info on authenticated user
99 | *
100 | * @return {Object} user
101 | */
102 | getCurrentUser: function () {
103 | return currentUser;
104 | },
105 |
106 | /**
107 | * Check if a user is logged in
108 | *
109 | * @return {Boolean}
110 | */
111 | isLoggedIn: function () {
112 | return currentUser.hasOwnProperty('role');
113 | },
114 |
115 | /**
116 | * Waits for currentUser to resolve before checking if user is logged in
117 | */
118 | isLoggedInAsync: function (cb) {
119 | if (currentUser.hasOwnProperty('$promise')) {
120 | currentUser.$promise.then(function () {
121 | cb(true);
122 | }).catch(function () {
123 | cb(false);
124 | });
125 | } else if (currentUser.hasOwnProperty('role')) {
126 | cb(true);
127 | } else {
128 | cb(false);
129 | }
130 | },
131 |
132 | /**
133 | * Check if a user is an admin
134 | *
135 | * @return {Boolean}
136 | */
137 | isAdmin: function () {
138 | return currentUser.role === 'admin';
139 | },
140 |
141 | /**
142 | * Get auth token
143 | */
144 | getToken: function () {
145 | return $cookieStore.get('token');
146 | }
147 | };
148 | };
149 |
150 | angular.module('angularJsSeedApp')
151 | .factory('Auth', Auth)
152 | })(angular);
153 |
--------------------------------------------------------------------------------
/client/components/config/config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by princesoni on 11/13/15.
3 | */
4 | 'use strict';
5 |
6 | (function (angular) {
7 | //configuration object
8 | function config() {
9 | var configuration = {
10 | ENV: 'DEVELOPMENT',
11 |
12 | ENVIRONMENTS: {
13 |
14 | STAGING: {
15 | URL: 'http://localhost:9000'
16 | },
17 |
18 | PRODUCTION: {
19 | URL: 'http://localhost:9000'
20 | },
21 |
22 | DEVELOPMENT: {
23 | URL: 'https://frozen-tundra-93174.herokuapp.com'
24 | }
25 | },
26 |
27 | getHost: function () {
28 | return this.ENVIRONMENTS[this.ENV] && this.ENVIRONMENTS[this.ENV].URL;
29 | }
30 |
31 | }
32 | return configuration;
33 | }
34 |
35 | //factory declaration
36 | angular.module('angularJsSeedApp')
37 | .factory('Config', config)
38 |
39 | })(angular);
40 |
--------------------------------------------------------------------------------
/client/components/constants/constants.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by princesoni on 11/13/15.
3 | */
4 | 'use strict';
5 |
6 | (function (angular) {
7 |
8 | function constants() {
9 |
10 | return {
11 | //User roles
12 | roles: {
13 | BUSINESS_USER: 'businessUser',
14 | USER: 'user'
15 | },
16 | popup: {
17 | SUCCESS: 'SUCCESS',
18 | ERROR: 'ERROR'
19 | }
20 | }
21 | }
22 |
23 | //factory declaration
24 | angular.module('angularJsSeedApp')
25 | .factory('Constants', constants);
26 |
27 | })(angular);
28 |
--------------------------------------------------------------------------------
/client/components/footer/footer.directive.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function (angular) {
4 |
5 | angular.module('angularJsSeedApp')
6 | .directive('footer', function () {
7 | return {
8 | templateUrl: 'components/footer/footer.html',
9 | restrict: 'E',
10 | link: function (scope, element) {
11 | element.addClass('footer');
12 | }
13 | };
14 | });
15 |
16 | })(angular);
17 |
--------------------------------------------------------------------------------
/client/components/footer/footer.html:
--------------------------------------------------------------------------------
1 |
2 |
Footer
3 |
4 |
--------------------------------------------------------------------------------
/client/components/header/header.controller.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function (angular) {
4 |
5 | function header($scope, Auth) {
6 | var Header = this;
7 | Header.menu = [{
8 | 'title': 'Home',
9 | 'state': 'home'
10 | }];
11 |
12 | Header.isCollapsed = true;
13 | Header.isLoggedIn = Auth.isLoggedIn;
14 | Header.isAdmin = Auth.isAdmin;
15 | Header.getCurrentUser = Auth.getCurrentUser;
16 | }
17 |
18 | //controller declaration
19 | angular.module('angularJsSeedApp')
20 | .controller('HeaderCtrl', header);
21 |
22 | })(angular)
23 |
--------------------------------------------------------------------------------
/client/components/header/header.directive.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function (angular) {
4 |
5 | angular.module('angularJsSeedApp')
6 | .directive('header', function () {
7 | return {
8 | templateUrl: 'components/header/header.html',
9 | restrict: 'E',
10 | controller: 'HeaderCtrl'
11 | };
12 | });
13 |
14 | })(angular)
15 |
16 |
--------------------------------------------------------------------------------
/client/components/header/header.html:
--------------------------------------------------------------------------------
1 |
24 |
--------------------------------------------------------------------------------
/client/components/loader/loader.service.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function (angular) {
4 | //Loader service
5 | function loaderService() {
6 | return {
7 | show: function (ele) {
8 | if (ele) {
9 | angular.element(ele).css('display', 'block');
10 | } else {
11 | angular.element('.loader').css('display', 'block');
12 | }
13 | },
14 |
15 | hide: function (ele) {
16 | if (ele) {
17 | angular.element(ele).css('display', 'none');
18 | } else {
19 | angular.element('.loader').css('display', 'none');
20 | }
21 | }
22 | }
23 | };
24 |
25 | angular.module('angularJsSeedApp')
26 | .factory('LoaderService', loaderService)
27 |
28 | })(angular);
29 |
--------------------------------------------------------------------------------
/client/components/messages/messages.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function (angular) {
4 | //Message constants
5 | function Constants() {
6 | return {
7 | api: {
8 | error: 'Error in getting data from server, Please try again later'
9 | }
10 | };
11 | };
12 |
13 | angular.module('angularJsSeedApp')
14 | .factory('Messages', Constants)
15 | })(angular)
16 |
--------------------------------------------------------------------------------
/client/components/modal/modal.controller.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 | (function (angular) {
4 |
5 | function ModalCtrl($modalInstance, $state, modalView, popupData, Constants, Messages, Helper, $timeout) {
6 | /**
7 | * Controller variable
8 | */
9 | var ctrl = this;
10 | ctrl.view = modalView;
11 | ctrl.popupData = popupData;
12 |
13 | /**
14 | * close modal
15 | * @param reload
16 | */
17 | ctrl.closeModal = function (reload) {
18 | $modalInstance.dismiss("cancel");
19 | };
20 | }
21 |
22 | angular.module('angularJsSeedApp')
23 | .controller('ModalCtrl', ModalCtrl);
24 | })(angular);
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/client/components/modal/modal.css:
--------------------------------------------------------------------------------
1 | .modal-primary .modal-header,
2 | .modal-info .modal-header,
3 | .modal-success .modal-header,
4 | .modal-warning .modal-header,
5 | .modal-danger .modal-header {
6 | color: #fff;
7 | border-radius: 5px 5px 0 0;
8 | }
9 | .modal-primary .modal-header {
10 | background: #428bca;
11 | }
12 | .modal-info .modal-header {
13 | background: #5bc0de;
14 | }
15 | .modal-success .modal-header {
16 | background: #5cb85c;
17 | }
18 | .modal-warning .modal-header {
19 | background: #f0ad4e;
20 | }
21 | .modal-danger .modal-header {
22 | background: #d9534f;
23 | }
24 |
--------------------------------------------------------------------------------
/client/components/modal/modal.service.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | (function (angular) {
3 | /**
4 | * Modal service
5 | * @param $modal
6 | * @param Constants
7 | * @param $timeout
8 | * @param $state
9 | * @returns {{successPopup: Function, errorPopup: Function}}
10 | * @constructor
11 | */
12 | function ModalService($modal, Constants,$timeout, $state) {
13 | function openModal(success, dismiss, view, data, sizeClass, controller) {
14 | controller = controller && controller + ' as popUp' || '';
15 | var modalInstance = $modal.open({
16 | templateUrl: 'components/modal/popUp.html',
17 | controller: controller || 'ModalCtrl as popUp',
18 | windowClass: 'modal-container',
19 | size: sizeClass,
20 | backdrop: "static",
21 | keyboard: false,
22 | resolve: {
23 | modalView: function () {
24 | return view;
25 | },
26 | popupData: function () {
27 | return data;
28 | }
29 | }
30 | });
31 | modalInstance.result.then(success, dismiss || angular.noop);
32 | }
33 |
34 | return {
35 | successPopup: function (data, successCallback, dismissCallback) {
36 | openModal(successCallback, dismissCallback, Constants.popup.SUCCESS, data, "md");
37 | },
38 | errorPopup: function (data, successCallback, dismissCallback) {
39 | openModal(successCallback, dismissCallback, Constants.popup.ERROR, data, "md");
40 | }
41 | }
42 | }
43 |
44 | angular.module("angularJsSeedApp")
45 | .factory("ModalService", ModalService);
46 | })(angular);
47 |
48 |
--------------------------------------------------------------------------------
/client/components/modal/popUp.html:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/client/components/modal/views/error.html:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/client/components/modal/views/success.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
9 |
Success
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/client/components/util/helper.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by princesoni on 11/13/15.
3 | */
4 | 'use strict';
5 |
6 | /**
7 | * Helper service
8 | */
9 | (function (angular) {
10 | function Helper() {
11 | return {
12 |
13 | /**
14 | *
15 | * @param obj
16 | * @param keys
17 | * @returns {{}}
18 | */
19 | filterObject: function (obj, keys) {
20 | var result = {};
21 | for (var type in obj)
22 | if (keys.indexOf(type) > -1)
23 | result[type] = obj[type];
24 | return result;
25 | },
26 |
27 | /**
28 | *
29 | * @param text
30 | * @returns {*}
31 | */
32 | trim: function (text) {
33 | return text.replace(/\s+/, "")
34 | },
35 |
36 | /**
37 | *
38 | * @param arr
39 | * @returns {{}}
40 | */
41 | sortByKey: function (arr) {
42 | var ordered = {};
43 | Object.keys(arr).sort().forEach(function (key) {
44 | ordered[key] = arr[key];
45 | });
46 | return ordered
47 | }
48 | }
49 | }
50 |
51 | angular.module('angularJsSeedApp')
52 | .factory('Helper', Helper)
53 | })
54 | (angular);
55 |
--------------------------------------------------------------------------------
/client/favicon.ico:
--------------------------------------------------------------------------------
1 | � ( @ -2Op"=p�Jt��Jt��b���������������������������������������������������b���Jt��Jt��"=p�Op-2 O`O�O�O�O�O�O�O�$\�Jt��������������v���v���������������Jt��$\�O�O�O�O�O�O�O�O` O�O�O�O�O�O�O�O�O�O� ;n�s���>���>���>���>���s��� ;n�O�O�O�O�O�O�O�O�O�O� O`O�O�O�O�O�O�O�O�O�O�$\�]���^n��^n��]���$\�O�O�O�O�O�O�O�O�O�O�O` O�O�O�O�O�O�O�O�O�O�O�n�* ��* ��n�O�O�O�O�O�O�O�O�O�O�O� O�O�O�O�O�O�O�O�O�O�O�5>Y�5>Y�O�O�O�O�O�O�O�O�O�O�O� -2O�O�O�O�O�O�O�O�O�O�&6e�&6e�O�O�O�O�O�O�O�O�O�O�-2 5r�4���E���$\�O�O�O�O�O�O�O�O�O�O�O�O�O�O�O�O�O�O�$\�E���4���5r� 5r�E���M���M���v���0\��O�O�O�O�O�O�O�$\�$\�O�O�O�O�O�O�O�0\��v���M���M���E���5r� )��p&��p��&��������������b���Jt��Jt��Jt��0\��#i��.r��.r��#i��0\��Jt��Jt��Jt��b���������������&��p��&��)��p 4���&��-���_������������������]���]�������7���p�����������p���7�������]���]�������������������_��-���-���4��� qֈp��p��p����������������������p���7���#i��p�����������p���#i��7���p�����������������������p��&��-���qֈ 8��(p��p��I���v���v���]���7���n���v���p���#i��]���v���v���]���#i��p���v���n���7���]���v���v���I���-���-���8��( ;��`-���M���7���7���7���.r��R��E��R��E��7���7���7���7���E��R��E��R��.r��7���7���7���M���M���;��` ���������������������������z ���������������������������
2 | � ���
3 | �
9�
9�
9�
9�
9�
9�
9�
9�
4 | �n�n�
5 | �
9�
9�
9�
9�
9�
9�
9�
9�
6 | ���� * �x* ��* ��* ��* ��* ��* ��* ��n�&