From 4a6995be18b15de1834a39c8921a0e4109671bb6 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 3 Jun 2016 22:08:03 +0200 Subject: [PATCH] First draft to use webpack instead of systemjs --- client/.bootstraprc | 125 +++ client/.gitignore | 10 +- client/app/shared/index.ts | 2 - client/app/videos/index.ts | 4 - client/config/helpers.js | 17 + client/config/webpack.common.js | 261 ++++++ client/config/webpack.dev.js | 159 ++++ client/config/webpack.prod.js | 0 client/images/loading.gif | Bin 673 -> 0 bytes client/index.html | 36 - client/package.json | 36 +- client/{ => src}/app/app.component.html | 0 client/{ => src}/app/app.component.scss | 0 client/{ => src}/app/app.component.ts | 12 +- .../{ => src}/app/friends/friend.service.ts | 2 +- client/{ => src}/app/friends/index.ts | 0 client/{ => src}/app/login/index.ts | 0 .../{ => src}/app/login/login.component.html | 0 client/{ => src}/app/login/login.component.ts | 4 +- client/src/app/shared/index.ts | 2 + client/{ => src}/app/shared/search/index.ts | 0 .../app/shared/search/search-field.type.ts | 0 .../app/shared/search/search.component.html | 0 .../app/shared/search/search.component.ts | 2 +- .../app/shared/search/search.model.ts | 0 .../app/shared/users/auth-status.model.ts | 0 .../app/shared/users/auth.service.ts | 0 client/{ => src}/app/shared/users/index.ts | 0 .../{ => src}/app/shared/users/token.model.ts | 0 .../{ => src}/app/shared/users/user.model.ts | 0 client/src/app/videos/index.ts | 4 + client/{ => src}/app/videos/shared/index.ts | 2 +- .../app/videos/shared/loader/index.ts | 0 .../shared/loader/loader.component.html | 0 .../shared/loader/loader.component.scss | 0 .../videos/shared/loader/loader.component.ts | 4 +- .../app/videos/shared/pagination.model.ts | 0 .../app/videos/shared/sort-field.type.ts | 0 .../app/videos/shared/video.model.ts | 0 .../app/videos/shared/video.service.ts | 4 +- .../{ => src}/app/videos/video-add/index.ts | 0 .../videos/video-add/video-add.component.html | 0 .../videos/video-add/video-add.component.scss | 0 .../videos/video-add/video-add.component.ts | 10 +- .../{ => src}/app/videos/video-list/index.ts | 0 .../video-list/video-list.component.html | 0 .../video-list/video-list.component.scss | 0 .../videos/video-list/video-list.component.ts | 8 +- .../video-list/video-miniature.component.html | 0 .../video-list/video-miniature.component.scss | 0 .../video-list/video-miniature.component.ts | 8 +- .../video-list/video-sort.component.html | 0 .../videos/video-list/video-sort.component.ts | 4 +- .../{ => src}/app/videos/video-watch/index.ts | 0 .../video-watch/video-watch.component.html | 0 .../video-watch/video-watch.component.scss | 0 .../video-watch/video-watch.component.ts | 6 +- .../videos/video-watch/webtorrent.service.ts | 2 +- client/{images => src/assets}/favicon.png | Bin client/src/custom-typings.d.ts | 119 +++ client/src/index.html | 17 + client/{ => src}/main.ts | 5 + client/src/polyfills.ts | 28 + .../base.scss => src/sass/application.scss} | 0 client/src/sass/pre-customizations.scss | 1 + client/src/vendor.ts | 28 + client/stylesheets/application.scss | 5 - client/stylesheets/bootstrap-variables.scss | 875 ------------------ client/systemjs.bundle.js | 15 - client/systemjs.config.js | 48 - client/tsconfig.json | 69 +- client/webpack.config.js | 16 + server.js | 4 +- 73 files changed, 888 insertions(+), 1066 deletions(-) create mode 100644 client/.bootstraprc delete mode 100644 client/app/shared/index.ts delete mode 100644 client/app/videos/index.ts create mode 100644 client/config/helpers.js create mode 100644 client/config/webpack.common.js create mode 100644 client/config/webpack.dev.js create mode 100644 client/config/webpack.prod.js delete mode 100644 client/images/loading.gif delete mode 100644 client/index.html rename client/{ => src}/app/app.component.html (100%) rename client/{ => src}/app/app.component.scss (100%) rename client/{ => src}/app/app.component.ts (89%) rename client/{ => src}/app/friends/friend.service.ts (95%) rename client/{ => src}/app/friends/index.ts (100%) rename client/{ => src}/app/login/index.ts (100%) rename client/{ => src}/app/login/login.component.html (100%) rename client/{ => src}/app/login/login.component.ts (86%) create mode 100644 client/src/app/shared/index.ts rename client/{ => src}/app/shared/search/index.ts (100%) rename client/{ => src}/app/shared/search/search-field.type.ts (100%) rename client/{ => src}/app/shared/search/search.component.html (100%) rename client/{ => src}/app/shared/search/search.component.ts (93%) rename client/{ => src}/app/shared/search/search.model.ts (100%) rename client/{ => src}/app/shared/users/auth-status.model.ts (100%) rename client/{ => src}/app/shared/users/auth.service.ts (100%) rename client/{ => src}/app/shared/users/index.ts (100%) rename client/{ => src}/app/shared/users/token.model.ts (100%) rename client/{ => src}/app/shared/users/user.model.ts (100%) create mode 100644 client/src/app/videos/index.ts rename client/{ => src}/app/videos/shared/index.ts (80%) rename client/{ => src}/app/videos/shared/loader/index.ts (100%) rename client/{ => src}/app/videos/shared/loader/loader.component.html (100%) rename client/{ => src}/app/videos/shared/loader/loader.component.scss (100%) rename client/{ => src}/app/videos/shared/loader/loader.component.ts (51%) rename client/{ => src}/app/videos/shared/pagination.model.ts (100%) rename client/{ => src}/app/videos/shared/sort-field.type.ts (100%) rename client/{ => src}/app/videos/shared/video.model.ts (100%) rename client/{ => src}/app/videos/shared/video.service.ts (96%) rename client/{ => src}/app/videos/video-add/index.ts (100%) rename client/{ => src}/app/videos/video-add/video-add.component.html (100%) rename client/{ => src}/app/videos/video-add/video-add.component.scss (100%) rename client/{ => src}/app/videos/video-add/video-add.component.ts (83%) rename client/{ => src}/app/videos/video-list/index.ts (100%) rename client/{ => src}/app/videos/video-list/video-list.component.html (100%) rename client/{ => src}/app/videos/video-list/video-list.component.scss (100%) rename client/{ => src}/app/videos/video-list/video-list.component.ts (92%) rename client/{ => src}/app/videos/video-list/video-miniature.component.html (100%) rename client/{ => src}/app/videos/video-list/video-miniature.component.scss (100%) rename client/{ => src}/app/videos/video-list/video-miniature.component.ts (78%) rename client/{ => src}/app/videos/video-list/video-sort.component.html (100%) rename client/{ => src}/app/videos/video-list/video-sort.component.ts (85%) rename client/{ => src}/app/videos/video-watch/index.ts (100%) rename client/{ => src}/app/videos/video-watch/video-watch.component.html (100%) rename client/{ => src}/app/videos/video-watch/video-watch.component.scss (100%) rename client/{ => src}/app/videos/video-watch/video-watch.component.ts (89%) rename client/{ => src}/app/videos/video-watch/webtorrent.service.ts (88%) rename client/{images => src/assets}/favicon.png (100%) create mode 100644 client/src/custom-typings.d.ts create mode 100644 client/src/index.html rename client/{ => src}/main.ts (56%) create mode 100644 client/src/polyfills.ts rename client/{stylesheets/base.scss => src/sass/application.scss} (100%) create mode 100644 client/src/sass/pre-customizations.scss create mode 100644 client/src/vendor.ts delete mode 100644 client/stylesheets/application.scss delete mode 100644 client/stylesheets/bootstrap-variables.scss delete mode 100644 client/systemjs.bundle.js delete mode 100644 client/systemjs.config.js create mode 100644 client/webpack.config.js diff --git a/client/.bootstraprc b/client/.bootstraprc new file mode 100644 index 000000000..a4d4fe689 --- /dev/null +++ b/client/.bootstraprc @@ -0,0 +1,125 @@ +--- +# Output debugging info +# loglevel: debug + +# Major version of Bootstrap: 3 or 4 +bootstrapVersion: 3 + +# If Bootstrap version 3 is used - turn on/off custom icon font path +useCustomIconFontPath: true + +# Webpack loaders, order matters +styleLoaders: + - style + - css + - sass + +# Extract styles to stand-alone css file +# Different settings for different environments can be used, +# It depends on value of NODE_ENV environment variable +# This param can also be set in webpack config: +# entry: 'bootstrap-loader/extractStyles' +extractStyles: false +# env: +# development: +# extractStyles: false +# production: +# extractStyles: true + +# Customize Bootstrap variables that get imported before the original Bootstrap variables. +# Thus original Bootstrap variables can depend on values from here. All the bootstrap +# variables are configured with !default, and thus, if you define the variable here, then +# that value is used, rather than the default. However, many bootstrap variables are derived +# from other bootstrap variables, and thus, you want to set this up before we load the +# official bootstrap versions. +# For example, _variables.scss contains: +# $input-color: $gray !default; +# This means you can define $input-color before we load _variables.scss +preBootstrapCustomizations: ./src/sass/pre-customizations.scss + +# This gets loaded after bootstrap/variables is loaded and before bootstrap is loaded. +# A good example of this is when you want to override a bootstrap variable to be based +# on the default value of bootstrap. This is pretty specialized case. Thus, you normally +# just override bootrap variables in preBootstrapCustomizations so that derived +# variables will use your definition. +# +# For example, in _variables.scss: +# $input-height: (($font-size-base * $line-height) + ($input-padding-y * 2) + ($border-width * 2)) !default; +# This means that you could define this yourself in preBootstrapCustomizations. Or you can do +# this in bootstrapCustomizations to make the input height 10% bigger than the default calculation. +# Thus you can leverage the default calculations. +# $input-height: $input-height * 1.10; +# bootstrapCustomizations: ./app/styles/bootstrap/customizations.scss + +# Import your custom styles here. You have access to all the bootstrap variables. If you require +# your sass files separately, you will not have access to the bootstrap variables, mixins, clases, etc. +# Usually this endpoint-file contains list of @imports of your application styles. +appStyles: ./src/sass/application.scss + +### Bootstrap styles +styles: + + # Mixins + mixins: true + + # Reset and dependencies + normalize: true + print: true + glyphicons: true + + # Core CSS + scaffolding: true + type: true + code: false + grid: true + tables: true + forms: true + buttons: true + + # Components + component-animations: false + dropdowns: true + button-groups: true + input-groups: true + navs: false + navbar: false + breadcrumbs: false + pagination: true + pager: false + labels: false + badges: false + jumbotron: false + thumbnails: true + alerts: false + progress-bars: true + media: true + list-group: false + panels: false + wells: false + responsive-embed: false + close: false + + # Components w/ JavaScript + modals: false + tooltip: false + popovers: false + carousel: false + + # Utility classes + utilities: true + responsive-utilities: true + +### Bootstrap scripts +scripts: + transition: false + alert: false + button: false + carousel: false + collapse: false + dropdown: false + modal: false + tooltip: false + popover: false + scrollspy: false + tab: false + affix: false diff --git a/client/.gitignore b/client/.gitignore index 81e4a1cf7..b20541002 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -1,8 +1,2 @@ -typings -app/**/*.js -app/**/*.map -app/**/*.css -stylesheets/index.css -bundles -main.js -main.js.map +dist/ +typings/ diff --git a/client/app/shared/index.ts b/client/app/shared/index.ts deleted file mode 100644 index ad3ee0098..000000000 --- a/client/app/shared/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './search/index'; -export * from './users/index' diff --git a/client/app/videos/index.ts b/client/app/videos/index.ts deleted file mode 100644 index 1c80ac5e5..000000000 --- a/client/app/videos/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './shared/index'; -export * from './video-add/index'; -export * from './video-list/index'; -export * from './video-watch/index'; diff --git a/client/config/helpers.js b/client/config/helpers.js new file mode 100644 index 000000000..24d7dae9f --- /dev/null +++ b/client/config/helpers.js @@ -0,0 +1,17 @@ +const path = require('path') + +const ROOT = path.resolve(__dirname, '..') + +console.log('root directory:', root() + '\n') + +function hasProcessFlag (flag) { + return process.argv.join('').indexOf(flag) > -1 +} + +function root (args) { + args = Array.prototype.slice.call(arguments, 0) + return path.join.apply(path, [ROOT].concat(args)) +} + +exports.hasProcessFlag = hasProcessFlag +exports.root = root diff --git a/client/config/webpack.common.js b/client/config/webpack.common.js new file mode 100644 index 000000000..5f3f44bb1 --- /dev/null +++ b/client/config/webpack.common.js @@ -0,0 +1,261 @@ +const webpack = require('webpack') +const helpers = require('./helpers') + +/* + * Webpack Plugins + */ + +var CopyWebpackPlugin = (CopyWebpackPlugin = require('copy-webpack-plugin'), CopyWebpackPlugin.default || CopyWebpackPlugin) +const HtmlWebpackPlugin = require('html-webpack-plugin') +const ForkCheckerPlugin = require('awesome-typescript-loader').ForkCheckerPlugin + +/* + * Webpack Constants + */ +const METADATA = { + title: 'PeerTube', + baseUrl: '/' +} + +/* + * Webpack configuration + * + * See: http://webpack.github.io/docs/configuration.html#cli + */ +module.exports = { + /* + * Static metadata for index.html + * + * See: (custom attribute) + */ + metadata: METADATA, + + /* + * 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.ts', + 'vendor': './src/vendor.ts', + 'main': './src/main.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', '.scss' ], + + // Make sure root is src + root: helpers.root('src'), + + // remove other default values + modulesDirectories: [ 'node_modules' ] + + }, + + /* + * Options affecting the normal modules. + * + * See: http://webpack.github.io/docs/configuration.html#module + */ + module: { + /* + * An array of applied pre and post loaders. + * + * See: http://webpack.github.io/docs/configuration.html#module-preloaders-module-postloaders + */ + preLoaders: [ + + /* + * Tslint loader support for *.ts files + * + * See: https://github.com/wbuchwalter/tslint-loader + */ + // { test: /\.ts$/, loader: 'tslint-loader', exclude: [ helpers.root('node_modules') ] }, + + /* + * 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 + */ + { + test: /\.js$/, + loader: 'source-map-loader', + exclude: [ + // these packages have problems with their sourcemaps + helpers.root('node_modules/rxjs'), + helpers.root('node_modules/@angular') + ] + } + + ], + + /* + * An array of automatically applied loaders. + * + * IMPORTANT: The loaders here are resolved relative to the resource which they are applied to. + * This means they are not resolved relative to the configuration file. + * + * See: http://webpack.github.io/docs/configuration.html#module-loaders + */ + loaders: [ + + /* + * Typescript loader support for .ts and Angular 2 async routes via .async.ts + * + * See: https://github.com/s-panferov/awesome-typescript-loader + */ + { + test: /\.ts$/, + loader: 'awesome-typescript-loader', + exclude: [/\.(spec|e2e)\.ts$/] + }, + + /* + * Json loader support for *.json files. + * + * See: https://github.com/webpack/json-loader + */ + { + test: /\.json$/, + loader: 'json-loader' + }, + + /* + * Raw loader support for *.css files + * Returns file content as string + * + * See: https://github.com/webpack/raw-loader + */ + { + test: /\.scss$/, + exclude: /node_modules/, + loaders: [ 'raw-loader', 'sass-loader' ] + }, + + { + test: /\.(woff2?|ttf|eot|svg)$/, + loader: 'url?limit=10000&name=assets/fonts/[hash].[ext]' + }, + + /* 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') ] + } + + ] + + }, + + /* + * Add additional plugins to the compiler. + * + * See: http://webpack.github.io/docs/configuration.html#plugins + */ + plugins: [ + + /* + * 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 ForkCheckerPlugin(), + + /* + * Plugin: OccurenceOrderPlugin + * Description: Varies the distribution of the ids to get the smallest id length + * for often used ids. + * + * See: https://webpack.github.io/docs/list-of-plugins.html#occurrenceorderplugin + * See: https://github.com/webpack/docs/wiki/optimization#minimize + */ + new webpack.optimize.OccurenceOrderPlugin(true), + + /* + * 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 webpack.optimize.CommonsChunkPlugin({ + name: [ 'polyfills', 'vendor' ].reverse() + }), + + /* + * 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' + }]), + + /* + * 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', + chunksSortMode: 'dependency' + }), + + new webpack.ProvidePlugin({ + jQuery: 'jquery', + $: 'jquery', + jquery: 'jquery' + }) + + ], + + /* + * Include polyfills or mocks for various node stuff + * Description: Node configuration + * + * See: https://webpack.github.io/docs/configuration.html#node + */ + node: { + global: 'window', + crypto: 'empty', + module: false, + clearImmediate: false, + setImmediate: false + } + +} diff --git a/client/config/webpack.dev.js b/client/config/webpack.dev.js new file mode 100644 index 000000000..19768d872 --- /dev/null +++ b/client/config/webpack.dev.js @@ -0,0 +1,159 @@ +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') + +/** + * Webpack Constants + */ +const ENV = process.env.ENV = process.env.NODE_ENV = 'development' +const HMR = helpers.hasProcessFlag('hot') +const METADATA = webpackMerge(commonConfig.metadata, { + host: 'localhost', + port: 3000, + ENV: ENV, + HMR: HMR +}) + +/** + * Webpack configuration + * + * See: http://webpack.github.io/docs/configuration.html#cli + */ +module.exports = webpackMerge(commonConfig, { + /** + * Merged metadata from webpack.common.js for index.html + * + * See: (custom attribute) + */ + metadata: METADATA, + + /** + * Switch loaders to debug mode. + * + * See: http://webpack.github.io/docs/configuration.html#debug + */ + debug: true, + + /** + * 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: '[name].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', + + publicPath: '/client/' + + }, + + 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 + } + }) + ], + + /** + * Static analysis linter for TypeScript advanced options configuration + * Description: An extensible linter for the TypeScript language. + * + * See: https://github.com/wbuchwalter/tslint-loader + */ + tslint: { + emitErrors: false, + failOnHint: false, + resourcePath: 'src' + }, + + /** + * 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 + }, + outputPath: helpers.root('dist') + }, + + /* + * Include polyfills or mocks for various node stuff + * Description: Node configuration + * + * See: https://webpack.github.io/docs/configuration.html#node + */ + node: { + global: 'window', + crypto: 'empty', + process: true, + module: false, + clearImmediate: false, + setImmediate: false + } + +}) diff --git a/client/config/webpack.prod.js b/client/config/webpack.prod.js new file mode 100644 index 000000000..e69de29bb diff --git a/client/images/loading.gif b/client/images/loading.gif deleted file mode 100644 index f2a1bc0c6f545e20e631a96e8e92f9822e75d046..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 673 zcmZ?wbhEHb6krfw_{6~Q|Nnmm28Kh24mmkF0U1e2Nli^nlO|14{3qpHl$uzQnxasi zS(2fUn3Y(Olb@KPmzkHA&!G5|g@FsGT=74*pKD04vtxj(k)8oFBTz^Oh=E26FfcG1 zbL_hF&)}42ws10s6^G;;cE1^EoUR)U5A70}d2pLv!jVIT7j&Z~EblI3x0K*v_sV|m z0W=b9G$XP(CLnYCdK49;TX=SFc-G}o=oA=|U?{1O;Nu!CwW3C5Yw7*Bi4yD$3fCnb zwK+>}QdQ9sf*QnxY>*kpE+b{_Q;sJloS71)&(@kO!}mqf@1v(v;*8Y=G9S3kY~Cw# zY=t&c z;3~JK4HxB^lY(MD+sYeQ=t%XSSW;x^1M?dTvN=W^yNcAcy`HCte31C;)5xP%b~qs> zDP&4(%TBqBNGHwnryK;BdMI$fEg xd0mc!C@j^ZpLxYv4HmnPfI0THYuv<%+6iSmMn&w3dPGDfL1|=LY008wP(boU~ diff --git a/client/index.html b/client/index.html deleted file mode 100644 index 6fbcd1fa6..000000000 --- a/client/index.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - PeerTube - - - - - - - - - - - - - - - - - - - - - - - - - - - Loading... - - diff --git a/client/package.json b/client/package.json index dea673357..bfdfe5574 100644 --- a/client/package.json +++ b/client/package.json @@ -13,11 +13,11 @@ "url": "git://github.com/Chocobozzz/PeerTube.git" }, "scripts": { - "tsc": "tsc", - "tsc:w": "tsc -w", "typings": "typings", "postinstall": "typings install", - "test": "standard && tslint -c ./tslint.json angular/**/*.ts" + "test": "standard && tslint -c ./tslint.json angular/**/*.ts", + "build": "webpack --config config/webpack.dev.js --progress --profile --colors --display-error-details --display-cached", + "watch": "npm run build -- --watch" }, "license": "GPLv3", "dependencies": { @@ -30,12 +30,15 @@ "@angular/router-deprecated": "2.0.0-rc.1", "angular-pipes": "^2.0.0", "blueimp-file-upload": "^9.12.1", + "bootstrap-loader": "^1.0.8", "bootstrap-sass": "^3.3.6", + "core-js": "^2.4.0", "es6-promise": "^3.0.2", "es6-shim": "^0.35.0", "jquery": "^2.2.3", "jquery.ui.widget": "^1.10.3", "ng2-bootstrap": "^1.0.16", + "normalize.css": "^4.1.1", "reflect-metadata": "0.1.3", "rxjs": "5.0.0-beta.6", "systemjs": "0.19.27", @@ -43,12 +46,37 @@ "zone.js": "0.6.12" }, "devDependencies": { + "awesome-typescript-loader": "^0.17.0", "codelyzer": "0.0.19", + "compression-webpack-plugin": "^0.3.1", + "copy-webpack-plugin": "^3.0.1", + "css-loader": "^0.23.1", + "es6-promise-loader": "^1.0.1", + "exports-loader": "^0.6.3", + "expose-loader": "^0.7.1", + "file-loader": "^0.8.5", + "html-webpack-plugin": "^2.19.0", + "imports-loader": "^0.6.5", + "json-loader": "^0.5.4", + "node-sass": "^3.7.0", + "raw-loader": "^0.5.1", + "resolve-url-loader": "^1.4.3", + "sass-loader": "^3.2.0", + "source-map-loader": "^0.1.5", "standard": "^7.0.1", + "style-loader": "^0.13.1", "systemjs-builder": "^0.15.16", + "ts-helpers": "^1.1.1", + "ts-node": "^0.7.3", "tslint": "^3.7.4", + "tslint-loader": "^2.1.4", "typescript": "^1.8.10", - "typings": "^1.0.4" + "typings": "^1.0.4", + "url-loader": "^0.5.7", + "webpack": "^1.13.1", + "webpack-dev-server": "^1.14.1", + "webpack-md5-hash": "0.0.5", + "webpack-merge": "^0.13.0" }, "standard": { "ignore": [ diff --git a/client/app/app.component.html b/client/src/app/app.component.html similarity index 100% rename from client/app/app.component.html rename to client/src/app/app.component.html diff --git a/client/app/app.component.scss b/client/src/app/app.component.scss similarity index 100% rename from client/app/app.component.scss rename to client/src/app/app.component.scss diff --git a/client/app/app.component.ts b/client/src/app/app.component.ts similarity index 89% rename from client/app/app.component.ts rename to client/src/app/app.component.ts index 94924a47a..81b700a21 100644 --- a/client/app/app.component.ts +++ b/client/src/app/app.component.ts @@ -2,20 +2,20 @@ import { Component } from '@angular/core'; import { HTTP_PROVIDERS } from '@angular/http'; import { RouteConfig, Router, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from '@angular/router-deprecated'; -import { FriendService } from './friends/index'; -import { LoginComponent } from './login/index'; +import { FriendService } from './friends'; +import { LoginComponent } from './login'; import { AuthService, AuthStatus, Search, SearchComponent -} from './shared/index'; +} from './shared'; import { VideoAddComponent, VideoListComponent, VideoWatchComponent, VideoService -} from './videos/index'; +} from './videos'; @RouteConfig([ { @@ -43,8 +43,8 @@ import { @Component({ selector: 'my-app', - templateUrl: 'client/app/app.component.html', - styleUrls: [ 'client/app/app.component.css' ], + template: require('./app.component.html'), + styles: [ require('./app.component.scss') ], directives: [ ROUTER_DIRECTIVES, SearchComponent ], providers: [ AuthService, FriendService, HTTP_PROVIDERS, ROUTER_PROVIDERS, VideoService ] }) diff --git a/client/app/friends/friend.service.ts b/client/src/app/friends/friend.service.ts similarity index 95% rename from client/app/friends/friend.service.ts rename to client/src/app/friends/friend.service.ts index d3684f08d..a8b1a1bd3 100644 --- a/client/app/friends/friend.service.ts +++ b/client/src/app/friends/friend.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'; import { Http, Response } from '@angular/http'; import { Observable } from 'rxjs/Rx'; -import { AuthService } from '../shared/index'; +import { AuthService } from '../shared'; @Injectable() export class FriendService { diff --git a/client/app/friends/index.ts b/client/src/app/friends/index.ts similarity index 100% rename from client/app/friends/index.ts rename to client/src/app/friends/index.ts diff --git a/client/app/login/index.ts b/client/src/app/login/index.ts similarity index 100% rename from client/app/login/index.ts rename to client/src/app/login/index.ts diff --git a/client/app/login/login.component.html b/client/src/app/login/login.component.html similarity index 100% rename from client/app/login/login.component.html rename to client/src/app/login/login.component.html diff --git a/client/app/login/login.component.ts b/client/src/app/login/login.component.ts similarity index 86% rename from client/app/login/login.component.ts rename to client/src/app/login/login.component.ts index 50f598d92..9d88536ca 100644 --- a/client/app/login/login.component.ts +++ b/client/src/app/login/login.component.ts @@ -1,11 +1,11 @@ import { Component } from '@angular/core'; import { Router } from '@angular/router-deprecated'; -import { AuthService, AuthStatus, User } from '../shared/index'; +import { AuthService, AuthStatus, User } from '../shared'; @Component({ selector: 'my-login', - templateUrl: 'client/app/login/login.component.html' + template: require('./login.component.html') }) export class LoginComponent { diff --git a/client/src/app/shared/index.ts b/client/src/app/shared/index.ts new file mode 100644 index 000000000..0cab7dad0 --- /dev/null +++ b/client/src/app/shared/index.ts @@ -0,0 +1,2 @@ +export * from './search'; +export * from './users' diff --git a/client/app/shared/search/index.ts b/client/src/app/shared/search/index.ts similarity index 100% rename from client/app/shared/search/index.ts rename to client/src/app/shared/search/index.ts diff --git a/client/app/shared/search/search-field.type.ts b/client/src/app/shared/search/search-field.type.ts similarity index 100% rename from client/app/shared/search/search-field.type.ts rename to client/src/app/shared/search/search-field.type.ts diff --git a/client/app/shared/search/search.component.html b/client/src/app/shared/search/search.component.html similarity index 100% rename from client/app/shared/search/search.component.html rename to client/src/app/shared/search/search.component.html diff --git a/client/app/shared/search/search.component.ts b/client/src/app/shared/search/search.component.ts similarity index 93% rename from client/app/shared/search/search.component.ts rename to client/src/app/shared/search/search.component.ts index d541cd0d6..31f8b1535 100644 --- a/client/app/shared/search/search.component.ts +++ b/client/src/app/shared/search/search.component.ts @@ -7,7 +7,7 @@ import { SearchField } from './search-field.type'; @Component({ selector: 'my-search', - templateUrl: 'client/app/shared/search/search.component.html', + template: require('./search.component.html'), directives: [ DROPDOWN_DIRECTIVES ] }) diff --git a/client/app/shared/search/search.model.ts b/client/src/app/shared/search/search.model.ts similarity index 100% rename from client/app/shared/search/search.model.ts rename to client/src/app/shared/search/search.model.ts diff --git a/client/app/shared/users/auth-status.model.ts b/client/src/app/shared/users/auth-status.model.ts similarity index 100% rename from client/app/shared/users/auth-status.model.ts rename to client/src/app/shared/users/auth-status.model.ts diff --git a/client/app/shared/users/auth.service.ts b/client/src/app/shared/users/auth.service.ts similarity index 100% rename from client/app/shared/users/auth.service.ts rename to client/src/app/shared/users/auth.service.ts diff --git a/client/app/shared/users/index.ts b/client/src/app/shared/users/index.ts similarity index 100% rename from client/app/shared/users/index.ts rename to client/src/app/shared/users/index.ts diff --git a/client/app/shared/users/token.model.ts b/client/src/app/shared/users/token.model.ts similarity index 100% rename from client/app/shared/users/token.model.ts rename to client/src/app/shared/users/token.model.ts diff --git a/client/app/shared/users/user.model.ts b/client/src/app/shared/users/user.model.ts similarity index 100% rename from client/app/shared/users/user.model.ts rename to client/src/app/shared/users/user.model.ts diff --git a/client/src/app/videos/index.ts b/client/src/app/videos/index.ts new file mode 100644 index 000000000..9a92fa57a --- /dev/null +++ b/client/src/app/videos/index.ts @@ -0,0 +1,4 @@ +export * from './shared'; +export * from './video-add'; +export * from './video-list'; +export * from './video-watch'; diff --git a/client/app/videos/shared/index.ts b/client/src/app/videos/shared/index.ts similarity index 80% rename from client/app/videos/shared/index.ts rename to client/src/app/videos/shared/index.ts index c535c46fc..a54120f5d 100644 --- a/client/app/videos/shared/index.ts +++ b/client/src/app/videos/shared/index.ts @@ -1,4 +1,4 @@ -export * from './loader/index'; +export * from './loader'; export * from './pagination.model'; export * from './sort-field.type'; export * from './video.model'; diff --git a/client/app/videos/shared/loader/index.ts b/client/src/app/videos/shared/loader/index.ts similarity index 100% rename from client/app/videos/shared/loader/index.ts rename to client/src/app/videos/shared/loader/index.ts diff --git a/client/app/videos/shared/loader/loader.component.html b/client/src/app/videos/shared/loader/loader.component.html similarity index 100% rename from client/app/videos/shared/loader/loader.component.html rename to client/src/app/videos/shared/loader/loader.component.html diff --git a/client/app/videos/shared/loader/loader.component.scss b/client/src/app/videos/shared/loader/loader.component.scss similarity index 100% rename from client/app/videos/shared/loader/loader.component.scss rename to client/src/app/videos/shared/loader/loader.component.scss diff --git a/client/app/videos/shared/loader/loader.component.ts b/client/src/app/videos/shared/loader/loader.component.ts similarity index 51% rename from client/app/videos/shared/loader/loader.component.ts rename to client/src/app/videos/shared/loader/loader.component.ts index 666d43bc3..cdd07d1b4 100644 --- a/client/app/videos/shared/loader/loader.component.ts +++ b/client/src/app/videos/shared/loader/loader.component.ts @@ -2,8 +2,8 @@ import { Component, Input } from '@angular/core'; @Component({ selector: 'my-loader', - styleUrls: [ 'client/app/videos/shared/loader/loader.component.css' ], - templateUrl: 'client/app/videos/shared/loader/loader.component.html' + styles: [ require('./loader.component.scss') ], + template: require('./loader.component.html') }) export class LoaderComponent { diff --git a/client/app/videos/shared/pagination.model.ts b/client/src/app/videos/shared/pagination.model.ts similarity index 100% rename from client/app/videos/shared/pagination.model.ts rename to client/src/app/videos/shared/pagination.model.ts diff --git a/client/app/videos/shared/sort-field.type.ts b/client/src/app/videos/shared/sort-field.type.ts similarity index 100% rename from client/app/videos/shared/sort-field.type.ts rename to client/src/app/videos/shared/sort-field.type.ts diff --git a/client/app/videos/shared/video.model.ts b/client/src/app/videos/shared/video.model.ts similarity index 100% rename from client/app/videos/shared/video.model.ts rename to client/src/app/videos/shared/video.model.ts diff --git a/client/app/videos/shared/video.service.ts b/client/src/app/videos/shared/video.service.ts similarity index 96% rename from client/app/videos/shared/video.service.ts rename to client/src/app/videos/shared/video.service.ts index a786b2ab2..76d46cbb4 100644 --- a/client/app/videos/shared/video.service.ts +++ b/client/src/app/videos/shared/video.service.ts @@ -3,9 +3,9 @@ import { Http, Response, URLSearchParams } from '@angular/http'; import { Observable } from 'rxjs/Rx'; import { Pagination } from './pagination.model'; -import { Search } from '../../shared/index'; +import { Search } from '../../shared'; import { SortField } from './sort-field.type'; -import { AuthService } from '../../shared/index'; +import { AuthService } from '../../shared'; import { Video } from './video.model'; @Injectable() diff --git a/client/app/videos/video-add/index.ts b/client/src/app/videos/video-add/index.ts similarity index 100% rename from client/app/videos/video-add/index.ts rename to client/src/app/videos/video-add/index.ts diff --git a/client/app/videos/video-add/video-add.component.html b/client/src/app/videos/video-add/video-add.component.html similarity index 100% rename from client/app/videos/video-add/video-add.component.html rename to client/src/app/videos/video-add/video-add.component.html diff --git a/client/app/videos/video-add/video-add.component.scss b/client/src/app/videos/video-add/video-add.component.scss similarity index 100% rename from client/app/videos/video-add/video-add.component.scss rename to client/src/app/videos/video-add/video-add.component.scss diff --git a/client/app/videos/video-add/video-add.component.ts b/client/src/app/videos/video-add/video-add.component.ts similarity index 83% rename from client/app/videos/video-add/video-add.component.ts rename to client/src/app/videos/video-add/video-add.component.ts index e17b1b0f6..8df4f951b 100644 --- a/client/app/videos/video-add/video-add.component.ts +++ b/client/src/app/videos/video-add/video-add.component.ts @@ -1,5 +1,5 @@ -/// -/// +/// +/// import { Component, ElementRef, OnInit } from '@angular/core'; import { Router } from '@angular/router-deprecated'; @@ -7,12 +7,12 @@ import { Router } from '@angular/router-deprecated'; import { BytesPipe } from 'angular-pipes/src/math/bytes.pipe'; import { PROGRESSBAR_DIRECTIVES } from 'ng2-bootstrap/components/progressbar'; -import { AuthService, User } from '../../shared/index'; +import { AuthService, User } from '../../shared'; @Component({ selector: 'my-videos-add', - styleUrls: [ 'client/app/videos/video-add/video-add.component.css' ], - templateUrl: 'client/app/videos/video-add/video-add.component.html', + styles: [ require('./video-add.component.scss') ], + template: require('./video-add.component.html'), directives: [ PROGRESSBAR_DIRECTIVES ], pipes: [ BytesPipe ] }) diff --git a/client/app/videos/video-list/index.ts b/client/src/app/videos/video-list/index.ts similarity index 100% rename from client/app/videos/video-list/index.ts rename to client/src/app/videos/video-list/index.ts diff --git a/client/app/videos/video-list/video-list.component.html b/client/src/app/videos/video-list/video-list.component.html similarity index 100% rename from client/app/videos/video-list/video-list.component.html rename to client/src/app/videos/video-list/video-list.component.html diff --git a/client/app/videos/video-list/video-list.component.scss b/client/src/app/videos/video-list/video-list.component.scss similarity index 100% rename from client/app/videos/video-list/video-list.component.scss rename to client/src/app/videos/video-list/video-list.component.scss diff --git a/client/app/videos/video-list/video-list.component.ts b/client/src/app/videos/video-list/video-list.component.ts similarity index 92% rename from client/app/videos/video-list/video-list.component.ts rename to client/src/app/videos/video-list/video-list.component.ts index baca00deb..b1ce55845 100644 --- a/client/app/videos/video-list/video-list.component.ts +++ b/client/src/app/videos/video-list/video-list.component.ts @@ -9,15 +9,15 @@ import { SortField, Video, VideoService -} from '../shared/index'; -import { AuthService, Search, SearchField, User } from '../../shared/index'; +} from '../shared'; +import { AuthService, Search, SearchField, User } from '../../shared'; import { VideoMiniatureComponent } from './video-miniature.component'; import { VideoSortComponent } from './video-sort.component'; @Component({ selector: 'my-videos-list', - styleUrls: [ 'client/app/videos/video-list/video-list.component.css' ], - templateUrl: 'client/app/videos/video-list/video-list.component.html', + styles: [ require('./video-list.component.scss') ], + template: require('./video-list.component.html'), directives: [ LoaderComponent, PAGINATION_DIRECTIVES, ROUTER_DIRECTIVES, VideoMiniatureComponent, VideoSortComponent ] }) diff --git a/client/app/videos/video-list/video-miniature.component.html b/client/src/app/videos/video-list/video-miniature.component.html similarity index 100% rename from client/app/videos/video-list/video-miniature.component.html rename to client/src/app/videos/video-list/video-miniature.component.html diff --git a/client/app/videos/video-list/video-miniature.component.scss b/client/src/app/videos/video-list/video-miniature.component.scss similarity index 100% rename from client/app/videos/video-list/video-miniature.component.scss rename to client/src/app/videos/video-list/video-miniature.component.scss diff --git a/client/app/videos/video-list/video-miniature.component.ts b/client/src/app/videos/video-list/video-miniature.component.ts similarity index 78% rename from client/app/videos/video-list/video-miniature.component.ts rename to client/src/app/videos/video-list/video-miniature.component.ts index 11b828ca6..639339b44 100644 --- a/client/app/videos/video-list/video-miniature.component.ts +++ b/client/src/app/videos/video-list/video-miniature.component.ts @@ -2,13 +2,13 @@ import { DatePipe } from '@angular/common'; import { Component, Input, Output, EventEmitter } from '@angular/core'; import { ROUTER_DIRECTIVES } from '@angular/router-deprecated'; -import { Video, VideoService } from '../shared/index'; -import { User } from '../../shared/index'; +import { Video, VideoService } from '../shared'; +import { User } from '../../shared'; @Component({ selector: 'my-video-miniature', - styleUrls: [ 'client/app/videos/video-list/video-miniature.component.css' ], - templateUrl: 'client/app/videos/video-list/video-miniature.component.html', + styles: [ require('./video-miniature.component.scss') ], + template: require('./video-miniature.component.html'), directives: [ ROUTER_DIRECTIVES ], pipes: [ DatePipe ] }) diff --git a/client/app/videos/video-list/video-sort.component.html b/client/src/app/videos/video-list/video-sort.component.html similarity index 100% rename from client/app/videos/video-list/video-sort.component.html rename to client/src/app/videos/video-list/video-sort.component.html diff --git a/client/app/videos/video-list/video-sort.component.ts b/client/src/app/videos/video-list/video-sort.component.ts similarity index 85% rename from client/app/videos/video-list/video-sort.component.ts rename to client/src/app/videos/video-list/video-sort.component.ts index 2cb810ff5..0d76b54b7 100644 --- a/client/app/videos/video-list/video-sort.component.ts +++ b/client/src/app/videos/video-list/video-sort.component.ts @@ -1,10 +1,10 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; -import { SortField } from '../shared/index'; +import { SortField } from '../shared'; @Component({ selector: 'my-video-sort', - templateUrl: 'client/app/videos/video-list/video-sort.component.html' + template: require('./video-sort.component.html') }) export class VideoSortComponent { diff --git a/client/app/videos/video-watch/index.ts b/client/src/app/videos/video-watch/index.ts similarity index 100% rename from client/app/videos/video-watch/index.ts rename to client/src/app/videos/video-watch/index.ts diff --git a/client/app/videos/video-watch/video-watch.component.html b/client/src/app/videos/video-watch/video-watch.component.html similarity index 100% rename from client/app/videos/video-watch/video-watch.component.html rename to client/src/app/videos/video-watch/video-watch.component.html diff --git a/client/app/videos/video-watch/video-watch.component.scss b/client/src/app/videos/video-watch/video-watch.component.scss similarity index 100% rename from client/app/videos/video-watch/video-watch.component.scss rename to client/src/app/videos/video-watch/video-watch.component.scss diff --git a/client/app/videos/video-watch/video-watch.component.ts b/client/src/app/videos/video-watch/video-watch.component.ts similarity index 89% rename from client/app/videos/video-watch/video-watch.component.ts rename to client/src/app/videos/video-watch/video-watch.component.ts index 71fb4f634..db82283b4 100644 --- a/client/app/videos/video-watch/video-watch.component.ts +++ b/client/src/app/videos/video-watch/video-watch.component.ts @@ -3,13 +3,13 @@ import { CanDeactivate, ComponentInstruction, RouteParams } from '@angular/route import { BytesPipe } from 'angular-pipes/src/math/bytes.pipe'; -import { LoaderComponent, Video, VideoService } from '../shared/index'; +import { LoaderComponent, Video, VideoService } from '../shared'; import { WebTorrentService } from './webtorrent.service'; @Component({ selector: 'my-video-watch', - templateUrl: 'client/app/videos/video-watch/video-watch.component.html', - styleUrls: [ 'client/app/videos/video-watch/video-watch.component.css' ], + template: require('./video-watch.component.html'), + styles: [ require('./video-watch.component.scss') ], providers: [ WebTorrentService ], directives: [ LoaderComponent ], pipes: [ BytesPipe ] diff --git a/client/app/videos/video-watch/webtorrent.service.ts b/client/src/app/videos/video-watch/webtorrent.service.ts similarity index 88% rename from client/app/videos/video-watch/webtorrent.service.ts rename to client/src/app/videos/video-watch/webtorrent.service.ts index 0c73ab4f4..bf38b5aaa 100644 --- a/client/app/videos/video-watch/webtorrent.service.ts +++ b/client/src/app/videos/video-watch/webtorrent.service.ts @@ -1,6 +1,6 @@ // Don't use webtorrent typings for now // It misses some little things I'll fix later -// +// import { Injectable } from '@angular/core'; diff --git a/client/images/favicon.png b/client/src/assets/favicon.png similarity index 100% rename from client/images/favicon.png rename to client/src/assets/favicon.png diff --git a/client/src/custom-typings.d.ts b/client/src/custom-typings.d.ts new file mode 100644 index 000000000..14c7d8ade --- /dev/null +++ b/client/src/custom-typings.d.ts @@ -0,0 +1,119 @@ +/* + * 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 typings + +typings install node --save + + * If you can't find the type definition in the registry we can make an ambient definition in + * this file for now. For example + +declare module "my-module" { + export function doesSomething(value: string): string; +} + + * + * If you're prototying and you will fix the types later you can also declare it as type any + * + +declare var assert: any; + + * + * If you're importing a module that uses Node.js modules which are CommonJS you need to import as + * + +import * as _ from 'lodash' + + * You can include your type definitions in this file until you create one for the typings registry + * see https://github.com/typings/registry + * + */ + + +// Extra variables that live on Global that will be replaced by webpack DefinePlugin +declare var ENV: string; +declare var HMR: boolean; +interface GlobalEnvironment { + ENV; + HMR; +} + +interface WebpackModule { + hot: { + data?: any, + idle: any, + accept(dependencies?: string | string[], callback?: (updatedDependencies?: any) => void): void; + decline(dependencies?: 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 { + context(file: string, flag?: boolean, exp?: RegExp): any; +} + + +interface ErrorStackTraceLimit { + stackTraceLimit: number; +} + + + +// Extend typings +interface NodeRequire extends WebpackRequire {} +interface ErrorConstructor extends ErrorStackTraceLimit {} +interface NodeModule extends WebpackModule {} +interface Global extends GlobalEnvironment {} + + +declare namespace Reflect { + function decorate(decorators: ClassDecorator[], target: Function): Function; + function decorate( + decorators: (PropertyDecorator | MethodDecorator)[], + target: Object, + targetKey: string | symbol, + descriptor?: PropertyDescriptor): PropertyDescriptor; + + function metadata(metadataKey: any, metadataValue: any): { + (target: Function): void; + (target: Object, propertyKey: string | symbol): void; + }; + function defineMetadata(metadataKey: any, metadataValue: any, target: Object): void; + function defineMetadata( + metadataKey: any, + metadataValue: any, + target: Object, + targetKey: string | symbol): void; + function hasMetadata(metadataKey: any, target: Object): boolean; + function hasMetadata(metadataKey: any, target: Object, targetKey: string | symbol): boolean; + function hasOwnMetadata(metadataKey: any, target: Object): boolean; + function hasOwnMetadata(metadataKey: any, target: Object, targetKey: string | symbol): boolean; + function getMetadata(metadataKey: any, target: Object): any; + function getMetadata(metadataKey: any, target: Object, targetKey: string | symbol): any; + function getOwnMetadata(metadataKey: any, target: Object): any; + function getOwnMetadata(metadataKey: any, target: Object, targetKey: string | symbol): any; + function getMetadataKeys(target: Object): any[]; + function getMetadataKeys(target: Object, targetKey: string | symbol): any[]; + function getOwnMetadataKeys(target: Object): any[]; + function getOwnMetadataKeys(target: Object, targetKey: string | symbol): any[]; + function deleteMetadata(metadataKey: any, target: Object): boolean; + function deleteMetadata(metadataKey: any, target: Object, targetKey: string | symbol): boolean; +} + + +// We need this here since there is a problem with Zone.js typings +interface Thenable { + then( + onFulfilled?: (value: T) => U | Thenable, + onRejected?: (error: any) => U | Thenable): Thenable; + then( + onFulfilled?: (value: T) => U | Thenable, + onRejected?: (error: any) => void): Thenable; + catch(onRejected?: (error: any) => U | Thenable): Thenable; +} diff --git a/client/src/index.html b/client/src/index.html new file mode 100644 index 000000000..83f4cc8f0 --- /dev/null +++ b/client/src/index.html @@ -0,0 +1,17 @@ + + + + + PeerTube + + + + + + + + + + Loading... + + diff --git a/client/main.ts b/client/src/main.ts similarity index 56% rename from client/main.ts rename to client/src/main.ts index 5e2ea0de0..76b3f498a 100644 --- a/client/main.ts +++ b/client/src/main.ts @@ -1,5 +1,10 @@ +import { enableProdMode } from '@angular/core'; import { bootstrap } from '@angular/platform-browser-dynamic'; import { AppComponent } from './app/app.component'; +if (process.env.ENV === 'production') { + enableProdMode(); +} + bootstrap(AppComponent); diff --git a/client/src/polyfills.ts b/client/src/polyfills.ts new file mode 100644 index 000000000..3395eed76 --- /dev/null +++ b/client/src/polyfills.ts @@ -0,0 +1,28 @@ +// Polyfills +// (these modules are what are in 'angular2/bundles/angular2-polyfills' so don't use that here) + +// import 'ie-shim'; // Internet Explorer +// import 'es6-shim'; +// import 'es6-promise'; +// import 'es7-reflect-metadata'; + +// Prefer CoreJS over the polyfills above +import 'core-js/es6'; +import 'core-js/es7/reflect'; +require('zone.js/dist/zone'); + +// Typescript emit helpers polyfill +import 'ts-helpers'; + +if ('production' === ENV) { + // Production + + +} else { + // Development + + Error.stackTraceLimit = Infinity; + + require('zone.js/dist/long-stack-trace-zone'); + +} diff --git a/client/stylesheets/base.scss b/client/src/sass/application.scss similarity index 100% rename from client/stylesheets/base.scss rename to client/src/sass/application.scss diff --git a/client/src/sass/pre-customizations.scss b/client/src/sass/pre-customizations.scss new file mode 100644 index 000000000..e92004128 --- /dev/null +++ b/client/src/sass/pre-customizations.scss @@ -0,0 +1 @@ +// $icon-font-path: "/assets/fonts/"; diff --git a/client/src/vendor.ts b/client/src/vendor.ts new file mode 100644 index 000000000..0f82c59a4 --- /dev/null +++ b/client/src/vendor.ts @@ -0,0 +1,28 @@ +// For vendors for example jQuery, Lodash, angular2-jwt just import them here unless you plan on +// chunking vendors files for async loading. You would need to import the async loaded vendors +// at the entry point of the async loaded file. Also see custom-typings.d.ts as you also need to +// run `typings install x` where `x` is your module + +// Angular 2 +import '@angular/platform-browser'; +import '@angular/platform-browser-dynamic'; +import '@angular/core'; +import '@angular/common'; +import '@angular/http'; +import '@angular/router-deprecated'; + +// RxJS +import 'rxjs/add/operator/map'; +import 'rxjs/add/operator/mergeMap'; + +import 'jquery'; +import 'bootstrap-loader'; + +if ('production' === ENV) { + // Production + + +} else { + // Development + +} diff --git a/client/stylesheets/application.scss b/client/stylesheets/application.scss deleted file mode 100644 index 98c1e37ad..000000000 --- a/client/stylesheets/application.scss +++ /dev/null @@ -1,5 +0,0 @@ -$icon-font-path: "/client/node_modules/bootstrap-sass/assets/fonts/bootstrap/"; - -@import "bootstrap-variables"; -@import "_bootstrap"; -@import "base.scss"; diff --git a/client/stylesheets/bootstrap-variables.scss b/client/stylesheets/bootstrap-variables.scss deleted file mode 100644 index a2472f357..000000000 --- a/client/stylesheets/bootstrap-variables.scss +++ /dev/null @@ -1,875 +0,0 @@ -// Override Bootstrap variables here (defaults from bootstrap-sass v3.3.6): - -// -// Variables -// -------------------------------------------------- - - -//== Colors -// -//## Gray and brand colors for use across Bootstrap. - -// $gray-base: #000 -// $gray-darker: lighten($gray-base, 13.5%) // #222 -// $gray-dark: lighten($gray-base, 20%) // #333 -// $gray: lighten($gray-base, 33.5%) // #555 -// $gray-light: lighten($gray-base, 46.7%) // #777 -// $gray-lighter: lighten($gray-base, 93.5%) // #eee - -// $brand-primary: darken(#428bca, 6.5%) // #337ab7 -// $brand-success: #5cb85c -// $brand-info: #5bc0de -// $brand-warning: #f0ad4e -// $brand-danger: #d9534f - - -//== Scaffolding -// -//## Settings for some of the most global styles. - -//** Background color for ``. -// $body-bg: #fff -//** Global text color on ``. -// $text-color: $gray-dark - -//** Global textual link color. -// $link-color: $brand-primary -//** Link hover color set via `darken()` function. -// $link-hover-color: darken($link-color, 15%) -//** Link hover decoration. -// $link-hover-decoration: underline - - -//== Typography -// -//## Font, line-height, and color for body text, headings, and more. - -// $font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif -// $font-family-serif: Georgia, "Times New Roman", Times, serif -//** Default monospace fonts for ``, ``, and `
`.
-// $font-family-monospace:   Menlo, Monaco, Consolas, "Courier New", monospace
-// $font-family-base:        $font-family-sans-serif
-
-// $font-size-base:          14px
-// $font-size-large:         ceil(($font-size-base * 1.25)) // ~18px
-// $font-size-small:         ceil(($font-size-base * 0.85)) // ~12px
-
-// $font-size-h1:            floor(($font-size-base * 2.6)) // ~36px
-// $font-size-h2:            floor(($font-size-base * 2.15)) // ~30px
-// $font-size-h3:            ceil(($font-size-base * 1.7)) // ~24px
-// $font-size-h4:            ceil(($font-size-base * 1.25)) // ~18px
-// $font-size-h5:            $font-size-base
-// $font-size-h6:            ceil(($font-size-base * 0.85)) // ~12px
-
-//** Unit-less `line-height` for use in components like buttons.
-// $line-height-base:        1.428571429 // 20/14
-//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
-// $line-height-computed:    floor(($font-size-base * $line-height-base)) // ~20px
-
-//** By default, this inherits from the ``.
-// $headings-font-family:    inherit
-// $headings-font-weight:    500
-// $headings-line-height:    1.1
-// $headings-color:          inherit
-
-
-//== Iconography
-//
-//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
-
-//** Load fonts from this directory.
-
-// [converter] If $bootstrap-sass-asset-helper if used, provide path relative to the assets load path.
-// [converter] This is because some asset helpers, such as Sprockets, do not work with file-relative paths.
-// $icon-font-path: if($bootstrap-sass-asset-helper, "bootstrap/", "../fonts/bootstrap/")
-
-//** File name for all font files.
-// $icon-font-name:          "glyphicons-halflings-regular"
-//** Element ID within SVG icon file.
-// $icon-font-svg-id:        "glyphicons_halflingsregular"
-
-
-//== Components
-//
-//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
-
-// $padding-base-vertical:     6px
-// $padding-base-horizontal:   12px
-
-// $padding-large-vertical:    10px
-// $padding-large-horizontal:  16px
-
-// $padding-small-vertical:    5px
-// $padding-small-horizontal:  10px
-
-// $padding-xs-vertical:       1px
-// $padding-xs-horizontal:     5px
-
-// $line-height-large:         1.3333333 // extra decimals for Win 8.1 Chrome
-// $line-height-small:         1.5
-
-// $border-radius-base:        0;
-// $border-radius-large:       0;
-// $border-radius-small:       0;
-
-//** Global color for active items (e.g., navs or dropdowns).
-// $component-active-color:    #fff
-//** Global background color for active items (e.g., navs or dropdowns).
-// $component-active-bg:       $brand-primary
-
-//** Width of the `border` for generating carets that indicator dropdowns.
-// $caret-width-base:          4px
-//** Carets increase slightly in size for larger components.
-// $caret-width-large:         5px
-
-
-//== Tables
-//
-//## Customizes the `.table` component with basic values, each used across all table variations.
-
-//** Padding for ``s and ``s.
-// $table-cell-padding:            8px
-//** Padding for cells in `.table-condensed`.
-// $table-condensed-cell-padding:  5px
-
-//** Default background color used for all tables.
-// $table-bg:                      transparent
-//** Background color used for `.table-striped`.
-// $table-bg-accent:               #f9f9f9
-//** Background color used for `.table-hover`.
-// $table-bg-hover:                #f5f5f5
-// $table-bg-active:               $table-bg-hover
-
-//** Border color for table and cell borders.
-// $table-border-color:            #ddd
-
-
-//== Buttons
-//
-//## For each of Bootstrap's buttons, define text, background and border color.
-
-// $btn-font-weight:                normal
-
-// $btn-default-color:              #333
-// $btn-default-bg:                 #fff
-// $btn-default-border:             #ccc
-
-// $btn-primary-color:              #fff
-// $btn-primary-bg:                 $brand-primary
-// $btn-primary-border:             darken($btn-primary-bg, 5%)
-
-// $btn-success-color:              #fff
-// $btn-success-bg:                 $brand-success
-// $btn-success-border:             darken($btn-success-bg, 5%)
-
-// $btn-info-color:                 #fff
-// $btn-info-bg:                    $brand-info
-// $btn-info-border:                darken($btn-info-bg, 5%)
-
-// $btn-warning-color:              #fff
-// $btn-warning-bg:                 $brand-warning
-// $btn-warning-border:             darken($btn-warning-bg, 5%)
-
-// $btn-danger-color:               #fff
-// $btn-danger-bg:                  $brand-danger
-// $btn-danger-border:              darken($btn-danger-bg, 5%)
-
-// $btn-link-disabled-color:        $gray-light
-
-// Allows for customizing button radius independently from global border radius
-// $btn-border-radius-base:         $border-radius-base
-// $btn-border-radius-large:        $border-radius-large
-// $btn-border-radius-small:        $border-radius-small
-
-
-//== Forms
-//
-//##
-
-//** `` background color
-// $input-bg:                       #fff
-//** `` background color
-// $input-bg-disabled:              $gray-lighter
-
-//** Text color for ``s
-// $input-color:                    $gray
-//** `` border color
-// $input-border:                   #ccc
-
-// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4
-//** Default `.form-control` border radius
-// This has no effect on ``s in CSS.
-// $input-border-radius:            $border-radius-base
-//** Large `.form-control` border radius
-// $input-border-radius-large:      $border-radius-large
-//** Small `.form-control` border radius
-// $input-border-radius-small:      $border-radius-small
-
-//** Border color for inputs on focus
-// $input-border-focus:             #66afe9
-
-//** Placeholder text color
-// $input-color-placeholder:        #999
-
-//** Default `.form-control` height
-// $input-height-base:              ($line-height-computed + ($padding-base-vertical * 2) + 2)
-//** Large `.form-control` height
-// $input-height-large:             (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2)
-//** Small `.form-control` height
-// $input-height-small:             (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2)
-
-//** `.form-group` margin
-// $form-group-margin-bottom:       15px
-
-// $legend-color:                   $gray-dark
-// $legend-border-color:            #e5e5e5
-
-//** Background color for textual input addons
-// $input-group-addon-bg:           $gray-lighter
-//** Border color for textual input addons
-// $input-group-addon-border-color: $input-border
-
-//** Disabled cursor for form controls and buttons.
-// $cursor-disabled:                not-allowed
-
-
-//== Dropdowns
-//
-//## Dropdown menu container and contents.
-
-//** Background for the dropdown menu.
-// $dropdown-bg:                    #fff
-//** Dropdown menu `border-color`.
-// $dropdown-border:                rgba(0,0,0,.15)
-//** Dropdown menu `border-color` **for IE8**.
-// $dropdown-fallback-border:       #ccc
-//** Divider color for between dropdown items.
-// $dropdown-divider-bg:            #e5e5e5
-
-//** Dropdown link text color.
-// $dropdown-link-color:            $gray-dark
-//** Hover color for dropdown links.
-// $dropdown-link-hover-color:      darken($gray-dark, 5%)
-//** Hover background for dropdown links.
-// $dropdown-link-hover-bg:         #f5f5f5
-
-//** Active dropdown menu item text color.
-// $dropdown-link-active-color:     $component-active-color
-//** Active dropdown menu item background color.
-// $dropdown-link-active-bg:        $component-active-bg
-
-//** Disabled dropdown menu item background color.
-// $dropdown-link-disabled-color:   $gray-light
-
-//** Text color for headers within dropdown menus.
-// $dropdown-header-color:          $gray-light
-
-//** Deprecated `$dropdown-caret-color` as of v3.1.0
-// $dropdown-caret-color:           #000
-
-
-//-- Z-index master list
-//
-// Warning: Avoid customizing these values. They're used for a bird's eye view
-// of components dependent on the z-axis and are designed to all work together.
-//
-// Note: These variables are not generated into the Customizer.
-
-// $zindex-navbar:            1000
-// $zindex-dropdown:          1000
-// $zindex-popover:           1060
-// $zindex-tooltip:           1070
-// $zindex-navbar-fixed:      1030
-// $zindex-modal-background:  1040
-// $zindex-modal:             1050
-
-
-//== Media queries breakpoints
-//
-//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
-
-// Extra small screen / phone
-//** Deprecated `$screen-xs` as of v3.0.1
-// $screen-xs:                  480px
-//** Deprecated `$screen-xs-min` as of v3.2.0
-// $screen-xs-min:              $screen-xs
-//** Deprecated `$screen-phone` as of v3.0.1
-// $screen-phone:               $screen-xs-min
-
-// Small screen / tablet
-//** Deprecated `$screen-sm` as of v3.0.1
-// $screen-sm:                  768px
-// $screen-sm-min:              $screen-sm
-//** Deprecated `$screen-tablet` as of v3.0.1
-// $screen-tablet:              $screen-sm-min
-
-// Medium screen / desktop
-//** Deprecated `$screen-md` as of v3.0.1
-// $screen-md:                  992px
-// $screen-md-min:              $screen-md
-//** Deprecated `$screen-desktop` as of v3.0.1
-// $screen-desktop:             $screen-md-min
-
-// Large screen / wide desktop
-//** Deprecated `$screen-lg` as of v3.0.1
-// $screen-lg:                  1200px
-// $screen-lg-min:              $screen-lg
-//** Deprecated `$screen-lg-desktop` as of v3.0.1
-// $screen-lg-desktop:          $screen-lg-min
-
-// So media queries don't overlap when required, provide a maximum
-// $screen-xs-max:              ($screen-sm-min - 1)
-// $screen-sm-max:              ($screen-md-min - 1)
-// $screen-md-max:              ($screen-lg-min - 1)
-
-
-//== Grid system
-//
-//## Define your custom responsive grid.
-
-//** Number of columns in the grid.
-// $grid-columns:              12
-//** Padding between columns. Gets divided in half for the left and right.
-// $grid-gutter-width:         30px
-// Navbar collapse
-//** Point at which the navbar becomes uncollapsed.
-// $grid-float-breakpoint:     $screen-sm-min
-//** Point at which the navbar begins collapsing.
-// $grid-float-breakpoint-max: ($grid-float-breakpoint - 1)
-
-
-//== Container sizes
-//
-//## Define the maximum width of `.container` for different screen sizes.
-
-// Small screen / tablet
-// $container-tablet:             (720px + $grid-gutter-width)
-//** For `$screen-sm-min` and up.
-// $container-sm:                 $container-tablet
-
-// Medium screen / desktop
-// $container-desktop:            (940px + $grid-gutter-width)
-//** For `$screen-md-min` and up.
-// $container-md:                 $container-desktop
-
-// Large screen / wide desktop
-// $container-large-desktop:      (1140px + $grid-gutter-width)
-//** For `$screen-lg-min` and up.
-// $container-lg:                 $container-large-desktop
-
-
-//== Navbar
-//
-//##
-
-// Basics of a navbar
-// $navbar-height:                    50px
-// $navbar-margin-bottom:             $line-height-computed
-// $navbar-border-radius:             $border-radius-base
-// $navbar-padding-horizontal:        floor(($grid-gutter-width / 2))
-// $navbar-padding-vertical:          (($navbar-height - $line-height-computed) / 2)
-// $navbar-collapse-max-height:       340px
-
-// $navbar-default-color:             #777
-// $navbar-default-bg:                #f8f8f8
-// $navbar-default-border:            darken($navbar-default-bg, 6.5%)
-
-// Navbar links
-// $navbar-default-link-color:                #777
-// $navbar-default-link-hover-color:          #333
-// $navbar-default-link-hover-bg:             transparent
-// $navbar-default-link-active-color:         #555
-// $navbar-default-link-active-bg:            darken($navbar-default-bg, 6.5%)
-// $navbar-default-link-disabled-color:       #ccc
-// $navbar-default-link-disabled-bg:          transparent
-
-// Navbar brand label
-// $navbar-default-brand-color:               $navbar-default-link-color
-// $navbar-default-brand-hover-color:         darken($navbar-default-brand-color, 10%)
-// $navbar-default-brand-hover-bg:            transparent
-
-// Navbar toggle
-// $navbar-default-toggle-hover-bg:           #ddd
-// $navbar-default-toggle-icon-bar-bg:        #888
-// $navbar-default-toggle-border-color:       #ddd
-
-
-//=== Inverted navbar
-// Reset inverted navbar basics
-// $navbar-inverse-color:                      lighten($gray-light, 15%)
-// $navbar-inverse-bg:                         #222
-// $navbar-inverse-border:                     darken($navbar-inverse-bg, 10%)
-
-// Inverted navbar links
-// $navbar-inverse-link-color:                 lighten($gray-light, 15%)
-// $navbar-inverse-link-hover-color:           #fff
-// $navbar-inverse-link-hover-bg:              transparent
-// $navbar-inverse-link-active-color:          $navbar-inverse-link-hover-color
-// $navbar-inverse-link-active-bg:             darken($navbar-inverse-bg, 10%)
-// $navbar-inverse-link-disabled-color:        #444
-// $navbar-inverse-link-disabled-bg:           transparent
-
-// Inverted navbar brand label
-// $navbar-inverse-brand-color:                $navbar-inverse-link-color
-// $navbar-inverse-brand-hover-color:          #fff
-// $navbar-inverse-brand-hover-bg:             transparent
-
-// Inverted navbar toggle
-// $navbar-inverse-toggle-hover-bg:            #333
-// $navbar-inverse-toggle-icon-bar-bg:         #fff
-// $navbar-inverse-toggle-border-color:        #333
-
-
-//== Navs
-//
-//##
-
-//=== Shared nav styles
-// $nav-link-padding:                          10px 15px
-// $nav-link-hover-bg:                         $gray-lighter
-
-// $nav-disabled-link-color:                   $gray-light
-// $nav-disabled-link-hover-color:             $gray-light
-
-//== Tabs
-// $nav-tabs-border-color:                     #ddd
-
-// $nav-tabs-link-hover-border-color:          $gray-lighter
-
-// $nav-tabs-active-link-hover-bg:             $body-bg
-// $nav-tabs-active-link-hover-color:          $gray
-// $nav-tabs-active-link-hover-border-color:   #ddd
-
-// $nav-tabs-justified-link-border-color:            #ddd
-// $nav-tabs-justified-active-link-border-color:     $body-bg
-
-//== Pills
-// $nav-pills-border-radius:                   $border-radius-base
-// $nav-pills-active-link-hover-bg:            $component-active-bg
-// $nav-pills-active-link-hover-color:         $component-active-color
-
-
-//== Pagination
-//
-//##
-
-// $pagination-color:                     $link-color
-// $pagination-bg:                        #fff
-// $pagination-border:                    #ddd
-
-// $pagination-hover-color:               $link-hover-color
-// $pagination-hover-bg:                  $gray-lighter
-// $pagination-hover-border:              #ddd
-
-// $pagination-active-color:              #fff
-// $pagination-active-bg:                 $brand-primary
-// $pagination-active-border:             $brand-primary
-
-// $pagination-disabled-color:            $gray-light
-// $pagination-disabled-bg:               #fff
-// $pagination-disabled-border:           #ddd
-
-
-//== Pager
-//
-//##
-
-// $pager-bg:                             $pagination-bg
-// $pager-border:                         $pagination-border
-// $pager-border-radius:                  15px
-
-// $pager-hover-bg:                       $pagination-hover-bg
-
-// $pager-active-bg:                      $pagination-active-bg
-// $pager-active-color:                   $pagination-active-color
-
-// $pager-disabled-color:                 $pagination-disabled-color
-
-
-//== Jumbotron
-//
-//##
-
-// $jumbotron-padding:              30px
-// $jumbotron-color:                inherit
-// $jumbotron-bg:                   $gray-lighter
-// $jumbotron-heading-color:        inherit
-// $jumbotron-font-size:            ceil(($font-size-base * 1.5))
-// $jumbotron-heading-font-size:    ceil(($font-size-base * 4.5))
-
-
-//== Form states and alerts
-//
-//## Define colors for form feedback states and, by default, alerts.
-
-// $state-success-text:             #3c763d
-// $state-success-bg:               #dff0d8
-// $state-success-border:           darken(adjust-hue($state-success-bg, -10), 5%)
-
-// $state-info-text:                #31708f
-// $state-info-bg:                  #d9edf7
-// $state-info-border:              darken(adjust-hue($state-info-bg, -10), 7%)
-
-// $state-warning-text:             #8a6d3b
-// $state-warning-bg:               #fcf8e3
-// $state-warning-border:           darken(adjust-hue($state-warning-bg, -10), 5%)
-
-// $state-danger-text:              #a94442
-// $state-danger-bg:                #f2dede
-// $state-danger-border:            darken(adjust-hue($state-danger-bg, -10), 5%)
-
-
-//== Tooltips
-//
-//##
-
-//** Tooltip max width
-// $tooltip-max-width:           200px
-//** Tooltip text color
-// $tooltip-color:               #fff
-//** Tooltip background color
-// $tooltip-bg:                  #000
-// $tooltip-opacity:             .9
-
-//** Tooltip arrow width
-// $tooltip-arrow-width:         5px
-//** Tooltip arrow color
-// $tooltip-arrow-color:         $tooltip-bg
-
-
-//== Popovers
-//
-//##
-
-//** Popover body background color
-// $popover-bg:                          #fff
-//** Popover maximum width
-// $popover-max-width:                   276px
-//** Popover border color
-// $popover-border-color:                rgba(0,0,0,.2)
-//** Popover fallback border color
-// $popover-fallback-border-color:       #ccc
-
-//** Popover title background color
-// $popover-title-bg:                    darken($popover-bg, 3%)
-
-//** Popover arrow width
-// $popover-arrow-width:                 10px
-//** Popover arrow color
-// $popover-arrow-color:                 $popover-bg
-
-//** Popover outer arrow width
-// $popover-arrow-outer-width:           ($popover-arrow-width + 1)
-//** Popover outer arrow color
-// $popover-arrow-outer-color:           fade_in($popover-border-color, 0.05)
-//** Popover outer arrow fallback color
-// $popover-arrow-outer-fallback-color:  darken($popover-fallback-border-color, 20%)
-
-
-//== Labels
-//
-//##
-
-//** Default label background color
-// $label-default-bg:            $gray-light
-//** Primary label background color
-// $label-primary-bg:            $brand-primary
-//** Success label background color
-// $label-success-bg:            $brand-success
-//** Info label background color
-// $label-info-bg:               $brand-info
-//** Warning label background color
-// $label-warning-bg:            $brand-warning
-//** Danger label background color
-// $label-danger-bg:             $brand-danger
-
-//** Default label text color
-// $label-color:                 #fff
-//** Default text color of a linked label
-// $label-link-hover-color:      #fff
-
-
-//== Modals
-//
-//##
-
-//** Padding applied to the modal body
-// $modal-inner-padding:         15px
-
-//** Padding applied to the modal title
-// $modal-title-padding:         15px
-//** Modal title line-height
-// $modal-title-line-height:     $line-height-base
-
-//** Background color of modal content area
-// $modal-content-bg:                             #fff
-//** Modal content border color
-// $modal-content-border-color:                   rgba(0,0,0,.2)
-//** Modal content border color **for IE8**
-// $modal-content-fallback-border-color:          #999
-
-//** Modal backdrop background color
-// $modal-backdrop-bg:           #000
-//** Modal backdrop opacity
-// $modal-backdrop-opacity:      .5
-//** Modal header border color
-// $modal-header-border-color:   #e5e5e5
-//** Modal footer border color
-// $modal-footer-border-color:   $modal-header-border-color
-
-// $modal-lg:                    900px
-// $modal-md:                    600px
-// $modal-sm:                    300px
-
-
-//== Alerts
-//
-//## Define alert colors, border radius, and padding.
-
-// $alert-padding:               15px
-// $alert-border-radius:         $border-radius-base
-// $alert-link-font-weight:      bold
-
-// $alert-success-bg:            $state-success-bg
-// $alert-success-text:          $state-success-text
-// $alert-success-border:        $state-success-border
-
-// $alert-info-bg:               $state-info-bg
-// $alert-info-text:             $state-info-text
-// $alert-info-border:           $state-info-border
-
-// $alert-warning-bg:            $state-warning-bg
-// $alert-warning-text:          $state-warning-text
-// $alert-warning-border:        $state-warning-border
-
-// $alert-danger-bg:             $state-danger-bg
-// $alert-danger-text:           $state-danger-text
-// $alert-danger-border:         $state-danger-border
-
-
-//== Progress bars
-//
-//##
-
-//** Background color of the whole progress component
-// $progress-bg:                 #f5f5f5
-//** Progress bar text color
-// $progress-bar-color:          #fff
-//** Variable for setting rounded corners on progress bar.
-// $progress-border-radius:      $border-radius-base
-
-//** Default progress bar color
-// $progress-bar-bg:             $brand-primary
-//** Success progress bar color
-// $progress-bar-success-bg:     $brand-success
-//** Warning progress bar color
-// $progress-bar-warning-bg:     $brand-warning
-//** Danger progress bar color
-// $progress-bar-danger-bg:      $brand-danger
-//** Info progress bar color
-// $progress-bar-info-bg:        $brand-info
-
-
-//== List group
-//
-//##
-
-//** Background color on `.list-group-item`
-// $list-group-bg:                 #fff
-//** `.list-group-item` border color
-// $list-group-border:             #ddd
-//** List group border radius
-// $list-group-border-radius:      $border-radius-base
-
-//** Background color of single list items on hover
-// $list-group-hover-bg:           #f5f5f5
-//** Text color of active list items
-// $list-group-active-color:       $component-active-color
-//** Background color of active list items
-// $list-group-active-bg:          $component-active-bg
-//** Border color of active list elements
-// $list-group-active-border:      $list-group-active-bg
-//** Text color for content within active list items
-// $list-group-active-text-color:  lighten($list-group-active-bg, 40%)
-
-//** Text color of disabled list items
-// $list-group-disabled-color:      $gray-light
-//** Background color of disabled list items
-// $list-group-disabled-bg:         $gray-lighter
-//** Text color for content within disabled list items
-// $list-group-disabled-text-color: $list-group-disabled-color
-
-// $list-group-link-color:         #555
-// $list-group-link-hover-color:   $list-group-link-color
-// $list-group-link-heading-color: #333
-
-
-//== Panels
-//
-//##
-
-// $panel-bg:                    #fff
-// $panel-body-padding:          15px
-// $panel-heading-padding:       10px 15px
-// $panel-footer-padding:        $panel-heading-padding
-// $panel-border-radius:         $border-radius-base
-
-//** Border color for elements within panels
-// $panel-inner-border:          #ddd
-// $panel-footer-bg:             #f5f5f5
-
-// $panel-default-text:          $gray-dark
-// $panel-default-border:        #ddd
-// $panel-default-heading-bg:    #f5f5f5
-
-// $panel-primary-text:          #fff
-// $panel-primary-border:        $brand-primary
-// $panel-primary-heading-bg:    $brand-primary
-
-// $panel-success-text:          $state-success-text
-// $panel-success-border:        $state-success-border
-// $panel-success-heading-bg:    $state-success-bg
-
-// $panel-info-text:             $state-info-text
-// $panel-info-border:           $state-info-border
-// $panel-info-heading-bg:       $state-info-bg
-
-// $panel-warning-text:          $state-warning-text
-// $panel-warning-border:        $state-warning-border
-// $panel-warning-heading-bg:    $state-warning-bg
-
-// $panel-danger-text:           $state-danger-text
-// $panel-danger-border:         $state-danger-border
-// $panel-danger-heading-bg:     $state-danger-bg
-
-
-//== Thumbnails
-//
-//##
-
-//** Padding around the thumbnail image
-// $thumbnail-padding:           4px
-//** Thumbnail background color
-// $thumbnail-bg:                $body-bg
-//** Thumbnail border color
-// $thumbnail-border:            #ddd
-//** Thumbnail border radius
-// $thumbnail-border-radius:     $border-radius-base
-
-//** Custom text color for thumbnail captions
-// $thumbnail-caption-color:     $text-color
-//** Padding around the thumbnail caption
-// $thumbnail-caption-padding:   9px
-
-
-//== Wells
-//
-//##
-
-// $well-bg:                     #f5f5f5
-// $well-border:                 darken($well-bg, 7%)
-
-
-//== Badges
-//
-//##
-
-// $badge-color:                 #fff
-//** Linked badge text color on hover
-// $badge-link-hover-color:      #fff
-// $badge-bg:                    $gray-light
-
-//** Badge text color in active nav link
-// $badge-active-color:          $link-color
-//** Badge background color in active nav link
-// $badge-active-bg:             #fff
-
-// $badge-font-weight:           bold
-// $badge-line-height:           1
-// $badge-border-radius:         10px
-
-
-//== Breadcrumbs
-//
-//##
-
-// $breadcrumb-padding-vertical:   8px
-// $breadcrumb-padding-horizontal: 15px
-//** Breadcrumb background color
-// $breadcrumb-bg:                 #f5f5f5
-//** Breadcrumb text color
-// $breadcrumb-color:              #ccc
-//** Text color of current page in the breadcrumb
-// $breadcrumb-active-color:       $gray-light
-//** Textual separator for between breadcrumb elements
-// $breadcrumb-separator:          "/"
-
-
-//== Carousel
-//
-//##
-
-// $carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6)
-
-// $carousel-control-color:                      #fff
-// $carousel-control-width:                      15%
-// $carousel-control-opacity:                    .5
-// $carousel-control-font-size:                  20px
-
-// $carousel-indicator-active-bg:                #fff
-// $carousel-indicator-border-color:             #fff
-
-// $carousel-caption-color:                      #fff
-
-
-//== Close
-//
-//##
-
-// $close-font-weight:           bold
-// $close-color:                 #000
-// $close-text-shadow:           0 1px 0 #fff
-
-
-//== Code
-//
-//##
-
-// $code-color:                  #c7254e
-// $code-bg:                     #f9f2f4
-
-// $kbd-color:                   #fff
-// $kbd-bg:                      #333
-
-// $pre-bg:                      #f5f5f5
-// $pre-color:                   $gray-dark
-// $pre-border-color:            #ccc
-// $pre-scrollable-max-height:   340px
-
-
-//== Type
-//
-//##
-
-//** Horizontal offset for forms and lists.
-// $component-offset-horizontal: 180px
-//** Text muted color
-// $text-muted:                  $gray-light
-//** Abbreviations and acronyms border color
-// $abbr-border-color:           $gray-light
-//** Headings small color
-// $headings-small-color:        $gray-light
-//** Blockquote small color
-// $blockquote-small-color:      $gray-light
-//** Blockquote font size
-// $blockquote-font-size:        ($font-size-base * 1.25)
-//** Blockquote border color
-// $blockquote-border-color:     $gray-lighter
-//** Page header border color
-// $page-header-border-color:    $gray-lighter
-//** Width of horizontal description list titles
-// $dl-horizontal-offset:        $component-offset-horizontal
-//** Point at which .dl-horizontal becomes horizontal
-// $dl-horizontal-breakpoint:    $grid-float-breakpoint
-//** Horizontal line color.
-// $hr-border:                   $gray-lighter
diff --git a/client/systemjs.bundle.js b/client/systemjs.bundle.js
deleted file mode 100644
index 2fd45156a..000000000
--- a/client/systemjs.bundle.js
+++ /dev/null
@@ -1,15 +0,0 @@
-var SystemBuilder = require('systemjs-builder')
-var builder = new SystemBuilder('node_modules', 'systemjs.config.js')
-
-var toBundle = [
-  'rxjs/Rx',
-  '@angular/common',
-  '@angular/compiler',
-  '@angular/core',
-  '@angular/http',
-  '@angular/platform-browser',
-  '@angular/platform-browser-dynamic',
-  '@angular/router-deprecated'
-]
-
-builder.bundle(toBundle.join(' + '), 'bundles/angular-rxjs.bundle.js')
diff --git a/client/systemjs.config.js b/client/systemjs.config.js
deleted file mode 100644
index d04bc4107..000000000
--- a/client/systemjs.config.js
+++ /dev/null
@@ -1,48 +0,0 @@
-;(function (global) {
-  var map = {
-    'angular-pipes': 'client/node_modules/angular-pipes',
-    'ng2-bootstrap': 'client/node_modules/ng2-bootstrap',
-    'angular-rxjs.bundle': 'client/bundles/angular-rxjs.bundle.js'
-  }
-
-  var packages = {
-    'client': { main: 'main.js', defaultExtension: 'js' },
-    'ng2-bootstrap': { defaultExtension: 'js' },
-    'rxjs': { defaultExtension: 'js' }
-  }
-  var packageNames = [
-    '@angular/common',
-    '@angular/compiler',
-    '@angular/core',
-    '@angular/http',
-    '@angular/platform-browser',
-    '@angular/platform-browser-dynamic',
-    '@angular/router-deprecated',
-    'angular-pipes'
-  ]
-
-  packageNames.forEach(function (pkgName) {
-    packages[pkgName] = { main: 'index.js', defaultExtension: 'js' }
-  })
-
-  var config = {
-    map: map,
-    packages: packages,
-    bundles: {
-      'angular-rxjs.bundle': [
-        'rxjs/Rx.js',
-        '@angular/common/index.js',
-        '@angular/compiler/index.js',
-        '@angular/core/index.js',
-        '@angular/http/index.js',
-        '@angular/platform-browser/index.js',
-        '@angular/platform-browser-dynamic/index.js',
-        '@angular/router-deprecated/index.js'
-      ]
-    }
-  }
-
-  // filterSystemConfig - index.html's chance to modify config before we register it.
-  if (global.filterSystemConfig) global.filterSystemConfig(config)
-  System.config(config)
-})(this)
diff --git a/client/tsconfig.json b/client/tsconfig.json
index a8b8269a4..1832d7b7e 100644
--- a/client/tsconfig.json
+++ b/client/tsconfig.json
@@ -20,39 +20,42 @@
   ],
   "compileOnSave": false,
   "files": [
-    "app/app.component.ts",
-    "app/friends/friend.service.ts",
-    "app/friends/index.ts",
-    "app/login/index.ts",
-    "app/login/login.component.ts",
-    "app/shared/index.ts",
-    "app/shared/search/index.ts",
-    "app/shared/search/search-field.type.ts",
-    "app/shared/search/search.component.ts",
-    "app/shared/search/search.model.ts",
-    "app/shared/users/auth-status.model.ts",
-    "app/shared/users/auth.service.ts",
-    "app/shared/users/index.ts",
-    "app/shared/users/token.model.ts",
-    "app/shared/users/user.model.ts",
-    "app/videos/index.ts",
-    "app/videos/shared/index.ts",
-    "app/videos/shared/loader/index.ts",
-    "app/videos/shared/loader/loader.component.ts",
-    "app/videos/shared/pagination.model.ts",
-    "app/videos/shared/sort-field.type.ts",
-    "app/videos/shared/video.model.ts",
-    "app/videos/shared/video.service.ts",
-    "app/videos/video-add/index.ts",
-    "app/videos/video-add/video-add.component.ts",
-    "app/videos/video-list/index.ts",
-    "app/videos/video-list/video-list.component.ts",
-    "app/videos/video-list/video-miniature.component.ts",
-    "app/videos/video-list/video-sort.component.ts",
-    "app/videos/video-watch/index.ts",
-    "app/videos/video-watch/video-watch.component.ts",
-    "app/videos/video-watch/webtorrent.service.ts",
-    "main.ts",
+    "src/app/app.component.ts",
+    "src/app/friends/friend.service.ts",
+    "src/app/friends/index.ts",
+    "src/app/login/index.ts",
+    "src/app/login/login.component.ts",
+    "src/app/shared/index.ts",
+    "src/app/shared/search/index.ts",
+    "src/app/shared/search/search-field.type.ts",
+    "src/app/shared/search/search.component.ts",
+    "src/app/shared/search/search.model.ts",
+    "src/app/shared/users/auth-status.model.ts",
+    "src/app/shared/users/auth.service.ts",
+    "src/app/shared/users/index.ts",
+    "src/app/shared/users/token.model.ts",
+    "src/app/shared/users/user.model.ts",
+    "src/app/videos/index.ts",
+    "src/app/videos/shared/index.ts",
+    "src/app/videos/shared/loader/index.ts",
+    "src/app/videos/shared/loader/loader.component.ts",
+    "src/app/videos/shared/pagination.model.ts",
+    "src/app/videos/shared/sort-field.type.ts",
+    "src/app/videos/shared/video.model.ts",
+    "src/app/videos/shared/video.service.ts",
+    "src/app/videos/video-add/index.ts",
+    "src/app/videos/video-add/video-add.component.ts",
+    "src/app/videos/video-list/index.ts",
+    "src/app/videos/video-list/video-list.component.ts",
+    "src/app/videos/video-list/video-miniature.component.ts",
+    "src/app/videos/video-list/video-sort.component.ts",
+    "src/app/videos/video-watch/index.ts",
+    "src/app/videos/video-watch/video-watch.component.ts",
+    "src/app/videos/video-watch/webtorrent.service.ts",
+    "src/custom-typings.d.ts",
+    "src/main.ts",
+    "src/polyfills.ts",
+    "src/vendor.ts",
     "typings/globals/es6-shim/index.d.ts",
     "typings/globals/jasmine/index.d.ts",
     "typings/globals/jquery.fileupload/index.d.ts",
diff --git a/client/webpack.config.js b/client/webpack.config.js
new file mode 100644
index 000000000..8f54d88e5
--- /dev/null
+++ b/client/webpack.config.js
@@ -0,0 +1,16 @@
+switch (process.env.NODE_ENV) {
+  case 'prod':
+  case 'production':
+    module.exports = require('./config/webpack.prod')
+    break
+
+  case 'test':
+  case 'testing':
+    module.exports = require('./config/webpack.test')
+    break
+
+  case 'dev':
+  case 'development':
+  default:
+    module.exports = require('./config/webpack.dev')
+}
diff --git a/server.js b/server.js
index 02c0d53cd..4c8e8cfd3 100644
--- a/server.js
+++ b/server.js
@@ -64,7 +64,7 @@ const apiRoute = '/api/' + constants.API_VERSION
 app.use(apiRoute, routes.api)
 
 // Static files
-app.use('/client', express.static(path.join(__dirname, '/client'), { maxAge: 0 }))
+app.use('/client', express.static(path.join(__dirname, '/client/dist'), { maxAge: 0 }))
 // 404 for static files not found
 app.use('/client/*', function (req, res, next) {
   res.sendStatus(404)
@@ -76,7 +76,7 @@ app.use(constants.THUMBNAILS_STATIC_PATH, express.static(thumbnailsPhysicalPath,
 
 // Client application
 app.use('/*', function (req, res, next) {
-  res.sendFile(path.join(__dirname, 'client/index.html'))
+  res.sendFile(path.join(__dirname, 'client/dist/index.html'))
 })
 
 // ----------- Tracker -----------