From eebd7df48e5ebe25d6b391099ef5ab49383c09fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Javier=20Arribas=20Fern=C3=A1ndez?= Date: Thu, 12 Jan 2017 16:01:14 +0100 Subject: [PATCH] Release 0.0.1 (Closes #8) * Copy all the seed files into the project folder * Remove all useless AngularClass mentions * Complete package.json info * Change the app angular2 components selectors prefix * Clean useless angular2 stuff from seed * Try Travis build * Remove app.service references * Remove AppState deprecated references * Update the netlify config file qith a basic config * Remove base option * Set the production build command as default * Update humans.txt * Fill manifest with the required metadata * Remove useless assets * Refactor manifest file * Remove seed images and declarations * Add logo images and set manifest colors * Add favicon files * Update head tags and move some assets * Register a 144px icon at manifest.json * Remove useless related plataforms field * Use the Travis yarn cache * Add a redirects file for allow history pushstate * Update the manifest location at meta tag * Install service workers API typescript types * Install offline-webpack-plugin * Prevent files with '_' prefix to be cached * Install angularfire2 * Apply a base angular2 app files structure * Init the firebase app and import into core module * Create user service and class * Include user service in core providers * Use service worker at production * Add User module and refactor app routing * Import the user module into the app * Update angularfire2 to avoid aot errors * Install firebaseui package * Linter fixes * Remove @types/firebase package for types duplications * Remove components empty style files * Exclude the node modules and compiled files folders from the tree view * Set markdown generic rules * Add markdown and js linter files * Add a superstatic file for redirect urls to index.html * Eslint errors fixed * Refactor lint scripts * Clean seed README content * Set Travis cache to 'bundler' * Remove typedoc and add doctoc package and scripts * Copy the README content from another project * Update build badge and add netlify one * Cache the node_modules directory at Travis CI * Remove docs folder till it exits * Add badge for commits since * Add description and app logo * Move the logo start centered * Update the docs with the project details * Lint the docs folder * Update the package version * Update README with the correct version * Remove binnary scripts * Add CONTRIBUTING file * Create the CHANGELOG and give basic content * Add version changes --- .editorconfig | 13 + .eslintrc.json | 25 ++ .gitattributes | 1 + .gitignore | 60 ++- .markdownlint.json | 10 + .nvmrc | 1 + .travis.yml | 31 ++ .vscode/launch.json | 27 ++ .vscode/settings.json | 8 + CHANGELOG.md | 29 ++ CONTRIBUTING.md | 4 + LICENSE | 5 +- README.md | 109 +++++- config/empty.js | 8 + config/github-deploy/index.js | 87 +++++ config/head-config.common.js | 42 +++ config/helpers.js | 25 ++ config/html-elements-plugin/index.js | 108 ++++++ config/karma.conf.js | 124 +++++++ config/protractor.conf.js | 45 +++ config/resource-override.js | 0 config/spec-bundle.js | 59 +++ config/webpack.common.js | 346 ++++++++++++++++++ config/webpack.dev.js | 190 ++++++++++ config/webpack.github-deploy.js | 74 ++++ config/webpack.prod.js | 324 ++++++++++++++++ config/webpack.test.js | 247 +++++++++++++ docs/architecture.md | 22 ++ docs/architecture/application.md | 85 +++++ docs/architecture/files-structure.md | 102 ++++++ docs/dev-flow.md | 91 +++++ docs/scripts.md | 98 +++++ karma.conf.js | 2 + netlify.toml | 29 ++ package.json | 169 +++++++++ protractor.conf.js | 2 + src/app/app-routing.module.ts | 18 + src/app/app.component.html | 2 + src/app/app.component.spec.ts | 39 ++ src/app/app.component.ts | 16 + src/app/app.e2e.ts | 15 + src/app/app.module.ts | 41 +++ src/app/core/core.module.ts | 31 ++ src/app/core/firebase/firebase-init.ts | 11 + src/app/core/firebase/index.ts | 1 + src/app/core/index.ts | 1 + src/app/core/user/index.ts | 2 + src/app/core/user/user.service.ts | 29 ++ src/app/core/user/user.ts | 8 + src/app/environment.ts | 64 ++++ src/app/index.ts | 2 + src/app/user/index.ts | 1 + src/app/user/user-routing.module.ts | 15 + src/app/user/user.component.html | 4 + src/app/user/user.component.ts | 20 + src/app/user/user.module.ts | 15 + src/assets/css/.gitkeep | 1 + src/assets/favicon.ico | Bin 0 -> 15086 bytes .../img/favicon/android-chrome-192x192.png | Bin 0 -> 14707 bytes .../img/favicon/android-chrome-512x512.png | Bin 0 -> 44182 bytes src/assets/img/favicon/apple-touch-icon.png | Bin 0 -> 10218 bytes src/assets/img/favicon/favicon-16x16.png | Bin 0 -> 928 bytes src/assets/img/favicon/favicon-32x32.png | Bin 0 -> 1547 bytes src/assets/img/favicon/mstile-144x144.png | Bin 0 -> 8166 bytes src/assets/img/favicon/mstile-150x150.png | Bin 0 -> 7894 bytes src/assets/img/favicon/mstile-310x150.png | Bin 0 -> 8527 bytes src/assets/img/favicon/mstile-310x310.png | Bin 0 -> 17089 bytes src/assets/img/favicon/mstile-70x70.png | Bin 0 -> 5637 bytes src/assets/img/favicon/safari-pinned-tab.svg | 31 ++ src/assets/img/logo/logo_inverted.png | Bin 0 -> 10972 bytes src/assets/img/logo/logo_rounded.png | Bin 0 -> 18285 bytes src/custom-typings.d.ts | 130 +++++++ src/index.html | 36 ++ src/main.browser.aot.ts | 26 ++ src/main.browser.ts | 25 ++ src/meta/_redirects | 1 + src/meta/browserconfig.xml | 12 + src/meta/humans.txt | 17 + src/meta/manifest.json | 27 ++ src/meta/robots.txt | 3 + src/polyfills.browser.ts | 46 +++ src/styles/styles.scss | 0 superstatic.json | 24 ++ tsconfig.json | 40 ++ tsconfig.webpack.json | 41 +++ tslint.json | 54 +++ webpack.config.js | 15 + 87 files changed, 3448 insertions(+), 18 deletions(-) create mode 100644 .editorconfig create mode 100644 .eslintrc.json create mode 100644 .gitattributes create mode 100644 .markdownlint.json create mode 100644 .nvmrc create mode 100644 .travis.yml create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md create mode 100644 config/empty.js create mode 100644 config/github-deploy/index.js create mode 100644 config/head-config.common.js create mode 100644 config/helpers.js create mode 100644 config/html-elements-plugin/index.js create mode 100644 config/karma.conf.js create mode 100644 config/protractor.conf.js create mode 100644 config/resource-override.js create mode 100644 config/spec-bundle.js create mode 100644 config/webpack.common.js create mode 100644 config/webpack.dev.js create mode 100644 config/webpack.github-deploy.js create mode 100644 config/webpack.prod.js create mode 100644 config/webpack.test.js create mode 100644 docs/architecture.md create mode 100644 docs/architecture/application.md create mode 100644 docs/architecture/files-structure.md create mode 100644 docs/dev-flow.md create mode 100644 docs/scripts.md create mode 100644 karma.conf.js create mode 100644 netlify.toml create mode 100644 package.json create mode 100644 protractor.conf.js create mode 100644 src/app/app-routing.module.ts create mode 100644 src/app/app.component.html create mode 100644 src/app/app.component.spec.ts create mode 100644 src/app/app.component.ts create mode 100644 src/app/app.e2e.ts create mode 100644 src/app/app.module.ts create mode 100644 src/app/core/core.module.ts create mode 100644 src/app/core/firebase/firebase-init.ts create mode 100644 src/app/core/firebase/index.ts create mode 100644 src/app/core/index.ts create mode 100644 src/app/core/user/index.ts create mode 100644 src/app/core/user/user.service.ts create mode 100644 src/app/core/user/user.ts create mode 100644 src/app/environment.ts create mode 100644 src/app/index.ts create mode 100644 src/app/user/index.ts create mode 100644 src/app/user/user-routing.module.ts create mode 100644 src/app/user/user.component.html create mode 100644 src/app/user/user.component.ts create mode 100644 src/app/user/user.module.ts create mode 100644 src/assets/css/.gitkeep create mode 100644 src/assets/favicon.ico create mode 100644 src/assets/img/favicon/android-chrome-192x192.png create mode 100644 src/assets/img/favicon/android-chrome-512x512.png create mode 100644 src/assets/img/favicon/apple-touch-icon.png create mode 100644 src/assets/img/favicon/favicon-16x16.png create mode 100644 src/assets/img/favicon/favicon-32x32.png create mode 100644 src/assets/img/favicon/mstile-144x144.png create mode 100644 src/assets/img/favicon/mstile-150x150.png create mode 100644 src/assets/img/favicon/mstile-310x150.png create mode 100644 src/assets/img/favicon/mstile-310x310.png create mode 100644 src/assets/img/favicon/mstile-70x70.png create mode 100644 src/assets/img/favicon/safari-pinned-tab.svg create mode 100644 src/assets/img/logo/logo_inverted.png create mode 100644 src/assets/img/logo/logo_rounded.png create mode 100644 src/custom-typings.d.ts create mode 100644 src/index.html create mode 100644 src/main.browser.aot.ts create mode 100644 src/main.browser.ts create mode 100644 src/meta/_redirects create mode 100644 src/meta/browserconfig.xml create mode 100644 src/meta/humans.txt create mode 100644 src/meta/manifest.json create mode 100644 src/meta/robots.txt create mode 100644 src/polyfills.browser.ts create mode 100644 src/styles/styles.scss create mode 100644 superstatic.json create mode 100644 tsconfig.json create mode 100644 tsconfig.webpack.json create mode 100644 tslint.json create mode 100644 webpack.config.js diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..ea03dba --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..a01f00a --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,25 @@ +{ + "env": { + "browser": true, + "commonjs": true, + "es6": true, + "node": true, + "jasmine": true, + "protractor": true + }, + "parserOptions": { + "ecmaFeatures": { + "jsx": true + }, + "sourceType": "module" + }, + "rules": { + "no-const-assign": "error", + "no-this-before-super": "error", + "no-undef": "warn", + "no-unreachable": "error", + "no-unused-vars": "error", + "constructor-super": "warn", + "valid-typeof": "error" + } +} \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..70e53ee --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +yarn.lock -diff diff --git a/.gitignore b/.gitignore index 5148e52..b9efd57 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ # Logs logs *.log -npm-debug.log* # Runtime data pids @@ -14,24 +13,57 @@ lib-cov # Coverage directory used by tools like istanbul coverage -# nyc test coverage -.nyc_output - # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt -# node-waf configuration -.lock-wscript - # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release -# Dependency directories -node_modules -jspm_packages +# Users Environment Variables +.lock-wscript + +# OS generated files # +.DS_Store +ehthumbs.db +Icon? +Thumbs.db + +# Node Files # +/node_modules/ +/bower_components/ +npm-debug.log +/npm-debug.log.* + +# Coverage # +/coverage/ + +# Typing # +/src/typings/tsd/ +/typings/ +/tsd_typings/ + +# Dist # +/dist +/public/__build__/ +/src/*/__build__/ +/__build__/** +/public/dist/ +/src/*/dist/ +/dist/** +/.awcache +.webpack.json +/compiled/ + +# Doc # +/doc/ + +# IDE # +.idea/ +*.swp -# Optional npm cache directory -.npm -# Optional REPL history -.node_repl_history +# Angular # +*.ngfactory.ts +*.css.shim.ts +*.ngsummary.json +*.shim.ngstyle.ts diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000..3823e40 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,10 @@ +{ + "default": true, + "first-line-h1": false, + "no-inline-html": false, + "no-duplicate-header": false, + "blanks-around-headers": false, + "line-length": { + "line_length": 100 + } +} \ No newline at end of file diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..b009dfb --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +lts/* diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..33fae61 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,31 @@ +sudo: required +dist: trusty +addons: + apt: + sources: + - google-chrome + packages: + - google-chrome-stable +language: node_js +node_js: + - "4" + - "5" + - "6" + - "node" +cache: + directories: + - node_modules + +# Matrix failure enabled for https://github.com/TheLarkInn/LazyParseWebpackPlugin/issues/6 +matrix: + fast_finish: true + allow_failures: + - node_js: "4" +install: + - npm install +before_script: + - export DISPLAY=:99.0 + - sh -e /etc/init.d/xvfb start + - sleep 3 +script: + - npm run ci diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..9fe889a --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,27 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Chrome against localhost, with sourcemaps", + "type": "chrome", + "request": "launch", + "url": "http://localhost:3000/*", + "runtimeArgs": [ + "--disable-web-security", + "--user-data-dir", + "--remote-debugging-port=9222" + ], + "sourceMaps": true, + "webRoot": "${workspaceRoot}" + }, + { + "name": "Attach to Chrome, with sourcemaps", + "type": "chrome", + "request": "attach", + "url": "http://localhost:3000/*", + "port": 9222, + "sourceMaps": true, + "webRoot": "${workspaceRoot}" + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..4bd72b4 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "typescript.tsdk": "node_modules/typescript/lib/", + "files.exclude": { + ".git*": true, + "**/node_modules/**": true, + "compiled": true + } +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..c7ce8cb --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,29 @@ +# Change Log +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +## [Unreleased] + +## [0.0.1] - 2017-01-12 +### Added + +- [angular2-webpack-starter](https://github.com/AngularClass/angular2-webpack-starter) seed used + to start the project +- [Travis CI](https://travis-ci.org) as CI environment for testing +- [Netlify](https://www.netlify.com) integration to have CD [here](https://poll-me.com). +- Fill the [Progressive Web App](https://developer.mozilla.org/en-US/Apps/Progressive) standard +- App logos +- Basic angular2 structure +- Initial documentation +- Lint of javascript and markdown files +- [Firebase](https://firebase.google.com/) integration for user authentication and data storage + +## 0.0.0 - 2017-01-09 +### Added + +- All, repository init + +[Unreleased]: https://gitlabnew.qdqmedia.com/shared-projects/eqonecta/compare/HEAD...develop +[0.0.1]: https://gitlabnew.qdqmedia.com/shared-projects/eqonecta/compare/v0.0.0...v0.0.1 \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..4dbc585 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,4 @@ +# Contributing to this project +All you need to know about how to contribute is at +[development flow documentation](docs/dev-flow.md) that explain the way to work at the +project. diff --git a/LICENSE b/LICENSE index 515743f..cd1fde6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ -MIT License +The MIT License (MIT) -Copyright (c) 2016 Poll-me +Copyright (c) 2015-2016 PollMe Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19,3 +19,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/README.md b/README.md index ca1b4de..1132335 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,107 @@ -# poll-me-webapp -The Poll-me webapp +

+ + PollMe WebApp + +

+ +# PollMe Web Application + +[![GitHub version](https://badge.fury.io/gh/Poll-me%2Fpoll-me-webapp.svg)](https://badge.fury.io/gh/Poll-me%2Fpoll-me-webapp) +[![GitHub release](https://img.shields.io/github/release/Poll-me/poll-me-webapp.svg)](https://github.com/Poll-me/poll-me-webapp/releases) +[![Build Status](https://travis-ci.org/Poll-me/poll-me-webapp.svg)](https://travis-ci.org/Poll-me/poll-me-webapp) +[![GitHub commits](https://img.shields.io/github/commits-since/Poll-me/poll-me-webapp/0.0.1.svg)](https://github.com/Poll-me/poll-me-webapp/compare/v0.0.1...develop) +[![Build Status](https://www.netlify.com/img/global/badges/netlify-color-accent.svg)](https://www.netlify.com) + +This is the awesome app with with you be able to collect in the most easy way any kind of +opinion or preferece from anyone. + +For example: + +- Are you trying to know the best date to a plan with you friends? **POLL THEM!!** +- Are you trying to decide which Star Wars movie is better? **POLL THEM!!** +- Are you trying to find out which friend of yours knows you better? **POLL THEM!!** + +[Enter now](https://www.poll-me.com) and try it out, it's **free FOREVER** + +The project follow this development technology stack: + +1. Angular2 +1. Webpack +1. Node + +And the build outputs all the static files that can be easily served from a web server. + + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [Requirements](#requirements) +- [Start working with the project](#start-working-with-the-project) +- [Development flow](#development-flow) +- [Package scripts](#package-scripts) +- [Enviroments](#enviroments) +- [Architecture](#architecture) +- [Continuous integration (CI)](#continuous-integration-ci) + + + +## Requirements +The only thing you need is: + +- Node >= 4.x +- Npm >= 3.x + +## Start working with the project +To contribute you just need to clone the repo and install the node dependencies, then you +can run any package script. + +```bash +# Clone the repo and enter inside +git clone git@github.com:Poll-me/poll-me-webapp.git +# by HTTPS: https://github.com/Poll-me/poll-me-webapp.git +cd poll-me-webapp + +# install node dependencies +npm install + +# Start the dev server with a watcher running +npm start +``` + +## Development flow +You must follow [this](docs/dev-flow.md) guidelines in order to contribute to the project in any way. + +## Package scripts +As the project do not have a task builder like Grunt or Gulp we need to use the npm package scripts +to run the tasks that manage the workflow of the project. + +All of this scripts are listed [here](docs/scripts.md) + +## Enviroments +This project contemplate many possible environments that are used at different parts +of the source code, for example, at webpack configuration. + +- **Development** (`dev`): the environment for develop the project. + For example at developers computers. +- **Test** (`test`): the environment for the tests execution. +- **Continuous Integration** (`ci`): the environment executed by the CI runner. +- **Production** (`prod`): the environment for serve the production app files. + For example at deploy environments. + +## Architecture +The app have a structure that ensure readability, maintainability and scalability. + +When you want to collaborate on the project you **MUST** consider this architecture as +guideline in order to add new functionality. + +Details are exposed at specific docs [here](docs/architecture.md) + +## Continuous integration (CI) +The central pillar of development flow, all the commits pushed to the remote github +repository have to pass the pipeline of the project at CI to can merge to `develop` +branch and then to `master`. + +The CI of the project is based on [Travis CI](https://travis-ci.org/), you can see the official documentation +[here](https://docs.travis-ci.com/). The configturation of the project that set how +the project is checked at CI is `.travis.yml`, if you want to know more about the CI +configuration for the project see the [official docs](https://docs.travis-ci.com/user/customizing-the-build/). diff --git a/config/empty.js b/config/empty.js new file mode 100644 index 0000000..1e8fc3c --- /dev/null +++ b/config/empty.js @@ -0,0 +1,8 @@ +module.exports = { + NgProbeToken: {}, + HmrState: function() {}, + _createConditionalRootRenderer: function(rootRenderer) { + return rootRenderer; + }, + __platform_browser_private__: {} +}; diff --git a/config/github-deploy/index.js b/config/github-deploy/index.js new file mode 100644 index 0000000..8ad9747 --- /dev/null +++ b/config/github-deploy/index.js @@ -0,0 +1,87 @@ +const execSync = require('child_process').execSync; +const webpackMerge = require('webpack-merge'); // used to merge webpack configs +const HtmlWebpackPlugin = require('html-webpack-plugin'); + +const REPO_NAME_RE = /Push {2}URL: ((git@github\.com:)|(https:\/\/github\.com\/)).+\/(.+)\.git/; + +function getWebpackConfigModule(options) { + if (options.githubDev) { + return require('../webpack.dev.js'); + } else if (options.githubProd) { + return require('../webpack.prod.js'); + } else { + throw new Error('Invalid compile option.'); + } +} + +function getRepoName(remoteName) { + remoteName = remoteName || 'origin'; + + var stdout = execSync('git remote show ' + remoteName), + match = REPO_NAME_RE.exec(stdout); + + if (!match) { + throw new Error('Could not find a repository on remote ' + remoteName); + } else { + return match[4]; + } +} + +function stripTrailing(str, char) { + + if (str[0] === char) { + str = str.substr(1); + } + + if (str.substr(-1) === char) { + str = str.substr(0, str.length - 1); + } + + return str; +} + +/** + * Given a string remove trailing slashes and adds 1 slash at the end of the string. + * + * Example: + * safeUrl('/value/') + * // 'value/' + * + * @param url + * @returns {string} + */ +function safeUrl(url) { + const stripped = stripTrailing(url || '', '/'); + return stripped ? stripped + '/' : ''; +} + +function replaceHtmlWebpackPlugin(plugins, ghRepoName) { + for (var i=0; i tags for 'apple-touch-icon' (AKA Web Clips). **/ + { rel: 'apple-touch-icon', sizes: '180x180', href: '/assets/img/favicon/apple-touch-icon.png' }, + + /** tags for safari web app icons **/ + { rel: 'mask-icon', color: '#d8403f', href: '/assets/img/favicon/safari-pinned-tab.svg' }, + + /** tags for android web app icons **/ + { rel: 'icon', type: 'image/png', sizes: '192x192', href: '/assets/img/favicon/android-chrome-192x192.png' }, + { rel: 'icon', type: 'image/png', sizes: '512x512', href: '/assets/img/favicon/android-chrome-512x512.png' }, + + /** tags for favicons **/ + { rel: 'icon', type: 'image/png', sizes: '32x32', href: '/assets/img/favicon/favicon-32x32.png' }, + { rel: 'icon', type: 'image/png', sizes: '16x16', href: '/assets/img/favicon/favicon-16x16.png' }, + { rel: 'shortcut icon', href: '/assets/favicon.ico' }, + + /** tags for a Web App Manifest **/ + { rel: 'manifest', href: '/manifest.json' } + ], + meta: [ + { name: 'msapplication-TileColor', content: '#b91d47' }, + { name: 'msapplication-TileImage', content: '/assets/img/favicon/mstile-144x144.png', '=content': true }, + { name: 'msapplication-config', content: '/browserconfig.xml' }, + { name: 'theme-color', content: '#d8403f' } + ] +}; diff --git a/config/helpers.js b/config/helpers.js new file mode 100644 index 0000000..3839224 --- /dev/null +++ b/config/helpers.js @@ -0,0 +1,25 @@ +var path = require('path'); + +const EVENT = process.env.npm_lifecycle_event || ''; + +// Helper functions +var ROOT = path.resolve(__dirname, '..'); + +function hasProcessFlag(flag) { + return process.argv.join('').indexOf(flag) > -1; +} + +function hasNpmFlag(flag) { + return EVENT.includes(flag); +} + +function isWebpackDevServer() { + return process.argv[1] && !! (/webpack-dev-server/.exec(process.argv[1])); +} + +var root = path.join.bind(path, ROOT); + +exports.hasProcessFlag = hasProcessFlag; +exports.hasNpmFlag = hasNpmFlag; +exports.isWebpackDevServer = isWebpackDevServer; +exports.root = root; diff --git a/config/html-elements-plugin/index.js b/config/html-elements-plugin/index.js new file mode 100644 index 0000000..4a0f853 --- /dev/null +++ b/config/html-elements-plugin/index.js @@ -0,0 +1,108 @@ + +function HtmlElementsPlugin(locations) { + this.locations = locations; +} + +HtmlElementsPlugin.prototype.apply = function(compiler) { + var self = this; + compiler.plugin('compilation', function(compilation) { + compilation.options.htmlElements = compilation.options.htmlElements || {}; + + compilation.plugin('html-webpack-plugin-before-html-generation', function(htmlPluginData, callback) { + const locations = self.locations; + + if (locations) { + const publicPath = htmlPluginData.assets.publicPath; + + Object.getOwnPropertyNames(locations).forEach(function(loc) { + compilation.options.htmlElements[loc] = getHtmlElementString(locations[loc], publicPath); + }); + } + + + callback(null, htmlPluginData); + }); + }); + +}; + +const RE_ENDS_WITH_BS = /\/$/; + +/** + * Create an HTML tag with attributes from a map. + * + * Example: + * createTag('link', { rel: "manifest", href: "/assets/manifest.json" }) + * // + * @param tagName The name of the tag + * @param attrMap A Map of attribute names (keys) and their values. + * @param publicPath a path to add to eh start of static asset url + * @returns {string} + */ +function createTag(tagName, attrMap, publicPath) { + publicPath = publicPath || ''; + + // add trailing slash if we have a publicPath and it doesn't have one. + if (publicPath && !RE_ENDS_WITH_BS.test(publicPath)) { + publicPath += '/'; + } + + const attributes = Object.getOwnPropertyNames(attrMap) + .filter(function(name) { return name[0] !== '='; } ) + .map(function(name) { + var value = attrMap[name]; + + if (publicPath) { + // check if we have explicit instruction, use it if so (e.g: =herf: false) + // if no instruction, use public path if it's href attribute. + const usePublicPath = attrMap.hasOwnProperty('=' + name) ? !!attrMap['=' + name] : name === 'href'; + + if (usePublicPath) { + // remove a starting trailing slash if the value has one so we wont have // + value = publicPath + (value[0] === '/' ? value.substr(1) : value); + } + } + + return `${name}="${value}"`; + }); + + const closingTag = tagName === 'script' ? '' : ''; + + return `<${tagName} ${attributes.join(' ')}>${closingTag}`; +} + +/** + * Returns a string representing all html elements defined in a data source. + * + * Example: + * + * const ds = { + * link: [ + * { rel: "apple-touch-icon", sizes: "57x57", href: "/assets/icon/apple-icon-57x57.png" } + * ], + * meta: [ + * { name: "msapplication-TileColor", content: "#00bcd4" } + * ] + * } + * + * getHeadTags(ds); + * // "" + * "" + * + * @returns {string} + */ +function getHtmlElementString(dataSource, publicPath) { + return Object.getOwnPropertyNames(dataSource) + .map(function(name) { + if (Array.isArray(dataSource[name])) { + return dataSource[name].map(function(attrs) { return createTag(name, attrs, publicPath); } ); + } else { + return [ createTag(name, dataSource[name], publicPath) ]; + } + }) + .reduce(function(arr, curr) { + return arr.concat(curr); + }, []) + .join('\n\t'); +} +module.exports = HtmlElementsPlugin; diff --git a/config/karma.conf.js b/config/karma.conf.js new file mode 100644 index 0000000..1b9a7eb --- /dev/null +++ b/config/karma.conf.js @@ -0,0 +1,124 @@ + +module.exports = function (config) { + var testWebpackConfig = require('./webpack.test.js')({ env: 'test' }); + + var configuration = { + + // base path that will be used to resolve all patterns (e.g. files, exclude) + basePath: '', + + /* + * Frameworks to use + * + * available frameworks: https://npmjs.org/browse/keyword/karma-adapter + */ + frameworks: ['jasmine'], + + // list of files to exclude + exclude: [], + + client: { + captureConsole: false + }, + + /* + * list of files / patterns to load in the browser + * + * we are building the test environment in ./spec-bundle.js + */ + files: [ + { pattern: './config/spec-bundle.js', watched: false }, + { pattern: './src/assets/**/*', watched: false, included: false, served: true, nocache: false } + ], + + /* + * By default all assets are served at http://localhost:[PORT]/base/ + */ + proxies: { + "/assets/": "/base/src/assets/" + }, + + /* + * preprocess matching files before serving them to the browser + * available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor + */ + preprocessors: { './config/spec-bundle.js': ['coverage', 'webpack', 'sourcemap'] }, + + // Webpack Config at ./webpack.test.js + webpack: testWebpackConfig, + + coverageReporter: { + type: 'in-memory' + }, + + remapCoverageReporter: { + 'text-summary': null, + json: './coverage/coverage.json', + html: './coverage/html' + }, + + // Webpack please don't spam the console when running in karma! + webpackMiddleware: { + // webpack-dev-middleware configuration + // i.e. + noInfo: true, + // and use stats to turn off verbose output + stats: { + // options i.e. + chunks: false + } + }, + + /* + * test results reporter to use + * + * possible values: 'dots', 'progress' + * available reporters: https://npmjs.org/browse/keyword/karma-reporter + */ + reporters: ['mocha', 'coverage', 'remap-coverage'], + + // web server port + port: 9876, + + // enable / disable colors in the output (reporters and logs) + colors: true, + + /* + * level of logging + * possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + */ + logLevel: config.LOG_WARN, + + // enable / disable watching file and executing tests whenever any file changes + autoWatch: false, + + /* + * start these browsers + * available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + */ + browsers: [ + 'Chrome' + ], + + customLaunchers: { + ChromeTravisCi: { + base: 'Chrome', + flags: ['--no-sandbox'] + } + }, + + /* + * Continuous Integration mode + * if true, Karma captures browsers, runs the tests and exits + */ + singleRun: true + }; + + if (process.env.TRAVIS) { + configuration.browsers = [ + 'ChromeTravisCi' + ]; + } + + config.set(configuration); +}; diff --git a/config/protractor.conf.js b/config/protractor.conf.js new file mode 100644 index 0000000..9902289 --- /dev/null +++ b/config/protractor.conf.js @@ -0,0 +1,45 @@ +require('ts-node/register'); +var helpers = require('./helpers'); + +exports.config = { + baseUrl: 'http://localhost:3000/', + + // use `npm run e2e` + specs: [ + helpers.root('src/**/**.e2e.ts'), + helpers.root('src/**/*.e2e.ts') + ], + exclude: [], + + framework: 'jasmine2', + + allScriptsTimeout: 110000, + + jasmineNodeOpts: { + showTiming: true, + showColors: true, + isVerbose: false, + includeStackTrace: false, + defaultTimeoutInterval: 400000 + }, + directConnect: true, + + capabilities: { + 'browserName': 'chrome', + 'chromeOptions': { + 'args': ['show-fps-counter=true'] + } + }, + + onPrepare: function() { + browser.ignoreSynchronization = true; + }, + + /** + * Angular 2 configuration + * + * useAllAngular2AppRoots: tells Protractor to wait for any angular2 apps on the page instead of just the one matching + * `rootEl` + */ + useAllAngular2AppRoots: true +}; diff --git a/config/resource-override.js b/config/resource-override.js new file mode 100644 index 0000000..e69de29 diff --git a/config/spec-bundle.js b/config/spec-bundle.js new file mode 100644 index 0000000..c1c999f --- /dev/null +++ b/config/spec-bundle.js @@ -0,0 +1,59 @@ +/* + * When testing with webpack and ES6, we have to do some extra + * things to get testing to work right. Because we are gonna write tests + * in ES6 too, we have to compile those as well. That's handled in + * karma.conf.js with the karma-webpack plugin. This is the entry + * file for webpack test. Just like webpack will create a bundle.js + * file for our client, when we run test, it will compile and bundle them + * all here! Crazy huh. So we need to do some setup + */ +Error.stackTraceLimit = Infinity; + +require('core-js/es6'); +require('core-js/es7/reflect'); + +// Typescript emit helpers polyfill +require('ts-helpers'); + +require('zone.js/dist/zone'); +require('zone.js/dist/long-stack-trace-zone'); +require('zone.js/dist/proxy'); // since zone.js 0.6.15 +require('zone.js/dist/sync-test'); +require('zone.js/dist/jasmine-patch'); // put here since zone.js 0.6.14 +require('zone.js/dist/async-test'); +require('zone.js/dist/fake-async-test'); + +// RxJS +require('rxjs/Rx'); + +var testing = require('@angular/core/testing'); +var browser = require('@angular/platform-browser-dynamic/testing'); + +testing.TestBed.initTestEnvironment( + browser.BrowserDynamicTestingModule, + browser.platformBrowserDynamicTesting() +); + +/* + * Ok, this is kinda crazy. We can use the context method on + * require that webpack created in order to tell webpack + * what files we actually want to require or import. + * Below, context will be a function/object with file names as keys. + * Using that regex we are saying look in ../src then find + * any file that ends with spec.ts and get its path. By passing in true + * we say do this recursively + */ +var testContext = require.context('../src', true, /\.spec\.ts/); + +/* + * get all the files, for each file, call the context function + * that will require the file and load it up here. Context will + * loop and require those spec files here + */ +function requireAll(requireContext) { + return requireContext.keys().map(requireContext); +} + +// requires and returns all modules that match +var modules = requireAll(testContext); +modules; diff --git a/config/webpack.common.js b/config/webpack.common.js new file mode 100644 index 0000000..dbd50c4 --- /dev/null +++ b/config/webpack.common.js @@ -0,0 +1,346 @@ +const helpers = require('./helpers'); + +/* + * Webpack Plugins + */ +// problem with copy-webpack-plugin +const AssetsPlugin = require('assets-webpack-plugin'); +const NormalModuleReplacementPlugin = require('webpack/lib/NormalModuleReplacementPlugin'); +const ContextReplacementPlugin = require('webpack/lib/ContextReplacementPlugin'); +const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); +const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin; +const HtmlElementsPlugin = require('./html-elements-plugin'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin'); +const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin'); +const ngcWebpack = require('ngc-webpack'); + +/* + * Webpack Constants + */ +const AOT = helpers.hasNpmFlag('aot'); +const METADATA = { + title: 'PollMe WebApp', + baseUrl: '/', + isDevServer: helpers.isWebpackDevServer() +}; + +/* + * Webpack configuration + * + * See: http://webpack.github.io/docs/configuration.html#cli + */ +module.exports = function (options) { + var isProd = options.env === 'production'; + return { + + /* + * Cache generated modules and chunks to improve performance for multiple incremental builds. + * This is enabled by default in watch mode. + * You can pass false to disable it. + * + * See: http://webpack.github.io/docs/configuration.html#cache + */ + //cache: false, + + /* + * The entry point for the bundle + * Our Angular.js app + * + * See: http://webpack.github.io/docs/configuration.html#entry + */ + entry: { + + 'polyfills': './src/polyfills.browser.ts', + 'main': AOT ? './src/main.browser.aot.ts' : + './src/main.browser.ts' + + }, + + /* + * Options affecting the resolving of modules. + * + * See: http://webpack.github.io/docs/configuration.html#resolve + */ + resolve: { + + /* + * An array of extensions that should be used to resolve modules. + * + * See: http://webpack.github.io/docs/configuration.html#resolve-extensions + */ + extensions: ['.ts', '.js', '.json'], + + // An array of directory names to be resolved to the current directory + modules: [helpers.root('src'), helpers.root('node_modules')], + + }, + + /* + * Options affecting the normal modules. + * + * See: http://webpack.github.io/docs/configuration.html#module + */ + module: { + + rules: [ + + /* + * Typescript loader support for .ts and Angular 2 async routes via .async.ts + * Replace templateUrl and stylesUrl with require() + * + * See: https://github.com/s-panferov/awesome-typescript-loader + * See: https://github.com/TheLarkInn/angular2-template-loader + */ + { + test: /\.ts$/, + use: [ + '@angularclass/hmr-loader?pretty=' + !isProd + '&prod=' + isProd, + 'awesome-typescript-loader?{configFileName: "tsconfig.webpack.json"}', + 'angular2-template-loader', + { + loader: 'ng-router-loader', + options: { + loader: 'async-system', + genDir: 'compiled', + aot: AOT + } + } + ], + exclude: [/\.(spec|e2e)\.ts$/] + }, + + /* + * Json loader support for *.json files. + * + * See: https://github.com/webpack/json-loader + */ + { + test: /\.json$/, + use: 'json-loader' + }, + + /* + * to string and css loader support for *.css files (from Angular components) + * Returns file content as string + * + */ + { + test: /\.css$/, + use: ['to-string-loader', 'css-loader'], + exclude: [helpers.root('src', 'styles')] + }, + + /* + * to string and sass loader support for *.scss files (from Angular components) + * Returns compiled css content as string + * + */ + { + test: /\.scss$/, + use: ['to-string-loader', 'css-loader', 'sass-loader'], + exclude: [helpers.root('src', 'styles')] + }, + + /* Raw loader support for *.html + * Returns file content as string + * + * See: https://github.com/webpack/raw-loader + */ + { + test: /\.html$/, + use: 'raw-loader', + exclude: [helpers.root('src/index.html')] + }, + + /* File loader for supporting images, for example, in CSS files. + */ + { + test: /\.(jpg|png|gif)$/, + use: 'file-loader' + }, + + ], + + }, + + /* + * Add additional plugins to the compiler. + * + * See: http://webpack.github.io/docs/configuration.html#plugins + */ + plugins: [ + new AssetsPlugin({ + path: helpers.root('dist'), + filename: 'webpack-assets.json', + prettyPrint: true + }), + + /* + * Plugin: ForkCheckerPlugin + * Description: Do type checking in a separate process, so webpack don't need to wait. + * + * See: https://github.com/s-panferov/awesome-typescript-loader#forkchecker-boolean-defaultfalse + */ + new CheckerPlugin(), + /* + * Plugin: CommonsChunkPlugin + * Description: Shares common code between the pages. + * It identifies common modules and put them into a commons chunk. + * + * See: https://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin + * See: https://github.com/webpack/docs/wiki/optimization#multi-page-app + */ + new CommonsChunkPlugin({ + name: 'polyfills', + chunks: ['polyfills'] + }), + // This enables tree shaking of the vendor modules + new CommonsChunkPlugin({ + name: 'vendor', + chunks: ['main'], + minChunks: module => /node_modules\//.test(module.resource) + }), + // Specify the correct order the scripts will be injected in + new CommonsChunkPlugin({ + name: ['polyfills', 'vendor'].reverse() + }), + + /** + * Plugin: ContextReplacementPlugin + * Description: Provides context to Angular's use of System.import + * + * See: https://webpack.github.io/docs/list-of-plugins.html#contextreplacementplugin + * See: https://github.com/angular/angular/issues/11580 + */ + new ContextReplacementPlugin( + // The (\\|\/) piece accounts for path separators in *nix and Windows + /angular(\\|\/)core(\\|\/)src(\\|\/)linker/, + helpers.root('src'), // location of your src + { + // your Angular Async Route paths relative to this root directory + } + ), + + /* + * Plugin: CopyWebpackPlugin + * Description: Copy files and directories in webpack. + * + * Copies project static assets. + * + * See: https://www.npmjs.com/package/copy-webpack-plugin + */ + new CopyWebpackPlugin([ + { from: 'src/assets', to: 'assets' }, + { from: 'src/meta'} + ]), + + + /* + * Plugin: HtmlWebpackPlugin + * Description: Simplifies creation of HTML files to serve your webpack bundles. + * This is especially useful for webpack bundles that include a hash in the filename + * which changes every compilation. + * + * See: https://github.com/ampedandwired/html-webpack-plugin + */ + new HtmlWebpackPlugin({ + template: 'src/index.html', + title: METADATA.title, + chunksSortMode: 'dependency', + metadata: METADATA, + inject: 'head' + }), + + /* + * Plugin: ScriptExtHtmlWebpackPlugin + * Description: Enhances html-webpack-plugin functionality + * with different deployment options for your scripts including: + * + * See: https://github.com/numical/script-ext-html-webpack-plugin + */ + new ScriptExtHtmlWebpackPlugin({ + defaultAttribute: 'defer' + }), + + /* + * Plugin: HtmlElementsPlugin + * Description: Generate html tags based on javascript maps. + * + * If a publicPath is set in the webpack output configuration, it will be automatically added to + * href attributes, you can disable that by adding a "=href": false property. + * You can also enable it to other attribute by settings "=attName": true. + * + * The configuration supplied is map between a location (key) and an element definition object (value) + * The location (key) is then exported to the template under then htmlElements property in webpack configuration. + * + * Example: + * Adding this plugin configuration + * new HtmlElementsPlugin({ + * headTags: { ... } + * }) + * + * Means we can use it in the template like this: + * <%= webpackConfig.htmlElements.headTags %> + * + * Dependencies: HtmlWebpackPlugin + */ + new HtmlElementsPlugin({ + headTags: require('./head-config.common') + }), + + /** + * Plugin LoaderOptionsPlugin (experimental) + * + * See: https://gist.github.com/sokra/27b24881210b56bbaff7 + */ + new LoaderOptionsPlugin({}), + + // Fix Angular 2 + new NormalModuleReplacementPlugin( + /facade(\\|\/)async/, + helpers.root('node_modules/@angular/core/src/facade/async.js') + ), + new NormalModuleReplacementPlugin( + /facade(\\|\/)collection/, + helpers.root('node_modules/@angular/core/src/facade/collection.js') + ), + new NormalModuleReplacementPlugin( + /facade(\\|\/)errors/, + helpers.root('node_modules/@angular/core/src/facade/errors.js') + ), + new NormalModuleReplacementPlugin( + /facade(\\|\/)lang/, + helpers.root('node_modules/@angular/core/src/facade/lang.js') + ), + new NormalModuleReplacementPlugin( + /facade(\\|\/)math/, + helpers.root('node_modules/@angular/core/src/facade/math.js') + ), + + new ngcWebpack.NgcWebpackPlugin({ + disabled: !AOT, + tsConfig: helpers.root('tsconfig.webpack.json'), + resourceOverride: helpers.root('config/resource-override.js') + }) + + ], + + /* + * Include polyfills or mocks for various node stuff + * Description: Node configuration + * + * See: https://webpack.github.io/docs/configuration.html#node + */ + node: { + global: true, + crypto: 'empty', + process: true, + module: false, + clearImmediate: false, + setImmediate: false + } + + }; +} diff --git a/config/webpack.dev.js b/config/webpack.dev.js new file mode 100644 index 0000000..ddd7c4b --- /dev/null +++ b/config/webpack.dev.js @@ -0,0 +1,190 @@ +const helpers = require('./helpers'); +const webpackMerge = require('webpack-merge'); // used to merge webpack configs +const commonConfig = require('./webpack.common.js'); // the settings that are common to prod and dev + +/** + * Webpack Plugins + */ +const DefinePlugin = require('webpack/lib/DefinePlugin'); +const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin'); + +/** + * Webpack Constants + */ +const ENV = process.env.ENV = process.env.NODE_ENV = 'development'; +const HOST = process.env.HOST || 'localhost'; +const PORT = process.env.PORT || 3000; +const HMR = helpers.hasProcessFlag('hot'); +const METADATA = webpackMerge(commonConfig({env: ENV}).metadata, { + host: HOST, + port: PORT, + ENV: ENV, + HMR: HMR +}); + +/** + * Webpack configuration + * + * See: http://webpack.github.io/docs/configuration.html#cli + */ +module.exports = function () { + return webpackMerge(commonConfig({env: ENV}), { + + /** + * Developer tool to enhance debugging + * + * See: http://webpack.github.io/docs/configuration.html#devtool + * See: https://github.com/webpack/docs/wiki/build-performance#sourcemaps + */ + devtool: 'cheap-module-source-map', + + /** + * Options affecting the output of the compilation. + * + * See: http://webpack.github.io/docs/configuration.html#output + */ + output: { + + /** + * The output directory as absolute path (required). + * + * See: http://webpack.github.io/docs/configuration.html#output-path + */ + path: helpers.root('dist'), + + /** + * Specifies the name of each output file on disk. + * IMPORTANT: You must not specify an absolute path here! + * + * See: http://webpack.github.io/docs/configuration.html#output-filename + */ + filename: '[name].bundle.js', + + /** + * The filename of the SourceMaps for the JavaScript files. + * They are inside the output.path directory. + * + * See: http://webpack.github.io/docs/configuration.html#output-sourcemapfilename + */ + sourceMapFilename: '[file].map', + + /** The filename of non-entry chunks as relative path + * inside the output.path directory. + * + * See: http://webpack.github.io/docs/configuration.html#output-chunkfilename + */ + chunkFilename: '[id].chunk.js', + + library: 'ac_[name]', + libraryTarget: 'var', + }, + + module: { + + rules: [ + + /* + * css loader support for *.css files (styles directory only) + * Loads external css styles into the DOM, supports HMR + * + */ + { + test: /\.css$/, + use: ['style-loader', 'css-loader'], + include: [helpers.root('src', 'styles')] + }, + + /* + * sass loader support for *.scss files (styles directory only) + * Loads external sass styles into the DOM, supports HMR + * + */ + { + test: /\.scss$/, + use: ['style-loader', 'css-loader', 'sass-loader'], + include: [helpers.root('src', 'styles')] + }, + + ] + + }, + + plugins: [ + + /** + * Plugin: DefinePlugin + * Description: Define free variables. + * Useful for having development builds with debug logging or adding global constants. + * + * Environment helpers + * + * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin + */ + // NOTE: when adding more properties, make sure you include them in custom-typings.d.ts + new DefinePlugin({ + 'ENV': JSON.stringify(METADATA.ENV), + 'HMR': METADATA.HMR, + 'process.env': { + 'ENV': JSON.stringify(METADATA.ENV), + 'NODE_ENV': JSON.stringify(METADATA.ENV), + 'HMR': METADATA.HMR, + } + }), + + /** + * Plugin: NamedModulesPlugin (experimental) + * Description: Uses file names as module name. + * + * See: https://github.com/webpack/webpack/commit/a04ffb928365b19feb75087c63f13cadfc08e1eb + */ + // new NamedModulesPlugin(), + + /** + * Plugin LoaderOptionsPlugin (experimental) + * + * See: https://gist.github.com/sokra/27b24881210b56bbaff7 + */ + new LoaderOptionsPlugin({ + debug: true, + options: { + + } + }), + + ], + + /** + * Webpack Development Server configuration + * Description: The webpack-dev-server is a little node.js Express server. + * The server emits information about the compilation state to the client, + * which reacts to those events. + * + * See: https://webpack.github.io/docs/webpack-dev-server.html + */ + devServer: { + port: METADATA.port, + host: METADATA.host, + historyApiFallback: true, + watchOptions: { + aggregateTimeout: 300, + poll: 1000 + } + }, + + /* + * Include polyfills or mocks for various node stuff + * Description: Node configuration + * + * See: https://webpack.github.io/docs/configuration.html#node + */ + node: { + global: true, + crypto: 'empty', + process: true, + module: false, + clearImmediate: false, + setImmediate: false + } + + }); +} diff --git a/config/webpack.github-deploy.js b/config/webpack.github-deploy.js new file mode 100644 index 0000000..7f409ef --- /dev/null +++ b/config/webpack.github-deploy.js @@ -0,0 +1,74 @@ +const fs = require('fs'); +const path = require('path'); +const ghDeploy = require('./github-deploy'); +const webpackMerge = require('webpack-merge'); // used to merge webpack configs +const ghpages = require('gh-pages'); + + +/** + * Webpack Constants + */ +const GIT_REMOTE_NAME = 'origin'; +const COMMIT_MESSAGE = 'Updates'; +const GH_REPO_NAME = ghDeploy.getRepoName(GIT_REMOTE_NAME); + +module.exports = function (options) { + const webpackConfigFactory = ghDeploy.getWebpackConfigModule(options); // the settings that are common to prod and dev + const webpackConfig = webpackConfigFactory(options); + + // replace the instance of HtmlWebpackPlugin with an updated one. + ghDeploy.replaceHtmlWebpackPlugin(webpackConfig.plugins, GH_REPO_NAME); + + return webpackMerge(webpackConfig, { + output: { + /** + * The public path is set to the REPO name. + * + * `HtmlElementsPlugin` will add it to all resources url's created by it. + * `HtmlWebpackPlugin` will add it to all webpack bundels/chunks. + * + * In theory publicPath shouldn't be used since the browser should automatically prefix the + * `baseUrl` into all URLs, however this is not the case when the URL is absolute (start with /) + * + * It's important to prefix & suffix the repo name with a slash (/). + * Prefixing so every resource will be absolute (otherwise it will be url.com/repoName/repoName... + * Suffixing since chunks will not do it automatically (testes against about page) + */ + publicPath: '/' + GH_REPO_NAME + '/' + ghDeploy.safeUrl(webpackConfig.output.publicPath) + }, + + plugins: [ + function() { + this.plugin('done', function() { + console.log('Starting deployment to GitHub.'); + + const logger = function (msg) { + console.log(msg); + }; + + const options = { + logger: logger, + remote: GIT_REMOTE_NAME, + message: COMMIT_MESSAGE, + dotfiles: true // for .nojekyll + }; + + // Since GitHub moved to Jekyll 3.3, their server ignores the "node_modules" and "vendors" folder by default. + // but, as of now, it also ignores "vendors*" files. + // This means vendor.bundle.js or vendor.[chunk].bundle.js will return 404. + // this is the fix for now. + fs.writeFileSync(path.join(webpackConfig.output.path, '.nojekyll'), ''); + + ghpages.publish(webpackConfig.output.path, options, function(err) { + if (err) { + console.log('GitHub deployment done. STATUS: ERROR.'); + throw err; + } else { + console.log('GitHub deployment done. STATUS: SUCCESS.'); + } + }); + }); + } + ] + }); +}; diff --git a/config/webpack.prod.js b/config/webpack.prod.js new file mode 100644 index 0000000..cf17c74 --- /dev/null +++ b/config/webpack.prod.js @@ -0,0 +1,324 @@ +const helpers = require('./helpers'); +const webpackMerge = require('webpack-merge'); // used to merge webpack configs +const commonConfig = require('./webpack.common.js'); // the settings that are common to prod and dev + +/** + * Webpack Plugins + */ +const DefinePlugin = require('webpack/lib/DefinePlugin'); +const ExtractTextPlugin = require('extract-text-webpack-plugin'); +const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin'); +const NormalModuleReplacementPlugin = require('webpack/lib/NormalModuleReplacementPlugin'); +const UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin'); +const WebpackMd5Hash = require('webpack-md5-hash'); +const OfflinePlugin = require('offline-plugin'); +/** + * Webpack Constants + */ +const ENV = process.env.NODE_ENV = process.env.ENV = 'production'; +const HOST = process.env.HOST || 'localhost'; +const PORT = process.env.PORT || 8080; +const METADATA = webpackMerge(commonConfig({env: ENV}).metadata, { + host: HOST, + port: PORT, + ENV: ENV, + HMR: false +}); + +module.exports = function () { + return webpackMerge(commonConfig({env: ENV}), { + + /** + * Developer tool to enhance debugging + * + * See: http://webpack.github.io/docs/configuration.html#devtool + * See: https://github.com/webpack/docs/wiki/build-performance#sourcemaps + */ + devtool: 'source-map', + + /** + * Options affecting the output of the compilation. + * + * See: http://webpack.github.io/docs/configuration.html#output + */ + output: { + + /** + * The output directory as absolute path (required). + * + * See: http://webpack.github.io/docs/configuration.html#output-path + */ + path: helpers.root('dist'), + + /** + * Specifies the name of each output file on disk. + * IMPORTANT: You must not specify an absolute path here! + * + * See: http://webpack.github.io/docs/configuration.html#output-filename + */ + filename: '[name].[chunkhash].bundle.js', + + /** + * The filename of the SourceMaps for the JavaScript files. + * They are inside the output.path directory. + * + * See: http://webpack.github.io/docs/configuration.html#output-sourcemapfilename + */ + sourceMapFilename: '[name].[chunkhash].bundle.map', + + /** + * The filename of non-entry chunks as relative path + * inside the output.path directory. + * + * See: http://webpack.github.io/docs/configuration.html#output-chunkfilename + */ + chunkFilename: '[id].[chunkhash].chunk.js' + + }, + + module: { + + rules: [ + + /* + * Extract CSS files from .src/styles directory to external CSS file + */ + { + test: /\.css$/, + loader: ExtractTextPlugin.extract({ + fallbackLoader: 'style-loader', + loader: 'css-loader' + }), + include: [helpers.root('src', 'styles')] + }, + + /* + * Extract and compile SCSS files from .src/styles directory to external CSS file + */ + { + test: /\.scss$/, + loader: ExtractTextPlugin.extract({ + fallbackLoader: 'style-loader', + loader: 'css-loader!sass-loader' + }), + include: [helpers.root('src', 'styles')] + }, + + ] + + }, + + /** + * Add additional plugins to the compiler. + * + * See: http://webpack.github.io/docs/configuration.html#plugins + */ + plugins: [ + + /** + * Plugin: ExtractTextPlugin + * Description: Extracts imported CSS files into external stylesheet + * + * See: https://github.com/webpack/extract-text-webpack-plugin + */ + new ExtractTextPlugin('[name].[contenthash].css'), + + /** + * Plugin: WebpackMd5Hash + * Description: Plugin to replace a standard webpack chunkhash with md5. + * + * See: https://www.npmjs.com/package/webpack-md5-hash + */ + new WebpackMd5Hash(), + + /** + * Plugin: DefinePlugin + * Description: Define free variables. + * Useful for having development builds with debug logging or adding global constants. + * + * Environment helpers + * + * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin + */ + // NOTE: when adding more properties make sure you include them in custom-typings.d.ts + new DefinePlugin({ + 'ENV': JSON.stringify(METADATA.ENV), + 'HMR': METADATA.HMR, + 'process.env': { + 'ENV': JSON.stringify(METADATA.ENV), + 'NODE_ENV': JSON.stringify(METADATA.ENV), + 'HMR': METADATA.HMR, + } + }), + + /** + * Plugin: UglifyJsPlugin + * Description: Minimize all JavaScript output of chunks. + * Loaders are switched into minimizing mode. + * + * See: https://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin + */ + // NOTE: To debug prod builds uncomment //debug lines and comment //prod lines + new UglifyJsPlugin({ + // beautify: true, //debug + // mangle: false, //debug + // dead_code: false, //debug + // unused: false, //debug + // deadCode: false, //debug + // compress: { + // screw_ie8: true, + // keep_fnames: true, + // drop_debugger: false, + // dead_code: false, + // unused: false + // }, // debug + // comments: true, //debug + + + beautify: false, //prod + output: { + comments: false + }, //prod + mangle: { + screw_ie8: true + }, //prod + compress: { + screw_ie8: true, + warnings: false, + conditionals: true, + unused: true, + comparisons: true, + sequences: true, + dead_code: true, + evaluate: true, + if_return: true, + join_vars: true, + negate_iife: false // we need this for lazy v8 + }, + }), + + /** + * Plugin: NormalModuleReplacementPlugin + * Description: Replace resources that matches resourceRegExp with newResource + * + * See: http://webpack.github.io/docs/list-of-plugins.html#normalmodulereplacementplugin + */ + + new NormalModuleReplacementPlugin( + /angular2-hmr/, + helpers.root('config/empty.js') + ), + + new NormalModuleReplacementPlugin( + /zone\.js(\\|\/)dist(\\|\/)long-stack-trace-zone/, + helpers.root('config/empty.js') + ), + + + // AoT + // new NormalModuleReplacementPlugin( + // /@angular(\\|\/)upgrade/, + // helpers.root('config/empty.js') + // ), + // new NormalModuleReplacementPlugin( + // /@angular(\\|\/)compiler/, + // helpers.root('config/empty.js') + // ), + // new NormalModuleReplacementPlugin( + // /@angular(\\|\/)platform-browser-dynamic/, + // helpers.root('config/empty.js') + // ), + // new NormalModuleReplacementPlugin( + // /dom(\\|\/)debug(\\|\/)ng_probe/, + // helpers.root('config/empty.js') + // ), + // new NormalModuleReplacementPlugin( + // /dom(\\|\/)debug(\\|\/)by/, + // helpers.root('config/empty.js') + // ), + // new NormalModuleReplacementPlugin( + // /src(\\|\/)debug(\\|\/)debug_node/, + // helpers.root('config/empty.js') + // ), + // new NormalModuleReplacementPlugin( + // /src(\\|\/)debug(\\|\/)debug_renderer/, + // helpers.root('config/empty.js') + // ), + + /** + * Plugin: CompressionPlugin + * Description: Prepares compressed versions of assets to serve + * them with Content-Encoding + * + * See: https://github.com/webpack/compression-webpack-plugin + */ + // install compression-webpack-plugin + // new CompressionPlugin({ + // regExp: /\.css$|\.html$|\.js$|\.map$/, + // threshold: 2 * 1024 + // }) + + /** + * Plugin LoaderOptionsPlugin (experimental) + * + * See: https://gist.github.com/sokra/27b24881210b56bbaff7 + */ + new LoaderOptionsPlugin({ + minimize: true, + debug: false, + options: { + + /** + * Html loader advanced options + * + * See: https://github.com/webpack/html-loader#advanced-options + */ + // TODO: Need to workaround Angular 2's html syntax => #id [bind] (event) *ngFor + htmlLoader: { + minimize: true, + removeAttributeQuotes: false, + caseSensitive: true, + customAttrSurround: [ + [/#/, /(?:)/], + [/\*/, /(?:)/], + [/\[?\(?/, /(?:)/] + ], + customAttrAssign: [/\)?\]?=/] + }, + + } + }), + + /** + * Plugin: BundleAnalyzerPlugin + * Description: Webpack plugin and CLI utility that represents + * bundle content as convenient interactive zoomable treemap + * + * `npm run build:prod -- --env.analyze` to use + * + * See: https://github.com/th0r/webpack-bundle-analyzer + */ + + new OfflinePlugin({ + excludes: ['**/.*', '**/*.map', '**/_*'] + }) + + ], + + /* + * Include polyfills or mocks for various node stuff + * Description: Node configuration + * + * See: https://webpack.github.io/docs/configuration.html#node + */ + node: { + global: true, + crypto: 'empty', + process: false, + module: false, + clearImmediate: false, + setImmediate: false + } + + }); +} diff --git a/config/webpack.test.js b/config/webpack.test.js new file mode 100644 index 0000000..7a0f096 --- /dev/null +++ b/config/webpack.test.js @@ -0,0 +1,247 @@ +const helpers = require('./helpers'); +const path = require('path'); + +/** + * Webpack Plugins + */ +const DefinePlugin = require('webpack/lib/DefinePlugin'); +const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin'); +const ContextReplacementPlugin = require('webpack/lib/ContextReplacementPlugin'); + +/** + * Webpack Constants + */ +const ENV = process.env.ENV = process.env.NODE_ENV = 'test'; + +/** + * Webpack configuration + * + * See: http://webpack.github.io/docs/configuration.html#cli + */ +module.exports = function () { + return { + + /** + * Source map for Karma from the help of karma-sourcemap-loader & karma-webpack + * + * Do not change, leave as is or it wont work. + * See: https://github.com/webpack/karma-webpack#source-maps + */ + devtool: 'inline-source-map', + + /** + * Options affecting the resolving of modules. + * + * See: http://webpack.github.io/docs/configuration.html#resolve + */ + resolve: { + + /** + * An array of extensions that should be used to resolve modules. + * + * See: http://webpack.github.io/docs/configuration.html#resolve-extensions + */ + extensions: ['.ts', '.js'], + + /** + * Make sure root is src + */ + modules: [path.resolve(__dirname, 'src'), 'node_modules'] + + }, + + /** + * Options affecting the normal modules. + * + * See: http://webpack.github.io/docs/configuration.html#module + * + * 'use:' revered back to 'loader:' as a temp. workaround for #1188 + * See: https://github.com/AngularClass/angular2-webpack-starter/issues/1188#issuecomment-262872034 + */ + module: { + + rules: [ + + /** + * Source map loader support for *.js files + * Extracts SourceMaps for source files that as added as sourceMappingURL comment. + * + * See: https://github.com/webpack/source-map-loader + */ + { + enforce: 'pre', + test: /\.js$/, + loader: 'source-map-loader', + exclude: [ + // these packages have problems with their sourcemaps + helpers.root('node_modules/rxjs'), + helpers.root('node_modules/@angular') + ] + }, + + /** + * Typescript loader support for .ts and Angular 2 async routes via .async.ts + * + * See: https://github.com/s-panferov/awesome-typescript-loader + */ + { + test: /\.ts$/, + use: [ + { + loader: 'awesome-typescript-loader', + query: { + // use inline sourcemaps for "karma-remap-coverage" reporter + sourceMap: false, + inlineSourceMap: true, + compilerOptions: { + + // Remove TypeScript helpers to be injected + // below by DefinePlugin + removeComments: true + + } + }, + }, + 'angular2-template-loader' + ], + exclude: [/\.e2e\.ts$/] + }, + + /** + * Json loader support for *.json files. + * + * See: https://github.com/webpack/json-loader + */ + { + test: /\.json$/, + loader: 'json-loader', + exclude: [helpers.root('src/index.html')] + }, + + /** + * Raw loader support for *.css files + * Returns file content as string + * + * See: https://github.com/webpack/raw-loader + */ + { + test: /\.css$/, + loader: ['to-string-loader', 'css-loader'], + exclude: [helpers.root('src/index.html')] + }, + + /** + * Raw loader support for *.html + * Returns file content as string + * + * See: https://github.com/webpack/raw-loader + */ + { + test: /\.html$/, + loader: 'raw-loader', + exclude: [helpers.root('src/index.html')] + }, + + /** + * Instruments JS files with Istanbul for subsequent code coverage reporting. + * Instrument only testing sources. + * + * See: https://github.com/deepsweet/istanbul-instrumenter-loader + */ + { + enforce: 'post', + test: /\.(js|ts)$/, + loader: 'istanbul-instrumenter-loader', + include: helpers.root('src'), + exclude: [ + /\.(e2e|spec)\.ts$/, + /node_modules/ + ] + } + + ] + }, + + /** + * Add additional plugins to the compiler. + * + * See: http://webpack.github.io/docs/configuration.html#plugins + */ + plugins: [ + + /** + * Plugin: DefinePlugin + * Description: Define free variables. + * Useful for having development builds with debug logging or adding global constants. + * + * Environment helpers + * + * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin + */ + // NOTE: when adding more properties make sure you include them in custom-typings.d.ts + new DefinePlugin({ + 'ENV': JSON.stringify(ENV), + 'HMR': false, + 'process.env': { + 'ENV': JSON.stringify(ENV), + 'NODE_ENV': JSON.stringify(ENV), + 'HMR': false, + } + }), + + /** + * Plugin: ContextReplacementPlugin + * Description: Provides context to Angular's use of System.import + * + * See: https://webpack.github.io/docs/list-of-plugins.html#contextreplacementplugin + * See: https://github.com/angular/angular/issues/11580 + */ + new ContextReplacementPlugin( + // The (\\|\/) piece accounts for path separators in *nix and Windows + /angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/, + helpers.root('src'), // location of your src + { + // your Angular Async Route paths relative to this root directory + } + ), + + /** + * Plugin LoaderOptionsPlugin (experimental) + * + * See: https://gist.github.com/sokra/27b24881210b56bbaff7 + */ + new LoaderOptionsPlugin({ + debug: false, + options: { + // legacy options go here + } + }), + + ], + + /** + * Disable performance hints + * + * See: https://github.com/a-tarasyuk/rr-boilerplate/blob/master/webpack/dev.config.babel.js#L41 + */ + performance: { + hints: false + }, + + /** + * Include polyfills or mocks for various node stuff + * Description: Node configuration + * + * See: https://webpack.github.io/docs/configuration.html#node + */ + node: { + global: true, + process: false, + crypto: 'empty', + module: false, + clearImmediate: false, + setImmediate: false + } + + }; +} diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..7c847a9 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,22 @@ +# Architecture + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [Files structure](#files-structure) +- [Application (Angular2)](#application-angular2) + + + +## Files structure +All the details about how the files are distributed along the project and why. + +You **MUST** contemplate this docs before make any structural change to the project. + +Access the docs [here](docs/architecture/files-structure.md) + +## Application (Angular2) +This project follows the [Angular2 guidelines](https://angular.io/docs/ts/latest/guide/style-guide.html) +in order to have a consistent project structure with all angular2 projects. + +You can view the project angular2 application architecture [here](docs/architecture/application.md). diff --git a/docs/architecture/application.md b/docs/architecture/application.md new file mode 100644 index 0000000..01a446d --- /dev/null +++ b/docs/architecture/application.md @@ -0,0 +1,85 @@ +# Application architecture + + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [Bootstrap](#bootstrap) +- [Modules](#modules) +- [Components](#components) + - [Templates](#templates) + - [Styles](#styles) +- [Services](#services) +- [Directives](#directives) +- [Pipes](#pipes) + + + +## Bootstrap +The files that require the entire application parts. We have three chunks with an +index file named `[chunk name].browser.ts`: + +- **main**: get the main app module and makes the bootstrap of the application. +- **polyfills**: group all the needed polyfills. +- **vendor**: an index for all vendor libraries such as jQuery. + +## Modules +The organization of angular2 elements is made by the _modules_ which group functionality +and import the needed stuff. We have different kind of modules in the project: + +- Main types + - App module (`app.module`) --> this module is the app root of angular2, the top level module. + - Feature modules (`[feature].module`) --> group all the angular2 elements related to a concrete feature. +- Common modules (can exists one per main module) + - Core module (`core.module`) --> group all the stuff needed to included just one time. For example + a whole app service + - Shared module (`shared.module`) --> group all the angular2 elements that needs every child + component of the module + - Routing module (`[app/feature]-routing.module`) --> group all the main module routing related stuff + +You can view the file structure [here](docs/architecture/files-structure#application-code) + +## Components +Represents the presentation of the app, manages the representation of the services information +with the templates. + +You can look as MVC pattern View-Controllers. + +### Templates +The MVC view of the application owned by a component, it can have bindings wich represents +the changes at app data. + +The file must be located as component file sibling and with the same name except by the extension. + +### Styles +All the component specific styles wich are processed to only affect to component template. + +The file must be located as component file sibling and with the same name except by the extension. + +## Services +Used for manage the app information like the user or the active website along the whole application. + +All the services have to be injectables by the `@Injectable()` decorator. + +There are two kind of services depending on where are provided: + +- Whole app service (singleton) --> provided at any module, in his list of providers. It creates + a instance of the service at the app injector so the same instance is injected to every + component, directive, pipe, etc... Create them at modules `core` folder +- Element based service --> provided at element array of providers by the component injector. + A new instance of the service is created at every component. Create them at modules + `shared` folder. + +You can look as MVC pattern Model-Controllers. + +## Directives +Makes appearance and behaviour changes to any html element in order to improve or give additional +functionality. + +It can be created at shared module of any main module (app or feature). + +## Pipes +Transform the content in order to accomplish some presentation goal, like print numbers or dates +in a special format. + +It can be created at shared module of any main module (app or feature). \ No newline at end of file diff --git a/docs/architecture/files-structure.md b/docs/architecture/files-structure.md new file mode 100644 index 0000000..78afaca --- /dev/null +++ b/docs/architecture/files-structure.md @@ -0,0 +1,102 @@ +# Files structure + + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [Project stuff](#project-stuff) +- [Application code](#application-code) + + + +## Project stuff +All the files that defines the type of project and also some code features +like CI support, tasks specification, etc... + +```tree +|- .vscode // Visual Studio Code editor stuff +| |- settings.json // Editor specific settings +| +|- config // All the project configuration files +| |- head-config.common.js // Head tags to include at index +| |- helpers.js // Configuration JavaScript utility functions +| |- karma.conf.js // Karma runner configuration required from root file +| |- protractor.conf.js // Protractor e2e runner configuration required from root file +| |- spec.bundle.js // Unit tests requirements bundle +| |- webpack.common.json // Webpack common configuration along all environments +| |- webpack.[env].json // Webpack environment specific configuration +| +|- docs // Root of project documentation +| |- architecture.md +| |- ... +| +|- src // Project source code files +| |- app // Application code (explained below) +| |- public // Root folder for serve the application (will be copied to `dist/`) +| | |- assets // Public raw files +| | | |- img // Web app images +| | | +| | |- meta // Public text info files +| | | |- _redirects // Plain text file to indicate netlify wich redirects to do +| | | |- browserconfig.xml // Microsoft application info +| | | |- humans.txt // Plain text file about webapp to read by humans +| | | |- manifest.json // App metadata file +| | | |- robots.txt // Text information for internet robots +| | +| |- custom-typings.d.ts // TypeScript types definitions needed for the app +| |- index.html // HTML template for the app index +| |- main.browser.ts // TypeScript bundle index for app code +| |- polyfills.browser.ts // TypeScript bundle index for polyfills +| +|- .editorconfig // Editors standar configuration +|- .eslintrc.json // Rules specification for the JavaScript linter +|- .gitignore // List of ignored files from git +|- .markdownlint.json // Rules config for markdown linter +|- .nvmrc // Node Version Manager config +|- .travis.yml // CI process specification +|- CHANGELOG.md // Project relevant changes along versions +|- CONTRIBUTING.md // All you need to know to contribute to this project +|- karma.conf.js // Karma runner configuration +|- LICENSE // License specification file +|- netlify.toml // Deploy settings with Netlify +|- package.json // Application meta information +|- protractor.conf.js // Protractor e2e test runner configuration +|- README.md // Quickly project guide and the root of documentation +|- superstatic.json // HTTP statics web server configuration +|- tsconfig.json // TypeScript language compiler configuration +|- tslint.json // Rules specification for the TypeScript linter +|- webpack.config.json // Root configuration file of the project builder (Webpack) +``` + +## Application code +The structure of all the angular2 web app source code files follow the +[Angular2 guidelines](https://angular.io/docs/ts/latest/guide/style-guide.html) but +we will explain the main details down below. + +The root is at `src/app/`. + +This is the basic structure: + +```tree +|- core +| |- core.module.ts +| |- index.ts +| +|- user [or any feature module] // Feature module folder +| |- core // Stuff to include in the module just one time +| |- shared // Stuff shared along all the module components and submodules +| |- user.component.[ts/html/scss] // Feature main component files +| |- user.[spec/e2e].ts // Feature tests +| |- user.module.ts +| |- user-routing.module.ts // Routes for user feature module +| |- index.ts +| +|- shared // Stuff to be included in all feature modules +| +|- app.component.[ts/html/scss] +|- app.[spec/e2e].ts +|- app.module.ts // App module definition +|- app-routing.module.ts // App main routes specification +|- environment.ts +|- index.ts +``` \ No newline at end of file diff --git a/docs/dev-flow.md b/docs/dev-flow.md new file mode 100644 index 0000000..b2f25ad --- /dev/null +++ b/docs/dev-flow.md @@ -0,0 +1,91 @@ +# Development flow +The project follow the **Git flow** model wich be based on Vicent Driessen model that you +can see the original post [here](http://nvie.com/posts/a-successful-git-branching-model/) +or a quick guide [here](http://danielkummer.github.io/git-flow-cheatsheet/). + + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [Main branches](#main-branches) + - [Develop](#develop) + - [Master](#master) +- [Support branches](#support-branches) + - [Feature (`feature/`)](#feature-feature) + - [Hotfix (`hotfix/`)](#hotfix-hotfix) + - [Release (`release/`)](#release-release) +- [Version flow](#version-flow) + + + +Well, this docs will explain the basis of the concept of **Git flow** applied to this project, the +main concepts are: + +- We have 2 main branches (`develop` and `master`) +- We use 4 different support branches identified by prefixes +- We use **code review** (Merge requests) for **ALL** merge commits +- We always publish the branches we are working on, _we never work alone_ +- The commit messages are very important, **DO NOT use generic messages** like _Minor bug fixes_ + +![Git flow banching model](http://nvie.com/img/git-model@2x.png) + +## Main branches +This branches are static to the project and are the representation of project main history +because all the things start from this branches and end at this branches. + +### Develop +This is the development integration branch where all the current features start +and ends before release. All the things developed but hotfixes **MUST START FROM DEVELOP**. + +When the changes at develop are enought to make another version of the project a new +release branch are created to manage the new version. + +The success commits in this brach are deployed to the [dev enviroment](http://eqonecta.tsurudev.qdqmedia.com/). + +### Master +The main branch of the project, **direct commits are FORBIDDEN** the changes to this branch are made +by code review merge request from `hotfix` or `release` branches and are always tagged with a version +number following the [version flow](#version-flow) of the project. + +The success commit of this branch are automatically deployed at beta enviroment. + +## Support branches +This kind of branches are the the way to make any changes on the project, depending the change you want +to do you should create a type of support branch or another. All support branches are prefixed with +the identifier of the branch kind. + +The branch name have to follow **CapitalCase convention**, for example: `feature/AwesomeComponent` or +`hotfix/FixApiEndpoint`. + +### Feature (`feature/`) +When you want to add something new, make some change or a non urgent fix +you have to create a feature branch +that starts and ends at `develop` by a merge request. + +### Hotfix (`hotfix/`) +This kind of branch is used for making important but small changes needed for production and always implict +a version upgrade of the project that must be a path, speaking in +[semantic versioning](http://semver.org/) terms. + +This branches always **HAVE TO END** commited to main branches. + +### Release (`release/`) +Integration branches for grouping all the changes made at the new version +and do all the new [version flow](#version-flow) which is explained down below. + +The name of this branch must be the number of the intended version to release, for example, +if the future version would be the `1.2.3` the release branch name would be `release/1.2.3`. + +## Version flow +The steps you must follow in order to create a new version of the project. + +1. \* Update the [CHANGELOG](CHANGELOG.md) with the revelant release changes +1. Update the project version in all the files that reference it +1. Create a merge request to merge the release in master +1. Accept the merge request when the build success +1. Tag the merge commit with the new version with the prefix `v` like `v1.2.3` +1. Merge with develop + +\* _Ignore for patch versions_ + +The project follow the [sematic versioning](http://semver.org/) concept. \ No newline at end of file diff --git a/docs/scripts.md b/docs/scripts.md new file mode 100644 index 0000000..d433afc --- /dev/null +++ b/docs/scripts.md @@ -0,0 +1,98 @@ +# NPM Scripts +All the things you need to know about the npm developer API. + + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [Task name convention](#task-name-convention) +- [Build (`build`)](#build-build) +- [CI (`ci`)](#ci-ci) +- [Clean (`clean`)](#clean-clean) +- [DocToc (`doctoc`)](#doctoc-doctoc) +- [Lint (`lint`)](#lint-lint) +- [Server (`server`)](#server-server) +- [Test (`test`)](#test-test) +- [Watch (`watch`)](#watch-watch) + + + +## Task name convention +All the scripts are in **lowercase** like `test`. + +For subtasks is to separate names with double dots like this `task:subtask` so you can +execute `npm run build:dev`. + +## Build (`build`) +Make the `dev` bundles of the app. + +Subtasks: + +- `aot`: build the app using angular _ahead of time_ compilation. +- `ci`: same as `build:dev` but with ci specific conf. +- `dev *`: make the app bundles in memory. +- `prod`: make the bundles, parse the `index.html` and copy the `src/public` directory content into + the `dist` folder. + +## CI (`ci`) +Scripts usefull to run into the CI environment. All the tasks run the lint and tests tasks. + +Subtasks: + +- `aot`: Runs the e2e tests with an aot build. +- `jit`: Runs the e2e tests with an normal production build. +- `nobuild`: Runs the same without building the app before. +- `testall *`: Runs the base and the e2e tests with all the different kinds of build. + +## Clean (`clean`) +Remove node modules folder, npm cache and all the stuff generated by other tasks like +tests, coverage, etc. + +Subtasks: + +- `aot`: remove only the compiled folder. +- `dist`: remove only the dist folder. +- `install`: execute `clean` task and install node dependencies. +- `start`: execute `clean` task and start the dev server. + +## DocToc (`doctoc`) +Create or updates the tables of content of the markdown documentation files. You can see the package +page [here](https://www.npmjs.com/package/doctoc). + +- `generate *`: Run the command against the markdown files. +- `ci`: Runs the generation tasks and check if there are changes at any file in the repo, + if yes exit an error because the generation command changed something. The documentation + must have the table of contents always updated when the repo is pushed to origin. + +## Lint (`lint`) +Executes all the main tasks for linting the source code and conf files. + +Subtasks: + +- `md`: Lint all the markdown code. +- `js`: Lint all the javascript code, including configuration files at `config/`. +- `ts`: Lint all the typescript app code, including tests files. + +## Server (`server`) +Start a webserver for being accesible from a browser. + +Subtasks: + +- `dev *`: start a webpack-dev-server that serves the app in memory in watch mode. +- `ci`: start the same as `server:dev` but with no watch or progress indicator. +- `prod`: start a simple web server that serves dist folder contents through port 8080. + +## Test (`test`) +Run the unit tests of the app with [Karma](https://karma-runner.github.io/) and calculate +the coverage. + +## Watch (`watch`) +He runs a task and stay waiting for files modifications. + +Subtasks: + +- `dev *`: executes the dev build task on every file modification. +- `prod`: executes the prod build task on every file modification. +- `test`: run the unit tests on every file modification. + +The `*` at subtask specification means that it runs when no subtask is specified. \ No newline at end of file diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000..75eda63 --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,2 @@ +// Look in ./config for karma.conf.js +module.exports = require('./config/karma.conf.js'); diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 0000000..a63054d --- /dev/null +++ b/netlify.toml @@ -0,0 +1,29 @@ +# Global settings applied to the whole site. +[build] + publish = "dist" + command = "npm run build:aot:prod" + +# Production context: All deploys to the main +# repository branch will inherit these settings. +# [context.production] +# command = "npm run build:aot:prod" + +# Deploy Preview context: All Deploy Previews +# will inherit these settings. +# [context.deploy-preview] +# command = "npm run build:aot:prod" + +# Branch Deploy context: All deploys to branches +# that are not the main one that are not in +# an active Deploy Preview will inherit these settings. +# [context.branch-deploy] +# command = "npm run build" + +# Specific branch context: Deploys from this branch +# will take these settings and override their +# current ones. +# [context.feature] +# command = "make feature" + +# [context."features/branch"] +# command = "gulp" \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..19b02c0 --- /dev/null +++ b/package.json @@ -0,0 +1,169 @@ +{ + "name": "poll-me-webapp", + "version": "0.0.1", + "description": "A single page application to view, edit and fill any kind of PollMe quiz or survey", + "keywords": [ + "angular2", + "webpack", + "typescript" + ], + "homepage": "https://github.com/Poll-me/poll-me-webapp", + "bugs": { + "url": "https://github.com/Poll-me/poll-me-webapp/issues", + "email": "arribasjavier@gmail.com" + }, + "license": "MIT", + "author": "Francisco Javier Arribas Fernández ", + "contributors": [], + "repository": { + "type": "git", + "url": "https://github.com/Poll-me/poll-me-webapp" + }, + "scripts": { + "build:aot:prod": "npm run clean:dist && npm run clean:aot && webpack --config config/webpack.prod.js --progress --profile --bail", + "build:aot": "npm run build:aot:prod", + "build:dev": "npm run clean:dist && webpack --config config/webpack.dev.js --progress --profile", + "build:docker": "npm run build:prod && docker build -t angular2-webpack-start:latest .", + "build:prod": "npm run clean:dist && webpack --config config/webpack.prod.js --progress --profile --bail", + "build": "npm run build:dev", + "ci:aot": "npm run lint && npm run test && npm run build:aot && npm run e2e", + "ci:jit": "npm run lint && npm run test && npm run build:prod && npm run e2e", + "ci:nobuild": "npm run lint && npm test && npm run e2e", + "ci:testall": "npm run doctoc:ci && npm run lint && npm run test && npm run build:prod && npm run e2e && npm run build:aot && npm run e2e", + "ci": "npm run ci:testall", + "clean:aot": "rimraf -- compiled", + "clean:dist": "rimraf -- dist", + "clean:install": "npm set progress=false && npm install", + "clean:start": "npm start", + "clean": "npm cache clean && rimraf -- node_modules doc coverage dist compiled", + "doctoc": "npm run doctoc:generate", + "doctoc:ci": "(npm run doctoc > /dev/null && git status | grep 'nothing to commit' > /dev/null ) || (echo 'Tables of contents of documentation files are not updated.\nUpdate them with \"npm run doctoc\".' && exit 1)", + "doctoc:generate": "doctoc --maxlevel 4 README.md docs/", + "e2e:live": "npm run e2e -- --elementExplorer", + "e2e": "npm-run-all -p -r server:prod:ci e2e:only", + "e2e:only": "protractor", + "github-deploy:dev": "webpack --config config/webpack.github-deploy.js --progress --profile --env.githubDev", + "github-deploy:prod": "webpack --config config/webpack.github-deploy.js --progress --profile --env.githubProd", + "github-deploy": "npm run github-deploy:dev", + "lint": "npm run lint:ts && npm run lint:md && npm run lint:js", + "lint:ts": "tslint \"src/**/*.ts\"", + "lint:js": "eslint --ignore-path .gitignore ./", + "lint:md": "markdownlint *.md docs/**", + "postversion": "git push && git push --tags", + "prebuild:dev": "npm run clean:dist", + "prebuild:prod": "npm run clean:dist", + "preclean:install": "npm run clean", + "preclean:start": "npm run clean", + "pree2e": "npm run webdriver:update -- --standalone", + "server:dev:hmr": "npm run server:dev -- --inline --hot", + "server:dev": "webpack-dev-server --config config/webpack.dev.js --progress --profile --watch --content-base src/", + "server:prod": "http-server dist -c-1 --cors", + "server:prod:ci": "http-server dist -p 3000 -c-1 --cors", + "server": "npm run server:dev", + "start:hmr": "npm run server:dev:hmr", + "start": "npm run server:dev", + "test": "npm run lint && karma start", + "watch:dev:hmr": "npm run watch:dev -- --hot", + "watch:dev": "npm run build:dev -- --watch", + "watch:prod": "npm run build:prod -- --watch", + "watch:test": "npm run test -- --auto-watch --no-single-run", + "watch": "npm run watch:dev", + "webdriver-manager": "webdriver-manager", + "webdriver:start": "npm run webdriver-manager start", + "webdriver:update": "npm run webdriver-manager update", + "webpack-dev-server": "webpack-dev-server" + }, + "dependencies": { + "@angular/common": "~2.4.1", + "@angular/compiler": "~2.4.1", + "@angular/core": "~2.4.1", + "@angular/forms": "~2.4.1", + "@angular/http": "~2.4.1", + "@angular/platform-browser": "~2.4.1", + "@angular/platform-browser-dynamic": "~2.4.1", + "@angular/platform-server": "~2.4.1", + "@angular/router": "~3.4.1", + "@angularclass/conventions-loader": "^1.0.2", + "@angularclass/hmr": "~1.2.2", + "@angularclass/hmr-loader": "~3.0.2", + "angularfire2": "^2.0.0-beta.7", + "core-js": "^2.4.1", + "firebase": "^3.6.5", + "firebaseui": "^1.0.0", + "http-server": "^0.9.0", + "ie-shim": "^0.1.0", + "jasmine-core": "^2.5.2", + "reflect-metadata": "^0.1.9", + "rxjs": "~5.0.2", + "zone.js": "~0.7.4" + }, + "devDependencies": { + "@angular/compiler-cli": "~2.4.1", + "@types/hammerjs": "^2.0.33", + "@types/jasmine": "^2.2.34", + "@types/node": "^6.0.38", + "@types/selenium-webdriver": "2.53.38", + "@types/service_worker_api": "0.0.8", + "@types/source-map": "^0.5.0", + "@types/uglify-js": "^2.0.27", + "@types/webpack": "^2.0.0", + "angular2-template-loader": "^0.6.0", + "assets-webpack-plugin": "^3.4.0", + "awesome-typescript-loader": "~3.0.0-beta.17", + "codelyzer": "~2.0.0-beta.4", + "copy-webpack-plugin": "^4.0.0", + "css-loader": "^0.26.0", + "doctoc": "^1.2.0", + "eslint": "^3.13.1", + "exports-loader": "^0.6.3", + "expose-loader": "^0.7.1", + "extract-text-webpack-plugin": "~2.0.0-beta.4", + "file-loader": "^0.9.0", + "gh-pages": "^0.12.0", + "html-webpack-plugin": "^2.21.0", + "imports-loader": "^0.7.0", + "istanbul-instrumenter-loader": "1.2.0", + "jasmine-core": "^2.5.2", + "json-loader": "^0.5.4", + "karma": "^1.2.0", + "karma-chrome-launcher": "^2.0.0", + "karma-coverage": "^1.1.1", + "karma-jasmine": "^1.0.2", + "karma-mocha-reporter": "^2.0.0", + "karma-remap-coverage": "^0.1.4", + "karma-sourcemap-loader": "^0.3.7", + "karma-webpack": "1.8.1", + "lodash": "^4.17.4", + "markdownlint-cli": "^0.2.0", + "ng-router-loader": "^1.0.2", + "ngc-webpack": "1.1.0", + "node-sass": "^4.1.1", + "npm-run-all": "^4.0.0", + "offline-plugin": "^4.5.4", + "parse5": "^3.0.1", + "protractor": "^4.0.10", + "raw-loader": "0.5.1", + "rimraf": "~2.5.4", + "sass-loader": "^4.1.1", + "script-ext-html-webpack-plugin": "^1.3.2", + "source-map-loader": "^0.1.5", + "string-replace-loader": "1.0.5", + "style-loader": "^0.13.1", + "to-string-loader": "^1.1.4", + "ts-helpers": "1.1.2", + "ts-node": "^2.0.0", + "tslint": "~4.3.1", + "typescript": "2.0.10", + "url-loader": "^0.5.7", + "v8-lazy-parse-webpack-plugin": "^0.3.0", + "webpack": "2.2.0-rc.3", + "webpack-dev-middleware": "^1.6.1", + "webpack-dev-server": "2.2.0-rc.0", + "webpack-md5-hash": "^0.0.5", + "webpack-merge": "~2.3.1" + }, + "engines": { + "node": ">= 4.2.1", + "npm": ">= 3" + } +} diff --git a/protractor.conf.js b/protractor.conf.js new file mode 100644 index 0000000..ef5d73b --- /dev/null +++ b/protractor.conf.js @@ -0,0 +1,2 @@ +// look in ./config for protractor.conf.js +exports.config = require('./config/protractor.conf.js').config; diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts new file mode 100644 index 0000000..cdd9bf1 --- /dev/null +++ b/src/app/app-routing.module.ts @@ -0,0 +1,18 @@ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; + +const routes: Routes = [{ + path: 'user', + loadChildren: 'app/user/user.module#UserModule', +}, { + path: '', + redirectTo: 'user', + pathMatch: 'full' +}]; + +@NgModule({ + imports: [ RouterModule.forRoot(routes) ], + exports: [ RouterModule ], + providers: [ ] +}) +export class AppRoutingModule { } diff --git a/src/app/app.component.html b/src/app/app.component.html new file mode 100644 index 0000000..366c1d4 --- /dev/null +++ b/src/app/app.component.html @@ -0,0 +1,2 @@ +

Hello world!!

+ \ No newline at end of file diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts new file mode 100644 index 0000000..e11510e --- /dev/null +++ b/src/app/app.component.spec.ts @@ -0,0 +1,39 @@ +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { + inject, + async, + TestBed, + ComponentFixture +} from '@angular/core/testing'; + +// Load the implementations that should be tested +import { AppComponent } from './app.component'; + +describe(`App`, () => { + let comp: AppComponent; + let fixture: ComponentFixture; + + // async beforeEach + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AppComponent ], + schemas: [NO_ERRORS_SCHEMA], + providers: [] + }) + .compileComponents(); // compile template and css + })); + + // synchronous beforeEach + beforeEach(() => { + fixture = TestBed.createComponent(AppComponent); + comp = fixture.componentInstance; + + fixture.detectChanges(); // trigger initial data binding + }); + + it(`should be readly initialized`, () => { + expect(fixture).toBeDefined(); + expect(comp).toBeDefined(); + }); + +}); diff --git a/src/app/app.component.ts b/src/app/app.component.ts new file mode 100644 index 0000000..c643f29 --- /dev/null +++ b/src/app/app.component.ts @@ -0,0 +1,16 @@ +import { Component, ViewEncapsulation } from '@angular/core'; + +/* + * App Component + * Top Level Component + */ +@Component({ + selector: 'pm-app', + encapsulation: ViewEncapsulation.None, + templateUrl: './app.component.html' +}) +export class AppComponent { + + // constructor( ) {} + +} diff --git a/src/app/app.e2e.ts b/src/app/app.e2e.ts new file mode 100644 index 0000000..44db81e --- /dev/null +++ b/src/app/app.e2e.ts @@ -0,0 +1,15 @@ +import { browser, by, element } from 'protractor'; + +describe('App', () => { + + beforeEach(() => { + browser.get('/'); + }); + + it('should have a title', () => { + let subject = browser.getTitle(); + let result = 'PollMe WebApp'; + expect(subject).toEqual(result); + }); + +}); diff --git a/src/app/app.module.ts b/src/app/app.module.ts new file mode 100644 index 0000000..e63e002 --- /dev/null +++ b/src/app/app.module.ts @@ -0,0 +1,41 @@ +import { NgModule, ApplicationRef } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { removeNgStyles } from '@angularclass/hmr'; + +// Main imports +import { CoreModule } from './core'; +import { AppRoutingModule } from './app-routing.module'; +import { AppComponent } from './app.component'; + +// Features +import { UserModule } from './user'; + +@NgModule({ + declarations: [ AppComponent ], + imports: [ + BrowserModule, + CoreModule, + AppRoutingModule, + UserModule + ], + bootstrap: [ AppComponent ] +}) +export class AppModule { + + constructor( + public appRef: ApplicationRef + ) {} + + public hmrOnInit() { + + this.appRef.tick(); + } + + public hmrOnDestroy() { + const cmpLocation = this.appRef.components.map((cmp) => cmp.location.nativeElement); + removeNgStyles(); + } + + // public hmrAfterDestroy() {} + +} diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts new file mode 100644 index 0000000..70e9248 --- /dev/null +++ b/src/app/core/core.module.ts @@ -0,0 +1,31 @@ +import { NgModule, Optional, SkipSelf } from '@angular/core'; +import { HttpModule } from '@angular/http'; + +// SERVICES AND PROVIDERS +import { ENV_PROVIDERS } from '../environment'; +import { FirebaseAppModule } from './firebase'; +import { UserService } from './user'; + +// PAGE COMPONENTS + +// PARTIALS + +@NgModule({ + declarations: [ ], + imports: [ + FirebaseAppModule + ], + providers: [ + ENV_PROVIDERS, + UserService + ] +}) +export class CoreModule { + + constructor (@Optional() @SkipSelf() parentModule: CoreModule) { + if (parentModule) { + throw new Error( + 'CoreModule is already loaded. Import it in the AppModule only'); + } + } +} diff --git a/src/app/core/firebase/firebase-init.ts b/src/app/core/firebase/firebase-init.ts new file mode 100644 index 0000000..7536282 --- /dev/null +++ b/src/app/core/firebase/firebase-init.ts @@ -0,0 +1,11 @@ +import { AngularFireModule } from 'angularfire2'; + +const firebaseConfig = { + apiKey: 'AIzaSyAncYW-RYkegv0gq8_laAlUTe3vfBd6KEY', + authDomain: 'poll-me-36f9a.firebaseapp.com', + databaseURL: 'https://poll-me-36f9a.firebaseio.com', + storageBucket: 'poll-me-36f9a.appspot.com', + messagingSenderId: '772514369454' +}; + +export const FirebaseAppModule = AngularFireModule.initializeApp(firebaseConfig); diff --git a/src/app/core/firebase/index.ts b/src/app/core/firebase/index.ts new file mode 100644 index 0000000..e0e1e09 --- /dev/null +++ b/src/app/core/firebase/index.ts @@ -0,0 +1 @@ +export * from './firebase-init'; diff --git a/src/app/core/index.ts b/src/app/core/index.ts new file mode 100644 index 0000000..a30d0c7 --- /dev/null +++ b/src/app/core/index.ts @@ -0,0 +1 @@ +export * from './core.module'; diff --git a/src/app/core/user/index.ts b/src/app/core/user/index.ts new file mode 100644 index 0000000..22e1da9 --- /dev/null +++ b/src/app/core/user/index.ts @@ -0,0 +1,2 @@ +export * from './user.service'; +export * from './user'; diff --git a/src/app/core/user/user.service.ts b/src/app/core/user/user.service.ts new file mode 100644 index 0000000..7bfeca0 --- /dev/null +++ b/src/app/core/user/user.service.ts @@ -0,0 +1,29 @@ +import { Injectable } from '@angular/core'; + +import { Observable, BehaviorSubject } from 'rxjs'; +import * as _ from 'lodash'; + +import { User } from './user'; + +@Injectable() +export class UserService { + + public currentUser: BehaviorSubject = new BehaviorSubject(undefined); + public redirectUrl: string; + + // constructor() {} + + public getUser(): User { + return this.currentUser.getValue(); + } + + public updateUser(newUser: User): User { + this.currentUser.next(newUser); + return this.getUser(); + } + + public isValid(): boolean { + const user = this.getUser(); + return !_.isUndefined(user) && !_.some(_.values(user), (val) => !val); + } +} diff --git a/src/app/core/user/user.ts b/src/app/core/user/user.ts new file mode 100644 index 0000000..c5155d8 --- /dev/null +++ b/src/app/core/user/user.ts @@ -0,0 +1,8 @@ +export class User { + + constructor( + public name?: string, + public email?: string, + public type?: string + ) {} +} diff --git a/src/app/environment.ts b/src/app/environment.ts new file mode 100644 index 0000000..3131154 --- /dev/null +++ b/src/app/environment.ts @@ -0,0 +1,64 @@ +// Angular 2 +import { + enableDebugTools, + disableDebugTools +} from '@angular/platform-browser'; +import { + ApplicationRef, + enableProdMode +} from '@angular/core'; + +import * as OfflineRuntime from 'offline-plugin/runtime'; + +// Environment Providers +let PROVIDERS: any[] = [ + // common env directives +]; + +// Angular debug tools in the dev console +// https://github.com/angular/angular/blob/86405345b781a9dc2438c0fbe3e9409245647019/TOOLS_JS.md +let _decorateModuleRef = (value: T): T => { return value; }; + +if ('production' === ENV) { + enableProdMode(); + + // Production + _decorateModuleRef = (modRef: any) => { + disableDebugTools(); + // Start the service worker runtime + OfflineRuntime.install(); + + return modRef; + }; + + PROVIDERS = [ + ...PROVIDERS, + // custom providers in production + ]; + +} else { + + _decorateModuleRef = (modRef: any) => { + const appRef = modRef.injector.get(ApplicationRef); + const cmpRef = appRef.components[0]; + + let _ng = ( window).ng; + enableDebugTools(cmpRef); + ( window).ng.probe = _ng.probe; + ( window).ng.coreTokens = _ng.coreTokens; + return modRef; + }; + + // Development + PROVIDERS = [ + ...PROVIDERS, + // custom providers in development + ]; + +} + +export const decorateModuleRef = _decorateModuleRef; + +export const ENV_PROVIDERS = [ + ...PROVIDERS +]; diff --git a/src/app/index.ts b/src/app/index.ts new file mode 100644 index 0000000..4d4a9db --- /dev/null +++ b/src/app/index.ts @@ -0,0 +1,2 @@ +// App +export * from './app.module'; diff --git a/src/app/user/index.ts b/src/app/user/index.ts new file mode 100644 index 0000000..6a191e4 --- /dev/null +++ b/src/app/user/index.ts @@ -0,0 +1 @@ +export * from './user.module'; diff --git a/src/app/user/user-routing.module.ts b/src/app/user/user-routing.module.ts new file mode 100644 index 0000000..d5f4965 --- /dev/null +++ b/src/app/user/user-routing.module.ts @@ -0,0 +1,15 @@ +import { NgModule } from '@angular/core'; +import { Routes, + RouterModule } from '@angular/router'; + +import { UserComponent } from './user.component'; + +const routes: Routes = [ + { path: '', component: UserComponent }, +]; + +@NgModule({ + imports: [ RouterModule.forChild(routes) ], + exports: [ RouterModule ] +}) +export class UserRoutingModule {} diff --git a/src/app/user/user.component.html b/src/app/user/user.component.html new file mode 100644 index 0000000..442a69a --- /dev/null +++ b/src/app/user/user.component.html @@ -0,0 +1,4 @@ +

The current user is:

+
+  {{ user }}
+
\ No newline at end of file diff --git a/src/app/user/user.component.ts b/src/app/user/user.component.ts new file mode 100644 index 0000000..5dc30a1 --- /dev/null +++ b/src/app/user/user.component.ts @@ -0,0 +1,20 @@ +import { Component } from '@angular/core'; + +import * as _ from 'lodash'; + +import { UserService, User } from '../core/user'; + +@Component({ + selector: 'pm-user', + templateUrl: './user.component.html' +}) +export class UserComponent { + + public user: User; + + constructor ( + private userService: UserService + ) { + userService.currentUser.subscribe((u) => this.user = u); + } +} diff --git a/src/app/user/user.module.ts b/src/app/user/user.module.ts new file mode 100644 index 0000000..0c20d01 --- /dev/null +++ b/src/app/user/user.module.ts @@ -0,0 +1,15 @@ +import { NgModule } from '@angular/core'; + +// import { SharedModule } from '../shared'; + +import { UserRoutingModule } from './user-routing.module'; +import { UserComponent } from './user.component'; + +@NgModule({ + declarations: [ UserComponent ], + imports: [ + // SharedModule, + UserRoutingModule + ] +}) +export class UserModule { } diff --git a/src/assets/css/.gitkeep b/src/assets/css/.gitkeep new file mode 100644 index 0000000..857ef8c --- /dev/null +++ b/src/assets/css/.gitkeep @@ -0,0 +1 @@ +@AngularClass diff --git a/src/assets/favicon.ico b/src/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..3f25ddcbf116a9c517a89806997b09a1b715ec53 GIT binary patch literal 15086 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 literal 0 HcmV?d00001 diff --git a/src/assets/img/favicon/android-chrome-512x512.png b/src/assets/img/favicon/android-chrome-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..af3a15bd896169e832f00810cabcde1763310e19 GIT binary patch literal 44182 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 literal 0 HcmV?d00001 diff --git a/src/assets/img/favicon/apple-touch-icon.png b/src/assets/img/favicon/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a3d051eedf40522bcc2dd163d336b3ce1cdfa823 GIT binary patch literal 10218 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 literal 0 HcmV?d00001 diff --git a/src/assets/img/favicon/favicon-16x16.png b/src/assets/img/favicon/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..a985cdbc49c6a76ec07c6e537f5baafcdbf36720 GIT binary patch literal 928 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>`T@Ck7RD!AcbPcpK% zyJ2U0)7|Y(NXRWO&*#0pU(TNW`Sj_pXV1Q!KYz>D=flpO|Ni{>|NsA&FJJCGeE9eG z@0YV?{{Q#y^XJbSHf>7F%DR95!ONL5Z~1tCyMDc?wav@Vf7|vQ-@bjj6B_#S*|WCJ zPGbwpiIb;%|Ni}^xA)hp*Z%$g-#=+mXHUM<{dqgRG5vFW-Ip=B@mdryo4JJ08c?7t|D0mDOGBw%oM%@afg> zzMjqfpO@i&oaxx#!;dH1?BCP$b#0U3y?gd{`}a+aJE*fO%zl4;mCmkHKg0CGEbpJ{ z{o=e@zVFL_#_$U=LK)}sV}X8FEpd$~Nl7e8wMs5Z1yT$~28QOk28OzZ1|f!~R;I>Q z#+KR!hE@g!-}t?rqG-s?PsvQH#I2z{=u;$6LwHq4L`hI$xk5ovep+TuszOO+L8?M# zK}j+LL&coOpLjS5!!$Hb`JX=H`80@uS(#fenOj&{*n6@Fv#^3ogUR6(X64Nx3a4*e nIdSC75t$?GryD#Lcbdmyp$%O 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 literal 0 HcmV?d00001 diff --git a/src/assets/img/favicon/mstile-150x150.png b/src/assets/img/favicon/mstile-150x150.png new file mode 100644 index 0000000000000000000000000000000000000000..16ad36ec880833978b90d234a8aa763fb379a044 GIT binary patch literal 7894 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 Zz$O!&_r9W38lek-+EY#C3PsDv{{o6+?(6^n literal 0 HcmV?d00001 diff --git a/src/assets/img/favicon/mstile-310x150.png b/src/assets/img/favicon/mstile-310x150.png new file mode 100644 index 0000000000000000000000000000000000000000..b2d1f536a139b49d27909bba504af8ecf1253b55 GIT binary patch literal 8527 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%0AX2z2!at=c3QgH#{GaWJ#g_&8_M8 zAbZxpOE2$QU!|SwsF01|60P~#5KO8oXUZHpNwpFonU!)Z^ zS^Krh;VyidpH(@WZyss^4$_Yg`*=E$k@HGkruy|t43?g5Tq+QthMjcW5$Ti}rf&az zSFgW5rKP@cAU*LL2eB7@!xZ|Co5BQEr+2_@GkR260HlrGVoCT)b0x32MSgpbGfJPR zCQWZUHT!%X{;6=1<=$SqCqvL#7A0YuCQzw(YW+e-vX$l&GJd{9^5s^_Oon(fNiUJe z;z0kHgo`q9vbV%M#h*J=a>v_)$?U9CL|oV?1g!0y=A}C?VKasXnV>e*CQ(46*Q2bK zmPxBQf{f)!lqywzL~7KJYl@SJptf^FT{aH0+}q+s?SDb$tY9;S!V>kxj$ik`ozcax zWopSy5Hr7fu`#%gWS`^(+!VlU?)mt0#~+_RRG$!HDW6aMmx0xD%CwH>D3eZxEu^FRe!()P8t9{jRiwy9co`%Pu(P7=M{aW%N{x=J;4$&_CurZq2lihX{Ih-l(KD7VF z#-bTh>{!$#ypGll;I(o9?vD|xA%kGQ;x=eJ4(9a<3->#YAJ*uV+zukYs1@l5+hlMz zoZ(gJQS^uLyc>nbV7Sm6HtJF4%mCUhNtX#lyXHh!dh}`i{AOMT5$y|mUjTiWb}YT0 zn(@LV%4quf@WaZx3G9?aHIC zAuTc!>nec^Jx?43*u2^jq0@f2&TGw}KOty&*Xjw|*sb-vn#@W&MNCxb|LuP#W>S9D zr-^i&rZR9)TLU60Hh_+olTZ@%o=G zl{a$o^~;ZcuSTzqEnOQK9o}pL+n-<^u6FLA9FjgTye<%=Jvp=8B&hre@XMmL)+Y^( zt-+M-%UFQz5b_b^r-!k5)6g zSht>K=Dp{bADhub8m+*CzH^_|!ZVZDgau^aR`uTB^B4G<6ve+Nee*u@VMWbaf`_E$ zh3YJzo6$Mzo$E7|IY93CdzYLSA;4MuYyILHhzAhLoQ37&*W3LTkl{++Yf@}61&9Gi zD_anVgHn5sj8AyYIMC-C+9#@APOJgduofEnfa`-1_}4bGPmuTL3kKJs34f{n6@B&l z?s0Ge?F~_7PQFkgOOW?ItMrWFWa5N2KR_4m>-^eu1rd8o3*b!Td^RvX0hgEW^KhNy zOC05ClvVk6X3_vnDTUe04wef2Sg2@=!=XHGeL2II!)U1H622f-GmVjA<)oyOM zM1j^(r7kD`wA{;;+Y~`jBQEyN#txuFWFnR<#IY?uXYoi_=ToZXr{X}|h?@iEOR@h>{ZHGO?is7)F%e*8>4`8B z8Sv;M01MmwdR?zSB2@>Q8rRe?=ZFA{C<;snpbU7%;Gp^k{iMA#i-pBiow|3JBX;Uj zXW~AX1b}4_gCR*?NVpZZf#Ws(B`cGzlSXVE`@_P-8Ag44uGw_YphLU>5S_|br&^vU zd;V}mhDU*C^NIqZ@lZv}yF_Pk*&ve-nQPrr?t7uuv1qc??k9^#pefg$tJ`|fJ;0|V zbx=M&vC8+rHBQ>q_e4W|%b7#@M^EVudpCXnhfBy1m43nEMkob24n-^|*o=R2yGuzx zc~A7Inpj}?&PritNm=--r~Gj$kAS%iTSC@5AZ0yUJI??Ur`9jf#!R~1(3z;W#cifj zvQ;H7|Nh{M!BQynJo!Xk3R_!nUmw-o;14^|Q¨kzsfle2zl@&X-XZF|%Uo&~~cR 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 C8nAQ# literal 0 HcmV?d00001 diff --git a/src/assets/img/favicon/safari-pinned-tab.svg b/src/assets/img/favicon/safari-pinned-tab.svg new file mode 100644 index 0000000..5ae606b --- /dev/null +++ b/src/assets/img/favicon/safari-pinned-tab.svg @@ -0,0 +1,31 @@ + + + + +Created by potrace 1.11, written by Peter Selinger 2001-2013 + + + + + + + + diff --git a/src/assets/img/logo/logo_inverted.png b/src/assets/img/logo/logo_inverted.png new file mode 100644 index 0000000000000000000000000000000000000000..813b3ccb8a50f4818d3644a2640e42da4f25553b GIT binary patch literal 10972 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 literal 0 HcmV?d00001 diff --git a/src/assets/img/logo/logo_rounded.png b/src/assets/img/logo/logo_rounded.png new file mode 100644 index 0000000000000000000000000000000000000000..3e89f901b5730ee256a88e937429afcdd2f77fff GIT binary patch literal 18285 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 literal 0 HcmV?d00001 diff --git a/src/custom-typings.d.ts b/src/custom-typings.d.ts new file mode 100644 index 0000000..7cb57b6 --- /dev/null +++ b/src/custom-typings.d.ts @@ -0,0 +1,130 @@ +/* + * Custom Type Definitions + * When including 3rd party modules you also need to include the type definition for the module + * if they don't provide one within the module. You can try to install it with @types + +npm install @types/node +npm install @types/lodash + + * If you can't find the type definition in the registry we can make an ambient/global definition in + * this file for now. For example + +declare module 'my-module' { + export function doesSomething(value: string): string; +} + + * If you are using a CommonJS module that is using module.exports then you will have to write your + * types using export = yourObjectOrFunction with a namespace above it + * notice how we have to create a namespace that is equal to the function we're + * assigning the export to + +declare module 'jwt-decode' { + function jwtDecode(token: string): any; + namespace jwtDecode {} + export = jwtDecode; +} + + * + * If you're prototying and you will fix the types later you can also declare it as type any + * + +declare var assert: any; +declare var _: any; +declare var $: any; + + * + * If you're importing a module that uses Node.js modules which are CommonJS you need to import as + * in the files such as main.browser.ts or any file within app/ + * + +import * as _ from 'lodash' + + * You can include your type definitions in this file until you create one for the @types + * + */ + +// support NodeJS modules without type definitions +declare module '*'; + +/* +// for legacy tslint etc to understand rename 'modern-lru' with your package +// then comment out `declare module '*';`. For each new module copy/paste +// this method of creating an `any` module type definition +declare module 'modern-lru' { + let x: any; + export = x; +} +*/ + +// Extra variables that live on Global that will be replaced by webpack DefinePlugin +declare var ENV: string; +declare var HMR: boolean; +declare var System: SystemJS; + +interface SystemJS { + import: (path?: string) => Promise; +} + +interface GlobalEnvironment { + ENV: string; + HMR: boolean; + SystemJS: SystemJS; + System: SystemJS; +} + +interface Es6PromiseLoader { + (id: string): (exportName?: string) => Promise; +} + +type FactoryEs6PromiseLoader = () => Es6PromiseLoader; +type FactoryPromise = () => Promise; + +type AsyncRoutes = { + [component: string]: Es6PromiseLoader | + Function | + FactoryEs6PromiseLoader | + FactoryPromise +}; + +type IdleCallbacks = Es6PromiseLoader | + Function | + FactoryEs6PromiseLoader | + FactoryPromise ; + +interface WebpackModule { + hot: { + data?: any, + idle: any, + accept(dependencies?: string | string[], callback?: (updatedDependencies?: any) => void): void; + decline(deps?: any | string | string[]): void; + dispose(callback?: (data?: any) => void): void; + addDisposeHandler(callback?: (data?: any) => void): void; + removeDisposeHandler(callback?: (data?: any) => void): void; + check(autoApply?: any, callback?: (err?: Error, outdatedModules?: any[]) => void): void; + apply(options?: any, callback?: (err?: Error, outdatedModules?: any[]) => void): void; + status(callback?: (status?: string) => void): void | string; + removeStatusHandler(callback?: (status?: string) => void): void; + }; +} + +interface WebpackRequire { + (id: string): any; + (paths: string[], callback: (...modules: any[]) => void): void; + ensure(ids: string[], callback: (req: WebpackRequire) => void, chunkName?: string): void; + context(directory: string, useSubDirectories?: boolean, regExp?: RegExp): WebpackContext; +} + +interface WebpackContext extends WebpackRequire { + keys(): string[]; +} + +interface ErrorStackTraceLimit { + stackTraceLimit: number; +} + +// Extend typings +interface NodeRequire extends WebpackRequire {} +interface ErrorConstructor extends ErrorStackTraceLimit {} +interface NodeRequireFunction extends Es6PromiseLoader {} +interface NodeModule extends WebpackModule {} +interface Global extends GlobalEnvironment {} diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..27d9886 --- /dev/null +++ b/src/index.html @@ -0,0 +1,36 @@ + + + + + + + + <%= htmlWebpackPlugin.options.title %> + + + + <% if (webpackConfig.htmlElements.headTags) { %> + + <%= webpackConfig.htmlElements.headTags %> + <% } %> + + + + + + + + + + + Loading... + + + <% if (htmlWebpackPlugin.options.metadata.isDevServer && htmlWebpackPlugin.options.metadata.HMR !== true) { %> + + + <% } %> + + + + diff --git a/src/main.browser.aot.ts b/src/main.browser.aot.ts new file mode 100644 index 0000000..5496805 --- /dev/null +++ b/src/main.browser.aot.ts @@ -0,0 +1,26 @@ +/* + * Angular bootstraping + */ +import { platformBrowser } from '@angular/platform-browser'; +import { decorateModuleRef } from './app/environment'; +/* + * App Module + * our top level module that holds all of our components + */ +import { AppModuleNgFactory } from '../compiled/src/app/app.module.ngfactory'; + +/* + * Bootstrap our Angular app with a top level NgModule + */ +export function main(): Promise { + return platformBrowser() + .bootstrapModuleFactory(AppModuleNgFactory) + .then(decorateModuleRef) + .catch((err) => console.error(err)); +} + +export function bootstrapDomReady() { + document.addEventListener('DOMContentLoaded', main); +} + +bootstrapDomReady(); diff --git a/src/main.browser.ts b/src/main.browser.ts new file mode 100644 index 0000000..e17eeb6 --- /dev/null +++ b/src/main.browser.ts @@ -0,0 +1,25 @@ +/* + * Angular bootstraping + */ +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { decorateModuleRef } from './app/environment'; +import { bootloader } from '@angularclass/hmr'; +/* + * App Module + * our top level module that holds all of our components + */ +import { AppModule } from './app'; + +/* + * Bootstrap our Angular app with a top level NgModule + */ +export function main(): Promise { + return platformBrowserDynamic() + .bootstrapModule(AppModule) + .then(decorateModuleRef) + .catch((err) => console.error(err)); +} + +// needed for hmr +// in prod this is replace for document ready +bootloader(main); diff --git a/src/meta/_redirects b/src/meta/_redirects new file mode 100644 index 0000000..50a4633 --- /dev/null +++ b/src/meta/_redirects @@ -0,0 +1 @@ +/* /index.html 200 \ No newline at end of file diff --git a/src/meta/browserconfig.xml b/src/meta/browserconfig.xml new file mode 100644 index 0000000..6891c8d --- /dev/null +++ b/src/meta/browserconfig.xml @@ -0,0 +1,12 @@ + + + + + + + + + #b91d47 + + + diff --git a/src/meta/humans.txt b/src/meta/humans.txt new file mode 100644 index 0000000..c5e44ab --- /dev/null +++ b/src/meta/humans.txt @@ -0,0 +1,17 @@ +# humanstxt.org/ +# The humans responsible & technology colophon + +# TEAM + + -- -- + Francisco Javier Arribas Fernández -- creator -- @mdo2 + +# THANKS + + -- + PollMe -- @PollMe + +# TECHNOLOGY COLOPHON + + HTML5, CSS3 + Angular2, TypeScript, Webpack diff --git a/src/meta/manifest.json b/src/meta/manifest.json new file mode 100644 index 0000000..29782a1 --- /dev/null +++ b/src/meta/manifest.json @@ -0,0 +1,27 @@ +{ + "name": "PollMe WebApp", + "description": "The best application for get the information you need for any kind of people.", + "short_name": "PollMe", + "start_url": "/index.html", + "display": "standalone", + "lang": "en-US", + "theme_color": "#c72928", + "background_color": "#d8403f", + "icons": [ + { + "src": "/assets/img/favicon/mstile-144x144.png", + "sizes": "144x144", + "type": "image/png" + }, + { + "src": "/assets/img/favicon/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/assets/img/favicon/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} diff --git a/src/meta/robots.txt b/src/meta/robots.txt new file mode 100644 index 0000000..9417495 --- /dev/null +++ b/src/meta/robots.txt @@ -0,0 +1,3 @@ +# robotstxt.org + +User-agent: * diff --git a/src/polyfills.browser.ts b/src/polyfills.browser.ts new file mode 100644 index 0000000..d6d33e3 --- /dev/null +++ b/src/polyfills.browser.ts @@ -0,0 +1,46 @@ +// TODO(gdi2290): switch to DLLs + +// Polyfills + +// import 'ie-shim'; // Internet Explorer 9 support + +// import 'core-js/es6'; +// Added parts of es6 which are necessary for your project or your browser support requirements. +import 'core-js/es6/symbol'; +import 'core-js/es6/object'; +import 'core-js/es6/function'; +import 'core-js/es6/parse-int'; +import 'core-js/es6/parse-float'; +import 'core-js/es6/number'; +import 'core-js/es6/math'; +import 'core-js/es6/string'; +import 'core-js/es6/date'; +import 'core-js/es6/array'; +import 'core-js/es6/regexp'; +import 'core-js/es6/map'; +import 'core-js/es6/set'; +import 'core-js/es6/weak-map'; +import 'core-js/es6/weak-set'; +import 'core-js/es6/typed'; +import 'core-js/es6/reflect'; +// see issue https://github.com/AngularClass/angular2-webpack-starter/issues/709 +// import 'core-js/es6/promise'; + +import 'core-js/es7/reflect'; +import 'zone.js/dist/zone'; + +// Typescript emit helpers polyfill +import 'ts-helpers'; + +if ('production' === ENV) { + // Production + +} else { + + // Development + Error.stackTraceLimit = Infinity; + + /* tslint:disable no-var-requires */ + require('zone.js/dist/long-stack-trace-zone'); + +} diff --git a/src/styles/styles.scss b/src/styles/styles.scss new file mode 100644 index 0000000..e69de29 diff --git a/superstatic.json b/superstatic.json new file mode 100644 index 0000000..aed424b --- /dev/null +++ b/superstatic.json @@ -0,0 +1,24 @@ +{ + "cleanUrls": [ + ], + "rewrites": [ + { + "source": "**", + "destination": "index.html" + } + ], + "redirects": [ + ], + "headers": [ + { + "source": "**/*.*", + "headers": [ + { + "key": "Access-Control-Allow-Origin", + "value": "*" + } + ] + } + ], + "trailingSlash": false +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..b525e2c --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,40 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "sourceMap": true, + "noEmit": true, + "noEmitHelpers": true, + "strictNullChecks": false, + "lib": [ + "dom", + "es6" + ], + "types": [ + "hammerjs", + "jasmine", + "node", + "selenium-webdriver", + "source-map", + "uglify-js", + "webpack" + ] + }, + "exclude": [ + "node_modules", + "dist" + ], + "awesomeTypescriptLoaderOptions": { + "forkChecker": true, + "useWebpackText": true + }, + "compileOnSave": false, + "buildOnSave": false, + "atom": { + "rewriteTsconfig": false + } +} diff --git a/tsconfig.webpack.json b/tsconfig.webpack.json new file mode 100644 index 0000000..f0d9e41 --- /dev/null +++ b/tsconfig.webpack.json @@ -0,0 +1,41 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "es2015", + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "sourceMap": true, + "noEmit": true, + "noEmitHelpers": true, + "strictNullChecks": false, + "lib": [ + "es2015", + "dom" + ], + "types": [ + "hammerjs", + "node" + ] + }, + "exclude": [ + "node_modules", + "dist", + "src/**/*.spec.ts", + "src/**/*.e2e.ts" + ], + "awesomeTypescriptLoaderOptions": { + "forkChecker": true, + "useWebpackText": true + }, + "angularCompilerOptions": { + "genDir": "./compiled", + "skipMetadataEmit": true + }, + "compileOnSave": false, + "buildOnSave": false, + "atom": { + "rewriteTsconfig": false + } +} diff --git a/tslint.json b/tslint.json new file mode 100644 index 0000000..3caa923 --- /dev/null +++ b/tslint.json @@ -0,0 +1,54 @@ +{ + "extends": [ + "tslint:recommended" + ], + "rulesDirectory": [ + "node_modules/codelyzer" + ], + "rules": { + "trailing-comma": [false, {"multiline": "always", "singleline": "never"}], + "interface-name": [false, "always-prefix"], + "component-selector": [true, "element", "pm", "kebab-case"], + "directive-selector": [true, "attribute", "pm", "camelCase"], + "import-destructuring-spacing": true, + "invoke-injectable": true, + "no-access-missing-member": true, + "no-attribute-parameter-decorator": true, + "no-forward-ref": true, + "no-input-rename": true, + "no-output-rename": true, + "pipe-naming": [true, "camelCase", "pm"], + "templates-use-public": true, + "use-host-property-decorator": true, + "use-input-property-decorator": true, + "use-life-cycle-interface": true, + "use-output-property-decorator": true, + "use-pipe-transform-interface": true, + // General + "no-console": [true, + "time", + "timeEnd", + "trace" + ], + "max-line-length": [ + true, + 100 + ], + "no-string-literal": false, + "no-use-before-declare": true, + "object-literal-sort-keys": false, + "ordered-imports": false, + "quotemark": [ + true, + "single", + "avoid-escape" + ], + "variable-name": [ + true, + "allow-leading-underscore", + "allow-pascal-case", + "ban-keywords", + "check-format" + ] + } +} \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..2925aa8 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,15 @@ +// Look in ./config folder for webpack.dev.js +switch (process.env.NODE_ENV) { + case 'prod': + case 'production': + module.exports = require('./config/webpack.prod')({env: 'production'}); + break; + case 'test': + case 'testing': + module.exports = require('./config/webpack.test')({env: 'test'}); + break; + case 'dev': + case 'development': + default: + module.exports = require('./config/webpack.dev')({env: 'development'}); +}