├── .gitignore
├── LICENSE
├── README.md
├── cookiecutter.json
└── {{cookiecutter.github_repository_name}}
└── src
├── .coveragerc
├── .travis.yml
├── Procfile
├── README.md
├── docs
├── api
│ ├── authentication.md
│ └── users.md
└── index.md
├── fabfile.py
├── frontend
├── .editorconfig
├── .travis.yml
├── README.md
├── config
│ ├── head-config.common.js
│ ├── helpers.js
│ ├── html-elements-plugin
│ │ └── index.js
│ ├── karma.conf.js
│ ├── modules
│ │ └── angular2-hmr-prod.js
│ ├── protractor.conf.js
│ ├── spec-bundle.js
│ ├── webpack.common.js
│ ├── webpack.dev.js
│ ├── webpack.prod.js
│ └── webpack.test.js
├── karma.conf.js
├── package.json
├── protractor.conf.js
├── src
│ ├── app
│ │ ├── +detail
│ │ │ ├── detail.component.ts
│ │ │ └── index.ts
│ │ ├── about
│ │ │ ├── about.component.ts
│ │ │ ├── about.spec.ts
│ │ │ └── index.ts
│ │ ├── app.component.ts
│ │ ├── app.e2e.ts
│ │ ├── app.module.ts
│ │ ├── app.resolver.ts
│ │ ├── app.routes.ts
│ │ ├── app.service.ts
│ │ ├── app.spec.ts
│ │ ├── app.style.css
│ │ ├── environment.ts
│ │ ├── home
│ │ │ ├── home.component.ts
│ │ │ ├── home.e2e.ts
│ │ │ ├── home.spec.ts
│ │ │ ├── home.style.scss
│ │ │ ├── home.template.pug
│ │ │ ├── index.ts
│ │ │ ├── title
│ │ │ │ ├── index.ts
│ │ │ │ ├── title.service.ts
│ │ │ │ └── title.spec.ts
│ │ │ └── x-large
│ │ │ │ ├── index.ts
│ │ │ │ ├── x-large.directive.ts
│ │ │ │ └── x-large.spec.ts
│ │ ├── index.ts
│ │ ├── md.module.ts
│ │ └── no-content
│ │ │ ├── index.ts
│ │ │ └── no-content.ts
│ ├── assets
│ │ ├── css
│ │ │ └── .gitkeep
│ │ ├── data.json
│ │ ├── humans.txt
│ │ ├── icon
│ │ │ ├── android-icon-144x144.png
│ │ │ ├── android-icon-192x192.png
│ │ │ ├── android-icon-36x36.png
│ │ │ ├── android-icon-48x48.png
│ │ │ ├── android-icon-72x72.png
│ │ │ ├── android-icon-96x96.png
│ │ │ ├── apple-icon-114x114.png
│ │ │ ├── apple-icon-120x120.png
│ │ │ ├── apple-icon-144x144.png
│ │ │ ├── apple-icon-152x152.png
│ │ │ ├── apple-icon-180x180.png
│ │ │ ├── apple-icon-57x57.png
│ │ │ ├── apple-icon-60x60.png
│ │ │ ├── apple-icon-72x72.png
│ │ │ ├── apple-icon-76x76.png
│ │ │ ├── apple-icon-precomposed.png
│ │ │ ├── apple-icon.png
│ │ │ ├── browserconfig.xml
│ │ │ ├── favicon-16x16.png
│ │ │ ├── favicon-32x32.png
│ │ │ ├── favicon-96x96.png
│ │ │ ├── favicon.ico
│ │ │ ├── ms-icon-144x144.png
│ │ │ ├── ms-icon-150x150.png
│ │ │ ├── ms-icon-310x310.png
│ │ │ └── ms-icon-70x70.png
│ │ ├── img
│ │ │ ├── angular-logo.png
│ │ │ ├── angularclass-avatar.png
│ │ │ └── angularclass-logo.png
│ │ ├── manifest.json
│ │ ├── mock-data
│ │ │ └── mock-data.json
│ │ ├── robots.txt
│ │ └── service-worker.js
│ ├── custom-typings.d.ts
│ ├── index.html
│ ├── main.browser.ts
│ ├── polyfills.browser.ts
│ └── vendor.browser.ts
├── tsconfig.json
├── tslint.json
├── typedoc.json
└── webpack.config.js
├── mkdocs.yml
├── requirements.txt
├── setup.cfg
├── setup.py
├── tests
├── setup.py
└── {{cookiecutter.app_name}}_tests
│ ├── __init__.py
│ ├── authentication
│ ├── __init__.py
│ └── test_signals.py
│ └── users
│ ├── __init__.py
│ ├── factories.py
│ ├── test_serializers.py
│ └── test_views.py
└── {{cookiecutter.app_name}}
├── __init__.py
├── authentication
├── __init__.py
├── migrations
│ └── __init__.py
├── models.py
├── urls.py
└── views.py
├── config
├── __init__.py
├── common.py
├── local.py
└── production.py
├── manage.py
├── urls.py
├── users
├── __init__.py
├── admin.py
├── migrations
│ ├── 0001_initial.py
│ └── __init__.py
├── models.py
├── permissions.py
├── serializers.py
└── views.py
└── wsgi.py
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | src/frontend/node_modules
3 | frontend/.gitignore
4 | frontend/src/app/about/about.spec.ts
5 | frontend/src/app/app.spec.ts
6 | frontend/src/app/app.style.css
7 | frontend/src/app/home/home.spec.ts
8 | frontend/src/app/home/home.style.scss
9 | frontend/src/app/home/home.template.pug
10 | frontend/src/app/home/title/title.spec.ts
11 | frontend/src/app/home/x-large/x-large.spec.ts
12 | frontend/src/app/md.module.ts
13 | frontend/src/app/no-content/no-content.ts
14 |
15 | *.pyc
16 | bin
17 | build
18 | include
19 | local
20 | man
21 | share
22 | Scripts
23 | .Python
24 | *~
25 | *.sqlite3
26 | .DS_Store
27 | .env
28 | static
29 |
30 | # @AngularClass
31 |
32 | # Logs
33 | logs
34 | *.log
35 |
36 | # Runtime data
37 | pids
38 | *.pid
39 | *.seed
40 |
41 | # Directory for instrumented libs generated by jscoverage/JSCover
42 | lib-cov
43 |
44 | # Coverage directory used by tools like istanbul
45 | coverage
46 |
47 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
48 | .grunt
49 |
50 | # Compiled binary addons (http://nodejs.org/api/addons.html)
51 | build/Release
52 |
53 | # Users Environment Variables
54 | .lock-wscript
55 |
56 | # OS generated files #
57 | ehthumbs.db
58 | Icon?
59 | Thumbs.db
60 |
61 | # Node Files #
62 | /node_modules
63 | /bower_components
64 | npm-debug.log
65 |
66 | # Coverage #
67 | /coverage/
68 |
69 | # Typing #
70 | /src/typings/tsd/
71 | /typings/
72 | /tsd_typings/
73 |
74 | # Dist #
75 | /dist
76 | /public/__build__/
77 | /src/*/__build__/
78 | /__build__/**
79 | /public/dist/
80 | /src/*/dist/
81 | /dist/**
82 | /.awcache
83 | .webpack.json
84 |
85 | # Doc #
86 | /doc/
87 |
88 | # IDE #
89 | .idea/
90 | *.swp
91 |
92 | *.db
93 |
94 | html/
95 | htmlcov/
96 | coverage/
97 | .coverage
98 | .tox
99 | nosetests.xml
100 | build/
101 | dist/
102 | *.egg-info/
103 | MANIFEST
104 |
105 | bin/
106 | include/
107 | lib/
108 | local/
109 |
110 | pip-log.txt
111 |
112 | env
113 | site
114 |
115 | scripts/make_angular_templates_raw.py
116 | */src/frontend/node_modules
117 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Amit Assaraf
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # angular 2 django boilerplate
2 | by @amitassaraf
3 |
4 | 
5 |
6 | Overview
7 | ===
8 | This is a flexiable boilerplate for Angular 2 and Django.
9 | It also uses cookiecutter.
10 |
11 | This repository is a merge of a django boilerplate and @AngularClass's angular2-webpack-starter.
12 |
13 | Quickstart
14 | ===
15 |
16 | To begin:
17 |
18 | Either use -
19 |
20 | ```bash
21 | cookiecutter gh:amitassaraf/angular2-django-boilerplate
22 | ```
23 |
24 | or
25 |
26 | ```bash
27 | git clone https://github.com/amitassaraf/angular2-django-boilerplate
28 |
29 | cd angular2-django-boilerplate
30 |
31 | cookiecutter .
32 | ```
33 |
34 | Then fill in all the information asked.
35 |
36 | If you don't have cookie cutter, install it using:
37 | ```bash
38 | pip install cookiecutter
39 | ```
40 |
41 | Frontend
42 | -----
43 | -----
44 |
45 | After running cookiecutter, enter yourappname/src/frontend
46 | and run:
47 | ```bash
48 | sudo npm install
49 | ```
50 |
51 | Then run:
52 | ```bash
53 | npm start
54 | ```
55 | To start the development web pack server and make sure everything is working good.
56 |
57 | at this point you can surf to http://localhost:3000 to see the boilerplate front end website.
58 |
59 | Backend
60 | ---
61 | -----
62 |
63 | Install all the requirements:
64 | ```bash
65 | pip install -r requirements.txt
66 | ```
67 |
68 | Create the Django DB:
69 | ```bash
70 | createdb {{cookiecutter.app_name}}
71 | ```
72 |
73 | Migrate the database and create a superuser:
74 | ```bash
75 | python {{cookiecutter.app_name}}/manage.py migrate
76 | python {{cookiecutter.app_name}}/manage.py createsuperuser
77 | ```
78 |
79 | Start the development server:
80 | ```bash
81 | python {{cookiecutter.app_name}}/manage.py runserver
82 | ```
83 |
84 | Contact Me
85 | ---
86 | ---
87 | If you have any problems/suggestions you can always contact me
88 |
89 | **Email**: amitassaraf@me.com
90 | **Website**: http://amitassaraf.com
91 |
--------------------------------------------------------------------------------
/cookiecutter.json:
--------------------------------------------------------------------------------
1 | {
2 | "github_repository_name": "my_app_g",
3 | "app_name": "my_app",
4 | "app_title": "{{cookiecutter.app_name | replace('_', ' ') | replace('-', ' ') | title}}",
5 | "angular_app_name": "{{cookiecutter.app_title | replace(cookiecutter.app_title | first, cookiecutter.app_title | first | lower, 1) | replace(' ', '')}}",
6 | "email": "amitassaraf@me.com",
7 | "description": "An angular 2 & django boilerplate",
8 | "github_username": "amitassaraf",
9 | "_copy_without_render": [
10 | "*node_modules"
11 | ]
12 | }
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/.coveragerc:
--------------------------------------------------------------------------------
1 | [run]
2 | branch = True
3 | omit = *migrations*,
4 | *urls*,
5 | *test*,
6 | *admin*,
7 | ./{{ cookiecutter.app_name }}/config/*,
8 | ./{{ cookiecutter.app_name }}/manage.py,
9 | ./{{ cookiecutter.app_name }}/wsgi.py,
10 | *__init__*
11 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 | services:
3 | - postgresql
4 | - redis-server
5 | python:
6 | - "2.7"
7 | before_script:
8 | - export DATABASE_URL=postgres://postgres@localhost/{{ cookiecutter.app_name }}
9 | - export DJANGO_SECRET=`openssl rand -base64 32`
10 | - psql -c 'CREATE DATABASE "{{ cookiecutter.app_name }}";' -U postgres
11 | install:
12 | - "pip install -r requirements/test.txt"
13 | script:
14 | - ./{{cookiecutter.app_name}}/manage.py test {{cookiecutter.app_name}}
15 | after_success:
16 | - coveralls
17 |
18 | deploy:
19 | provider: heroku
20 | app:
21 | master: {{cookiecutter.app_name}}-dev
22 | qa: {{cookiecutter.app_name}}-qa
23 | prod: {{cookiecutter.app_name}}-prod
24 | on:
25 | repo: {{cookiecutter.github_username}}/{{cookiecutter.github_repository_name}}
26 | run:
27 | - "./{{cookiecutter.app_name}}/manage.py migrate"
28 |
29 | notifications:
30 | email: false
31 |
32 | # This reportedly works around an issue downloading packages from pypi on
33 | # travis. Consider removing this after the underlying issue is fixed.
34 | # https://github.com/travis-ci/travis-ci/issues/2389
35 | sudo: false
36 |
37 | matrix:
38 | fast_finish: true
39 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/Procfile:
--------------------------------------------------------------------------------
1 | web: newrelic-admin run-program gunicorn --pythonpath="$PWD/{{ cookiecutter.app_name }}" wsgi:application
2 | worker: python {{cookiecutter.app_name}}/manage.py rqworker default
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/README.md:
--------------------------------------------------------------------------------
1 | #{{cookiecutter.github_repository_name}}
2 | [](https://travis-ci.org/{{cookiecutter.github_username}}/{{cookiecutter.github_repository_name}})
3 |
4 | {{cookiecutter.description}}. Check out the project's [documentation](http://{{cookiecutter.github_username}}.github.io/{{cookiecutter.github_repository_name}}/).
5 |
6 | # Prerequisites
7 | - [virtualenv](https://virtualenv.pypa.io/en/latest/)
8 | - [postgresql](http://www.postgresql.org/)
9 | - [redis](http://redis.io/)
10 | - [travis cli](http://blog.travis-ci.com/2013-01-14-new-client/)
11 | - [heroku toolbelt](https://toolbelt.heroku.com/)
12 |
13 | # Initialize the project
14 | Create and activate a virtualenv:
15 |
16 | ```bash
17 | virtualenv env
18 | source env/bin/activate
19 | ```
20 | Install dependencies:
21 |
22 | ```bash
23 | pip install -r requirements/local.txt
24 | ```
25 | Create the database:
26 |
27 | ```bash
28 | createdb {{cookiecutter.app_name}}
29 | ```
30 | Initialize the git repository
31 |
32 | ```
33 | git init
34 | git remote add origin git@github.com:{{cookiecutter.github_username}}/{{cookiecutter.github_repository_name}}.git
35 | ```
36 |
37 | Migrate the database and create a superuser:
38 | ```bash
39 | python {{cookiecutter.app_name}}/manage.py migrate
40 | python {{cookiecutter.app_name}}/manage.py createsuperuser
41 | ```
42 |
43 | Run the development server:
44 | ```bash
45 | python {{cookiecutter.app_name}}/manage.py runserver
46 | ```
47 |
48 | # Create Servers
49 | By default the included fabfile will setup three environments:
50 |
51 | - dev -- The bleeding edge of development
52 | - qa -- For quality assurance testing
53 | - prod -- For the live application
54 |
55 | Create these servers on Heroku with:
56 |
57 | ```bash
58 | fab init
59 | ```
60 |
61 | # Automated Deployment
62 | Deployment is handled via Travis. When builds pass Travis will automatically deploy that branch to Heroku. Enable this with:
63 | ```bash
64 | travis encrypt $(heroku auth:token) --add deploy.api_key
65 | ```
66 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/docs/api/authentication.md:
--------------------------------------------------------------------------------
1 | # Authentication
2 | For clients to authenticate, the token key should be included in the Authorization HTTP header. The key should be prefixed by the string literal "Token", with whitespace separating the two strings. For example:
3 |
4 | ```
5 | Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
6 | ```
7 |
8 | Unauthenticated responses that are denied permission will result in an HTTP `401 Unauthorized` response with an appropriate `WWW-Authenticate` header. For example:
9 |
10 | ```
11 | WWW-Authenticate: Token
12 | ```
13 |
14 | The curl command line tool may be useful for testing token authenticated APIs. For example:
15 |
16 | ```bash
17 | curl -X GET http://127.0.0.1:8000/api/v1/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'
18 | ```
19 |
20 | ## Retrieving Tokens
21 | Authorization tokens are issued and returned when a user registers. A registered user can also retrieve their token with the following request:
22 |
23 | **Request**:
24 |
25 | `POST` `api-token-auth/`
26 |
27 | Parameters:
28 |
29 | Name | Type | Description
30 | ---|---|---
31 | username | string | The user's username
32 | password | string | The user's password
33 |
34 | **Response**:
35 | ```json
36 | {
37 | "token" : "9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b"
38 | }
39 | ```
40 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/docs/api/users.md:
--------------------------------------------------------------------------------
1 | # Users
2 | Supports registering, viewing, and updating user accounts.
3 |
4 | ## Register a new user account
5 |
6 | **Request**:
7 |
8 | `POST` `/users/`
9 |
10 | Parameters:
11 |
12 | Name | Type | Description
13 | ---------|--------|---
14 | username | string | The username for the new user.
15 | password | string | The password for the new user.
16 |
17 | *Note:*
18 |
19 | - *Not* **Authorization Protected**
20 |
21 | **Response**:
22 |
23 | ```json
24 | Content-Type application/json
25 | 201 Created
26 |
27 | {
28 | "id": "6d5f9bae-a31b-4b7b-82c4-3853eda2b011",
29 | "username": "richard",
30 | "password": "pbkdf2_sha256$24000$aGozcCr6QXhv$WCgPt2voqVO+Nno2flVnNnLcfks6Yq8XJyxoadB/r50=",
31 | "auth_token": "132cf952e0165a274bf99e115ab483671b3d9ff6"
32 | }
33 | ```
34 |
35 | The `auth_token` returned with this response should be stored by the client for
36 | authenticating future requests to the API. See [Authentication](authentication.md).
37 |
38 |
39 | ## Get a user's profile information
40 |
41 | **Request**:
42 |
43 | `GET` `/users/:id`
44 |
45 | Parameters:
46 |
47 | *Note:*
48 |
49 | - **[Authorization Protected](authentication.md)**
50 |
51 | **Response**:
52 |
53 | ```json
54 | Content-Type application/json
55 | 200 OK
56 |
57 | {
58 | "id": "6d5f9bae-a31b-4b7b-82c4-3853eda2b011",
59 | "username": "richard",
60 | "first_name": "Richard",
61 | "last_name": "Hendriks"
62 | }
63 | ```
64 |
65 |
66 | ## Update your profile information
67 |
68 | **Request**:
69 |
70 | `PUT/PATCH` `/users/:id`
71 |
72 | Parameters:
73 |
74 | Name | Type | Description
75 | -----------|--------|---
76 | first_name | string | The new first_name of the user object.
77 | last_name | string | The new last_name of the user object.
78 |
79 |
80 | *Note:*
81 |
82 | - All parameters are optional
83 | - **[Authorization Protected](authentication.md)**
84 |
85 | **Response**:
86 |
87 | ```json
88 | Content-Type application/json
89 | 200 OK
90 |
91 | {
92 | "id": "6d5f9bae-a31b-4b7b-82c4-3853eda2b011",
93 | "username": "richard",
94 | "first_name": "Richard",
95 | "last_name": "Hendriks"
96 | }
97 | ```
98 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/docs/index.md:
--------------------------------------------------------------------------------
1 | #{{cookiecutter.github_repository_name}}
2 | [](https://travis-ci.org/{{cookiecutter.github_username}}/{{cookiecutter.github_repository_name}})
3 |
4 | {{cookiecutter.description}}. Check out the project's [documentation](http://{{cookiecutter.github_username}}.github.io/{{cookiecutter.github_repository_name}}/).
5 |
6 | # Prerequisites
7 | - [virtualenv](https://virtualenv.pypa.io/en/latest/)
8 | - [postgresql](http://www.postgresql.org/)
9 | - [redis](http://redis.io/)
10 | - [travis cli](http://blog.travis-ci.com/2013-01-14-new-client/)
11 | - [heroku toolbelt](https://toolbelt.heroku.com/)
12 |
13 | # Initialize the project
14 | Create and activate a virtualenv:
15 |
16 | ```bash
17 | virtualenv env
18 | source env/bin/activate
19 | ```
20 | Install dependencies:
21 |
22 | ```bash
23 | pip install -r requirements/local.txt
24 | ```
25 | Create the database:
26 |
27 | ```bash
28 | createdb {{cookiecutter.app_name}}
29 | ```
30 | Initialize the git repository
31 |
32 | ```
33 | git init
34 | git remote add origin git@github.com:{{cookiecutter.github_username}}/{{cookiecutter.github_repository_name}}.git
35 | ```
36 |
37 | Migrate, create a superuser, and run the server:
38 | ```bash
39 | python {{cookiecutter.app_name}}/manage.py migrate
40 | python {{cookiecutter.app_name}}/manage.py createsuperuser
41 | python {{cookiecutter.app_name}}/manage.py runserver
42 | ```
43 |
44 | # Create Servers
45 | By default the included fabfile will setup three environments:
46 |
47 | - dev -- The bleeding edge of development
48 | - qa -- For quality assurance testing
49 | - prod -- For the live application
50 |
51 | Create these servers on Heroku with:
52 |
53 | ```bash
54 | fab init
55 | ```
56 |
57 | # Automated Deployment
58 | Deployment is handled via Travis. When builds pass Travis will automatically deploy that branch to Heroku. Enable this with:
59 | ```bash
60 | travis encrypt $(heroku auth:token) --add deploy.api_key
61 | ```
62 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/fabfile.py:
--------------------------------------------------------------------------------
1 | import os
2 | import random
3 | import string
4 |
5 | from fabric.api import env, local, require, lcd
6 | from fabric.colors import cyan
7 | from fabric.operations import prompt
8 |
9 | current_dir = os.getcwd()
10 | env.project_name = '{{cookiecutter.app_name}}'
11 | env.branch = 'master'
12 | env.environments = ['dev',
13 | 'qa',
14 | 'prod']
15 |
16 |
17 | def serve():
18 | local('python {}/manage.py runserver'.format(env.project_name))
19 |
20 |
21 | def test():
22 | """
23 | Runs nose test suite
24 | """
25 | local('flake8 {}'.format(env.project_name))
26 | print cyan('flake8 passed!', bold=True)
27 | local('python {}/manage.py test'.format(env.project_name))
28 |
29 |
30 | def init():
31 | """
32 | Deploys servers
33 | """
34 | print cyan('Initializing...', bold=True)
35 | set_remotes()
36 | ask_for_aws_keys()
37 | for environment in env.environments:
38 | env.environment = environment
39 | env.server_name = '{}-{}'.format(env.project_name, env.environment)
40 | create_standard_server()
41 | deploy_docs()
42 |
43 |
44 | def set_remotes():
45 | """
46 | Sets git remotes based on project structure
47 | """
48 | require('project_name')
49 | print cyan('Setting git remotes...')
50 |
51 | local('git remote add dev git@heroku.com:{}-dev.git'.format(env.project_name))
52 | local('git remote add qa git@heroku.com:{}-qa.git'.format(env.project_name))
53 | local('git remote add prod git@heroku.com:{}-prod.git'.format(env.project_name))
54 |
55 |
56 | def ask_for_aws_keys():
57 | """
58 | Gets AWS keys from user
59 | """
60 | env.aws_access = prompt('AWS_ACCESS_KEY_ID?')
61 | env.aws_secret = prompt('AWS_SECRET_ACCESS_KEY?')
62 |
63 |
64 | def create_standard_server():
65 | """
66 | Creates a sever with a standard build
67 | """
68 | create_server()
69 | configure_sever()
70 | push()
71 | migrate()
72 | create_superuser()
73 | ps()
74 | open_heroku()
75 |
76 |
77 | def create_server():
78 | """
79 | Creates a new server on heroku
80 | """
81 | require('environment')
82 | require('project_name')
83 |
84 | print cyan('Creating new server'.format(env.project_name, env.environment))
85 | require('environment')
86 | local('heroku create {}-{} --buildpack https://github.com/heroku/heroku-buildpack-python'
87 | .format(env.project_name, env.environment))
88 |
89 |
90 | def configure_sever():
91 | """
92 | Configures server with a general configuration
93 | """
94 | require('environment')
95 | local('heroku addons:create heroku-postgresql --remote {}'.format(env.environment))
96 | local('heroku pg:backups schedule DATABASE --at "04:00 UTC" --remote {}'.format(env.environment))
97 | local('heroku pg:promote DATABASE_URL --remote {}'.format(env.environment))
98 | local('heroku addons:create redistogo:nano --remote {}'.format(env.environment))
99 | local('heroku addons:create newrelic:wayne --remote {}'.format(env.environment))
100 | local('heroku config:set NEW_RELIC_APP_NAME="{}" --remote {}'.format(env.project_name, env.environment))
101 | local('heroku config:set DJANGO_CONFIGURATION=Production --remote {}'.format(env.environment))
102 | local('heroku config:set DJANGO_SECRET_KEY="{}" --remote {}'.format(create_secret_key(), env.environment))
103 | set_aws_keys()
104 |
105 |
106 | def deploy_docs():
107 | print cyan('Deploying docs...')
108 | local('mkdocs gh-deploy')
109 |
110 |
111 | def push():
112 | require('environment')
113 | require('branch')
114 |
115 | print cyan('Pushing to Heroku...')
116 | require('environment')
117 | local('git push {} {}:master'.format(env.environment, env.branch))
118 |
119 |
120 | def migrate():
121 | require('environment')
122 | local('heroku run python {}/manage.py migrate --remote {}'.format(env.project_name,
123 | env.environment))
124 |
125 | def create_superuser():
126 | require('environment')
127 | local('heroku run python {}/manage.py '
128 | 'createsuperuser --remote {}'.format(env.project_name, env.environment))
129 |
130 |
131 | def ps():
132 | """
133 | Scales a web dyno on Heroku
134 | """
135 | require('environment')
136 | local('heroku ps:scale web=1:hobby --remote {}'.format(env.environment))
137 |
138 |
139 | def open_heroku():
140 | require('environment')
141 | local('heroku open --remote {}'.format(env.environment))
142 |
143 |
144 | def set_aws_keys():
145 | """
146 | Configures S3 Keys
147 | """
148 | require('aws_access')
149 | require('aws_secret')
150 | require('project_name')
151 |
152 | local('heroku config:set DJANGO_AWS_ACCESS_KEY_ID={} --remote {}'
153 | .format(env.aws_access, env.environment))
154 | local('heroku config:set DJANGO_AWS_SECRET_ACCESS_KEY={} --remote {}'
155 | .format(env.aws_secret, env.environment))
156 | local('heroku config:set DJANGO_AWS_STORAGE_BUCKET_NAME={0}-{1} --remote {1}'
157 | .format(env.project_name, env.environment))
158 |
159 |
160 | def create_secret_key():
161 | """
162 | Creates a random string of letters and numbers
163 | """
164 | return ''.join(random.choice(string.ascii_letters + string.digits) for i in range(30))
165 |
166 |
167 | def dev():
168 | """fab dev [command]"""
169 | env.environment = 'dev'
170 | env.branch = 'master'
171 |
172 |
173 | def qa():
174 | """fab staging [command]"""
175 | env.environment = 'qa'
176 | env.branch = 'qa'
177 |
178 |
179 | def prod():
180 | """fab staging [command]"""
181 | env.environment = 'prod'
182 | env.branch = 'prod'
183 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/.editorconfig:
--------------------------------------------------------------------------------
1 | # @AngularClass
2 | # http://editorconfig.org
3 |
4 | root = true
5 |
6 | [*]
7 | charset = utf-8
8 | indent_style = space
9 | indent_size = 2
10 | end_of_line = lf
11 | insert_final_newline = true
12 | trim_trailing_whitespace = true
13 |
14 | [*.md]
15 | insert_final_newline = false
16 | trim_trailing_whitespace = false
17 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "4"
4 | - "5"
5 | - "node"
6 | before_install:
7 | - export CHROME_BIN=chromium-browser
8 | - export DISPLAY=:99.0
9 | - sh -e /etc/init.d/xvfb start
10 | - sleep 3
11 | sudo: false
12 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | ___
8 |
9 |
10 |
11 | [](https://twitter.com/SwiftOnSecurity)
12 | [](https://github.com/auchenberg/volkswagen) [](https://badge.fury.io/gh/angularclass%2Fangular2-webpack-starter) [](https://david-dm.org/angularclass/angular2-webpack-starter)
13 | [](http://stackshare.io/angularclass/angular-2-webpack-starter)
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | # Angular2 Webpack Starter [](https://angularclass.com/slack-join) [](https://gitter.im/angularclass/angular2-webpack-starter?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
22 |
23 |
24 | > An Angular 2 starter kit featuring [Angular 2](https://angular.io) ([Router](https://angular.io/docs/js/latest/api/router/), [Forms](https://angular.io/docs/js/latest/api/forms/),
25 | [Http](https://angular.io/docs/js/latest/api/http/),
26 | [Services](https://gist.github.com/gdi2290/634101fec1671ee12b3e#_follow_@AngularClass_on_twitter),
27 | [Tests](https://angular.io/docs/js/latest/api/test/), [E2E](https://angular.github.io/protractor/#/faq#what-s-the-difference-between-karma-and-protractor-when-do-i-use-which-)), [Material](https://github.com/angular/material2), [Karma](https://karma-runner.github.io/), [Protractor](https://angular.github.io/protractor/), [Jasmine](https://github.com/jasmine/jasmine), [Istanbul](https://github.com/gotwarlost/istanbul), [TypeScript](http://www.typescriptlang.org/), [@types](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&cad=rja&uact=8&ved=0ahUKEwjgjdrR7u_NAhUQ7GMKHXgpC4EQFggnMAI&url=https%3A%2F%2Fwww.npmjs.com%2F~types&usg=AFQjCNG2PFhwEo88JKo12mrw_4d0w1oNiA&sig2=N69zbO0yN8ET7v4KVCUOKA), [TsLint](http://palantir.github.io/tslint/), [Codelyzer](https://github.com/mgechev/codelyzer), [Hot Module Replacement](https://webpack.github.io/docs/hot-module-replacement-with-webpack.html), and [Webpack 2](http://webpack.github.io/) by [AngularClass](https://angularclass.com).
28 |
29 | > If you're looking for Angular 1.x please use [NG6-starter](https://github.com/angularclass/NG6-starter)
30 | > If you're looking to learn about Webpack and ES6 Build Tools check out [ES6-build-tools](https://github.com/AngularClass/ES6-build-tools)
31 | > If you're looking to learn TypeScript see [TypeStrong/learn-typescript](https://github.com/TypeStrong/learn-typescript)
32 | > If you're looking for something easier to get started with then see the angular2-seed that I also maintain [angular/angular2-seed](https://github.com/AngularClass/angular2-seed)
33 | > If you're looking to add Angular 2 Material Design we have a branch [material2](https://github.com/AngularClass/angular2-webpack-starter/tree/material2)
34 |
35 | This seed repo serves as an Angular 2 starter for anyone looking to get up and running with Angular 2 and TypeScript fast. Using a [Webpack 2](http://webpack.github.io/) for building our files and assisting with boilerplate. We're also using Protractor for our end-to-end story and Karma for our unit tests.
36 | * Best practices in file and application organization for Angular 2.
37 | * Ready to go build system using Webpack for working with TypeScript.
38 | * Angular 2 examples that are ready to go when experimenting with Angular 2.
39 | * A great Angular 2 seed repo for anyone who wants to start their project.
40 | * Testing Angular 2 code with Jasmine and Karma.
41 | * Coverage with Istanbul and Karma
42 | * End-to-end Angular 2 code using Protractor.
43 | * Type manager with @types
44 | * Hot Module Replacement with Webpack and [@angularclass/hmr](https://github.com/angularclass/angular2-hmr) and [@angularclass/hmr-loader](https://github.com/angularclass/angular2-hmr-loader)
45 | * Material Design with [angular/material2](https://github.com/angular/material2)
46 |
47 | ### Quick start
48 | **Make sure you have Node version >= 5.0 and NPM >= 3**
49 | > Clone/Download the repo then edit `app.ts` inside [`/src/app/app.ts`](/src/app/app.ts)
50 |
51 | ```bash
52 | # clone our repo
53 | # --depth 1 removes all but one .git commit history
54 | git clone --depth 1 https://github.com/angularclass/angular2-webpack-starter.git
55 |
56 | # change directory to our repo
57 | cd angular2-webpack-starter
58 |
59 | # install the repo with npm
60 | npm install
61 |
62 | # start the server
63 | npm start
64 |
65 | # use Hot Module Replacement
66 | npm run server:dev:hmr
67 |
68 | # if you're in China use cnpm
69 | # https://github.com/cnpm/cnpm
70 | ```
71 | go to [http://0.0.0.0:3000](http://0.0.0.0:3000) or [http://localhost:3000](http://localhost:3000) in your browser
72 |
73 | # Table of Contents
74 | * [File Structure](#file-structure)
75 | * [Getting Started](#getting-started)
76 | * [Dependencies](#dependencies)
77 | * [Installing](#installing)
78 | * [Running the app](#running-the-app)
79 | * [Configuration](#configuration)
80 | * [Contributing](#contributing)
81 | * [TypeScript](#typescript)
82 | * [@Types](#types)
83 | * [Frequently asked questions](#frequently-asked-questions)
84 | * [Support, Questions, or Feedback](#support-questions-or-feedback)
85 | * [License](#license)
86 |
87 |
88 | ## File Structure
89 | We use the component approach in our starter. This is the new standard for developing Angular apps and a great way to ensure maintainable code by encapsulation of our behavior logic. A component is basically a self contained app usually in a single file or a folder with each concern as a file: style, template, specs, e2e, and component class. Here's how it looks:
90 | ```
91 | angular2-webpack-starter/
92 | ├──config/ * our configuration
93 | | ├──helpers.js * helper functions for our configuration files
94 | | ├──spec-bundle.js * ignore this magic that sets up our angular 2 testing environment
95 | | ├──karma.conf.js * karma config for our unit tests
96 | | ├──protractor.conf.js * protractor config for our end-to-end tests
97 | │ ├──webpack.dev.js * our development webpack config
98 | │ ├──webpack.prod.js * our production webpack config
99 | │ └──webpack.test.js * our testing webpack config
100 | │
101 | ├──src/ * our source files that will be compiled to javascript
102 | | ├──main.browser.ts * our entry file for our browser environment
103 | │ │
104 | | ├──index.html * Index.html: where we generate our index page
105 | │ │
106 | | ├──polyfills.ts * our polyfills file
107 | │ │
108 | | ├──vendor.ts * our vendor file
109 | │ │
110 | │ ├──app/ * WebApp: folder
111 | │ │ ├──app.spec.ts * a simple test of components in app.ts
112 | │ │ ├──app.e2e.ts * a simple end-to-end test for /
113 | │ │ └──app.ts * App.ts: a simple version of our App component components
114 | │ │
115 | │ └──assets/ * static assets are served here
116 | │ ├──icon/ * our list of icons from www.favicon-generator.org
117 | │ ├──service-worker.js * ignore this. Web App service worker that's not complete yet
118 | │ ├──robots.txt * for search engines to crawl your website
119 | │ └──humans.txt * for humans to know who the developers are
120 | │
121 | │
122 | ├──tslint.json * typescript lint config
123 | ├──typedoc.json * typescript documentation generator
124 | ├──tsconfig.json * config that webpack uses for typescript
125 | ├──package.json * what npm uses to manage it's dependencies
126 | └──webpack.config.js * webpack main configuration file
127 |
128 | ```
129 |
130 | # Getting Started
131 | ## Dependencies
132 | What you need to run this app:
133 | * `node` and `npm` (`brew install node`)
134 | * Ensure you're running the latest versions Node `v4.x.x`+ (or `v5.x.x`) and NPM `3.x.x`+
135 |
136 | Once you have those, you should install these globals with `npm install --global`:
137 | * `webpack` (`npm install --global webpack`)
138 | * `webpack-dev-server` (`npm install --global webpack-dev-server`)
139 | * `karma` (`npm install --global karma-cli`)
140 | * `protractor` (`npm install --global protractor`)
141 | * `typescript` (`npm install --global typescript`)
142 |
143 | ## Installing
144 | * `fork` this repo
145 | * `clone` your fork
146 | * `npm install webpack-dev-server rimraf webpack -g` to install required global dependencies
147 | * `npm install` to install all dependencies
148 | * `npm run server` to start the dev server in another tab
149 |
150 | ## Running the app
151 | After you have installed all dependencies you can now run the app. Run `npm run server` to start a local server using `webpack-dev-server` which will watch, build (in-memory), and reload for you. The port will be displayed to you as `http://0.0.0.0:3000` (or if you prefer IPv6, if you're using `express` server, then it's `http://[::1]:3000/`).
152 |
153 | ### server
154 | ```bash
155 | # development
156 | npm run server
157 | # production
158 | npm run build:prod
159 | npm run server:prod
160 | ```
161 |
162 | ## Other commands
163 |
164 | ### build files
165 | ```bash
166 | # development
167 | npm run build:dev
168 | # production
169 | npm run build:prod
170 | ```
171 |
172 | ### hot module replacement
173 | ```bash
174 | npm run server:dev:hmr
175 | ```
176 |
177 | ### watch and build files
178 | ```bash
179 | npm run watch
180 | ```
181 |
182 | ### run tests
183 | ```bash
184 | npm run test
185 | ```
186 |
187 | ### watch and run our tests
188 | ```bash
189 | npm run watch:test
190 | ```
191 |
192 | ### run end-to-end tests
193 | ```bash
194 | # make sure you have your server running in another terminal
195 | npm run e2e
196 | ```
197 |
198 | ### run webdriver (for end-to-end)
199 | ```bash
200 | npm run webdriver:update
201 | npm run webdriver:start
202 | ```
203 |
204 | ### run Protractor's elementExplorer (for end-to-end)
205 | ```bash
206 | npm run webdriver:start
207 | # in another terminal
208 | npm run e2e:live
209 | ```
210 |
211 | # Configuration
212 | Configuration files live in `config/` we are currently using webpack, karma, and protractor for different stages of your application
213 |
214 | # Contributing
215 | You can include more examples as components but they must introduce a new concept such as `Home` component (separate folders), and Todo (services). I'll accept pretty much everything so feel free to open a Pull-Request
216 |
217 | # TypeScript
218 | > To take full advantage of TypeScript with autocomplete you would have to install it globally and use an editor with the correct TypeScript plugins.
219 |
220 | ## Use latest TypeScript compiler
221 | TypeScript 1.7.x includes everything you need. Make sure to upgrade, even if you installed TypeScript previously.
222 |
223 | ```
224 | npm install --global typescript
225 | ```
226 |
227 | ## Use a TypeScript-aware editor
228 | We have good experience using these editors:
229 |
230 | * [Visual Studio Code](https://code.visualstudio.com/)
231 | * [Webstorm 10](https://www.jetbrains.com/webstorm/download/)
232 | * [Atom](https://atom.io/) with [TypeScript plugin](https://atom.io/packages/atom-typescript)
233 | * [Sublime Text](http://www.sublimetext.com/3) with [Typescript-Sublime-Plugin](https://github.com/Microsoft/Typescript-Sublime-plugin#installation)
234 |
235 | # Types
236 | > When you include a module that doesn't include Type Definitions inside of the module you can include external Type Definitions with @types
237 |
238 | ## Custom Type Definitions
239 | When including 3rd party modules you also need to include the type definition for the module
240 | if they don't provide one within the module. You can try to install it with @types
241 |
242 | ```
243 | npm install @types/node
244 | npm install @types/lodash
245 | ```
246 |
247 | If you can't find the type definition in the registry we can make an ambient definition in
248 | this file for now. For example
249 |
250 | ```typescript
251 | declare module "my-module" {
252 | export function doesSomething(value: string): string;
253 | }
254 | ```
255 |
256 |
257 | If you're prototyping and you will fix the types later you can also declare it as type any
258 |
259 | ```typescript
260 | declare var assert: any;
261 | declare var _: any;
262 | declare var $: any;
263 | ```
264 |
265 | If you're importing a module that uses Node.js modules which are CommonJS you need to import as
266 |
267 | ```typescript
268 | import * as _ from 'lodash';
269 | ```
270 |
271 |
272 | # Frequently asked questions
273 | * What's the current browser support for Angular 2 Beta?
274 | * Please view the updated list of [browser support for Angular 2](https://github.com/angularclass/awesome-angular2#current-browser-support-for-angular-2)
275 | * Why is my service, aka provider, is not injecting parameter correctly?
276 | * Please use `@Injectable()` for your service for typescript to correctly attach the metadata (this is a TypeScript problem)
277 | * How do I run protractor with node 0.12.x?
278 | * please check out this repo to use the old version of protractor [#146](https://github.com/AngularClass/angular2-webpack-starter/pull/146/files)
279 | * Where do I write my tests?
280 | * You can write your tests next to your component files. See [`/src/app/home/home.spec.ts`](/src/app/home/home.spec.ts)
281 | * How do I start the app when I get `EACCES` and `EADDRINUSE` errors?
282 | * The `EADDRINUSE` error means the port `3000` is currently being used and `EACCES` is lack of permission for webpack to build files to `./dist/`
283 | * How to use `sass` for css?
284 | * `loaders: ['raw-loader','sass-loader']` and `@Component({ styles: [ require('./filename.scss') ] })` see issue [#136](https://github.com/AngularClass/angular2-webpack-starter/issues/136)
285 | * How do I test a Service?
286 | * See issue [#130](https://github.com/AngularClass/angular2-webpack-starter/issues/130#issuecomment-158872648)
287 | * How do I add `vscode-chrome-debug` support?
288 | * The VS Code chrome debug extension support can be done via `launch.json` see issue [#144](https://github.com/AngularClass/angular2-webpack-starter/issues/144#issuecomment-164063790)
289 | * How do I make the repo work in a virtual machine?
290 | * You need to use `0.0.0.0` so revert these changes [#205](https://github.com/AngularClass/angular2-webpack-starter/pull/205/files)
291 | * What are the naming conventions for Angular 2?
292 | * please see issue [#185](https://github.com/AngularClass/angular2-webpack-starter/issues/185) and PR [196](https://github.com/AngularClass/angular2-webpack-starter/pull/196)
293 | * How do I include bootstrap or jQuery?
294 | * please see issue [#215](https://github.com/AngularClass/angular2-webpack-starter/issues/215) and [#214](https://github.com/AngularClass/angular2-webpack-starter/issues/214#event-511768416)
295 | * How do I async load a component?
296 | * see wiki [How-do-I-async-load-a-component-with-AsyncRoute](https://github.com/AngularClass/angular2-webpack-starter/wiki/How-do-I-async-load-a-component-with-AsyncRoute)
297 | * Error: Cannot find module 'tapable'
298 | * Remove `node_modules/` and run `npm cache clean` then `npm install`
299 | * What about Webpack 2?
300 | * If you're looking for Webpack 2 version then see the [experimental version](https://github.com/gdi2290/angular2-webpack2-starter) that will be merged soon.
301 | * How do I turn on Hot Module Replacement
302 | * Run `npm run server:dev:hmr`
303 | * `RangeError: Maximum call stack size exceeded`
304 | * This is a problem with minifying Angular 2 and it's recent JIT templates. If you set `mangle` to `false` then you should be good.
305 | * Why is the size of my app larger in development?
306 | * We are using inline source-maps and hot module replacement which will increase the bundle size.
307 | * If you're in China
308 | * check out https://github.com/cnpm/cnpm
309 | * If you're looking to add Angular 2 Material Design
310 | * check out the [material2](https://github.com/AngularClass/angular2-webpack-starter/tree/material2) branch
311 | * node-pre-gyp ERR in npm install (Windows)
312 | * install Python x86 version between 2.5 and 3.0 on windows see issue [#626](https://github.com/AngularClass/angular2-webpack-starter/issues/626)
313 | * `Error:Error: Parse tsconfig error [{"messageText":"Unknown compiler option 'lib'.","category":1,"code":5023},{"messageText":"Unknown compiler option 'strictNullChecks'.","category":1,"code":5023},{"messageText":"Unknown compiler option 'baseUrl'.","category":1,"code":5023},{"messageText":"Unknown compiler option 'paths'.","category":1,"code":5023},{"messageText":"Unknown compiler option 'types'.","category":1,"code":5023}]`
314 | * remove `node_modules/typescript` and run `npm install typescript@beta`. This repo now uses ts 2.0
315 |
316 | # Support, Questions, or Feedback
317 | > Contact us anytime for anything about this repo or Angular 2
318 |
319 | * [Chat: AngularClass.slack](http://angularclass.com/member-join/)
320 | * [Twitter: @AngularClass](https://twitter.com/AngularClass)
321 | * [Gitter: AngularClass/angular2-webpack-starter](https://gitter.im/angularclass/angular2-webpack-starter)
322 |
323 | # Quick Start Guides
324 |
325 | ## Nitrous
326 |
327 | You can quickly create a free development environment to get started using this
328 | starter kit in the cloud on [Nitrous](https://www.nitrous.io/):
329 |
330 |
331 |
332 |
333 |
334 | Simply run `HOST=0.0.0.0 npm start` from the terminal inside of
335 | `~/code/angular2-webpack-starter` and access your site via the "Preview > 3000"
336 | link in the IDE.
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 | ___
345 |
346 | enjoy — **AngularClass**
347 |
348 |
349 |
350 | [](https://angularclass.com)
351 | ##[AngularClass](https://angularclass.com)
352 | > Learn AngularJS, Angular 2, and Modern Web Development from the best.
353 | > Looking for corporate Angular training, want to host us, or Angular consulting? patrick@angularclass.com
354 |
355 | ___
356 |
357 | # License
358 | [MIT](/LICENSE)
359 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/config/head-config.common.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Configuration for head elements added during the creation of index.html.
3 | *
4 | * All href attributes are added the publicPath (if exists) by default.
5 | * You can explicitly hint to prefix a publicPath by setting a boolean value to a key that has
6 | * the same name as the attribute you want to operate on, but prefix with =
7 | *
8 | * Example:
9 | * { name: "msapplication-TileImage", content: "/assets/icon/ms-icon-144x144.png", "=content": true },
10 | * Will prefix the publicPath to content.
11 | *
12 | * { rel: "apple-touch-icon", sizes: "57x57", href: "/assets/icon/apple-icon-57x57.png", "=href": false },
13 | * Will not prefix the publicPath on href (href attributes are added by default
14 | *
15 | */
16 | module.exports = {
17 | link: [
18 | /** tags for "apple-touch-icon" (AKA Web Clips). **/
19 | { rel: "apple-touch-icon", sizes: "57x57", href: "/assets/icon/apple-icon-57x57.png" },
20 | { rel: "apple-touch-icon", sizes: "60x60", href: "/assets/icon/apple-icon-60x60.png" },
21 | { rel: "apple-touch-icon", sizes: "72x72", href: "/assets/icon/apple-icon-72x72.png" },
22 | { rel: "apple-touch-icon", sizes: "76x76", href: "/assets/icon/apple-icon-76x76.png" },
23 | { rel: "apple-touch-icon", sizes: "114x114", href: "/assets/icon/apple-icon-114x114.png" },
24 | { rel: "apple-touch-icon", sizes: "120x120", href: "/assets/icon/apple-icon-120x120.png" },
25 | { rel: "apple-touch-icon", sizes: "144x144", href: "/assets/icon/apple-icon-144x144.png" },
26 | { rel: "apple-touch-icon", sizes: "152x152", href: "/assets/icon/apple-icon-152x152.png" },
27 | { rel: "apple-touch-icon", sizes: "180x180", href: "/assets/icon/apple-icon-180x180.png" },
28 |
29 | /** tags for android web app icons **/
30 | { rel: "icon", type: "image/png", sizes: "192x192", href: "/assets/icon/android-icon-192x192.png" },
31 |
32 | /** tags for favicons **/
33 | { rel: "icon", type: "image/png", sizes: "32x32", href: "/assets/icon/favicon-32x32.png" },
34 | { rel: "icon", type: "image/png", sizes: "96x96", href: "/assets/icon/favicon-96x96.png" },
35 | { rel: "icon", type: "image/png", sizes: "16x16", href: "/assets/icon/favicon-16x16.png" },
36 |
37 | /** tags for a Web App Manifest **/
38 | { rel: "manifest", href: "/assets/manifest.json" }
39 | ],
40 | meta: [
41 | { name: "msapplication-TileColor", content: "#00bcd4" },
42 | { name: "msapplication-TileImage", content: "/assets/icon/ms-icon-144x144.png", "=content": true },
43 | { name: "theme-color", content: "#00bcd4" }
44 | ]
45 | };
46 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/config/helpers.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: @AngularClass
3 | */
4 | var path = require('path');
5 |
6 | // Helper functions
7 | var ROOT = path.resolve(__dirname, '..');
8 |
9 | function hasProcessFlag(flag) {
10 | return process.argv.join('').indexOf(flag) > -1;
11 | }
12 |
13 | function isWebpackDevServer() {
14 | return process.argv[1] && !! (/webpack-dev-server$/.exec(process.argv[1]));
15 | }
16 |
17 | function root(args) {
18 | args = Array.prototype.slice.call(arguments, 0);
19 | return path.join.apply(path, [ROOT].concat(args));
20 | }
21 |
22 | function checkNodeImport(context, request, cb) {
23 | if (!path.isAbsolute(request) && request.charAt(0) !== '.') {
24 | cb(null, 'commonjs ' + request); return;
25 | }
26 | cb();
27 | }
28 |
29 | exports.hasProcessFlag = hasProcessFlag;
30 | exports.isWebpackDevServer = isWebpackDevServer;
31 | exports.root = root;
32 | exports.checkNodeImport = checkNodeImport;
33 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/config/html-elements-plugin/index.js:
--------------------------------------------------------------------------------
1 |
2 | function HtmlElementsPlugin(locations) {
3 | this.locations = locations;
4 | }
5 |
6 | HtmlElementsPlugin.prototype.apply = function(compiler) {
7 | var self = this;
8 | compiler.plugin('compilation', function(compilation) {
9 | compilation.options.htmlElements = compilation.options.htmlElements || {};
10 |
11 | compilation.plugin('html-webpack-plugin-before-html-generation', function(htmlPluginData, callback) {
12 | const locations = self.locations;
13 |
14 | if (locations) {
15 | const publicPath = htmlPluginData.assets.publicPath;
16 |
17 | Object.getOwnPropertyNames(locations).forEach(function(loc) {
18 | compilation.options.htmlElements[loc] = getHtmlElementString(locations[loc], publicPath);
19 | });
20 | }
21 |
22 |
23 | callback(null, htmlPluginData);
24 | });
25 | });
26 |
27 | };
28 |
29 | const RE_ENDS_WITH_BS = /\/$/;
30 |
31 | /**
32 | * Create an HTML tag with attributes from a map.
33 | *
34 | * Example:
35 | * createTag('link', { rel: "manifest", href: "/assets/manifest.json" })
36 | * //
37 | * @param tagName The name of the tag
38 | * @param attrMap A Map of attribute names (keys) and their values.
39 | * @param publicPath a path to add to eh start of static asset url
40 | * @returns {string}
41 | */
42 | function createTag(tagName, attrMap, publicPath) {
43 | publicPath = publicPath || '';
44 |
45 | // add trailing slash if we have a publicPath and it doesn't have one.
46 | if (publicPath && !RE_ENDS_WITH_BS.test(publicPath)) publicPath += '/';
47 |
48 | const attributes = Object.getOwnPropertyNames(attrMap)
49 | .filter(function(name) { return name[0] !== '='; } )
50 | .map(function(name) {
51 | var value = attrMap[name];
52 |
53 | if (publicPath) {
54 | // check if we have explicit instruction, use it if so (e.g: =herf: false)
55 | // if no instruction, use public path if it's href attribute.
56 | const usePublicPath = attrMap.hasOwnProperty('=' + name) ? !!attrMap['=' + name] : name === 'href';
57 |
58 | if (usePublicPath) {
59 | // remove a starting trailing slash if the value has one so we wont have //
60 | value = publicPath + (value[0] === '/' ? value.substr(1) : value);
61 | }
62 | }
63 |
64 | return name + '="' + value + '"';
65 | });
66 |
67 | return '<' + tagName + ' ' + attributes.join(' ') + '>';
68 | }
69 |
70 | /**
71 | * Returns a string representing all html elements defined in a data source.
72 | *
73 | * Example:
74 | *
75 | * const ds = {
76 | * link: [
77 | * { rel: "apple-touch-icon", sizes: "57x57", href: "/assets/icon/apple-icon-57x57.png" }
78 | * ],
79 | * meta: [
80 | * { name: "msapplication-TileColor", content: "#00bcd4" }
81 | * ]
82 | * }
83 | *
84 | * getHeadTags(ds);
85 | * // " "
86 | * " "
87 | *
88 | * @returns {string}
89 | */
90 | function getHtmlElementString(dataSource, publicPath) {
91 | return Object.getOwnPropertyNames(dataSource)
92 | .map(function(name) {
93 | if (Array.isArray(dataSource[name])) {
94 | return dataSource[name].map(function(attrs) { return createTag(name, attrs, publicPath); } );
95 | } else {
96 | return [ createTag(name, dataSource[name], publicPath) ];
97 | }
98 | })
99 | .reduce(function(arr, curr) {
100 | return arr.concat(curr);
101 | }, [])
102 | .join('\n\t');
103 | }
104 | module.exports = HtmlElementsPlugin;
105 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/config/karma.conf.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: @AngularClass
3 | */
4 |
5 | module.exports = function(config) {
6 | var testWebpackConfig = require('./webpack.test.js');
7 |
8 | var configuration = {
9 |
10 | // base path that will be used to resolve all patterns (e.g. files, exclude)
11 | basePath: '',
12 |
13 | /*
14 | * Frameworks to use
15 | *
16 | * available frameworks: https://npmjs.org/browse/keyword/karma-adapter
17 | */
18 | frameworks: ['jasmine'],
19 |
20 | // list of files to exclude
21 | exclude: [ ],
22 |
23 | /*
24 | * list of files / patterns to load in the browser
25 | *
26 | * we are building the test environment in ./spec-bundle.js
27 | */
28 | files: [ { pattern: './config/spec-bundle.js', watched: false } ],
29 |
30 | /*
31 | * preprocess matching files before serving them to the browser
32 | * available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
33 | */
34 | preprocessors: { './config/spec-bundle.js': ['coverage', 'webpack', 'sourcemap'] },
35 |
36 | // Webpack Config at ./webpack.test.js
37 | webpack: testWebpackConfig,
38 |
39 | coverageReporter: {
40 | dir : 'coverage/',
41 | reporters: [
42 | { type: 'text-summary' },
43 | { type: 'json' },
44 | { type: 'html' }
45 | ]
46 | },
47 |
48 | // Webpack please don't spam the console when running in karma!
49 | webpackServer: { noInfo: true },
50 |
51 | /*
52 | * test results reporter to use
53 | *
54 | * possible values: 'dots', 'progress'
55 | * available reporters: https://npmjs.org/browse/keyword/karma-reporter
56 | */
57 | reporters: [ 'mocha', 'coverage' ],
58 |
59 | // web server port
60 | port: 9876,
61 |
62 | // enable / disable colors in the output (reporters and logs)
63 | colors: true,
64 |
65 | /*
66 | * level of logging
67 | * possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
68 | */
69 | logLevel: config.LOG_INFO,
70 |
71 | // enable / disable watching file and executing tests whenever any file changes
72 | autoWatch: false,
73 |
74 | /*
75 | * start these browsers
76 | * available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
77 | */
78 | browsers: [
79 | 'Chrome'
80 | ],
81 |
82 | customLaunchers: {
83 | Chrome_travis_ci: {
84 | base: 'Chrome',
85 | flags: ['--no-sandbox']
86 | }
87 | },
88 |
89 | /*
90 | * Continuous Integration mode
91 | * if true, Karma captures browsers, runs the tests and exits
92 | */
93 | singleRun: true
94 | };
95 |
96 | if(process.env.TRAVIS){
97 | configuration.browsers = ['Chrome_travis_ci'];
98 | }
99 |
100 | config.set(configuration);
101 | };
102 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/config/modules/angular2-hmr-prod.js:
--------------------------------------------------------------------------------
1 | exports.HmrState = function() {
2 |
3 | }
4 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/config/protractor.conf.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: @AngularClass
3 | */
4 |
5 | require('ts-node/register');
6 | var helpers = require('./helpers');
7 |
8 | exports.config = {
9 | baseUrl: 'http://localhost:3000/',
10 |
11 | // use `npm run e2e`
12 | specs: [
13 | helpers.root('src/**/**.e2e.ts'),
14 | helpers.root('src/**/*.e2e.ts')
15 | ],
16 | exclude: [],
17 |
18 | framework: 'jasmine2',
19 |
20 | allScriptsTimeout: 110000,
21 |
22 | jasmineNodeOpts: {
23 | showTiming: true,
24 | showColors: true,
25 | isVerbose: false,
26 | includeStackTrace: false,
27 | defaultTimeoutInterval: 400000
28 | },
29 | directConnect: true,
30 |
31 | capabilities: {
32 | 'browserName': 'chrome',
33 | 'chromeOptions': {
34 | 'args': ['show-fps-counter=true']
35 | }
36 | },
37 |
38 | onPrepare: function() {
39 | browser.ignoreSynchronization = true;
40 | },
41 |
42 | /**
43 | * Angular 2 configuration
44 | *
45 | * useAllAngular2AppRoots: tells Protractor to wait for any angular2 apps on the page instead of just the one matching
46 | * `rootEl`
47 | */
48 | useAllAngular2AppRoots: true
49 | };
50 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/config/spec-bundle.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: @AngularClass
3 | */
4 |
5 | /*
6 | * When testing with webpack and ES6, we have to do some extra
7 | * things to get testing to work right. Because we are gonna write tests
8 | * in ES6 too, we have to compile those as well. That's handled in
9 | * karma.conf.js with the karma-webpack plugin. This is the entry
10 | * file for webpack test. Just like webpack will create a bundle.js
11 | * file for our client, when we run test, it will compile and bundle them
12 | * all here! Crazy huh. So we need to do some setup
13 | */
14 | Error.stackTraceLimit = Infinity;
15 |
16 | require('core-js/es6');
17 | require('core-js/es7/reflect');
18 |
19 | // Typescript emit helpers polyfill
20 | require('ts-helpers');
21 |
22 | require('zone.js/dist/zone');
23 | require('zone.js/dist/long-stack-trace-zone');
24 | require('zone.js/dist/async-test');
25 | require('zone.js/dist/fake-async-test');
26 | require('zone.js/dist/sync-test');
27 | require('zone.js/dist/proxy'); // since zone.js 0.6.15
28 | require('zone.js/dist/jasmine-patch'); // put here since zone.js 0.6.14
29 |
30 | // RxJS
31 | require('rxjs/Rx');
32 |
33 | var testing = require('@angular/core/testing');
34 | var browser = require('@angular/platform-browser-dynamic/testing');
35 |
36 | testing.setBaseTestProviders(
37 | browser.TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
38 | browser.TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS
39 | );
40 |
41 | /*
42 | * Ok, this is kinda crazy. We can use the context method on
43 | * require that webpack created in order to tell webpack
44 | * what files we actually want to require or import.
45 | * Below, context will be a function/object with file names as keys.
46 | * Using that regex we are saying look in ../src then find
47 | * any file that ends with spec.ts and get its path. By passing in true
48 | * we say do this recursively
49 | */
50 | var testContext = require.context('../src', true, /\.spec\.ts/);
51 |
52 | /*
53 | * get all the files, for each file, call the context function
54 | * that will require the file and load it up here. Context will
55 | * loop and require those spec files here
56 | */
57 | function requireAll(requireContext) {
58 | return requireContext.keys().map(requireContext);
59 | }
60 |
61 | // requires and returns all modules that match
62 | var modules = requireAll(testContext);
63 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/config/webpack.common.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: @AngularClass
3 | */
4 |
5 | const webpack = require('webpack');
6 | const helpers = require('./helpers');
7 |
8 | /*
9 | * Webpack Plugins
10 | */
11 | // problem with copy-webpack-plugin
12 | const CopyWebpackPlugin = require('copy-webpack-plugin');
13 | const HtmlWebpackPlugin = require('html-webpack-plugin');
14 | const ForkCheckerPlugin = require('awesome-typescript-loader').ForkCheckerPlugin;
15 | const HtmlElementsPlugin = require('./html-elements-plugin');
16 |
17 | /*
18 | * Webpack Constants
19 | */
20 | const METADATA = {
21 | title: '{{cookiecutter.github_repository_name}}',
22 | baseUrl: '/',
23 | isDevServer: helpers.isWebpackDevServer()
24 | };
25 |
26 | /*
27 | * Webpack configuration
28 | *
29 | * See: http://webpack.github.io/docs/configuration.html#cli
30 | */
31 | module.exports = {
32 |
33 | /*
34 | * Static metadata for index.html
35 | *
36 | * See: (custom attribute)
37 | */
38 | metadata: METADATA,
39 |
40 | /*
41 | * Cache generated modules and chunks to improve performance for multiple incremental builds.
42 | * This is enabled by default in watch mode.
43 | * You can pass false to disable it.
44 | *
45 | * See: http://webpack.github.io/docs/configuration.html#cache
46 | */
47 | //cache: false,
48 |
49 | /*
50 | * The entry point for the bundle
51 | * Our Angular.js app
52 | *
53 | * See: http://webpack.github.io/docs/configuration.html#entry
54 | */
55 | entry: {
56 |
57 | 'polyfills': './src/polyfills.browser.ts',
58 | 'vendor': './src/vendor.browser.ts',
59 | 'main': './src/main.browser.ts'
60 |
61 | },
62 |
63 | /*
64 | * Options affecting the resolving of modules.
65 | *
66 | * See: http://webpack.github.io/docs/configuration.html#resolve
67 | */
68 | resolve: {
69 |
70 | /*
71 | * An array of extensions that should be used to resolve modules.
72 | *
73 | * See: http://webpack.github.io/docs/configuration.html#resolve-extensions
74 | */
75 | extensions: ['', '.ts', '.js', '.json'],
76 |
77 | // Make sure root is src
78 | root: helpers.root('src'),
79 |
80 | // remove other default values
81 | modulesDirectories: ['node_modules']
82 |
83 | },
84 |
85 | /*
86 | * Options affecting the normal modules.
87 | *
88 | * See: http://webpack.github.io/docs/configuration.html#module
89 | */
90 | module: {
91 |
92 | /*
93 | * An array of applied pre and post loaders.
94 | *
95 | * See: http://webpack.github.io/docs/configuration.html#module-preloaders-module-postloaders
96 | */
97 | preLoaders: [
98 | {
99 | test: /\.ts$/,
100 | loader: 'string-replace-loader',
101 | query: {
102 | search: '(System|SystemJS)(.*[\\n\\r]\\s*\\.|\\.)import\\((.+)\\)',
103 | replace: '$1.import($3).then(mod => mod.__esModule ? mod.default : mod)',
104 | flags: 'g'
105 | },
106 | include: [helpers.root('src')]
107 | }
108 | ],
109 |
110 | /*
111 | * An array of automatically applied loaders.
112 | *
113 | * IMPORTANT: The loaders here are resolved relative to the resource which they are applied to.
114 | * This means they are not resolved relative to the configuration file.
115 | *
116 | * See: http://webpack.github.io/docs/configuration.html#module-loaders
117 | */
118 | loaders: [
119 |
120 | /*
121 | * Typescript loader support for .ts and Angular 2 async routes via .async.ts
122 | * Replace templateUrl and stylesUrl with require()
123 | *
124 | * See: https://github.com/s-panferov/awesome-typescript-loader
125 | * See: https://github.com/TheLarkInn/angular2-template-loader
126 | */
127 | {
128 | test: /\.ts$/,
129 | loaders: [
130 | 'awesome-typescript-loader',
131 | 'angular2-template-loader',
132 | '@angularclass/hmr-loader'
133 | ],
134 | exclude: [/\.(spec|e2e)\.ts$/]
135 | },
136 |
137 | /*
138 | * Json loader support for *.json files.
139 | *
140 | * See: https://github.com/webpack/json-loader
141 | */
142 | {
143 | test: /\.json$/,
144 | loader: 'json-loader'
145 | },
146 |
147 | /*
148 | * to string and css loader support for *.css files
149 | * Returns file content as string
150 | *
151 | */
152 | {
153 | test: /\.css$/,
154 | loaders: ['to-string-loader', 'css-loader']
155 | },
156 |
157 | {
158 | test: /\.scss$/,
159 | exclude: /node_modules/,
160 | loaders: ['raw-loader', 'sass-loader'] // sass-loader not scss-loader
161 | },
162 |
163 | /* Raw loader support for *.html
164 | * Returns file content as string
165 | *
166 | * See: https://github.com/webpack/raw-loader
167 | */
168 | {
169 | test: /\.html$/,
170 | loader: 'raw-loader',
171 | exclude: [helpers.root('src/index.html')]
172 | },
173 |
174 | {
175 | test: /\.(pug|jade)$/,
176 | loader: 'pug-html-loader'
177 | },
178 |
179 | /* File loader for supporting images, for example, in CSS files.
180 | */
181 | {
182 | test: /\.(jpg|png|gif)$/,
183 | loader: 'file'
184 | }
185 | ]
186 |
187 | },
188 |
189 | /*
190 | * Add additional plugins to the compiler.
191 | *
192 | * See: http://webpack.github.io/docs/configuration.html#plugins
193 | */
194 | plugins: [
195 |
196 | /*
197 | * Plugin: ForkCheckerPlugin
198 | * Description: Do type checking in a separate process, so webpack don't need to wait.
199 | *
200 | * See: https://github.com/s-panferov/awesome-typescript-loader#forkchecker-boolean-defaultfalse
201 | */
202 | new ForkCheckerPlugin(),
203 | /*
204 | * Plugin: CommonsChunkPlugin
205 | * Description: Shares common code between the pages.
206 | * It identifies common modules and put them into a commons chunk.
207 | *
208 | * See: https://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin
209 | * See: https://github.com/webpack/docs/wiki/optimization#multi-page-app
210 | */
211 | new webpack.optimize.CommonsChunkPlugin({
212 | name: ['polyfills', 'vendor'].reverse()
213 | }),
214 |
215 | /*
216 | * Plugin: CopyWebpackPlugin
217 | * Description: Copy files and directories in webpack.
218 | *
219 | * Copies project static assets.
220 | *
221 | * See: https://www.npmjs.com/package/copy-webpack-plugin
222 | */
223 | new CopyWebpackPlugin([{
224 | from: 'src/assets',
225 | to: 'assets'
226 | }]),
227 |
228 | /*
229 | * Plugin: HtmlWebpackPlugin
230 | * Description: Simplifies creation of HTML files to serve your webpack bundles.
231 | * This is especially useful for webpack bundles that include a hash in the filename
232 | * which changes every compilation.
233 | *
234 | * See: https://github.com/ampedandwired/html-webpack-plugin
235 | */
236 | new HtmlWebpackPlugin({
237 | template: 'src/index.html',
238 | chunksSortMode: 'dependency'
239 | }),
240 |
241 | /*
242 | * Plugin: HtmlHeadConfigPlugin
243 | * Description: Generate html tags based on javascript maps.
244 | *
245 | * If a publicPath is set in the webpack output configuration, it will be automatically added to
246 | * href attributes, you can disable that by adding a "=href": false property.
247 | * You can also enable it to other attribute by settings "=attName": true.
248 | *
249 | * The configuration supplied is map between a location (key) and an element definition object (value)
250 | * The location (key) is then exported to the template under then htmlElements property in webpack configuration.
251 | *
252 | * Example:
253 | * Adding this plugin configuration
254 | * new HtmlElementsPlugin({
255 | * headTags: { ... }
256 | * })
257 | *
258 | * Means we can use it in the template like this:
259 | * <%= webpackConfig.htmlElements.headTags %>
260 | *
261 | * Dependencies: HtmlWebpackPlugin
262 | */
263 | new HtmlElementsPlugin({
264 | headTags: require('./head-config.common')
265 | })
266 |
267 | ],
268 |
269 | /*
270 | * Include polyfills or mocks for various node stuff
271 | * Description: Node configuration
272 | *
273 | * See: https://webpack.github.io/docs/configuration.html#node
274 | */
275 | node: {
276 | global: 'window',
277 | crypto: 'empty',
278 | process: true,
279 | module: false,
280 | clearImmediate: false,
281 | setImmediate: false
282 | }
283 |
284 | };
285 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/config/webpack.dev.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: @AngularClass
3 | */
4 |
5 | const helpers = require('./helpers');
6 | const webpackMerge = require('webpack-merge'); // used to merge webpack configs
7 | const commonConfig = require('./webpack.common.js'); // the settings that are common to prod and dev
8 |
9 | /**
10 | * Webpack Plugins
11 | */
12 | const DefinePlugin = require('webpack/lib/DefinePlugin');
13 |
14 | /**
15 | * Webpack Constants
16 | */
17 | const ENV = process.env.ENV = process.env.NODE_ENV = 'development';
18 | const HOST = process.env.HOST || 'localhost';
19 | const PORT = process.env.PORT || 3000;
20 | const HMR = helpers.hasProcessFlag('hot');
21 | const METADATA = webpackMerge(commonConfig.metadata, {
22 | host: HOST,
23 | port: PORT,
24 | ENV: ENV,
25 | HMR: HMR
26 | });
27 |
28 | /**
29 | * Webpack configuration
30 | *
31 | * See: http://webpack.github.io/docs/configuration.html#cli
32 | */
33 | module.exports = webpackMerge(commonConfig, {
34 |
35 | /**
36 | * Merged metadata from webpack.common.js for index.html
37 | *
38 | * See: (custom attribute)
39 | */
40 | metadata: METADATA,
41 |
42 | /**
43 | * Switch loaders to debug mode.
44 | *
45 | * See: http://webpack.github.io/docs/configuration.html#debug
46 | */
47 | debug: true,
48 |
49 | /**
50 | * Developer tool to enhance debugging
51 | *
52 | * See: http://webpack.github.io/docs/configuration.html#devtool
53 | * See: https://github.com/webpack/docs/wiki/build-performance#sourcemaps
54 | */
55 | devtool: 'cheap-module-source-map',
56 |
57 | /**
58 | * Options affecting the output of the compilation.
59 | *
60 | * See: http://webpack.github.io/docs/configuration.html#output
61 | */
62 | output: {
63 |
64 | /**
65 | * The output directory as absolute path (required).
66 | *
67 | * See: http://webpack.github.io/docs/configuration.html#output-path
68 | */
69 | path: helpers.root('dist'),
70 |
71 | /**
72 | * Specifies the name of each output file on disk.
73 | * IMPORTANT: You must not specify an absolute path here!
74 | *
75 | * See: http://webpack.github.io/docs/configuration.html#output-filename
76 | */
77 | filename: '[name].bundle.js',
78 |
79 | /**
80 | * The filename of the SourceMaps for the JavaScript files.
81 | * They are inside the output.path directory.
82 | *
83 | * See: http://webpack.github.io/docs/configuration.html#output-sourcemapfilename
84 | */
85 | sourceMapFilename: '[name].map',
86 |
87 | /** The filename of non-entry chunks as relative path
88 | * inside the output.path directory.
89 | *
90 | * See: http://webpack.github.io/docs/configuration.html#output-chunkfilename
91 | */
92 | chunkFilename: '[id].chunk.js',
93 |
94 | library: 'ac_[name]',
95 | libraryTarget: 'var',
96 | },
97 |
98 | plugins: [
99 |
100 | /**
101 | * Plugin: DefinePlugin
102 | * Description: Define free variables.
103 | * Useful for having development builds with debug logging or adding global constants.
104 | *
105 | * Environment helpers
106 | *
107 | * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin
108 | */
109 | // NOTE: when adding more properties, make sure you include them in custom-typings.d.ts
110 | new DefinePlugin({
111 | 'ENV': JSON.stringify(METADATA.ENV),
112 | 'HMR': METADATA.HMR,
113 | 'process.env': {
114 | 'ENV': JSON.stringify(METADATA.ENV),
115 | 'NODE_ENV': JSON.stringify(METADATA.ENV),
116 | 'HMR': METADATA.HMR,
117 | }
118 | }),
119 | ],
120 |
121 | /**
122 | * Static analysis linter for TypeScript advanced options configuration
123 | * Description: An extensible linter for the TypeScript language.
124 | *
125 | * See: https://github.com/wbuchwalter/tslint-loader
126 | */
127 | tslint: {
128 | emitErrors: false,
129 | failOnHint: false,
130 | resourcePath: 'src'
131 | },
132 |
133 | /**
134 | * Webpack Development Server configuration
135 | * Description: The webpack-dev-server is a little node.js Express server.
136 | * The server emits information about the compilation state to the client,
137 | * which reacts to those events.
138 | *
139 | * See: https://webpack.github.io/docs/webpack-dev-server.html
140 | */
141 | devServer: {
142 | port: METADATA.port,
143 | host: METADATA.host,
144 | historyApiFallback: true,
145 | watchOptions: {
146 | aggregateTimeout: 300,
147 | poll: 1000
148 | },
149 | outputPath: helpers.root('dist')
150 | },
151 |
152 | /*
153 | * Include polyfills or mocks for various node stuff
154 | * Description: Node configuration
155 | *
156 | * See: https://webpack.github.io/docs/configuration.html#node
157 | */
158 | node: {
159 | global: 'window',
160 | crypto: 'empty',
161 | process: true,
162 | module: false,
163 | clearImmediate: false,
164 | setImmediate: false
165 | }
166 |
167 | });
168 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/config/webpack.prod.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: @AngularClass
3 | */
4 |
5 | const helpers = require('./helpers');
6 | const webpackMerge = require('webpack-merge'); // used to merge webpack configs
7 | const commonConfig = require('./webpack.common.js'); // the settings that are common to prod and dev
8 |
9 | /**
10 | * Webpack Plugins
11 | */
12 | const ProvidePlugin = require('webpack/lib/ProvidePlugin');
13 | const DefinePlugin = require('webpack/lib/DefinePlugin');
14 | const NormalModuleReplacementPlugin = require('webpack/lib/NormalModuleReplacementPlugin');
15 | const IgnorePlugin = require('webpack/lib/IgnorePlugin');
16 | const DedupePlugin = require('webpack/lib/optimize/DedupePlugin');
17 | const UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin');
18 | const WebpackMd5Hash = require('webpack-md5-hash');
19 |
20 | /**
21 | * Webpack Constants
22 | */
23 | const ENV = process.env.NODE_ENV = process.env.ENV = 'production';
24 | const HOST = process.env.HOST || 'localhost';
25 | const PORT = process.env.PORT || 8080;
26 | const METADATA = webpackMerge(commonConfig.metadata, {
27 | host: HOST,
28 | port: PORT,
29 | ENV: ENV,
30 | HMR: false
31 | });
32 |
33 | module.exports = webpackMerge(commonConfig, {
34 |
35 | /**
36 | * Switch loaders to debug mode.
37 | *
38 | * See: http://webpack.github.io/docs/configuration.html#debug
39 | */
40 | debug: false,
41 |
42 | /**
43 | * Developer tool to enhance debugging
44 | *
45 | * See: http://webpack.github.io/docs/configuration.html#devtool
46 | * See: https://github.com/webpack/docs/wiki/build-performance#sourcemaps
47 | */
48 | devtool: 'source-map',
49 |
50 | /**
51 | * Options affecting the output of the compilation.
52 | *
53 | * See: http://webpack.github.io/docs/configuration.html#output
54 | */
55 | output: {
56 |
57 | /**
58 | * The output directory as absolute path (required).
59 | *
60 | * See: http://webpack.github.io/docs/configuration.html#output-path
61 | */
62 | path: helpers.root('dist'),
63 |
64 | /**
65 | * Specifies the name of each output file on disk.
66 | * IMPORTANT: You must not specify an absolute path here!
67 | *
68 | * See: http://webpack.github.io/docs/configuration.html#output-filename
69 | */
70 | filename: '[name].[chunkhash].bundle.js',
71 |
72 | /**
73 | * The filename of the SourceMaps for the JavaScript files.
74 | * They are inside the output.path directory.
75 | *
76 | * See: http://webpack.github.io/docs/configuration.html#output-sourcemapfilename
77 | */
78 | sourceMapFilename: '[name].[chunkhash].bundle.map',
79 |
80 | /**
81 | * The filename of non-entry chunks as relative path
82 | * inside the output.path directory.
83 | *
84 | * See: http://webpack.github.io/docs/configuration.html#output-chunkfilename
85 | */
86 | chunkFilename: '[id].[chunkhash].chunk.js'
87 |
88 | },
89 |
90 | /**
91 | * Add additional plugins to the compiler.
92 | *
93 | * See: http://webpack.github.io/docs/configuration.html#plugins
94 | */
95 | plugins: [
96 |
97 | /**
98 | * Plugin: WebpackMd5Hash
99 | * Description: Plugin to replace a standard webpack chunkhash with md5.
100 | *
101 | * See: https://www.npmjs.com/package/webpack-md5-hash
102 | */
103 | new WebpackMd5Hash(),
104 |
105 | /**
106 | * Plugin: DedupePlugin
107 | * Description: Prevents the inclusion of duplicate code into your bundle
108 | * and instead applies a copy of the function at runtime.
109 | *
110 | * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin
111 | * See: https://github.com/webpack/docs/wiki/optimization#deduplication
112 | */
113 | new DedupePlugin(),
114 |
115 | /**
116 | * Plugin: DefinePlugin
117 | * Description: Define free variables.
118 | * Useful for having development builds with debug logging or adding global constants.
119 | *
120 | * Environment helpers
121 | *
122 | * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin
123 | */
124 | // NOTE: when adding more properties make sure you include them in custom-typings.d.ts
125 | new DefinePlugin({
126 | 'ENV': JSON.stringify(METADATA.ENV),
127 | 'HMR': METADATA.HMR,
128 | 'process.env': {
129 | 'ENV': JSON.stringify(METADATA.ENV),
130 | 'NODE_ENV': JSON.stringify(METADATA.ENV),
131 | 'HMR': METADATA.HMR,
132 | }
133 | }),
134 |
135 | /**
136 | * Plugin: UglifyJsPlugin
137 | * Description: Minimize all JavaScript output of chunks.
138 | * Loaders are switched into minimizing mode.
139 | *
140 | * See: https://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin
141 | */
142 | // NOTE: To debug prod builds uncomment //debug lines and comment //prod lines
143 | new UglifyJsPlugin({
144 | // beautify: true, //debug
145 | // mangle: false, //debug
146 | // dead_code: false, //debug
147 | // unused: false, //debug
148 | // deadCode: false, //debug
149 | // compress: {
150 | // screw_ie8: true,
151 | // keep_fnames: true,
152 | // drop_debugger: false,
153 | // dead_code: false,
154 | // unused: false
155 | // }, // debug
156 | // comments: true, //debug
157 |
158 |
159 | beautify: false, //prod
160 | mangle: {screw_ie8: true, keep_fnames: true}, //prod
161 | compress: {screw_ie8: true}, //prod
162 | comments: false //prod
163 | }),
164 |
165 | /**
166 | * Plugin: NormalModuleReplacementPlugin
167 | * Description: Replace resources that matches resourceRegExp with newResource
168 | *
169 | * See: http://webpack.github.io/docs/list-of-plugins.html#normalmodulereplacementplugin
170 | */
171 |
172 | new NormalModuleReplacementPlugin(
173 | /angular2-hmr/,
174 | helpers.root('config/modules/angular2-hmr-prod.js')
175 | ),
176 |
177 | /**
178 | * Plugin: IgnorePlugin
179 | * Description: Don’t generate modules for requests matching the provided RegExp.
180 | *
181 | * See: http://webpack.github.io/docs/list-of-plugins.html#ignoreplugin
182 | */
183 |
184 | // new IgnorePlugin(/angular2-hmr/),
185 |
186 | /**
187 | * Plugin: CompressionPlugin
188 | * Description: Prepares compressed versions of assets to serve
189 | * them with Content-Encoding
190 | *
191 | * See: https://github.com/webpack/compression-webpack-plugin
192 | */
193 | // install compression-webpack-plugin
194 | // new CompressionPlugin({
195 | // regExp: /\.css$|\.html$|\.js$|\.map$/,
196 | // threshold: 2 * 1024
197 | // })
198 |
199 | ],
200 |
201 | /**
202 | * Static analysis linter for TypeScript advanced options configuration
203 | * Description: An extensible linter for the TypeScript language.
204 | *
205 | * See: https://github.com/wbuchwalter/tslint-loader
206 | */
207 | tslint: {
208 | emitErrors: true,
209 | failOnHint: true,
210 | resourcePath: 'src'
211 | },
212 |
213 | /**
214 | * Html loader advanced options
215 | *
216 | * See: https://github.com/webpack/html-loader#advanced-options
217 | */
218 | // TODO: Need to workaround Angular 2's html syntax => #id [bind] (event) *ngFor
219 | htmlLoader: {
220 | minimize: true,
221 | removeAttributeQuotes: false,
222 | caseSensitive: true,
223 | customAttrSurround: [
224 | [/#/, /(?:)/],
225 | [/\*/, /(?:)/],
226 | [/\[?\(?/, /(?:)/]
227 | ],
228 | customAttrAssign: [/\)?\]?=/]
229 | },
230 |
231 | /*
232 | * Include polyfills or mocks for various node stuff
233 | * Description: Node configuration
234 | *
235 | * See: https://webpack.github.io/docs/configuration.html#node
236 | */
237 | node: {
238 | global: 'window',
239 | crypto: 'empty',
240 | process: false,
241 | module: false,
242 | clearImmediate: false,
243 | setImmediate: false
244 | }
245 |
246 | });
247 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/config/webpack.test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: @AngularClass
3 | */
4 |
5 | const helpers = require('./helpers');
6 |
7 | /**
8 | * Webpack Plugins
9 | */
10 | const ProvidePlugin = require('webpack/lib/ProvidePlugin');
11 | const DefinePlugin = require('webpack/lib/DefinePlugin');
12 |
13 | /**
14 | * Webpack Constants
15 | */
16 | const ENV = process.env.ENV = process.env.NODE_ENV = 'test';
17 |
18 | /**
19 | * Webpack configuration
20 | *
21 | * See: http://webpack.github.io/docs/configuration.html#cli
22 | */
23 | module.exports = {
24 |
25 | /**
26 | * Source map for Karma from the help of karma-sourcemap-loader & karma-webpack
27 | *
28 | * Do not change, leave as is or it wont work.
29 | * See: https://github.com/webpack/karma-webpack#source-maps
30 | */
31 | devtool: 'inline-source-map',
32 |
33 | /**
34 | * Options affecting the resolving of modules.
35 | *
36 | * See: http://webpack.github.io/docs/configuration.html#resolve
37 | */
38 | resolve: {
39 |
40 | /**
41 | * An array of extensions that should be used to resolve modules.
42 | *
43 | * See: http://webpack.github.io/docs/configuration.html#resolve-extensions
44 | */
45 | extensions: ['', '.ts', '.js'],
46 |
47 | /**
48 | * Make sure root is src
49 | */
50 | root: helpers.root('src'),
51 |
52 | },
53 |
54 | /**
55 | * Options affecting the normal modules.
56 | *
57 | * See: http://webpack.github.io/docs/configuration.html#module
58 | */
59 | module: {
60 |
61 | /**
62 | * An array of applied pre and post loaders.
63 | *
64 | * See: http://webpack.github.io/docs/configuration.html#module-preloaders-module-postloaders
65 | */
66 | preLoaders: [
67 |
68 | /**
69 | * Tslint loader support for *.ts files
70 | *
71 | * See: https://github.com/wbuchwalter/tslint-loader
72 | */
73 | {
74 | test: /\.ts$/,
75 | loader: 'tslint-loader',
76 | exclude: [helpers.root('node_modules')]
77 | },
78 |
79 | /**
80 | * Source map loader support for *.js files
81 | * Extracts SourceMaps for source files that as added as sourceMappingURL comment.
82 | *
83 | * See: https://github.com/webpack/source-map-loader
84 | */
85 | {
86 | test: /\.js$/,
87 | loader: 'source-map-loader',
88 | exclude: [
89 | // these packages have problems with their sourcemaps
90 | helpers.root('node_modules/rxjs'),
91 | helpers.root('node_modules/@angular')
92 | ]}
93 |
94 | ],
95 |
96 | /**
97 | * An array of automatically applied loaders.
98 | *
99 | * IMPORTANT: The loaders here are resolved relative to the resource which they are applied to.
100 | * This means they are not resolved relative to the configuration file.
101 | *
102 | * See: http://webpack.github.io/docs/configuration.html#module-loaders
103 | */
104 | loaders: [
105 |
106 | /**
107 | * Typescript loader support for .ts and Angular 2 async routes via .async.ts
108 | *
109 | * See: https://github.com/s-panferov/awesome-typescript-loader
110 | */
111 | {
112 | test: /\.ts$/,
113 | loader: 'awesome-typescript-loader',
114 | query: {
115 | compilerOptions: {
116 |
117 | // Remove TypeScript helpers to be injected
118 | // below by DefinePlugin
119 | removeComments: true
120 |
121 | }
122 | },
123 | exclude: [/\.e2e\.ts$/]
124 | },
125 |
126 | /**
127 | * Json loader support for *.json files.
128 | *
129 | * See: https://github.com/webpack/json-loader
130 | */
131 | { test: /\.json$/, loader: 'json-loader', exclude: [helpers.root('src/index.html')] },
132 |
133 | /**
134 | * Raw loader support for *.css files
135 | * Returns file content as string
136 | *
137 | * See: https://github.com/webpack/raw-loader
138 | */
139 | { test: /\.css$/, loaders: ['to-string-loader', 'css-loader'], exclude: [helpers.root('src/index.html')] },
140 |
141 | /**
142 | * Raw loader support for *.html
143 | * Returns file content as string
144 | *
145 | * See: https://github.com/webpack/raw-loader
146 | */
147 | { test: /\.html$/, loader: 'raw-loader', exclude: [helpers.root('src/index.html')] }
148 |
149 | ],
150 |
151 | /**
152 | * An array of applied pre and post loaders.
153 | *
154 | * See: http://webpack.github.io/docs/configuration.html#module-preloaders-module-postloaders
155 | */
156 | postLoaders: [
157 |
158 | /**
159 | * Instruments JS files with Istanbul for subsequent code coverage reporting.
160 | * Instrument only testing sources.
161 | *
162 | * See: https://github.com/deepsweet/istanbul-instrumenter-loader
163 | */
164 | {
165 | test: /\.(js|ts)$/, loader: 'istanbul-instrumenter-loader',
166 | include: helpers.root('src'),
167 | exclude: [
168 | /\.(e2e|spec)\.ts$/,
169 | /node_modules/
170 | ]
171 | }
172 |
173 | ]
174 | },
175 |
176 | /**
177 | * Add additional plugins to the compiler.
178 | *
179 | * See: http://webpack.github.io/docs/configuration.html#plugins
180 | */
181 | plugins: [
182 |
183 | /**
184 | * Plugin: DefinePlugin
185 | * Description: Define free variables.
186 | * Useful for having development builds with debug logging or adding global constants.
187 | *
188 | * Environment helpers
189 | *
190 | * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin
191 | */
192 | // NOTE: when adding more properties make sure you include them in custom-typings.d.ts
193 | new DefinePlugin({
194 | 'ENV': JSON.stringify(ENV),
195 | 'HMR': false,
196 | 'process.env': {
197 | 'ENV': JSON.stringify(ENV),
198 | 'NODE_ENV': JSON.stringify(ENV),
199 | 'HMR': false,
200 | }
201 | }),
202 |
203 |
204 | ],
205 |
206 | /**
207 | * Static analysis linter for TypeScript advanced options configuration
208 | * Description: An extensible linter for the TypeScript language.
209 | *
210 | * See: https://github.com/wbuchwalter/tslint-loader
211 | */
212 | tslint: {
213 | emitErrors: false,
214 | failOnHint: false,
215 | resourcePath: 'src'
216 | },
217 |
218 | /**
219 | * Include polyfills or mocks for various node stuff
220 | * Description: Node configuration
221 | *
222 | * See: https://webpack.github.io/docs/configuration.html#node
223 | */
224 | node: {
225 | global: 'window',
226 | process: false,
227 | crypto: 'empty',
228 | module: false,
229 | clearImmediate: false,
230 | setImmediate: false
231 | }
232 |
233 | };
234 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/karma.conf.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: @AngularClass
3 | */
4 |
5 | // Look in ./config for karma.conf.js
6 | module.exports = require('./config/karma.conf.js');
7 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular2-webpack-starter",
3 | "version": "5.0.5",
4 | "description": "An Angular 2 Webpack Starter kit featuring Angular 2 (Router, Http, Forms, Services, Tests, E2E, Coverage), Karma, Protractor, Jasmine, Istanbul, TypeScript, and Webpack by AngularClass",
5 | "keywords": [
6 | "angular2",
7 | "webpack",
8 | "typescript"
9 | ],
10 | "author": "Patrick Stapleton ",
11 | "homepage": "https://github.com/angularclass/angular2-webpack-starter",
12 | "license": "MIT",
13 | "scripts": {
14 | "rimraf": "rimraf",
15 | "tslint": "tslint",
16 | "typedoc": "typedoc",
17 | "webpack": "webpack",
18 | "webpack-dev-server": "webpack-dev-server",
19 | "webdriver-manager": "webdriver-manager",
20 | "protractor": "protractor",
21 | "clean": "npm cache clean && npm run rimraf -- node_modules doc coverage dist",
22 | "clean:dist": "npm run rimraf -- dist",
23 | "preclean:install": "npm run clean",
24 | "clean:install": "npm set progress=false && npm install",
25 | "preclean:start": "npm run clean",
26 | "clean:start": "npm start",
27 | "watch": "npm run watch:dev",
28 | "watch:dev": "npm run build:dev -- --watch",
29 | "watch:dev:hmr": "npm run watch:dev -- --hot",
30 | "watch:test": "npm run test -- --auto-watch --no-single-run",
31 | "watch:prod": "npm run build:prod -- --watch",
32 | "build": "npm run build:dev",
33 | "prebuild:dev": "npm run clean:dist",
34 | "build:dev": "webpack --config config/webpack.dev.js --progress --profile",
35 | "prebuild:prod": "npm run clean:dist",
36 | "build:prod": "webpack --config config/webpack.prod.js --progress --profile --bail",
37 | "github-deploy": "npm run github-deploy:dev",
38 | "github-deploy:dev": "webpack --config config/webpack.github-deploy.js --progress --profile --github-dev",
39 | "github-deploy:prod": "webpack --config config/webpack.github-deploy.js --progress --profile --github-prod",
40 | "server": "npm run server:dev",
41 | "server:dev": "webpack-dev-server --config config/webpack.dev.js --progress --profile --watch --content-base src/",
42 | "server:dev:hmr": "npm run server:dev -- --inline --hot",
43 | "server:prod": "http-server dist --cors",
44 | "webdriver:update": "npm run webdriver-manager update",
45 | "webdriver:start": "npm run webdriver-manager start",
46 | "lint": "npm run tslint \"src/**/*.ts\"",
47 | "pree2e": "npm run webdriver:update -- --standalone",
48 | "e2e": "npm run protractor",
49 | "e2e:live": "npm run e2e -- --elementExplorer",
50 | "test": "karma start",
51 | "ci": "npm run lint && npm test && npm run e2e",
52 | "docs": "npm run typedoc -- --options typedoc.json --exclude '**/*.spec.ts' ./src/",
53 | "start": "npm run server:dev",
54 | "start:hmr": "npm run server:dev:hmr",
55 | "preversion": "npm test",
56 | "version": "npm run build",
57 | "postversion": "git push && git push --tags"
58 | },
59 | "dependencies": {
60 | "@angular/common": "2.0.0-rc.5",
61 | "@angular/compiler": "2.0.0-rc.5",
62 | "@angular/core": "2.0.0-rc.5",
63 | "@angular/forms": "^0.3.0",
64 | "@angular/http": "2.0.0-rc.5",
65 | "@angular/platform-browser": "2.0.0-rc.5",
66 | "@angular/platform-browser-dynamic": "2.0.0-rc.5",
67 | "@angular/platform-server": "2.0.0-rc.5",
68 | "@angular/router": "github:gdi2290/router-builds",
69 | "@angular2-material/button": "2.0.0-alpha.7-4",
70 | "@angular2-material/button-toggle": "2.0.0-alpha.7-4",
71 | "@angular2-material/card": "2.0.0-alpha.7-4",
72 | "@angular2-material/checkbox": "2.0.0-alpha.7-4",
73 | "@angular2-material/core": "2.0.0-alpha.7-4",
74 | "@angular2-material/grid-list": "2.0.0-alpha.7-4",
75 | "@angular2-material/icon": "2.0.0-alpha.7-4",
76 | "@angular2-material/input": "2.0.0-alpha.7-4",
77 | "@angular2-material/list": "2.0.0-alpha.7-4",
78 | "@angular2-material/menu": "2.0.0-alpha.7-4",
79 | "@angular2-material/progress-bar": "2.0.0-alpha.7-4",
80 | "@angular2-material/progress-circle": "2.0.0-alpha.7-4",
81 | "@angular2-material/radio": "2.0.0-alpha.7-4",
82 | "@angular2-material/sidenav": "2.0.0-alpha.7-4",
83 | "@angular2-material/slide-toggle": "2.0.0-alpha.7-4",
84 | "@angular2-material/slider": "2.0.0-alpha.7-4",
85 | "@angular2-material/tabs": "2.0.0-alpha.7-4",
86 | "@angular2-material/toolbar": "2.0.0-alpha.7-4",
87 | "@angular2-material/tooltip": "2.0.0-alpha.7-4",
88 | "@angularclass/conventions-loader": "^1.0.2",
89 | "@angularclass/request-idle-callback": "^1.0.7",
90 | "@angularclass/webpack-toolkit": "^1.3.3",
91 | "angular2-template-loader": "^0.5.0",
92 | "core-js": "^2.4.0",
93 | "hammerjs": "^2.0.8",
94 | "http-server": "^0.9.0",
95 | "ie-shim": "^0.1.0",
96 | "rxjs": "5.0.0-beta.6",
97 | "zone.js": "~0.6.17"
98 | },
99 | "devDependencies": {
100 | "@angularclass/hmr": "^1.0.1",
101 | "@angularclass/hmr-loader": "^1.0.1",
102 | "@types/core-js": "^0.9.28",
103 | "@types/hammerjs": "^2.0.28",
104 | "@types/jasmine": "^2.2.29",
105 | "@types/node": "^4.0.29",
106 | "@types/protractor": "^1.5.16",
107 | "@types/selenium-webdriver": "2.44.26",
108 | "@types/source-map": "^0.1.26",
109 | "@types/uglify-js": "^2.0.27",
110 | "@types/webpack": "^1.12.29",
111 | "angular2-hmr": "~0.8.0",
112 | "awesome-typescript-loader": "1.1.1",
113 | "codelyzer": "~0.0.21",
114 | "copy-webpack-plugin": "^3.0.1",
115 | "css-loader": "^0.24.0",
116 | "es6-promise-loader": "^1.0.1",
117 | "exports-loader": "^0.6.3",
118 | "expose-loader": "^0.7.1",
119 | "file-loader": "^0.9.0",
120 | "gh-pages": "^0.11.0",
121 | "html-webpack-plugin": "^2.21.0",
122 | "imports-loader": "^0.6.5",
123 | "istanbul-instrumenter-loader": "^0.2.0",
124 | "json-loader": "^0.5.4",
125 | "karma": "^0.13.22",
126 | "karma-chrome-launcher": "^1.0.1",
127 | "karma-coverage": "^1.0.0",
128 | "karma-jasmine": "^1.0.2",
129 | "karma-mocha-reporter": "^2.0.0",
130 | "karma-sourcemap-loader": "^0.3.7",
131 | "karma-webpack": "1.7.0",
132 | "node-sass": "^3.4.2",
133 | "parse5": "^1.5.1",
134 | "protractor": "^3.2.2",
135 | "pug": "^2.0.0-beta6",
136 | "pug-html-loader": "^1.0.9",
137 | "pug-loader": "^2.3.0",
138 | "raw-loader": "^0.5.1",
139 | "remap-istanbul": "^0.6.3",
140 | "rimraf": "^2.5.2",
141 | "sass-loader": "^4.0.0",
142 | "source-map-loader": "^0.1.5",
143 | "string-replace-loader": "^1.0.3",
144 | "style-loader": "^0.13.1",
145 | "to-string-loader": "^1.1.4",
146 | "ts-helpers": "1.1.1",
147 | "ts-node": "^0.9.1",
148 | "tslint": "^3.7.1",
149 | "tslint-loader": "^2.1.3",
150 | "typedoc": "^0.4.4",
151 | "typescript": "^2.0.0-beta",
152 | "url-loader": "^0.5.7",
153 | "webpack": "2.1.0-beta.22",
154 | "webpack-dev-middleware": "^1.6.1",
155 | "webpack-dev-server": "^2.1.0-beta.0",
156 | "webpack-md5-hash": "^0.0.5",
157 | "webpack-merge": "^0.14.0"
158 | },
159 | "repository": {
160 | "type": "git",
161 | "url": "https://github.com/angularclass/angular2-webpack-starter.git"
162 | },
163 | "bugs": {
164 | "url": "https://github.com/angularclass/angular2-webpack-starter/issues"
165 | },
166 | "engines": {
167 | "node": ">= 4.2.1",
168 | "npm": ">= 3"
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/protractor.conf.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: @AngularClass
3 | */
4 |
5 | // look in ./config for protractor.conf.js
6 | exports.config = require('./config/protractor.conf.js').config;
7 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/+detail/detail.component.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | import { Component } from '@angular/core';
3 |
4 | @Component({
5 | selector: 'detail',
6 | template: `
7 | Hello from Detail
8 |
9 | `
10 | })
11 | export class Detail {
12 | constructor() {
13 |
14 | }
15 |
16 | ngOnInit() {
17 | console.log('hello `Detail` component');
18 | }
19 |
20 | }
21 |
22 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/+detail/index.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | import { BrowserModule } from '@angular/platform-browser'
3 | import { RouterModule } from '@angular/router';
4 | import { NgModule } from '@angular/core';
5 | import { FormsModule } from '@angular/forms';
6 |
7 | import { Detail } from './detail.component';
8 |
9 | console.log('`Detail` bundle loaded asynchronously');
10 | // async components must be named routes for WebpackAsyncRoute
11 | export const routes = [
12 | { path: '', component: Detail, pathMatch: 'full' }
13 | ];
14 |
15 | @NgModule({
16 | declarations: [
17 | // Components / Directives/ Pipes
18 | Detail
19 | ],
20 | imports: [
21 | BrowserModule,
22 | FormsModule,
23 | RouterModule.forChild(routes),
24 | ]
25 | })
26 | export default class AboutModule {
27 | static routes = routes;
28 | }
29 |
30 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/about/about.component.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | import { Component } from '@angular/core';
3 | import { ActivatedRoute } from '@angular/router';
4 | /*
5 | * We're loading this component asynchronously
6 | * We are using some magic with es6-promise-loader that will wrap the module with a Promise
7 | * see https://github.com/gdi2290/es6-promise-loader for more info
8 | */
9 |
10 | console.log('`About` component loaded asynchronously');
11 |
12 | @Component({
13 | selector: 'about',
14 | styles: [`
15 | md-card{
16 | margin: 25px;
17 | }
18 | `],
19 | template: `
20 |
21 | For hot module reloading run
22 | npm run start:hmr
23 |
24 |
25 |
26 | patrick@AngularClass.com
27 |
28 |
29 |
30 | this.localState = {{ localState | json }}
31 |
32 | `
33 | })
34 | export class About {
35 | localState;
36 | constructor(public route: ActivatedRoute) {
37 |
38 | }
39 |
40 | ngOnInit() {
41 | this.route
42 | .data
43 | .subscribe((data: any) => {
44 | // your resolved data from route
45 | this.localState = data.yourData;
46 | });
47 |
48 | console.log('hello `About` component');
49 | // static data that is bundled
50 | // var mockData = require('assets/mock-data/mock-data.json');
51 | // console.log('mockData', mockData);
52 | // if you're working with mock data you can also use http.get('assets/mock-data/mock-data.json')
53 | // this.asyncDataWithWebpack();
54 | }
55 | asyncDataWithWebpack() {
56 | // you can also async load mock data with 'es6-promise-loader'
57 | // you would do this if you don't want the mock-data bundled
58 | // remember that 'es6-promise-loader' is a promise
59 | // var asyncMockDataPromiseFactory = require('es6-promise!assets/mock-data/mock-data.json');
60 | // setTimeout(() => {
61 | //
62 | // let asyncDataPromise = asyncMockDataPromiseFactory();
63 | // asyncDataPromise.then(json => {
64 | // console.log('async mockData', json);
65 | // });
66 | //
67 | // });
68 | }
69 |
70 | }
71 |
72 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/about/about.spec.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | import { TestComponentBuilder } from '@angular/core/testing';
3 | import { Component } from '@angular/core';
4 | import { ActivatedRoute } from '@angular/router';
5 | import {
6 | addProviders,
7 | inject
8 | } from '@angular/core/testing';
9 |
10 | // Load the implementations that should be tested
11 | import { About } from './about.component';
12 |
13 | describe('About', () => {
14 | // provide our implementations or mocks to the dependency injector
15 | beforeEach(() => addProviders([
16 | // provide a better mock
17 | {
18 | provide: ActivatedRoute,
19 | useValue: {
20 | data: {
21 | subscribe: (fn) => fn({yourData: 'yolo'})
22 | }
23 | }
24 | },
25 | About
26 | ]));
27 |
28 | it('should log ngOnInit', inject([ About ], (about) => {
29 | spyOn(console, 'log');
30 | expect(console.log).not.toHaveBeenCalled();
31 |
32 | Home.ngOnInit();
33 | expect(console.log).toHaveBeenCalled();
34 | }));
35 |
36 | });
37 |
38 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/about/index.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | export * from './about.component';
3 |
4 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | /*
3 | * Angular 2 decorators and services
4 | */
5 | import { Component, ViewEncapsulation } from '@angular/core';
6 |
7 | import { AppState } from './app.service';
8 |
9 | /*
10 | * App Component
11 | * Top Level Component
12 | */
13 | @Component({
14 | selector: 'app',
15 | encapsulation: ViewEncapsulation.None,
16 | styleUrls: [
17 | './app.style.css'
18 | ],
19 | template: `
20 |
21 |
22 | {{ name }}
23 |
24 |
25 | Index
26 |
27 |
28 | Home
29 |
30 |
31 | Detail
32 |
33 |
34 | About
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | this.appState.state = {{ appState.state | json }}
45 |
46 |
47 |
48 |
49 |
50 | `
51 | })
52 | export class App {
53 | angularclassLogo = 'assets/img/angularclass-avatar.png';
54 | loading = false;
55 | name = '{{cookiecutter.github_repository_name}}';
56 | url = '';
57 |
58 | constructor(
59 | public appState: AppState) {
60 |
61 | }
62 |
63 | ngOnInit() {
64 | console.log('Initial App State', this.appState.state);
65 | }
66 |
67 | }
68 |
69 | /*
70 | * Please review the https://github.com/AngularClass/angular2-examples/ repo for
71 | * more angular app examples that you may copy/paste
72 | * (The examples may not be updated as quickly. Please open an issue on github for us to update it)
73 | * For help or questions please contact us at @AngularClass on twitter
74 | * or our chat on Slack at https://AngularClass.com/slack-join
75 | */
76 |
77 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/app.e2e.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | describe('App', () => {
3 |
4 | beforeEach(() => {
5 | browser.get('/');
6 | });
7 |
8 |
9 | it('should have a title', () => {
10 | let subject = browser.getTitle();
11 | let result = 'Angular2 Webpack Starter by @gdi2290 from @AngularClass';
12 | expect(subject).toEqual(result);
13 | });
14 |
15 | it('should have ', () => {
16 | let subject = element(by.css('app md-toolbar')).isPresent();
17 | let result = true;
18 | expect(subject).toEqual(result);
19 | });
20 |
21 | it('should have ', () => {
22 | let subject = element(by.css('app md-content')).isPresent();
23 | let result = true;
24 | expect(subject).toEqual(result);
25 | });
26 |
27 | it('should have buttons', () => {
28 | let subject = element(by.css('button')).getText();
29 | let result = 'Submit Value';
30 | expect(subject).toEqual(result);
31 | });
32 |
33 | });
34 |
35 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | import { NgModule, ApplicationRef } from '@angular/core';
3 | import { BrowserModule } from '@angular/platform-browser';
4 | import { FormsModule } from '@angular/forms';
5 | import { HttpModule } from '@angular/http';
6 | import { RouterModule } from '@angular/router';
7 | import { removeNgStyles, createNewHosts } from '@angularclass/hmr';
8 |
9 | /*
10 | * Platform and Environment providers/directives/pipes
11 | */
12 | import { ENV_PROVIDERS } from './environment';
13 | import { ROUTES } from './app.routes';
14 | // App is our top level component
15 | import { App } from './app.component';
16 | import { MdModule } from './md.module';
17 | import { APP_RESOLVER_PROVIDERS } from './app.resolver';
18 | import { AppState } from './app.service';
19 | import { Home } from './home';
20 | import { About } from './about';
21 | import { NoContent } from './no-content';
22 |
23 | // Import diretives
24 | import { XLarge } from './home/x-large';
25 |
26 | // Application wide providers
27 | const APP_PROVIDERS = [
28 | ...APP_RESOLVER_PROVIDERS,
29 | AppState
30 | ];
31 |
32 | /**
33 | * `AppModule` is the main entry point into Angular2's bootstraping process
34 | */
35 | @NgModule({
36 | bootstrap: [ App ],
37 | declarations: [
38 | App,
39 | About,
40 | Home,
41 | NoContent,
42 | XLarge
43 | ],
44 | imports: [ // import Angular's modules
45 | BrowserModule,
46 | FormsModule,
47 | HttpModule,
48 | RouterModule.forRoot(ROUTES, { useHash: true }),
49 | MdModule.forRoot()
50 | ],
51 | providers: [ // expose our Services and Providers into Angular's dependency injection
52 | ENV_PROVIDERS,
53 | APP_PROVIDERS
54 | ]
55 | })
56 | export class AppModule {
57 | constructor(public appRef: ApplicationRef, public appState: AppState) {}
58 | hmrOnInit(store) {
59 | if (!store || !store.state) return;
60 | console.log('HMR store', store);
61 | this.appState._state = store.state;
62 | this.appRef.tick();
63 | delete store.state;
64 | }
65 | hmrOnDestroy(store) {
66 | var cmpLocation = this.appRef.components.map(cmp => cmp.location.nativeElement);
67 | // recreate elements
68 | var state = this.appState._state;
69 | store.state = state;
70 | store.disposeOldHosts = createNewHosts(cmpLocation)
71 | // remove styles
72 | removeNgStyles();
73 | }
74 | hmrAfterDestroy(store) {
75 | // display new elements
76 | store.disposeOldHosts()
77 | delete store.disposeOldHosts;
78 | }
79 | }
80 |
81 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/app.resolver.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
3 | import { Injectable } from '@angular/core';
4 | import { Observable } from 'rxjs/Observable';
5 | import 'rxjs/add/observable/of';
6 |
7 | @Injectable()
8 | export class DataResolver implements Resolve {
9 | constructor() {
10 |
11 | }
12 | resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
13 | return Observable.of({ res: 'I am data'});
14 | }
15 | }
16 |
17 | // an array of services to resolve routes with data
18 | export const APP_RESOLVER_PROVIDERS = [
19 | DataResolver
20 | ];
21 |
22 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/app.routes.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | import { Routes, RouterModule } from '@angular/router';
3 | import { Home } from './home';
4 | import { About } from './about';
5 | import { NoContent } from './no-content';
6 |
7 | import { DataResolver } from './app.resolver';
8 |
9 |
10 | export const ROUTES: Routes = [
11 | { path: '', component: Home },
12 | { path: 'home', component: Home },
13 | { path: 'about', component: About },
14 | {
15 | path: 'detail', loadChildren: () => System.import('./+detail')
16 | },
17 | { path: '**', component: NoContent },
18 | ];
19 |
20 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/app.service.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | import { Injectable } from '@angular/core';
3 |
4 | @Injectable()
5 | export class AppState {
6 | _state = { };
7 |
8 | constructor() {
9 |
10 | }
11 |
12 | // already return a clone of the current state
13 | get state() {
14 | return this._state = this._clone(this._state);
15 | }
16 | // never allow mutation
17 | set state(value) {
18 | throw new Error('do not mutate the `.state` directly');
19 | }
20 |
21 |
22 | get(prop?: any) {
23 | // use our state getter for the clone
24 | const state = this.state;
25 | return state.hasOwnProperty(prop) ? state[prop] : state;
26 | }
27 |
28 | set(prop: string, value: any) {
29 | // internally mutate our state
30 | return this._state[prop] = value;
31 | }
32 |
33 |
34 | _clone(object) {
35 | // simple object clone
36 | return JSON.parse(JSON.stringify( object ));
37 | }
38 | }
39 |
40 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/app.spec.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | import {
3 | addProviders,
4 | inject
5 | } from '@angular/core/testing';
6 |
7 | // Load the implementations that should be tested
8 | import { App } from './app.component';
9 | import { AppState } from './app.service';
10 |
11 | describe('App', () => {
12 | // provide our implementations or mocks to the dependency injector
13 | beforeEach(() => addProviders([
14 | AppState,
15 | App
16 | ]));
17 |
18 | it('should have a url', inject([ App ], (app) => {
19 | expect(app.url).toEqual('https://twitter.com/AngularClass');
20 | }));
21 |
22 | });
23 |
24 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/app.style.css:
--------------------------------------------------------------------------------
1 | html, body{
2 | height: 100%;
3 | background: #F4FAFA;
4 | font-family: Arial, Helvetica, sans-serif;
5 | }
6 | button.active{
7 | background: #fff;
8 | color: #009688;
9 | }
10 | button.active:hover{
11 | color: #fff;
12 | }
13 | .fill{
14 | flex: 1 1 auto;
15 | }
16 | .app-state{
17 | margin: 15px;
18 | flex: 1;
19 | }
20 | .home{
21 | flex: 1;
22 | }
23 | md-content{
24 | display: flex;
25 | flex-direction: column;
26 | height: 100%;
27 | }
28 | footer{
29 | flex: 0 0 60px;
30 | padding: 10px;
31 | display: flex;
32 | align-items: center;
33 | justify-content: center;
34 | background: #fff;
35 | }
36 |
37 |
38 | /** remove when fixed in angular2-material **/
39 | /** The overlay-container is an invisible element which contains all individual overlays. */
40 | .md-overlay-container {
41 | position: absolute;
42 | pointer-events: none;
43 | top: 0;
44 | left: 0;
45 | height: 100%;
46 | width: 100%; }
47 |
48 | /** A single overlay pane. */
49 | .md-overlay-pane {
50 | position: absolute;
51 | pointer-events: auto;
52 | box-sizing: border-box;
53 | z-index: 1000; }
54 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/environment.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 |
3 | // Angular 2
4 | // rc2 workaround
5 | import { enableDebugTools, disableDebugTools } from '@angular/platform-browser';
6 | import { enableProdMode, ApplicationRef } from '@angular/core';
7 | // Environment Providers
8 | let PROVIDERS = [
9 | // common env directives
10 | ];
11 |
12 | // Angular debug tools in the dev console
13 | // https://github.com/angular/angular/blob/86405345b781a9dc2438c0fbe3e9409245647019/TOOLS_JS.md
14 | let _decorateModuleRef = function identity(value) { return value; };
15 |
16 | if ('production' === ENV) {
17 | // Production
18 | disableDebugTools();
19 | enableProdMode();
20 |
21 | PROVIDERS = [
22 | ...PROVIDERS,
23 | // custom providers in production
24 | ];
25 |
26 | } else {
27 |
28 | _decorateModuleRef = (modRef: any) => {
29 | var appRef = modRef.injector.get(ApplicationRef);
30 | var cmpRef = appRef.components[0];
31 |
32 | let _ng = (window).ng;
33 | enableDebugTools(cmpRef);
34 | (window).ng.probe = _ng.probe;
35 | (window).ng.coreTokens = _ng.coreTokens;
36 | return modRef
37 | };
38 |
39 | // Development
40 | PROVIDERS = [
41 | ...PROVIDERS,
42 | // custom providers in development
43 | ];
44 |
45 | }
46 |
47 | export const decorateModuleRef = _decorateModuleRef;
48 |
49 | export const ENV_PROVIDERS = [
50 | ...PROVIDERS
51 | ];
52 |
53 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/home/home.component.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | import { Component } from '@angular/core';
3 |
4 | import { AppState } from '../app.service';
5 | import { Title } from './title';
6 |
7 | @Component({
8 | // The selector is what angular internally uses
9 | // for `document.querySelectorAll(selector)` in our index.html
10 | // where, in this case, selector is the string 'home'
11 | selector: 'home', //
12 | // We need to tell Angular's Dependency Injection which providers are in our app.
13 | providers: [
14 | Title
15 | ],
16 |
17 | // Our list of styles in our component. We may add more to compose many styles together
18 | styleUrls: [ './home.style.scss' ],
19 | // Every Angular template is first compiled by the browser before Angular runs it's compiler
20 | templateUrl: './home.template.pug'
21 | })
22 | export class Home {
23 | // Set our default values
24 | localState = { value: '' };
25 | // TypeScript public modifiers
26 | constructor(public appState: AppState, public title: Title) {
27 |
28 | }
29 |
30 | static ngOnInit() {
31 | console.log('hello `Home` component');
32 | // this.title.getData().subscribe(data => this.data = data);
33 | }
34 |
35 | submitState(value) {
36 | console.log('submitState', value);
37 | this.appState.set('value', value);
38 | this.localState.value = '';
39 | }
40 |
41 | }
42 |
43 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/home/home.e2e.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | describe('App', () => {
3 |
4 | beforeEach(() => {
5 | // change hash depending on router LocationStrategy
6 | browser.get('/#/home');
7 | });
8 |
9 |
10 | it('should have a title', () => {
11 | let subject = browser.getTitle();
12 | let result = 'Angular2 Webpack Starter by @gdi2290 from @AngularClass';
13 | expect(subject).toEqual(result);
14 | });
15 |
16 | it('should have `your content here` x-large', () => {
17 | let subject = element(by.css('[x-large]')).getText();
18 | let result = 'Your Content Here';
19 | expect(subject).toEqual(result);
20 | });
21 |
22 |
23 | });
24 |
25 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/home/home.spec.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | import {
3 | addProviders,
4 | inject
5 | } from '@angular/core/testing';
6 | import { Component } from '@angular/core';
7 | import { BaseRequestOptions, Http } from '@angular/http';
8 | import { MockBackend } from '@angular/http/testing';
9 |
10 | // Load the implementations that should be tested
11 | import { AppState } from '../app.service';
12 | import { Home } from './home.component';
13 | import { Title } from './title';
14 |
15 | describe('Home', () => {
16 | // provide our implementations or mocks to the dependency injector
17 | beforeEach(() => addProviders([
18 | BaseRequestOptions,
19 | MockBackend,
20 | {
21 | provide: Http,
22 | useFactory: function(backend, defaultOptions) {
23 | return new Http(backend, defaultOptions);
24 | },
25 | deps: [MockBackend, BaseRequestOptions]
26 | },
27 |
28 | AppState,
29 | Title,
30 | Home
31 | ]));
32 |
33 | it('should have default data', inject([ Home ], (home) => {
34 | expect(home.localState).toEqual({ value: '' });
35 | }));
36 |
37 | it('should have a title', inject([ Home ], (home) => {
38 | expect(!!home.title).toEqual(true);
39 | }));
40 |
41 | it('should log ngOnInit', inject([ Home ], (home) => {
42 | spyOn(console, 'log');
43 | expect(console.log).not.toHaveBeenCalled();
44 |
45 | Home.ngOnInit();
46 | expect(console.log).toHaveBeenCalled();
47 | }));
48 |
49 | });
50 |
51 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/home/home.style.scss:
--------------------------------------------------------------------------------
1 | .card-container {
2 | display: flex;
3 | flex-direction: column;
4 | margin: 15px;
5 | }
6 |
7 | .sample-content {
8 | flex: 1;
9 | }
10 |
11 | .card-container md-card {
12 | margin: 5px;
13 | }
14 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/home/home.template.pug:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | .card-container
3 | h1.sample-content(x-large='') {{cookiecutter.github_repository_name}}
4 | hr
5 | div
6 | | For hot module reloading run
7 | pre.
8 | npm run start:hmr
9 | hr
10 | div
11 | h4 Local State
12 | form((ngsubmit)='submitState(localState.value)', autocomplete='off')
13 | input([value]='localState.value', (input)='localState.value = $event.target.value', placeholder='Submit Local State to App State', autofocus='')
14 | button(md-raised-button='', color='primary') Submit Value
15 | //
16 |
17 | Rather than wiring up two-way data-binding ourselves with [value] and (input)
18 | we can use Angular's [(ngModel)] syntax
19 |
20 | pre.
21 | \nthis.localState = {{ localState | json }}
22 | md-card
23 | md-card-title Slider with Value
24 | md-card-content
25 | md-slider(value='24')
26 | md-card
27 | md-card-title Tooltips
28 | md-card-content
29 | button(md-raised-button='', md-tooltip='This is a tooltip!') Hello
30 | button(md-raised-button='', md-tooltip='Another tooltip') World
31 |
32 |
33 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/home/index.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | export * from './home.component';
3 |
4 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/home/title/index.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | export * from './title.service';
3 |
4 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/home/title/title.service.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | import { Injectable } from '@angular/core';
3 | import { Http } from '@angular/http';
4 |
5 | @Injectable()
6 | export class Title {
7 | value = 'Angular 2';
8 | constructor(public http: Http) {
9 |
10 | }
11 |
12 | getData() {
13 | console.log('Title#getData(): Get Data');
14 | // return this.http.get('/assets/data.json')
15 | // .map(res => res.json());
16 | return {
17 | value: 'AngularClass'
18 | };
19 | }
20 |
21 | }
22 |
23 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/home/title/title.spec.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | import {
3 | addProviders,
4 | inject
5 | } from '@angular/core/testing';
6 | import { TestComponentBuilder } from '@angular/core/testing';
7 | import { Component } from '@angular/core';
8 | import { BaseRequestOptions, Http } from '@angular/http';
9 | import { MockBackend } from '@angular/http/testing';
10 |
11 | import { Title } from './title.service';
12 |
13 | describe('Title', () => {
14 | beforeEach(() => addProviders([
15 | BaseRequestOptions,
16 | MockBackend,
17 | {
18 | provide: Http,
19 | useFactory: function(backend, defaultOptions) {
20 | return new Http(backend, defaultOptions);
21 | },
22 | deps: [MockBackend, BaseRequestOptions]
23 | },
24 |
25 | Title
26 | ]));
27 |
28 |
29 | it('should have http', inject([ Title ], (title) => {
30 | expect(!!title.http).toEqual(true);
31 | }));
32 |
33 | it('should get data from the server', inject([ Title ], (title) => {
34 | spyOn(console, 'log');
35 | expect(console.log).not.toHaveBeenCalled();
36 |
37 | title.getData();
38 | expect(console.log).toHaveBeenCalled();
39 | expect(title.getData()).toEqual({ value: 'AngularClass' });
40 | }));
41 |
42 | });
43 |
44 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/home/x-large/index.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | export * from './x-large.directive';
3 |
4 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/home/x-large/x-large.directive.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | import { Component, Directive, ElementRef, Renderer } from '@angular/core';
3 | /*
4 | * Directive
5 | * XLarge is a simple directive to show how one is made
6 | */
7 | @Directive({
8 | selector: '[x-large]' // using [ ] means selecting attributes
9 | })
10 | export class XLarge {
11 | constructor(element: ElementRef, renderer: Renderer) {
12 | // simple DOM manipulation to set font size to x-large
13 | // `nativeElement` is the direct reference to the DOM element
14 | // element.nativeElement.style.fontSize = 'x-large';
15 |
16 | // for server/webworker support use the renderer
17 | renderer.setElementStyle(element.nativeElement, 'fontSize', 'x-large');
18 | }
19 | }
20 |
21 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/home/x-large/x-large.spec.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | import {
3 | async,
4 | addProviders,
5 | inject
6 | } from '@angular/core/testing';
7 | import { TestComponentBuilder } from '@angular/core/testing';
8 | import { Component } from '@angular/core';
9 | import { BaseRequestOptions, Http } from '@angular/http';
10 | import { MockBackend } from '@angular/http/testing';
11 |
12 | // Load the implementations that should be tested
13 | import { XLarge } from './x-large.directive';
14 |
15 | describe('x-large directive', () => {
16 | // Create a test component to test directives
17 | @Component({
18 | template: '',
19 | directives: [ XLarge ]
20 | })
21 | class TestComponent {}
22 |
23 | it('should sent font-size to x-large', async(inject([TestComponentBuilder], (tcb) => {
24 | return tcb.overrideTemplate(TestComponent, 'Content
')
25 | .createAsync(TestComponent).then((fixture: any) => {
26 | fixture.detectChanges();
27 | let compiled = fixture.debugElement.nativeElement.children[0];
28 | expect(compiled.style.fontSize).toBe('x-large');
29 | });
30 | })));
31 |
32 | });
33 |
34 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/index.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | // App
3 | export * from './app.module';
4 |
5 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/md.module.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | /* This module is an example how you can package all services and components
3 | from Angular2-Material into one Angular2 module, which you can import in other modules
4 | */
5 | import { NgModule, ModuleWithProviders } from '@angular/core';
6 |
7 | import { MdButtonModule } from '@angular2-material/button';
8 | import { MdButtonToggleModule } from '@angular2-material/button-toggle';
9 | import { MdCardModule } from '@angular2-material/card';
10 | import { MdCheckboxModule } from '@angular2-material/checkbox';
11 | import { MdGridListModule } from '@angular2-material/grid-list';
12 | import { MdIconModule } from '@angular2-material/icon';
13 | import { MdInputModule } from '@angular2-material/input';
14 | import { MdListModule } from '@angular2-material/list';
15 | import { MdMenuModule } from '@angular2-material/menu';
16 | import { MdProgressBarModule } from '@angular2-material/progress-bar';
17 | import { MdProgressCircleModule } from '@angular2-material/progress-circle';
18 | import { MdRadioModule } from '@angular2-material/radio';
19 | import { MdSidenavModule } from '@angular2-material/sidenav';
20 | import { MdSliderModule } from '@angular2-material/slider';
21 | import { MdSlideToggleModule } from '@angular2-material/slide-toggle';
22 | import { MdTabsModule } from '@angular2-material/tabs';
23 | import { MdToolbarModule } from '@angular2-material/toolbar';
24 | import { MdTooltipModule } from '@angular2-material/tooltip';
25 |
26 | @NgModule({
27 |
28 | exports: [
29 | MdButtonModule,
30 | MdButtonToggleModule,
31 | MdCardModule,
32 | MdCheckboxModule,
33 | MdGridListModule,
34 | MdIconModule,
35 | MdInputModule,
36 | MdListModule,
37 | MdMenuModule,
38 | MdProgressBarModule,
39 | MdProgressCircleModule,
40 | MdRadioModule,
41 | MdSidenavModule,
42 | MdSliderModule,
43 | MdSlideToggleModule,
44 | MdTabsModule,
45 | MdToolbarModule,
46 | MdTooltipModule
47 | ]
48 | })
49 |
50 | export class MdModule {
51 |
52 | static forRoot(): ModuleWithProviders {
53 | return {
54 | ngModule: MdModule
55 | };
56 | }
57 | }
58 |
59 |
60 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/no-content/index.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | export * from './no-content';
3 |
4 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/app/no-content/no-content.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | import { Component } from '@angular/core';
3 |
4 | @Component({
5 | selector: 'no-content',
6 | template: `
7 |
8 |
404: page missing
9 |
10 | `
11 | })
12 | export class NoContent {
13 |
14 | }
15 |
16 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/css/.gitkeep:
--------------------------------------------------------------------------------
1 | @AngularClass
2 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/data.json:
--------------------------------------------------------------------------------
1 | {
2 | "value": "AngularClass"
3 | }
4 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/humans.txt:
--------------------------------------------------------------------------------
1 | # humanstxt.org/
2 | # The humans responsible & technology colophon
3 |
4 | # TEAM
5 |
6 | -- --
7 |
8 | # THANKS
9 |
10 |
11 | PatrickJS -- @gdi2290
12 | AngularClass -- @AngularClass
13 |
14 | # TECHNOLOGY COLOPHON
15 |
16 | HTML5, CSS3
17 | Angular2, TypeScript, Webpack
18 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/android-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/android-icon-144x144.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/android-icon-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/android-icon-192x192.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/android-icon-36x36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/android-icon-36x36.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/android-icon-48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/android-icon-48x48.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/android-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/android-icon-72x72.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/android-icon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/android-icon-96x96.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon-114x114.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon-114x114.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon-120x120.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon-144x144.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon-152x152.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon-180x180.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon-57x57.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon-57x57.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon-60x60.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon-72x72.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon-76x76.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon-precomposed.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/apple-icon.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 | #ffffff
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/favicon-16x16.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/favicon-32x32.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/favicon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/favicon-96x96.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/favicon.ico
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/ms-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/ms-icon-144x144.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/ms-icon-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/ms-icon-150x150.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/ms-icon-310x310.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/ms-icon-310x310.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/ms-icon-70x70.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/icon/ms-icon-70x70.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/img/angular-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/img/angular-logo.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/img/angularclass-avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/img/angularclass-avatar.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/img/angularclass-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/img/angularclass-logo.png
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "App",
3 | "icons": [
4 | {
5 | "src": "/assets/icon/android-icon-36x36.png",
6 | "sizes": "36x36",
7 | "type": "image/png",
8 | "density": 0.75
9 | },
10 | {
11 | "src": "/assets/icon/android-icon-48x48.png",
12 | "sizes": "48x48",
13 | "type": "image/png",
14 | "density": 1.0
15 | },
16 | {
17 | "src": "/assets/icon/android-icon-72x72.png",
18 | "sizes": "72x72",
19 | "type": "image/png",
20 | "density": 1.5
21 | },
22 | {
23 | "src": "/assets/icon/android-icon-96x96.png",
24 | "sizes": "96x96",
25 | "type": "image/png",
26 | "density": 2.0
27 | },
28 | {
29 | "src": "/assets/icon/android-icon-144x144.png",
30 | "sizes": "144x144",
31 | "type": "image/png",
32 | "density": 3.0
33 | },
34 | {
35 | "src": "/assets/icon/android-icon-192x192.png",
36 | "sizes": "192x192",
37 | "type": "image/png",
38 | "density": 4.0
39 | }
40 | ]
41 | }
42 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/mock-data/mock-data.json:
--------------------------------------------------------------------------------
1 | [
2 | {"res": "data"}
3 | ]
4 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/robots.txt:
--------------------------------------------------------------------------------
1 | # robotstxt.org
2 |
3 | User-agent: *
4 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/assets/service-worker.js:
--------------------------------------------------------------------------------
1 | // This file is intentionally without code.
2 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/custom-typings.d.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | /*
3 | * Custom Type Definitions
4 | * When including 3rd party modules you also need to include the type definition for the module
5 | * if they don't provide one within the module. You can try to install it with @types
6 |
7 | npm install @types/node
8 | npm install @types/lodash
9 |
10 | * If you can't find the type definition in the registry we can make an ambient/global definition in
11 | * this file for now. For example
12 |
13 | declare module 'my-module' {
14 | export function doesSomething(value: string): string;
15 | }
16 |
17 | * If you are using a CommonJS module that is using module.exports then you will have to write your
18 | * types using export = yourObjectOrFunction with a namespace above it
19 | * notice how we have to create a namespace that is equal to the function we're
20 | * assigning the export to
21 |
22 | declare module 'jwt-decode' {
23 | function jwtDecode(token: string): any;
24 | namespace jwtDecode {}
25 | export = jwtDecode;
26 | }
27 |
28 | *
29 | * If you're prototying and you will fix the types later you can also declare it as type any
30 | *
31 |
32 | declare var assert: any;
33 | declare var _: any;
34 | declare var $: any;
35 |
36 | *
37 | * If you're importing a module that uses Node.js modules which are CommonJS you need to import as
38 | * in the files such as main.browser.ts or any file within app/
39 | *
40 |
41 | import * as _ from 'lodash'
42 |
43 | * You can include your type definitions in this file until you create one for the @types
44 | *
45 | */
46 |
47 | // support NodeJS modules without type definitions
48 | declare module '*';
49 |
50 | // Extra variables that live on Global that will be replaced by webpack DefinePlugin
51 | declare var ENV: string;
52 | declare var HMR: boolean;
53 | declare var System: SystemJS;
54 |
55 | interface SystemJS {
56 | import: (path?: string) => Promise;
57 | }
58 |
59 | interface GlobalEnvironment {
60 | ENV;
61 | HMR;
62 | SystemJS: SystemJS;
63 | System: SystemJS;
64 | }
65 |
66 | interface Es6PromiseLoader {
67 | (id: string): (exportName?: string) => Promise;
68 | }
69 |
70 | type FactoryEs6PromiseLoader = () => Es6PromiseLoader;
71 | type FactoryPromise = () => Promise;
72 |
73 | type AsyncRoutes = {
74 | [component: string]: Es6PromiseLoader |
75 | Function |
76 | FactoryEs6PromiseLoader |
77 | FactoryPromise
78 | };
79 |
80 |
81 | type IdleCallbacks = Es6PromiseLoader |
82 | Function |
83 | FactoryEs6PromiseLoader |
84 | FactoryPromise ;
85 |
86 | interface WebpackModule {
87 | hot: {
88 | data?: any,
89 | idle: any,
90 | accept(dependencies?: string | string[], callback?: (updatedDependencies?: any) => void): void;
91 | decline(deps?: any | string | string[]): void;
92 | dispose(callback?: (data?: any) => void): void;
93 | addDisposeHandler(callback?: (data?: any) => void): void;
94 | removeDisposeHandler(callback?: (data?: any) => void): void;
95 | check(autoApply?: any, callback?: (err?: Error, outdatedModules?: any[]) => void): void;
96 | apply(options?: any, callback?: (err?: Error, outdatedModules?: any[]) => void): void;
97 | status(callback?: (status?: string) => void): void | string;
98 | removeStatusHandler(callback?: (status?: string) => void): void;
99 | };
100 | }
101 |
102 |
103 | interface WebpackRequire {
104 | (id: string): any;
105 | (paths: string[], callback: (...modules: any[]) => void): void;
106 | ensure(ids: string[], callback: (req: WebpackRequire) => void, chunkName?: string): void;
107 | context(directory: string, useSubDirectories?: boolean, regExp?: RegExp): WebpackContext;
108 | }
109 |
110 | interface WebpackContext extends WebpackRequire {
111 | keys(): string[];
112 | }
113 |
114 | interface ErrorStackTraceLimit {
115 | stackTraceLimit: number;
116 | }
117 |
118 |
119 | // Extend typings
120 | interface NodeRequire extends WebpackRequire {}
121 | interface ErrorConstructor extends ErrorStackTraceLimit {}
122 | interface NodeRequireFunction extends Es6PromiseLoader {}
123 | interface NodeModule extends WebpackModule {}
124 | interface Global extends GlobalEnvironment {}
125 |
126 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/index.html:
--------------------------------------------------------------------------------
1 | {% raw %}
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | <%= webpackConfig.metadata.title %>
11 |
12 |
13 |
14 | <% if (webpackConfig.htmlElements.headTags) { %>
15 |
16 | <%= webpackConfig.htmlElements.headTags %>
17 | <% } %>
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | Loading...
29 |
30 |
31 |
32 |
41 |
42 | <% if (webpackConfig.metadata.isDevServer && webpackConfig.metadata.HMR !== true) { %>
43 |
44 |
45 | <% } %>
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/main.browser.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | /*
3 | * Angular bootstraping
4 | */
5 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
6 | import { decorateModuleRef } from './app/environment';
7 | import { ApplicationRef } from '@angular/core';
8 | import { bootloader } from '@angularclass/hmr';
9 | /*
10 | * App Module
11 | * our top level module that holds all of our components
12 | */
13 | import { AppModule } from './app';
14 |
15 | /*
16 | * Bootstrap our Angular app with a top level NgModule
17 | */
18 | export function main(): Promise {
19 | return platformBrowserDynamic()
20 | .bootstrapModule(AppModule)
21 | .then(decorateModuleRef)
22 | .catch(err => console.error(err));
23 |
24 | }
25 |
26 |
27 | bootloader(main);
28 |
29 |
30 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/polyfills.browser.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | // TODO(gdi2290): switch to DLLs
3 |
4 | // Polyfills
5 |
6 | // import 'ie-shim'; // Internet Explorer 9 support
7 |
8 |
9 | // import 'core-js/es6';
10 | // Added parts of es6 which are necessary for your project or your browser support requirements.
11 | import 'core-js/es6/symbol';
12 | import 'core-js/es6/object';
13 | import 'core-js/es6/function';
14 | import 'core-js/es6/parse-int';
15 | import 'core-js/es6/parse-float';
16 | import 'core-js/es6/number';
17 | import 'core-js/es6/math';
18 | import 'core-js/es6/string';
19 | import 'core-js/es6/date';
20 | import 'core-js/es6/array';
21 | import 'core-js/es6/regexp';
22 | import 'core-js/es6/map';
23 | import 'core-js/es6/set';
24 | import 'core-js/es6/weak-map';
25 | import 'core-js/es6/weak-set';
26 | import 'core-js/es6/typed';
27 | import 'core-js/es6/reflect';
28 | // see issue https://github.com/AngularClass/angular2-webpack-starter/issues/709
29 | // import 'core-js/es6/promise';
30 |
31 | import 'core-js/es7/reflect';
32 | import 'zone.js/dist/zone';
33 |
34 | // Typescript emit helpers polyfill
35 | import 'ts-helpers';
36 |
37 | if ('production' === ENV) {
38 | // Production
39 |
40 |
41 | } else {
42 | // Development
43 |
44 | Error.stackTraceLimit = Infinity;
45 |
46 | require('zone.js/dist/long-stack-trace-zone');
47 |
48 | }
49 |
50 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/src/vendor.browser.ts:
--------------------------------------------------------------------------------
1 | {% raw %}
2 | // For vendors for example jQuery, Lodash, angular2-jwt just import them here unless you plan on
3 | // chunking vendors files for async loading. You would need to import the async loaded vendors
4 | // at the entry point of the async loaded file. Also see custom-typings.d.ts as you also need to
5 | // run `typings install x` where `x` is your module
6 |
7 | // TODO(gdi2290): switch to DLLs
8 |
9 | // Angular 2
10 | import '@angular/platform-browser';
11 | import '@angular/platform-browser-dynamic';
12 | import '@angular/core';
13 | import '@angular/common';
14 | import '@angular/forms';
15 | import '@angular/http';
16 | import '@angular/router';
17 |
18 | // Hammer.js
19 | // We need to import this library in order for Material to work
20 | // Material needs this for md-tooltips
21 | import 'hammerjs/hammer.js';
22 |
23 | // AngularClass
24 | import '@angularclass/hmr';
25 |
26 | // RxJS
27 | import 'rxjs/add/operator/map';
28 | import 'rxjs/add/operator/mergeMap';
29 |
30 | if ('production' === ENV) {
31 | // Production
32 |
33 |
34 | } else {
35 | // Development
36 |
37 | }
38 |
39 | {% endraw %}
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "commonjs",
5 | "moduleResolution": "node",
6 | "emitDecoratorMetadata": true,
7 | "experimentalDecorators": true,
8 | "allowSyntheticDefaultImports": true,
9 | "sourceMap": true,
10 | "noEmitHelpers": true,
11 | "strictNullChecks": false,
12 | "baseUrl": "./src",
13 | "paths": [
14 | ],
15 | "lib": [
16 | "dom",
17 | "es6"
18 | ],
19 | "types": [
20 | "core-js",
21 | "hammerjs",
22 | "jasmine",
23 | "node",
24 | "protractor",
25 | "selenium-webdriver",
26 | "source-map",
27 | "uglify-js",
28 | "webpack"
29 | ]
30 | },
31 | "exclude": [
32 | "node_modules",
33 | "dist"
34 | ],
35 | "awesomeTypescriptLoaderOptions": {
36 | "forkChecker": true,
37 | "useWebpackText": true
38 | },
39 | "compileOnSave": false,
40 | "buildOnSave": false,
41 | "atom": { "rewriteTsconfig": false }
42 | }
43 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rulesDirectory": [
3 | "node_modules/codelyzer"
4 | ],
5 | "rules": {
6 | "member-access": false,
7 | "member-ordering": [
8 | true,
9 | "public-before-private",
10 | "static-before-instance",
11 | "variables-before-functions"
12 | ],
13 | "no-any": false,
14 | "no-inferrable-types": false,
15 | "no-internal-module": true,
16 | "no-var-requires": false,
17 | "typedef": false,
18 | "typedef-whitespace": [
19 | true,
20 | {
21 | "call-signature": "nospace",
22 | "index-signature": "nospace",
23 | "parameter": "nospace",
24 | "property-declaration": "nospace",
25 | "variable-declaration": "nospace"
26 | },
27 | {
28 | "call-signature": "space",
29 | "index-signature": "space",
30 | "parameter": "space",
31 | "property-declaration": "space",
32 | "variable-declaration": "space"
33 | }
34 | ],
35 |
36 | "ban": false,
37 | "curly": false,
38 | "forin": true,
39 | "label-position": true,
40 | "label-undefined": true,
41 | "no-arg": true,
42 | "no-bitwise": true,
43 | "no-conditional-assignment": true,
44 | "no-console": [
45 | true,
46 | "debug",
47 | "info",
48 | "time",
49 | "timeEnd",
50 | "trace"
51 | ],
52 | "no-construct": true,
53 | "no-debugger": true,
54 | "no-duplicate-key": true,
55 | "no-duplicate-variable": true,
56 | "no-empty": false,
57 | "no-eval": true,
58 | "no-null-keyword": false,
59 | "no-shadowed-variable": true,
60 | "no-string-literal": false,
61 | "no-switch-case-fall-through": true,
62 | "no-unreachable": true,
63 | "no-unused-expression": true,
64 | "no-unused-variable": false,
65 | "no-use-before-declare": true,
66 | "no-var-keyword": true,
67 | "radix": true,
68 | "switch-default": true,
69 | "triple-equals": [
70 | true,
71 | "allow-null-check"
72 | ],
73 | "use-strict": [
74 | true,
75 | "check-module"
76 | ],
77 |
78 | "eofline": true,
79 | "indent": [
80 | true,
81 | "spaces"
82 | ],
83 | "max-line-length": [
84 | true,
85 | 100
86 | ],
87 | "no-require-imports": false,
88 | "no-trailing-whitespace": true,
89 | "object-literal-sort-keys": false,
90 | "trailing-comma": [
91 | true,
92 | {
93 | "multiline": false,
94 | "singleline": "never"
95 | }
96 | ],
97 |
98 | "align": false,
99 | "class-name": true,
100 | "comment-format": [
101 | true,
102 | "check-space"
103 | ],
104 | "interface-name": false,
105 | "jsdoc-format": true,
106 | "no-consecutive-blank-lines": false,
107 | "no-constructor-vars": false,
108 | "one-line": [
109 | true,
110 | "check-open-brace",
111 | "check-catch",
112 | "check-else",
113 | "check-finally",
114 | "check-whitespace"
115 | ],
116 | "quotemark": [
117 | true,
118 | "single",
119 | "avoid-escape"
120 | ],
121 | "semicolon": [true, "always"],
122 | "variable-name": [
123 | true,
124 | "check-format",
125 | "allow-leading-underscore",
126 | "ban-keywords"
127 | ],
128 | "whitespace": [
129 | true,
130 | "check-branch",
131 | "check-decl",
132 | "check-operator",
133 | "check-separator",
134 | "check-type"
135 | ],
136 | "import-destructuring-spacing": true
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/typedoc.json:
--------------------------------------------------------------------------------
1 | {
2 | "mode": "modules",
3 | "out": "doc",
4 | "theme": "default",
5 | "ignoreCompilerErrors": "true",
6 | "experimentalDecorators": "true",
7 | "emitDecoratorMetadata": "true",
8 | "target": "ES5",
9 | "moduleResolution": "node",
10 | "preserveConstEnums": "true",
11 | "stripInternal": "true",
12 | "suppressExcessPropertyErrors": "true",
13 | "suppressImplicitAnyIndexErrors": "true",
14 | "module": "commonjs"
15 | }
16 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/frontend/webpack.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: @AngularClass
3 | */
4 |
5 | // Look in ./config folder for webpack.dev.js
6 | switch (process.env.NODE_ENV) {
7 | case 'prod':
8 | case 'production':
9 | module.exports = require('./config/webpack.prod');
10 | break;
11 | case 'test':
12 | case 'testing':
13 | module.exports = require('./config/webpack.test');
14 | break;
15 | case 'dev':
16 | case 'development':
17 | default:
18 | module.exports = require('./config/webpack.dev');
19 | }
20 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/mkdocs.yml:
--------------------------------------------------------------------------------
1 | site_name: {{cookiecutter.app_name}}
2 | site_description: {{cookiecutter.description}}
3 | repo_url: https://github.com/{{cookiecutter.github_username}}/{{cookiecutter.github_repository_name}}
4 | site_dir: site
5 | copyright: Copyright © 2015, {{cookiecutter.github_username}} .
6 |
7 | pages:
8 | - Home: 'index.md'
9 | - API:
10 | - Authentication: 'api/authentication.md'
11 | - Users: 'api/users.md'
12 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/requirements.txt:
--------------------------------------------------------------------------------
1 | # Django
2 | Django==1.9.7
3 |
4 | # Environmental var configuration
5 | django-configurations==1.0
6 |
7 | # For the persistence stores
8 | psycopg2==2.6.1
9 | dj-database-url==0.4.0
10 |
11 | # Models
12 | django-model-utils==2.4
13 |
14 | # Rest apis
15 | djangorestframework==3.3.3
16 | Markdown==2.6.6
17 | django-filter==0.13.0
18 |
19 | # Static files
20 | whitenoise==3.0
21 |
22 | # Media files
23 | boto==2.39.0
24 | django_unique_upload==0.2.1
25 |
26 | # Image manipulation
27 | django-versatileimagefield==1.3
28 |
29 | # For asynchronous queuing
30 | django-rq==0.9.0
31 |
32 | # Time zones support
33 | pytz==2016.3
34 |
35 | # Admion Theme
36 | django-suit==0.2.18
37 |
38 | # WSGI Handler
39 | gevent==1.0.2
40 | gunicorn==19.3.0
41 |
42 | # Static and Media Storage
43 | django-storages-redux==1.2.3
44 |
45 | # Caching
46 | hiredis==0.2.0
47 | django-redis-cache==1.6.5
48 |
49 | # Django-secure
50 | django-secure==1.0.1
51 |
52 | # App Monitoring
53 | newrelic==2.50.0.39
54 |
55 | # Debugging
56 | ipdb==0.9.0
57 | ipython==4.1.2
58 |
59 | # Docs
60 | mkdocs==0.15.3
61 |
62 | # Command Utils
63 | Fabric==1.10.2
64 |
65 | # Mocking
66 | mock==1.3.0
67 |
68 | pytest==2.9.1
69 | pytest-django==2.9.1
70 |
71 | # Code Coverage
72 | coverage==4.0.3
73 |
74 | # Style Enforcement
75 | flake8==2.5.4
76 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/setup.cfg:
--------------------------------------------------------------------------------
1 | [flake8]
2 | ignore = E226,E302,E41,E702
3 | max-line-length = 160
4 | exclude = migrations
5 |
6 | [pytest]
7 | DJANGO_SETTINGS_MODULE={{cookiecutter.app_name}}.config
8 | DJANGO_CONFIGURATION=Local
9 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup, find_packages
2 |
3 | setup(
4 | name = "{{cookiecutter.app_name}}",
5 | version = "0.1",
6 | author = "{{cookiecutter.github_username}}",
7 | author_email = "{{cookiecutter.email}}",
8 | description = ("{{cookiecutter.description}}"),
9 | packages=find_packages(),
10 | )
11 |
12 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/tests/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup, find_packages
2 |
3 | setup(
4 | name = "{{cookiecutter.app_name}}_tests",
5 | version = "0.1",
6 | author = "{{cookiecutter.github_username}}",
7 | author_email = "{{cookiecutter.email}}",
8 | packages=find_packages(),
9 | )
10 |
11 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/tests/{{cookiecutter.app_name}}_tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/tests/{{cookiecutter.app_name}}_tests/__init__.py
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/tests/{{cookiecutter.app_name}}_tests/authentication/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/tests/{{cookiecutter.app_name}}_tests/authentication/__init__.py
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/tests/{{cookiecutter.app_name}}_tests/authentication/test_signals.py:
--------------------------------------------------------------------------------
1 | # from django.test import TestCase
2 | # from nose.tools import ok_
3 | # from {{cookiecutter.app_name}}_tests.users.factories import UserFactory
4 | #
5 | # class AuthTokenTestCase(TestCase):
6 | #
7 | # def setUp(self):
8 | # self.user = UserFactory()
9 | #
10 | # def test_new_users_get_auth_token(self):
11 | # ok_(self.user.auth_token)
12 |
13 | # TODO: rewrite tests in pytest
14 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/tests/{{cookiecutter.app_name}}_tests/users/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/tests/{{cookiecutter.app_name}}_tests/users/__init__.py
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/tests/{{cookiecutter.app_name}}_tests/users/factories.py:
--------------------------------------------------------------------------------
1 | # import uuid
2 | # import factory
3 | #
4 | # class UserFactory(factory.django.DjangoModelFactory):
5 | #
6 | # class Meta:
7 | # model = 'users.User'
8 | # django_get_or_create = ('username',)
9 | #
10 | # id = factory.Sequence(lambda n: uuid.uuid4())
11 | # username = factory.Sequence(lambda n: 'testuser{}'.format(n))
12 | # password = factory.Faker('password', length=10, special_chars=True, digits=True, upper_case=True, lower_case=True)
13 | # email = factory.Faker('email')
14 | # first_name = factory.Faker('first_name')
15 | # last_name = factory.Faker('last_name')
16 | # is_active = True
17 | # is_staff = False
18 |
19 | # TODO: rewrite tests in pytest
20 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/tests/{{cookiecutter.app_name}}_tests/users/test_serializers.py:
--------------------------------------------------------------------------------
1 | # from django.test import TestCase
2 | # from django.forms.models import model_to_dict
3 | # from django.contrib.auth.hashers import check_password
4 | # from nose.tools import eq_, ok_
5 | # from {{cookiecutter.app_name}}_tests.users.factories import UserFactory
6 | # from {{cookiecutter.app_name}}.users.serializers import CreateUserSerializer
7 | #
8 | #
9 | # class TestCreateUserSerializer(TestCase):
10 | #
11 | # def setUp(self):
12 | # self.user_data = model_to_dict(UserFactory.build())
13 | #
14 | # def test_serializer_with_empty_data(self):
15 | # serializer = CreateUserSerializer(data={})
16 | # eq_(serializer.is_valid(), False)
17 | #
18 | # def test_serializer_with_valid_data(self):
19 | # serializer = CreateUserSerializer(data=self.user_data)
20 | # ok_(serializer.is_valid())
21 | #
22 | # def test_serializer_hashes_password(self):
23 | # serializer = CreateUserSerializer(data=self.user_data)
24 | # ok_(serializer.is_valid())
25 | #
26 | # user = serializer.save()
27 | # ok_(check_password(self.user_data.get('password'), user.password))
28 |
29 | # TODO: rewrite tests in pytest
30 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/tests/{{cookiecutter.app_name}}_tests/users/test_views.py:
--------------------------------------------------------------------------------
1 | # from django.core.urlresolvers import reverse
2 | # from django.forms.models import model_to_dict
3 | # from django.contrib.auth.hashers import check_password
4 | # from nose.tools import ok_, eq_
5 | # from rest_framework.test import APITestCase
6 | # from faker import Faker
7 | # from {{cookiecutter.app_name}}.users.models import User
8 | # from {{cookiecutter.app_name}}_tests.users.factories import UserFactory
9 | #
10 | # fake = Faker()
11 | #
12 | #
13 | # class TestUserAPI(APITestCase):
14 | # """
15 | # Tests the /users endpoint.
16 | # """
17 | #
18 | # def setUp(self):
19 | # self.url = reverse('user-list')
20 | # self.user_data = model_to_dict(UserFactory.build())
21 | #
22 | # def test_post_request_with_no_data_fails(self):
23 | # response = self.client.post(self.url, {})
24 | # eq_(response.status_code, 400)
25 | #
26 | # def test_post_request_with_valid_data_succeeds(self):
27 | # response = self.client.post(self.url, self.user_data)
28 | # eq_(response.status_code, 201)
29 | #
30 | # user = User.objects.get(pk=response.data.get('id'))
31 | # eq_(user.username, self.user_data.get('username'))
32 | # ok_(check_password(self.user_data.get('password'), user.password))
33 | #
34 | #
35 | # class TestUserDetailAPI(APITestCase):
36 | #
37 | # def setUp(self):
38 | # self.user = UserFactory()
39 | # self.url = reverse('user-detail', kwargs={'pk': self.user.pk})
40 | # self.client.credentials(HTTP_AUTHORIZATION='Token {}'.format(self.user.auth_token))
41 | #
42 | # def test_get_request_returns_a_given_user(self):
43 | # response = self.client.get(self.url)
44 | # eq_(response.status_code, 200)
45 | #
46 | # def test_put_request_updates_a_user(self):
47 | # new_first_name = fake.first_name()
48 | # payload = {'first_name': new_first_name}
49 | # response = self.client.put(self.url, payload)
50 | # eq_(response.status_code, 200)
51 | #
52 | # user = User.objects.get(pk=self.user.id)
53 | # eq_(user.first_name, new_first_name)
54 |
55 | # TODO: rewrite tests in pytest
56 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/__init__.py
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/authentication/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/authentication/__init__.py
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/authentication/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/authentication/migrations/__init__.py
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/authentication/models.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 | from django.db.models.signals import post_save
3 | from django.dispatch import receiver
4 | from rest_framework.authtoken.models import Token
5 |
6 |
7 | @receiver(post_save, sender=settings.AUTH_USER_MODEL)
8 | def create_auth_token(sender, instance=None, created=False, **kwargs):
9 | if created:
10 | Token.objects.create(user=instance)
11 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/authentication/urls.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import include, url
2 | from rest_framework.authtoken.views import obtain_auth_token
3 | from rest_framework import urls
4 |
5 | from rest_framework.urlpatterns import format_suffix_patterns
6 |
7 | from {{cookiecutter.app_name}}.authentication import views
8 |
9 | urlpatterns = [
10 | url(r'^login/$', views.Login.as_view()),
11 | url(r'^logout/$', views.Logout.as_view()),
12 | url(r'^active-user/$', views.ActiveUser.as_view()),
13 | # url(r'^api-token-auth/', obtain_auth_token),
14 | url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
15 | ]
16 |
17 | urlpatterns = format_suffix_patterns(urlpatterns)
18 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/authentication/views.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth import login, logout
2 | from django.contrib.auth.forms import AuthenticationForm
3 | from rest_framework.permissions import AllowAny, IsAuthenticated
4 | from rest_framework.response import Response
5 | from rest_framework.views import APIView
6 | from rest_framework.serializers import ValidationError
7 |
8 | from {{cookiecutter.app_name}}.users.serializers import UserSerializer
9 |
10 |
11 | class Login(APIView):
12 | permission_classes = (AllowAny, )
13 |
14 | def post(self, request, format=None):
15 | form = AuthenticationForm(request, data=request.data)
16 | if not form.is_valid():
17 | raise ValidationError(form.errors)
18 |
19 | user = form.get_user()
20 | login(request, user)
21 |
22 | return Response(UserSerializer(user).data)
23 |
24 |
25 | class Logout(APIView):
26 | permission_classes = (IsAuthenticated, )
27 |
28 | def get(self, request, format=None):
29 | logout(request)
30 |
31 | return Response({'status': 'success'})
32 |
33 |
34 | class ActiveUser(APIView):
35 | permission_classes = (IsAuthenticated, )
36 |
37 | def get(self, request, format=None):
38 | return Response(UserSerializer(request.user).data)
39 |
40 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/config/__init__.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 |
3 | from {{cookiecutter.app_name}}.config.local import Local # noqa
4 | from {{cookiecutter.app_name}}.config.production import Production # noqa
5 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/config/common.py:
--------------------------------------------------------------------------------
1 | import os
2 | from os.path import join
3 |
4 | from configurations import Configuration, values
5 |
6 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
7 | PROJECT_PATH = os.path.dirname(os.path.dirname(BASE_DIR))
8 |
9 |
10 | class Common(Configuration):
11 |
12 | INSTALLED_APPS = (
13 | # Admin templates
14 | 'suit',
15 |
16 | # Django
17 | 'django.contrib.admin',
18 | 'django.contrib.auth',
19 | 'django.contrib.contenttypes',
20 | 'django.contrib.sessions',
21 | 'django.contrib.messages',
22 | 'django.contrib.staticfiles',
23 |
24 | # Third party apps
25 | 'rest_framework', # utilities for rest apis
26 | 'rest_framework.authtoken', # token authentication
27 | 'django_rq', # asynchronous queuing
28 | 'versatileimagefield', # image manipulation
29 |
30 | # Your apps
31 | '{{cookiecutter.app_name}}.authentication',
32 | '{{cookiecutter.app_name}}.users'
33 |
34 | )
35 |
36 | # https://docs.djangoproject.com/en/1.8/topics/http/middleware/
37 | MIDDLEWARE_CLASSES = (
38 | 'django.contrib.sessions.middleware.SessionMiddleware',
39 | 'django.middleware.common.CommonMiddleware',
40 | 'django.middleware.csrf.CsrfViewMiddleware',
41 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
42 | 'django.contrib.messages.middleware.MessageMiddleware',
43 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
44 | 'django.middleware.security.SecurityMiddleware'
45 | )
46 |
47 | ROOT_URLCONF = 'urls'
48 |
49 | SECRET_KEY = 'Not a secret'
50 | WSGI_APPLICATION = 'wsgi.application'
51 |
52 | # Email
53 | EMAIL_BACKEND = values.Value('django.core.mail.backends.smtp.EmailBackend')
54 |
55 | MANAGERS = (
56 | ('Author', '{{cookiecutter.email}}'),
57 | )
58 |
59 | # General
60 | APPEND_SLASH = values.BooleanValue(False)
61 | TIME_ZONE = 'Asia/Jerusalem'
62 | LANGUAGE_CODE = 'en-us'
63 | # If you set this to False, Django will make some optimizations so as not
64 | # to load the internationalization machinery.
65 | USE_I18N = False
66 | USE_L10N = True
67 | USE_TZ = True
68 | LOGIN_REDIRECT_URL = '/'
69 |
70 | # Static Files
71 | STATIC_ROOT = join(PROJECT_PATH, 'static_root', 'static')
72 | STATICFILES_DIRS = [join(PROJECT_PATH, 'client', 'static'), ]
73 | STATIC_URL = '/static/'
74 | STATICFILES_FINDERS = (
75 | 'django.contrib.staticfiles.finders.FileSystemFinder',
76 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
77 | )
78 |
79 | # Media files
80 | MEDIA_ROOT = join(PROJECT_PATH, 'client', 'static')
81 | MEDIA_URL = '/media/'
82 |
83 | TEMPLATES = [
84 | {
85 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
86 | 'DIRS': [join(MEDIA_ROOT, 'build')],
87 | 'OPTIONS': {
88 | 'context_processors': [
89 | 'django.core.context_processors.request',
90 | 'django.contrib.auth.context_processors.auth',
91 | 'django.template.context_processors.debug',
92 | 'django.template.context_processors.i18n',
93 | 'django.template.context_processors.media',
94 | 'django.template.context_processors.static',
95 | 'django.template.context_processors.tz',
96 | 'django.contrib.messages.context_processors.messages'
97 | ],
98 | 'loaders':[
99 | ('django.template.loaders.cached.Loader', [
100 | 'django.template.loaders.filesystem.Loader',
101 | 'django.template.loaders.app_directories.Loader',
102 | ]),
103 | ],
104 | },
105 | },
106 | ]
107 |
108 | SUIT_CONFIG = {
109 | # header
110 | 'ADMIN_NAME': '{{cookiecutter.app_name | replace("_", " ") | replace("-", " ") | title}} Admin',
111 |
112 | # menu
113 | 'MENU_ICONS': {
114 | 'sites': 'icon-leaf',
115 | 'auth': 'icon-lock',
116 | },
117 | 'MENU_OPEN_FIRST_CHILD': False,
118 | 'MENU_EXCLUDE': ('authtoken'),
119 | }
120 |
121 |
122 | # Set DEBUG to False as a default for safety
123 | # https://docs.djangoproject.com/en/dev/ref/settings/#debug
124 | DEBUG = values.BooleanValue(False)
125 | for config in TEMPLATES:
126 | config['OPTIONS']['debug'] = DEBUG
127 |
128 | # Logging
129 | LOGGING = {
130 | 'version': 1,
131 | 'disable_existing_loggers': False,
132 | 'filters': {
133 | 'require_debug_false': {
134 | '()': 'django.utils.log.RequireDebugFalse'
135 | }
136 | },
137 | 'formatters': {
138 | 'verbose': {
139 | 'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
140 | },
141 | 'simple': {
142 | 'format': '%(levelname)s %(message)s'
143 | },
144 | 'rq_console': {
145 | 'format': '%(asctime)s %(message)s',
146 | 'datefmt': '%H:%M:%S',
147 | },
148 | },
149 | 'handlers': {
150 | 'mail_admins': {
151 | 'level': 'ERROR',
152 | 'filters': ['require_debug_false'],
153 | 'class': 'django.utils.log.AdminEmailHandler'
154 | },
155 | 'console': {
156 | 'level': 'DEBUG',
157 | 'class': 'logging.StreamHandler',
158 | 'formatter': 'simple'
159 | },
160 | 'rq_console': {
161 | 'level': 'DEBUG',
162 | 'class': 'rq.utils.ColorizingStreamHandler',
163 | 'formatter': 'rq_console',
164 | 'exclude': ['%(asctime)s'],
165 | },
166 | },
167 | 'loggers': {
168 | 'django.request': {
169 | 'handlers': ['mail_admins'],
170 | 'level': 'ERROR',
171 | 'propagate': True
172 | },
173 | 'rq.worker': {
174 | 'handlers': ['rq_console'],
175 | 'level': 'DEBUG'
176 | },
177 | }
178 | }
179 |
180 | # Custom user app
181 | AUTH_USER_MODEL = 'users.User'
182 |
183 | # Django Rest Framework
184 | REST_FRAMEWORK = {
185 | 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
186 | 'PAGE_SIZE': 100,
187 | 'DATETIME_FORMAT': '%Y-%m-%dT%H:%M:%S%z',
188 | 'DEFAULT_RENDERER_CLASSES': (
189 | 'rest_framework.renderers.JSONRenderer',
190 | 'rest_framework.renderers.BrowsableAPIRenderer',
191 | ),
192 | 'DEFAULT_PERMISSION_CLASSES': [
193 | 'rest_framework.permissions.IsAuthenticated',
194 | ],
195 | 'DEFAULT_AUTHENTICATION_CLASSES': (
196 | 'rest_framework.authentication.SessionAuthentication',
197 | 'rest_framework.authentication.TokenAuthentication',
198 | )
199 | }
200 |
201 | # Versatile Image Field
202 | VERSATILEIMAGEFIELD_SETTINGS = {
203 | # The amount of time, in seconds, that references to created images
204 | # should be stored in the cache. Defaults to `2592000` (30 days)
205 | 'cache_length': 2592000,
206 | 'cache_name': 'versatileimagefield_cache',
207 | 'jpeg_resize_quality': 70,
208 | 'sized_directory_name': '__sized__',
209 | 'filtered_directory_name': '__filtered__',
210 | 'placeholder_directory_name': '__placeholder__',
211 | 'create_images_on_demand': False
212 | }
213 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/config/local.py:
--------------------------------------------------------------------------------
1 | import os
2 | from {{cookiecutter.app_name}}.config.common import Common
3 | from configurations import values
4 |
5 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
6 |
7 |
8 | class Local(Common):
9 |
10 | DEBUG = values.BooleanValue(True)
11 | for config in Common.TEMPLATES:
12 | config['OPTIONS']['debug'] = DEBUG
13 |
14 | DATABASES = {
15 | 'default': {
16 | 'ENGINE': 'django.db.backends.sqlite3',
17 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
18 | }
19 | }
20 |
21 |
22 | # Testing
23 | # INSTALLED_APPS = Common.INSTALLED_APPS
24 | # INSTALLED_APPS += ('django_nose',)
25 | # TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
26 | # NOSE_ARGS = [
27 | # BASE_DIR,
28 | # '--nologcapture',
29 | # '--with-coverage',
30 | # '--with-progressive',
31 | # '--cover-package={}'.format(BASE_DIR)
32 | # ]
33 |
34 | # Mail
35 | EMAIL_HOST = 'localhost'
36 | EMAIL_PORT = 1025
37 | EMAIL_BACKEND = values.Value('django.core.mail.backends.console.EmailBackend')
38 |
39 | # Django RQ local settings
40 | RQ_QUEUES = {
41 | 'default': {
42 | 'URL': os.getenv('REDISTOGO_URL', 'redis://localhost:6379'),
43 | 'DB': 0,
44 | 'DEFAULT_TIMEOUT': 500,
45 | },
46 | }
47 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/config/production.py:
--------------------------------------------------------------------------------
1 | import os
2 | from configurations import values
3 | from boto.s3.connection import OrdinaryCallingFormat
4 | from {{cookiecutter.app_name}}.config.common import Common
5 |
6 | try:
7 | # Python 2.x
8 | import urlparse
9 | except ImportError:
10 | # Python 3.x
11 | from urllib import parse as urlparse
12 |
13 |
14 | class Production(Common):
15 |
16 | # Honor the 'X-Forwarded-Proto' header for request.is_secure()
17 | # https://devcenter.heroku.com/articles/getting-started-with-django
18 | SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
19 |
20 | INSTALLED_APPS = Common.INSTALLED_APPS
21 | SECRET_KEY = values.SecretValue()
22 |
23 | # Postgres
24 | DATABASES = values.DatabaseURLValue('postgres://localhost/{{cookiecutter.app_name}}')
25 |
26 | # django-secure
27 | # http://django-secure.readthedocs.org/en/v0.1.2/settings.html
28 | INSTALLED_APPS += ("djangosecure", )
29 |
30 | SECURE_HSTS_SECONDS = 60
31 | SECURE_HSTS_INCLUDE_SUBDOMAINS = values.BooleanValue(True)
32 | SECURE_FRAME_DENY = values.BooleanValue(True)
33 | SECURE_CONTENT_TYPE_NOSNIFF = values.BooleanValue(True)
34 | SECURE_BROWSER_XSS_FILTER = values.BooleanValue(True)
35 | SESSION_COOKIE_SECURE = values.BooleanValue(False)
36 | SESSION_COOKIE_HTTPONLY = values.BooleanValue(True)
37 | SECURE_SSL_REDIRECT = values.BooleanValue(True)
38 |
39 | # Site
40 | # https://docs.djangoproject.com/en/1.6/ref/settings/#allowed-hosts
41 | ALLOWED_HOSTS = ["*"]
42 |
43 | INSTALLED_APPS += ("gunicorn", )
44 |
45 | # Template
46 | # https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs
47 | TEMPLATE_LOADERS = (
48 | ('django.template.loaders.cached.Loader', (
49 | 'django.template.loaders.filesystem.Loader',
50 | 'django.template.loaders.app_directories.Loader',
51 | )),
52 | )
53 |
54 | # Media files
55 | # http://django-storages.readthedocs.org/en/latest/index.html
56 | INSTALLED_APPS += ('storages',)
57 | DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
58 | AWS_ACCESS_KEY_ID = values.Value('DJANGO_AWS_ACCESS_KEY_ID')
59 | AWS_SECRET_ACCESS_KEY = values.Value('DJANGO_AWS_SECRET_ACCESS_KEY')
60 | AWS_STORAGE_BUCKET_NAME = values.Value('DJANGO_AWS_STORAGE_BUCKET_NAME')
61 | AWS_AUTO_CREATE_BUCKET = True
62 | AWS_QUERYSTRING_AUTH = False
63 | MEDIA_URL = 'https://s3.amazonaws.com/{}/'.format(AWS_STORAGE_BUCKET_NAME)
64 | AWS_S3_CALLING_FORMAT = OrdinaryCallingFormat()
65 |
66 | # https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching#cache-control
67 | # Response can be cached by browser and any intermediary caches (i.e. it is "public") for up to 1 day
68 | # 86400 = (60 seconds x 60 minutes x 24 hours)
69 | AWS_HEADERS = {
70 | 'Cache-Control': 'max-age=86400, s-maxage=86400, must-revalidate',
71 | }
72 |
73 | # Static files
74 | STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
75 |
76 | # Caching
77 | redis_url = urlparse.urlparse(os.environ.get('REDISTOGO_URL', 'redis://localhost:6379'))
78 | CACHES = {
79 | 'default': {
80 | 'BACKEND': 'redis_cache.RedisCache',
81 | 'LOCATION': '{}:{}'.format(redis_url.hostname, redis_url.port),
82 | 'OPTIONS': {
83 | 'DB': 0,
84 | 'PASSWORD': redis_url.password,
85 | 'PARSER_CLASS': 'redis.connection.HiredisParser',
86 | 'CONNECTION_POOL_CLASS': 'redis.BlockingConnectionPool',
87 | 'CONNECTION_POOL_CLASS_KWARGS': {
88 | 'max_connections': 50,
89 | 'timeout': 20,
90 | }
91 | }
92 | }
93 | }
94 |
95 | # Django RQ production settings
96 | RQ_QUEUES = {
97 | 'default': {
98 | 'URL': os.getenv('REDISTOGO_URL', 'redis://localhost:6379'),
99 | 'DB': 0,
100 | 'DEFAULT_TIMEOUT': 500,
101 | },
102 | }
103 |
104 | Common.VERSATILEIMAGEFIELD_SETTINGS['create_images_on_demand'] = False
105 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | if __name__ == "__main__":
6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{cookiecutter.app_name}}.config")
7 | os.environ.setdefault("DJANGO_CONFIGURATION", "Local")
8 |
9 | from configurations.management import execute_from_command_line
10 |
11 | execute_from_command_line(sys.argv)
12 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/urls.py:
--------------------------------------------------------------------------------
1 | from __future__ import unicode_literals
2 |
3 | from django.conf import settings
4 | from django.conf.urls import include, url
5 | from django.core.urlresolvers import reverse_lazy
6 | from django.conf.urls.static import static
7 | from django.contrib import admin
8 | from django.contrib.auth import views
9 | from django.views.generic.base import RedirectView
10 | from rest_framework.routers import DefaultRouter
11 |
12 | from {{cookiecutter.app_name}}.users.views import UserViewSet, home
13 |
14 | router = DefaultRouter()
15 | router.register(r'users', UserViewSet)
16 |
17 | urlpatterns = ([
18 | url(r'^$', home),
19 |
20 | url(r'^admin/', include(admin.site.urls)),
21 | url(r'^api/', include('authentication.urls')),
22 | url(r'^api/', include(router.urls)),
23 |
24 | # the 'api-root' from django rest-frameworks default router
25 | # http://www.django-rest-framework.org/api-guide/routers/#defaultrouter
26 | # url(r'^rest/$', RedirectView.as_view(url=reverse_lazy('api-root'), permanent=False)),
27 |
28 | ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
29 | + [url(r'^.*$', home)])
30 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/users/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/users/__init__.py
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/users/admin.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, unicode_literals
2 |
3 | from django import forms
4 | from django.contrib import admin
5 | from django.contrib.auth.admin import UserAdmin as AuthUserAdmin
6 | from django.contrib.auth.forms import UserChangeForm, UserCreationForm
7 |
8 | from {{cookiecutter.app_name}}.users.models import User
9 |
10 |
11 | class CustomUserChangeForm(UserChangeForm):
12 |
13 | class Meta(UserChangeForm.Meta):
14 | model = User
15 |
16 |
17 | class CustomUserCreationForm(UserCreationForm):
18 |
19 | # http://james.lin.net.nz/2013/06/08/django-custom-user-model-in-admin-relation-auth_user-does-not-exist/
20 | def clean_username(self):
21 | # Since User.username is unique, this check is redundant,
22 | # but it sets a nicer error message than the ORM. See #13147.
23 | username = self.cleaned_data["username"]
24 | try:
25 | User._default_manager.get(username=username)
26 | except User.DoesNotExist:
27 | return username
28 | raise forms.ValidationError(self.error_messages['duplicate_username'])
29 |
30 | class Meta(UserCreationForm.Meta):
31 | model = User
32 |
33 |
34 | @admin.register(User)
35 | class UserAdmin(AuthUserAdmin):
36 | form = CustomUserChangeForm
37 | add_form = CustomUserCreationForm
38 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/users/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9 on 2016-01-31 23:31
3 | from __future__ import unicode_literals
4 |
5 | import django.contrib.auth.models
6 | import django.core.validators
7 | from django.db import migrations, models
8 | import django.utils.timezone
9 | import uuid
10 |
11 |
12 | class Migration(migrations.Migration):
13 |
14 | initial = True
15 |
16 | dependencies = [
17 | ('auth', '0007_alter_validators_add_error_messages'),
18 | ]
19 |
20 | operations = [
21 | migrations.CreateModel(
22 | name='User',
23 | fields=[
24 | ('password', models.CharField(max_length=128, verbose_name='password')),
25 | ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last auth')),
26 | ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
27 | ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=30, unique=True, validators=[django.core.validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.')], verbose_name='username')),
28 | ('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')),
29 | ('last_name', models.CharField(blank=True, max_length=30, verbose_name='last name')),
30 | ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
31 | ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
32 | ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
33 | ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
34 | ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
35 | ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
36 | ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
37 | ],
38 | options={
39 | 'abstract': False,
40 | 'verbose_name': 'user',
41 | 'verbose_name_plural': 'users',
42 | },
43 | managers=[
44 | ('objects', django.contrib.auth.models.UserManager()),
45 | ],
46 | ),
47 | ]
48 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/users/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitassaraf/angular2-django-boilerplate/8c7c738b7c0202d437be7198b331e3b39bfa14d4/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/users/migrations/__init__.py
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/users/models.py:
--------------------------------------------------------------------------------
1 | from __future__ import unicode_literals
2 |
3 | import uuid
4 | from django.db import models
5 | from django.contrib.auth.models import AbstractUser
6 | from django.utils.encoding import python_2_unicode_compatible
7 | # from django.utils.translation import ugettext_lazy as _
8 |
9 |
10 | @python_2_unicode_compatible
11 | class User(AbstractUser):
12 | id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
13 |
14 | def __str__(self):
15 | return self.username
16 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/users/permissions.py:
--------------------------------------------------------------------------------
1 | from rest_framework import permissions
2 |
3 |
4 | class IsOwnerOrReadOnly(permissions.BasePermission):
5 | """
6 | Object-level permission to only allow owners of an object to edit it.
7 | """
8 |
9 | def has_object_permission(self, request, view, obj):
10 |
11 | if request.method in permissions.SAFE_METHODS:
12 | return True
13 |
14 | return obj == request.user
15 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/users/serializers.py:
--------------------------------------------------------------------------------
1 | from rest_framework import serializers
2 |
3 | from {{cookiecutter.app_name}}.users.models import User
4 |
5 |
6 | class UserSerializer(serializers.ModelSerializer):
7 |
8 | class Meta:
9 | model = User
10 | fields = ('username', 'first_name', 'last_name', 'email')
11 | write_only_fields = ('password',)
12 |
13 | def create(self, validated_data):
14 | # call create_user on user object. Without this
15 | # the password will be stored in plain text.
16 | user = User.objects.create_user(**validated_data)
17 | return user
18 |
19 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/users/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render
2 | from django.views.decorators.csrf import ensure_csrf_cookie
3 | from rest_framework import viewsets, mixins
4 | from rest_framework.permissions import AllowAny
5 |
6 | from {{cookiecutter.app_name}}.users.models import User
7 | from {{cookiecutter.app_name}}.users.permissions import IsOwnerOrReadOnly
8 | from {{cookiecutter.app_name}}.users.serializers import UserSerializer
9 |
10 |
11 | @ensure_csrf_cookie
12 | def home(request):
13 | return render(request, 'index.html', {
14 | 'USE_LIVE_RELOAD': False # settings.DEBUG
15 | })
16 |
17 |
18 | class UserViewSet(mixins.CreateModelMixin,
19 | mixins.RetrieveModelMixin,
20 | mixins.UpdateModelMixin,
21 | viewsets.GenericViewSet):
22 | """
23 | Creates, Updates, and retrives User accounts
24 | """
25 | queryset = User.objects.all()
26 | serializer_class = UserSerializer
27 | permission_classes = (IsOwnerOrReadOnly,)
28 |
29 | def get_permissions(self):
30 | if self.request.method == 'POST':
31 | return [AllowAny()]
32 | return [IsOwnerOrReadOnly()]
33 |
34 |
35 |
--------------------------------------------------------------------------------
/{{cookiecutter.github_repository_name}}/src/{{cookiecutter.app_name}}/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for {{cookiecutter.app_name}} project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/
8 | """
9 | import os
10 |
11 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config")
12 | os.environ.setdefault("DJANGO_CONFIGURATION", "Production")
13 |
14 | from configurations.wsgi import get_wsgi_application # noqa
15 | from whitenoise.django import DjangoWhiteNoise # noqa
16 |
17 | application = get_wsgi_application()
18 | application = DjangoWhiteNoise(application)
19 |
--------------------------------------------------------------------------------